diff --git a/configure b/configure index 27842e149e..a5cfbe0ec6 100755 --- a/configure +++ b/configure @@ -6806,7 +6806,7 @@ else # If they didn't specify it, we try to find it if test $have_lua != yes; then - for ac_header in lua.h lua/lua.h lua5.1/lua.h + for ac_header in lua.h lua/lua.h lua5.2/lua.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -6814,9 +6814,9 @@ if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua_call in -llua" >&5 -$as_echo_n "checking for lua_call in -llua... " >&6; } -if ${ac_cv_lib_lua_lua_call+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua_yieldk in -llua" >&5 +$as_echo_n "checking for lua_yieldk in -llua... " >&6; } +if ${ac_cv_lib_lua_lua_yieldk+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -6830,37 +6830,37 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char lua_call (); +char lua_yieldk (); int main () { -return lua_call (); +return lua_yieldk (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_lua_lua_call=yes + ac_cv_lib_lua_lua_yieldk=yes else - ac_cv_lib_lua_lua_call=no + ac_cv_lib_lua_lua_yieldk=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lua_lua_call" >&5 -$as_echo "$ac_cv_lib_lua_lua_call" >&6; } -if test "x$ac_cv_lib_lua_lua_call" = xyes; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lua_lua_yieldk" >&5 +$as_echo "$ac_cv_lib_lua_lua_yieldk" >&6; } +if test "x$ac_cv_lib_lua_lua_yieldk" = xyes; then : have_lua=yes; LIBLUA_LIBS="-llua"; CPPFLAGS="-I/usr/include/lua $CPPFLAGS"; break fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua_call in -llua5.1" >&5 -$as_echo_n "checking for lua_call in -llua5.1... " >&6; } -if ${ac_cv_lib_lua5_1_lua_call+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua_yieldk in -llua5.2" >&5 +$as_echo_n "checking for lua_yieldk in -llua5.2... " >&6; } +if ${ac_cv_lib_lua5_2_lua_yieldk+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-llua5.1 -lm $LIBS" +LIBS="-llua5.2 -lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -6870,28 +6870,28 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext #ifdef __cplusplus extern "C" #endif -char lua_call (); +char lua_yieldk (); int main () { -return lua_call (); +return lua_yieldk (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_lua5_1_lua_call=yes + ac_cv_lib_lua5_2_lua_yieldk=yes else - ac_cv_lib_lua5_1_lua_call=no + ac_cv_lib_lua5_2_lua_yieldk=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lua5_1_lua_call" >&5 -$as_echo "$ac_cv_lib_lua5_1_lua_call" >&6; } -if test "x$ac_cv_lib_lua5_1_lua_call" = xyes; then : - have_lua=yes; LIBLUA_LIBS="-llua5.1"; CPPFLAGS="-I/usr/include/lua5.1 $CPPFLAGS"; break +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lua5_2_lua_yieldk" >&5 +$as_echo "$ac_cv_lib_lua5_2_lua_yieldk" >&6; } +if test "x$ac_cv_lib_lua5_2_lua_yieldk" = xyes; then : + have_lua=yes; LIBLUA_LIBS="-llua5.2"; CPPFLAGS="-I/usr/include/lua5.2 $CPPFLAGS"; break fi @@ -6906,8 +6906,8 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua version >= 501" >&5 -$as_echo_n "checking for lua version >= 501... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lua version >= 502" >&5 +$as_echo_n "checking for lua version >= 502... " >&6; } if test "$cross_compiling" = yes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: cross-compiling -- assuming yes" >&5 @@ -6919,7 +6919,7 @@ else int main () { -if(LUA_VERSION_NUM < 501) return 1; +if(LUA_VERSION_NUM < 502) return 1; ; return 0; } diff --git a/configure.ac b/configure.ac index 1712c30595..ce83226319 100644 --- a/configure.ac +++ b/configure.ac @@ -606,16 +606,17 @@ else # If they didn't specify it, we try to find it if test $have_lua != yes; then - AC_CHECK_HEADERS([lua.h lua/lua.h lua5.1/lua.h], - AC_CHECK_LIB(lua, lua_call, [have_lua=yes; LIBLUA_LIBS="-llua"; CPPFLAGS="-I/usr/include/lua $CPPFLAGS"; break],, [-lm]) - AC_CHECK_LIB(lua5.1, lua_call, [have_lua=yes; LIBLUA_LIBS="-llua5.1"; CPPFLAGS="-I/usr/include/lua5.1 $CPPFLAGS"; break],, [-lm]) + AC_CHECK_HEADERS([lua.h lua/lua.h lua5.2/lua.h], + AC_CHECK_LIB(lua, lua_yieldk, [have_lua=yes; LIBLUA_LIBS="-llua"; CPPFLAGS="-I/usr/include/lua $CPPFLAGS"; break],, [-lm]) + AC_CHECK_LIB(lua52, lua_yieldk, [have_lua=yes; LIBLUA_LIBS="-llua52"; CPPFLAGS="-I/usr/include/lua52 $CPPFLAGS"; break],, [-lm]) + AC_CHECK_LIB(lua5.2, lua_yieldk, [have_lua=yes; LIBLUA_LIBS="-llua5.2"; CPPFLAGS="-I/usr/include/lua5.2 $CPPFLAGS"; break],, [-lm]) ) AC_LANG_PUSH(C++) - AC_MSG_CHECKING([for lua version >= 501]) + AC_MSG_CHECKING([for lua version >= 502]) AC_RUN_IFELSE([ AC_LANG_PROGRAM( [[#include ]], - [[if(LUA_VERSION_NUM < 501) return 1;]])], + [[if(LUA_VERSION_NUM < 502) return 1;]])], have_lua=yes, have_lua=no, AC_MSG_RESULT(cross-compiling -- assuming yes); have_lua=yes) AC_LANG_POP(C++) diff --git a/liblua/Makefile b/liblua/Makefile index e4a3cd6108..eb11149282 100644 --- a/liblua/Makefile +++ b/liblua/Makefile @@ -1,6 +1,5 @@ -# makefile for building Lua -# see ../INSTALL for installation instructions -# see ../Makefile and luaconf.h for further customization +# Makefile for building Lua +# See ../doc/readme.html for installation and customization instructions. # == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= @@ -8,37 +7,46 @@ PLAT= none CC= gcc -CFLAGS= -O2 -Wall $(MYCFLAGS) +CFLAGS= -O2 -Wall $(SYSCFLAGS) $(MYCFLAGS) +LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) +LIBS= -lm $(SYSLIBS) $(MYLIBS) + AR= ar rcu RANLIB= ranlib RM= rm -f -LIBS= -lm $(MYLIBS) + +SYSCFLAGS= +SYSLDFLAGS= +SYSLIBS= MYCFLAGS= MYLDFLAGS= MYLIBS= +MYOBJS= -# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= +# == 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 +CORE_O= lapi.o lcode.o lctype.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 lbitlib.o lcorolib.o ldblib.o liolib.o \ + lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o +BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) LUA_T= lua LUA_O= lua.o LUAC_T= luac -LUAC_O= luac.o print.o +LUAC_O= luac.o -ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O) +ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O) ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) ALL_A= $(LUA_A) +# Targets start here. default: $(PLAT) all: $(ALL_T) @@ -47,136 +55,133 @@ o: $(ALL_O) a: $(ALL_A) -$(LUA_A): $(CORE_O) $(LIB_O) +$(LUA_A): $(BASE_O) $(AR) $@ $? $(RANLIB) $@ $(LUA_T): $(LUA_O) $(LUA_A) - $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) + $(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) $(LUAC_T): $(LUAC_O) $(LUA_A) - $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) + $(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) clean: $(RM) $(ALL_T) $(ALL_O) depend: - @$(CC) $(CFLAGS) -MM l*.c print.c + @$(CC) $(CFLAGS) -MM l*.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 + @echo "PLAT= $(PLAT)" + @echo "CC= $(CC)" + @echo "CFLAGS= $(CFLAGS)" + @echo "LDFLAGS= $(SYSLDFLAGS)" + @echo "LIBS= $(LIBS)" + @echo "AR= $(AR)" + @echo "RANLIB= $(RANLIB)" + @echo "RM= $(RM)" + +# Convenience targets for popular platforms +ALL= all none: - @echo "Please choose a platform:" + @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" @echo " $(PLATS)" aix: - $(MAKE) all CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall" + $(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall" ansi: - $(MAKE) all MYCFLAGS=-DLUA_ANSI + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_ANSI" bsd: - $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E" freebsd: - $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline" + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline" -generic: - $(MAKE) all MYCFLAGS= +generic: $(ALL) linux: - $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline -lncurses" macosx: - $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline" -# use this on Mac OS X 10.3- -# $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" mingw: - $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ + $(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \ "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ - "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe + "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe $(MAKE) "LUAC_T=luac.exe" luac.exe posix: - $(MAKE) all MYCFLAGS=-DLUA_USE_POSIX + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" solaris: - $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-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 +lapi.o: lapi.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ + lzio.h lmem.h ldebug.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 +lbitlib.o: lbitlib.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 + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ + lstring.h ltable.h lvm.h +lcorolib.o: lcorolib.c lua.h luaconf.h lauxlib.h lualib.h +lctype.o: lctype.c lctype.h lua.h luaconf.h llimits.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 +ldebug.o: ldebug.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ + ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h ldebug.h ldo.h \ + lfunc.h lstring.h lgc.h ltable.h lvm.h +ldo.o: ldo.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ + lzio.h lmem.h ldebug.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 + lzio.h lmem.h lundump.h +lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h \ + lstate.h ltm.h lzio.h lmem.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 + 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 +llex.o: llex.c lua.h luaconf.h lctype.h llimits.h ldo.h lobject.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 + ltm.h lzio.h lmem.h ldo.h lgc.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 +lobject.o: lobject.c lua.h luaconf.h lctype.h llimits.h ldebug.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h ldo.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 + 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 lapi.h llimits.h lstate.h lobject.h \ + ltm.h lzio.h lmem.h ldebug.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 + 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 + ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.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 + 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 +luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.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 + 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.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 + lzio.h -# (end of Makefile) diff --git a/liblua/lapi.c b/liblua/lapi.c index 9a39513fbd..e96ceb9e14 100644 --- a/liblua/lapi.c +++ b/liblua/lapi.c @@ -1,12 +1,10 @@ /* -** $Id: lapi.c,v 2.55.1.3 2008/01/03 15:20:39 roberto Exp $ +** $Id: lapi.c,v 2.159 2011/11/30 12:32:05 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ -#include -#include #include #include @@ -32,76 +30,71 @@ const char lua_ident[] = - "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" - "$Authors: " LUA_AUTHORS " $\n" - "$URL: www.lua.org $\n"; + "$LuaVersion: " LUA_COPYRIGHT " $" + "$LuaAuthors: " LUA_AUTHORS " $"; +/* value at a non-valid index */ +#define NONVALIDVALUE cast(TValue *, luaO_nilobject) -#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) +/* corresponding test */ +#define isvalid(o) ((o) != luaO_nilobject) -#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) +#define api_checkvalidindex(L, i) api_check(L, isvalid(i), "invalid index") -#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} - - -static TValue *index2adr (lua_State *L, int idx) { +static TValue *index2addr (lua_State *L, int idx) { + CallInfo *ci = L->ci; 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); + TValue *o = ci->func + idx; + api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); + if (o >= L->top) return NONVALIDVALUE; else return o; } else if (idx > LUA_REGISTRYINDEX) { - api_check(L, idx != 0 && -idx <= L->top - L->base); + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); 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); + else if (idx == LUA_REGISTRYINDEX) + return &G(L)->l_registry; + else { /* upvalues */ + idx = LUA_REGISTRYINDEX - idx; + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); + if (ttislcf(ci->func)) /* light C function? */ + return NONVALIDVALUE; /* it has no upvalues */ + else { + CClosure *func = clCvalue(ci->func); + return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; } } } -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); +/* +** to be called by 'lua_checkstack' in protected mode, to grow stack +** capturing memory errors +*/ +static void growstack (lua_State *L, void *ud) { + int size = *(int *)ud; + luaD_growstack(L, size); } LUA_API int lua_checkstack (lua_State *L, int size) { - int res = 1; + int res; + CallInfo *ci = L->ci; 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; + if (L->stack_last - L->top > size) /* stack large enough? */ + res = 1; /* yes; check is OK */ + else { /* no; need to grow stack */ + int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; + if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */ + res = 0; /* no */ + else /* try to grow stack */ + res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK); } + if (res && ci->top < L->top + size) + ci->top = L->top + size; /* adjust frame top */ lua_unlock(L); return res; } @@ -112,8 +105,8 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { 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); + api_check(from, G(from) == G(to), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); from->top -= n; for (i = 0; i < n; i++) { setobj2s(to, to->top++, from->top + i); @@ -122,11 +115,6 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { } -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); @@ -137,16 +125,10 @@ LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { } -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; +LUA_API const lua_Number *lua_version (lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + else return G(L)->version; } @@ -156,21 +138,32 @@ LUA_API lua_State *lua_newthread (lua_State *L) { */ +/* +** convert an acceptable stack index into an absolute index +*/ +LUA_API int lua_absindex (lua_State *L, int idx) { + return (idx > 0 || idx <= LUA_REGISTRYINDEX) + ? idx + : cast_int(L->top - L->ci->func + idx); +} + + LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - L->base); + return cast_int(L->top - (L->ci->func + 1)); } LUA_API void lua_settop (lua_State *L, int idx) { + StkId func = L->ci->func; lua_lock(L); if (idx >= 0) { - api_check(L, idx <= L->stack_last - L->base); - while (L->top < L->base + idx) + api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); + while (L->top < (func + 1) + idx) setnilvalue(L->top++); - L->top = L->base + idx; + L->top = (func + 1) + idx; } else { - api_check(L, -(idx+1) <= (L->top - L->base)); + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); L->top += idx+1; /* `subtract' index (index is negative) */ } lua_unlock(L); @@ -180,7 +173,7 @@ LUA_API void lua_settop (lua_State *L, int idx) { LUA_API void lua_remove (lua_State *L, int idx) { StkId p; lua_lock(L); - p = index2adr(L, idx); + p = index2addr(L, idx); api_checkvalidindex(L, p); while (++p < L->top) setobjs2s(L, p-1, p); L->top--; @@ -192,7 +185,7 @@ LUA_API void lua_insert (lua_State *L, int idx) { StkId p; StkId q; lua_lock(L); - p = index2adr(L, idx); + p = index2addr(L, idx); api_checkvalidindex(L, p); for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); setobjs2s(L, p, L->top); @@ -200,34 +193,39 @@ LUA_API void lua_insert (lua_State *L, int idx) { } +static void moveto (lua_State *L, TValue *fr, int idx) { + TValue *to = index2addr(L, idx); + api_checkvalidindex(L, to); + setobj(L, to, fr); + if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ + luaC_barrier(L, clCvalue(L->ci->func), fr); + /* LUA_REGISTRYINDEX does not need gc barrier + (collector revisits it before finishing collection) */ +} + + 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); - } + moveto(L, L->top - 1, idx); L->top--; lua_unlock(L); } +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { + TValue *fr; + lua_lock(L); + fr = index2addr(L, fromidx); + api_checkvalidindex(L, fr); + moveto(L, fr, toidx); + lua_unlock(L); +} + + LUA_API void lua_pushvalue (lua_State *L, int idx) { lua_lock(L); - setobj2s(L, L->top, index2adr(L, idx)); + setobj2s(L, L->top, index2addr(L, idx)); api_incr_top(L); lua_unlock(L); } @@ -240,26 +238,26 @@ LUA_API void lua_pushvalue (lua_State *L, int idx) { LUA_API int lua_type (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); + StkId o = index2addr(L, idx); + return (isvalid(o) ? ttypenv(o) : LUA_TNONE); } LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); - return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; + return ttypename(t); } LUA_API int lua_iscfunction (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - return iscfunction(o); + StkId o = index2addr(L, idx); + return (ttislcf(o) || (ttisCclosure(o))); } LUA_API int lua_isnumber (lua_State *L, int idx) { TValue n; - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(L, idx); return tonumber(o, &n); } @@ -271,77 +269,116 @@ LUA_API int lua_isstring (lua_State *L, int idx) { LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(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); + StkId o1 = index2addr(L, index1); + StkId o2 = index2addr(L, index2); + return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; } -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_API void lua_arith (lua_State *L, int op) { + StkId o1; /* 1st operand */ + StkId o2; /* 2nd operand */ + lua_lock(L); + if (op != LUA_OPUNM) /* all other operations expect two operands */ + api_checknelems(L, 2); + else { /* for unary minus, add fake 2nd operand */ + api_checknelems(L, 1); + setobjs2s(L, L->top, L->top - 1); + L->top++; + } + o1 = L->top - 2; + o2 = L->top - 1; + if (ttisnumber(o1) && ttisnumber(o2)) { + changenvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); + } + else + luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); + L->top--; lua_unlock(L); - return i; } -LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { +LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { StkId o1, o2; - int i; + int i = 0; 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); + o1 = index2addr(L, index1); + o2 = index2addr(L, index2); + if (isvalid(o1) && isvalid(o2)) { + switch (op) { + case LUA_OPEQ: i = equalobj(L, o1, o2); break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; + default: api_check(L, 0, "invalid option"); + } + } lua_unlock(L); return i; } - -LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { TValue n; - const TValue *o = index2adr(L, idx); - if (tonumber(o, &n)) + const TValue *o = index2addr(L, idx); + if (tonumber(o, &n)) { + if (isnum) *isnum = 1; return nvalue(o); - else + } + else { + if (isnum) *isnum = 0; return 0; + } } -LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { TValue n; - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(L, idx); if (tonumber(o, &n)) { lua_Integer res; lua_Number num = nvalue(o); lua_number2integer(res, num); + if (isnum) *isnum = 1; return res; } - else + else { + if (isnum) *isnum = 0; + return 0; + } +} + + +LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) { + TValue n; + const TValue *o = index2addr(L, idx); + if (tonumber(o, &n)) { + lua_Unsigned res; + lua_Number num = nvalue(o); + lua_number2unsigned(res, num); + if (isnum) *isnum = 1; + return res; + } + else { + if (isnum) *isnum = 0; return 0; + } } LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2adr(L, idx); + const TValue *o = index2addr(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); + StkId o = index2addr(L, idx); if (!ttisstring(o)) { lua_lock(L); /* `luaV_tostring' may create a new string */ if (!luaV_tostring(L, o)) { /* conversion failed? */ @@ -350,7 +387,7 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { return NULL; } luaC_checkGC(L); - o = index2adr(L, idx); /* previous call may reallocate the stack */ + o = index2addr(L, idx); /* previous call may reallocate the stack */ lua_unlock(L); } if (len != NULL) *len = tsvalue(o)->len; @@ -358,33 +395,29 @@ 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) { - StkId o = index2adr(L, idx); - switch (ttype(o)) { +LUA_API size_t lua_rawlen (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttypenv(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; + StkId o = index2addr(L, idx); + if (ttislcf(o)) return fvalue(o); + else if (ttisCclosure(o)) + return clCvalue(o)->f; + else return NULL; /* not a C function */ } LUA_API void *lua_touserdata (lua_State *L, int idx) { - StkId o = index2adr(L, idx); - switch (ttype(o)) { + StkId o = index2addr(L, idx); + switch (ttypenv(o)) { case LUA_TUSERDATA: return (rawuvalue(o) + 1); case LUA_TLIGHTUSERDATA: return pvalue(o); default: return NULL; @@ -393,16 +426,18 @@ LUA_API void *lua_touserdata (lua_State *L, int idx) { LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); return (!ttisthread(o)) ? NULL : thvalue(o); } LUA_API const void *lua_topointer (lua_State *L, int idx) { - StkId o = index2adr(L, idx); + StkId o = index2addr(L, idx); switch (ttype(o)) { case LUA_TTABLE: return hvalue(o); - case LUA_TFUNCTION: return clvalue(o); + case LUA_TLCL: return clLvalue(o); + case LUA_TCCL: return clCvalue(o); + case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); case LUA_TTHREAD: return thvalue(o); case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA: @@ -429,6 +464,8 @@ LUA_API void lua_pushnil (lua_State *L) { LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { lua_lock(L); setnvalue(L->top, n); + luai_checknum(L, L->top, + luaG_runerror(L, "C API - attempt to push a signaling NaN")); api_incr_top(L); lua_unlock(L); } @@ -442,20 +479,43 @@ LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { } -LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { +LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) { + lua_Number n; + lua_lock(L); + n = lua_unsigned2number(u); + setnvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { + TString *ts; lua_lock(L); luaC_checkGC(L); - setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); + ts = luaS_newlstr(L, s, len); + setsvalue2s(L, L->top, ts); api_incr_top(L); lua_unlock(L); + return getstr(ts); } -LUA_API void lua_pushstring (lua_State *L, const char *s) { - if (s == NULL) +LUA_API const char *lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) { lua_pushnil(L); - else - lua_pushlstring(L, s, strlen(s)); + return NULL; + } + else { + TString *ts; + lua_lock(L); + luaC_checkGC(L); + ts = luaS_new(L, s); + setsvalue2s(L, L->top, ts); + api_incr_top(L); + lua_unlock(L); + return getstr(ts); + } } @@ -484,17 +544,22 @@ 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) { - 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))); + if (n == 0) { + setfvalue(L->top, fn); + } + else { + Closure *cl; + api_checknelems(L, n); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); + luaC_checkGC(L); + cl = luaF_newCclosure(L, n); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(L, &cl->c.upvalue[n], L->top + n); + setclCvalue(L, L->top, cl); + } api_incr_top(L); lua_unlock(L); } @@ -531,10 +596,21 @@ LUA_API int lua_pushthread (lua_State *L) { */ +LUA_API void lua_getglobal (lua_State *L, const char *var) { + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt; /* global table */ + lua_lock(L); + gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + setsvalue2s(L, L->top++, luaS_new(L, var)); + luaV_gettable(L, gt, L->top - 1, L->top - 1); + lua_unlock(L); +} + + LUA_API void lua_gettable (lua_State *L, int idx) { StkId t; lua_lock(L); - t = index2adr(L, idx); + t = index2addr(L, idx); api_checkvalidindex(L, t); luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); @@ -543,13 +619,12 @@ LUA_API void lua_gettable (lua_State *L, int idx) { LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { StkId t; - TValue key; lua_lock(L); - t = index2adr(L, idx); + t = index2addr(L, idx); api_checkvalidindex(L, t); - setsvalue(L, &key, luaS_new(L, k)); - luaV_gettable(L, t, &key, L->top); + setsvalue2s(L, L->top, luaS_new(L, k)); api_incr_top(L); + luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); } @@ -557,29 +632,46 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { LUA_API void lua_rawget (lua_State *L, int idx) { StkId t; lua_lock(L); - t = index2adr(L, idx); - api_check(L, ttistable(t)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); 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; + StkId t; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top, luaH_getint(hvalue(t), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; lua_lock(L); - o = index2adr(L, idx); - api_check(L, ttistable(o)); - setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2s(L, L->top, luaH_get(hvalue(t), &k)); api_incr_top(L); lua_unlock(L); } LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + Table *t; lua_lock(L); luaC_checkGC(L); - sethvalue(L, L->top, luaH_new(L, narray, nrec)); + t = luaH_new(L); + sethvalue(L, L->top, t); api_incr_top(L); + if (narray > 0 || nrec > 0) + luaH_resize(L, t, narray, nrec); lua_unlock(L); } @@ -589,8 +681,8 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { Table *mt = NULL; int res; lua_lock(L); - obj = index2adr(L, objindex); - switch (ttype(obj)) { + obj = index2addr(L, objindex); + switch (ttypenv(obj)) { case LUA_TTABLE: mt = hvalue(obj)->metatable; break; @@ -598,7 +690,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { mt = uvalue(obj)->metatable; break; default: - mt = G(L)->mt[ttype(obj)]; + mt = G(L)->mt[ttypenv(obj)]; break; } if (mt == NULL) @@ -613,25 +705,16 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { } -LUA_API void lua_getfenv (lua_State *L, int idx) { +LUA_API void lua_getuservalue (lua_State *L, int idx) { StkId o; lua_lock(L); - o = index2adr(L, idx); + o = index2addr(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_check(L, ttisuserdata(o), "userdata expected"); + if (uvalue(o)->env) { + sethvalue(L, L->top, uvalue(o)->env); + } else + setnilvalue(L->top); api_incr_top(L); lua_unlock(L); } @@ -642,11 +725,24 @@ LUA_API void lua_getfenv (lua_State *L, int idx) { */ +LUA_API void lua_setglobal (lua_State *L, const char *var) { + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt; /* global table */ + lua_lock(L); + api_checknelems(L, 1); + gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + setsvalue2s(L, L->top++, luaS_new(L, var)); + luaV_settable(L, gt, L->top - 1, L->top - 2); + L->top -= 2; /* pop value and key */ + lua_unlock(L); +} + + LUA_API void lua_settable (lua_State *L, int idx) { StkId t; lua_lock(L); api_checknelems(L, 2); - t = index2adr(L, idx); + t = index2addr(L, idx); api_checkvalidindex(L, t); luaV_settable(L, t, L->top - 2, L->top - 1); L->top -= 2; /* pop index and value */ @@ -656,14 +752,13 @@ LUA_API void lua_settable (lua_State *L, int idx) { 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); + t = index2addr(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 */ + setsvalue2s(L, L->top++, luaS_new(L, k)); + luaV_settable(L, t, L->top - 1, L->top - 2); + L->top -= 2; /* pop value and key */ lua_unlock(L); } @@ -672,23 +767,39 @@ 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)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); - luaC_barriert(L, hvalue(t), L->top-1); + invalidateTMcache(hvalue(t)); + luaC_barrierback(L, gcvalue(t), L->top-1); L->top -= 2; lua_unlock(L); } LUA_API void lua_rawseti (lua_State *L, int idx, int n) { - StkId o; + StkId t; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + luaH_setint(L, hvalue(t), n, L->top - 1); + luaC_barrierback(L, gcvalue(t), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; 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); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); + luaC_barrierback(L, gcvalue(t), L->top - 1); L->top--; lua_unlock(L); } @@ -699,29 +810,32 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { Table *mt; lua_lock(L); api_checknelems(L, 1); - obj = index2adr(L, objindex); + obj = index2addr(L, objindex); api_checkvalidindex(L, obj); if (ttisnil(L->top - 1)) mt = NULL; else { - api_check(L, ttistable(L->top - 1)); + api_check(L, ttistable(L->top - 1), "table expected"); mt = hvalue(L->top - 1); } - switch (ttype(obj)) { + switch (ttypenv(obj)) { case LUA_TTABLE: { hvalue(obj)->metatable = mt; if (mt) - luaC_objbarriert(L, hvalue(obj), mt); + luaC_objbarrierback(L, gcvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); break; } case LUA_TUSERDATA: { uvalue(obj)->metatable = mt; - if (mt) + if (mt) { luaC_objbarrier(L, rawuvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } break; } default: { - G(L)->mt[ttype(obj)] = mt; + G(L)->mt[ttypenv(obj)] = mt; break; } } @@ -731,32 +845,22 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { } -LUA_API int lua_setfenv (lua_State *L, int idx) { +LUA_API void lua_setuservalue (lua_State *L, int idx) { StkId o; - int res = 1; lua_lock(L); api_checknelems(L, 1); - o = index2adr(L, idx); + o = index2addr(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; + api_check(L, ttisuserdata(o), "userdata expected"); + if (ttisnil(L->top - 1)) + uvalue(o)->env = NULL; + else { + api_check(L, ttistable(L->top - 1), "table expected"); + uvalue(o)->env = hvalue(L->top - 1); + luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); } - if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); L->top--; lua_unlock(L); - return res; } @@ -765,21 +869,37 @@ LUA_API int lua_setfenv (lua_State *L, int idx) { */ -#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)), \ + "results from function overflow current stack size") -#define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) - +LUA_API int lua_getctx (lua_State *L, int *ctx) { + if (L->ci->callstatus & CIST_YIELDED) { + if (ctx) *ctx = L->ci->u.c.ctx; + return L->ci->u.c.status; + } + else return LUA_OK; +} + -LUA_API void lua_call (lua_State *L, int nargs, int nresults) { +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, + lua_CFunction k) { StkId func; lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); func = L->top - (nargs+1); - luaD_call(L, func, nresults); + if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ + L->ci->u.c.k = k; /* save continuation */ + L->ci->u.c.ctx = ctx; /* save context */ + luaD_call(L, func, nresults, 1); /* do the call */ + } + else /* no continuation or no yieldable */ + luaD_call(L, func, nresults, 0); /* just do the call */ adjustresults(L, nresults); lua_unlock(L); } @@ -797,76 +917,75 @@ struct CallS { /* data to `f_call' */ static void f_call (lua_State *L, void *ud) { struct CallS *c = cast(struct CallS *, ud); - luaD_call(L, c->func, c->nresults); + luaD_call(L, c->func, c->nresults, 0); } -LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { +LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, + int ctx, lua_CFunction k) { struct CallS c; int status; ptrdiff_t func; lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); if (errfunc == 0) func = 0; else { - StkId o = index2adr(L, errfunc); + StkId o = index2addr(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); + if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ + c.nresults = nresults; /* do a 'conventional' protected call */ + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + } + else { /* prepare continuation (call is already protected by 'resume') */ + CallInfo *ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ + /* save information for error recovery */ + ci->u.c.extra = savestack(L, c.func); + ci->u.c.old_allowhook = L->allowhook; + ci->u.c.old_errfunc = L->errfunc; + L->errfunc = func; + /* mark that function may do error recovery */ + ci->callstatus |= CIST_YPCALL; + luaD_call(L, c.func, nresults, 1); /* do the call */ + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + status = LUA_OK; /* if it is here, there were no errors */ + } 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) { + const char *chunkname, const char *mode) { ZIO z; int status; lua_lock(L); if (!chunkname) chunkname = "?"; luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname); + status = luaD_protectedparser(L, &z, chunkname, mode); + if (status == LUA_OK) { /* no errors? */ + LClosure *f = clLvalue(L->top - 1); /* get newly created function */ + if (f->nupvalues == 1) { /* does it have one upvalue? */ + /* get global table from registry */ + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + setobj(L, f->upvals[0]->v, gt); + luaC_barrier(L, f->upvals[0], gt); + } + } lua_unlock(L); return status; } @@ -879,7 +998,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { api_checknelems(L, 1); o = L->top - 1; if (isLfunction(o)) - status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); + status = luaU_dump(L, getproto(o), writer, data, 0); else status = 1; lua_unlock(L); @@ -903,36 +1022,41 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { g = G(L); switch (what) { case LUA_GCSTOP: { - g->GCthreshold = MAX_LUMEM; + g->gcrunning = 0; break; } case LUA_GCRESTART: { - g->GCthreshold = g->totalbytes; + luaE_setdebt(g, 0); + g->gcrunning = 1; break; } case LUA_GCCOLLECT: { - luaC_fullgc(L); + luaC_fullgc(L, 0); break; } case LUA_GCCOUNT: { /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(g->totalbytes >> 10); + res = cast_int(gettotalbytes(g) >> 10); break; } case LUA_GCCOUNTB: { - res = cast_int(g->totalbytes & 0x3ff); + res = cast_int(gettotalbytes(g) & 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 */ + if (g->gckind == KGC_GEN) { /* generational mode? */ + res = (g->lastmajormem == 0); /* 1 if will do major collection */ + luaC_forcestep(L); /* do a single step */ + } + else { + while (data-- >= 0) { + luaC_forcestep(L); + if (g->gcstate == GCSpause) { /* end of cycle? */ + res = 1; /* signal it */ + break; + } + } + } break; } case LUA_GCSETPAUSE: { @@ -940,11 +1064,28 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { g->gcpause = data; break; } + case LUA_GCSETMAJORINC: { + res = g->gcmajorinc; + g->gcmajorinc = data; + break; + } case LUA_GCSETSTEPMUL: { res = g->gcstepmul; g->gcstepmul = data; break; } + case LUA_GCISRUNNING: { + res = g->gcrunning; + break; + } + case LUA_GCGEN: { /* change collector to generational mode */ + luaC_changemode(L, KGC_GEN); + break; + } + case LUA_GCINC: { /* change collector to incremental mode */ + luaC_changemode(L, KGC_NORMAL); + break; + } default: res = -1; /* invalid option */ } lua_unlock(L); @@ -971,8 +1112,8 @@ 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)); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); more = luaH_next(L, hvalue(t), L->top - 1); if (more) { api_incr_top(L); @@ -989,8 +1130,7 @@ LUA_API void lua_concat (lua_State *L, int n) { 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); + luaV_concat(L, n); } else if (n == 0) { /* push empty string */ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); @@ -1001,6 +1141,16 @@ LUA_API void lua_concat (lua_State *L, int n) { } +LUA_API void lua_len (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_objlen(L, L->top, t); + api_incr_top(L); + lua_unlock(L); +} + + LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { lua_Alloc f; lua_lock(L); @@ -1023,7 +1173,7 @@ 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)); + u = luaS_newudata(L, size, NULL); setuvalue(L, L->top, u); api_incr_top(L); lua_unlock(L); @@ -1032,30 +1182,36 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { - -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]); +static const char *aux_upvalue (StkId fi, int n, TValue **val, + GCObject **owner) { + switch (ttype(fi)) { + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + if (!(1 <= n && n <= f->nupvalues)) return NULL; + *val = &f->upvalue[n-1]; + if (owner) *owner = obj2gco(f); + return ""; + } + case LUA_TLCL: { /* Lua closure */ + LClosure *f = clLvalue(fi); + TString *name; + Proto *p = f->p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->upvals[n-1]->v; + if (owner) *owner = obj2gco(f->upvals[n - 1]); + name = p->upvalues[n-1].name; + return (name == NULL) ? "" : getstr(name); + } + default: return NULL; /* not a closure */ } } LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { const char *name; - TValue *val; + TValue *val = NULL; /* to avoid warnings */ lua_lock(L); - name = aux_upvalue(index2adr(L, funcindex), n, &val); + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); if (name) { setobj2s(L, L->top, val); api_incr_top(L); @@ -1067,18 +1223,59 @@ 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) { const char *name; - TValue *val; + TValue *val = NULL; /* to avoid warnings */ + GCObject *owner = NULL; /* to avoid warnings */ StkId fi; lua_lock(L); - fi = index2adr(L, funcindex); + fi = index2addr(L, funcindex); api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val); + name = aux_upvalue(fi, n, &val, &owner); if (name) { L->top--; setobj(L, val, L->top); - luaC_barrier(L, clvalue(fi), L->top); + luaC_barrier(L, owner, L->top); } lua_unlock(L); return name; } + +static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { + LClosure *f; + StkId fi = index2addr(L, fidx); + api_check(L, ttisLclosure(fi), "Lua function expected"); + f = clLvalue(fi); + api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); + if (pf) *pf = f; + return &f->upvals[n - 1]; /* get its upvalue pointer */ +} + + +LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { + StkId fi = index2addr(L, fidx); + switch (ttype(fi)) { + case LUA_TLCL: { /* lua closure */ + return *getupvalref(L, fidx, n, NULL); + } + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); + return &f->upvalue[n - 1]; + } + default: { + api_check(L, 0, "closure expected"); + return NULL; + } + } +} + + +LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, + int fidx2, int n2) { + LClosure *f1; + UpVal **up1 = getupvalref(L, fidx1, n1, &f1); + UpVal **up2 = getupvalref(L, fidx2, n2, NULL); + *up1 = *up2; + luaC_objbarrier(L, f1, *up2); +} + diff --git a/liblua/lapi.h b/liblua/lapi.h index 2c3fab244e..0909a3911d 100644 --- a/liblua/lapi.h +++ b/liblua/lapi.h @@ -1,5 +1,5 @@ /* -** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lapi.h,v 2.7 2009/11/27 15:37:59 roberto Exp $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ @@ -8,9 +8,17 @@ #define lapi_h -#include "lobject.h" +#include "llimits.h" +#include "lstate.h" +#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ + "stack overflow");} + +#define adjustresults(L,nres) \ + { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + +#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ + "not enough elements in the stack") -LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); #endif diff --git a/liblua/lauxlib.c b/liblua/lauxlib.c index 10f14e2c08..0aa80fd94a 100644 --- a/liblua/lauxlib.c +++ b/liblua/lauxlib.c @@ -1,11 +1,10 @@ /* -** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ +** $Id: lauxlib.c,v 1.240 2011/12/06 16:33:55 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ -#include #include #include #include @@ -25,12 +24,124 @@ #include "lauxlib.h" -#define FREELIST_REF 0 /* free list of references */ +/* +** {====================================================== +** Traceback +** ======================================================= +*/ + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + + + +/* +** search for 'objidx' in table at index -1. +** return 1 + string at top if find a good name. +*/ +static int findfield (lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + + +static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushglobaltable(L); + if (findfield(L, top + 1, 2)) { + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + +static void pushfuncname (lua_State *L, lua_Debug *ar) { + if (*ar->namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, "function " LUA_QS, ar->name); + else if (*ar->what == 'm') /* main? */ + lua_pushfstring(L, "main chunk"); + else if (*ar->what == 'C') { + if (pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); + } + else + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); +} -/* convert a stack index to positive */ -#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ - lua_gettop(L) + (i) + 1) + +static int countlevels (lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le)/2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + + +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int numlevels = countlevels(L1); + int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; + if (msg) lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level == mark) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = numlevels - LEVELS2; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + if (ar.istailcall) + lua_pushliteral(L, "\n\t(...tail calls...)"); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + +/* }====================================================== */ /* @@ -39,7 +150,6 @@ ** ======================================================= */ - 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? */ @@ -48,17 +158,16 @@ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { 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); + return luaL_error(L, "calling " LUA_QS " on bad self", ar.name); } if (ar.name == NULL) - ar.name = "?"; + ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; 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) { +static int typeerror (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); @@ -66,7 +175,7 @@ LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { static void tag_error (lua_State *L, int narg, int tag) { - luaL_typerror(L, narg, lua_typename(L, tag)); + typeerror(L, narg, lua_typename(L, tag)); } @@ -93,24 +202,74 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { return lua_error(L); } -/* }====================================================== */ +LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, strerror(en)); + else + lua_pushfstring(L, "%s", strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} -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)); + +#if !defined(inspectstat) /* { */ + +#if defined(LUA_USE_POSIX) + +#include + +/* +** use appropriate macros to interpret 'pclose' return status +*/ +#define inspectstat(stat,what) \ + if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ + else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } + +#else + +#define inspectstat(stat,what) /* no op */ + +#endif + +#endif /* } */ + + +LUALIB_API int luaL_execresult (lua_State *L, int stat) { + const char *what = "exit"; /* type of termination */ + if (stat == -1) /* error? */ + return luaL_fileresult(L, 0, NULL); + else { + inspectstat(stat, what); /* interpret result */ + if (*what == 'e' && stat == 0) /* successful termination? */ + lua_pushboolean(L, 1); + else + lua_pushnil(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; /* return true/nil,what,code */ + } } +/* }====================================================== */ + + +/* +** {====================================================== +** Userdata's metatable manipulation +** ======================================================= +*/ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ + luaL_getmetatable(L, tname); /* try to get metatable */ if (!lua_isnil(L, -1)) /* name already in use? */ return 0; /* leave previous value on top, but return 0 */ lua_pop(L, 1); @@ -121,25 +280,64 @@ 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_setmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + + +LUALIB_API void *luaL_testudata (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_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; } } - luaL_typerror(L, ud, tname); /* else error */ - return NULL; /* to avoid warnings */ + return NULL; /* value is not a userdata with a metatable */ +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = luaL_testudata(L, ud, tname); + if (p == NULL) typeerror(L, ud, tname); + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Argument check functions +** ======================================================= +*/ + +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 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_checkstack (lua_State *L, int space, const char *msg) { + /* keep some extra space to run error routines, if needed */ + const int extra = LUA_MINSTACK; + if (!lua_checkstack(L, space + extra)) { + if (msg) + luaL_error(L, "stack overflow (%s)", msg); + else + luaL_error(L, "stack overflow"); + } } @@ -174,8 +372,9 @@ LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, 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 */ + int isnum; + lua_Number d = lua_tonumberx(L, narg, &isnum); + if (!isnum) tag_error(L, narg, LUA_TNUMBER); return d; } @@ -187,255 +386,79 @@ LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number 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 */ + int isnum; + lua_Integer d = lua_tointegerx(L, narg, &isnum); + if (!isnum) 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 lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { + int isnum; + lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); + if (!isnum) + tag_error(L, narg, LUA_TNUMBER); + return d; } -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 lua_Integer luaL_optinteger (lua_State *L, int narg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, narg, def); } -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); +LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg, + lua_Unsigned def) { + return luaL_opt(L, luaL_checkunsigned, narg, def); } -#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; - } -} +/* +** check whether buffer is using a userdata on the stack as a temporary +** buffer +*/ +#define buffonstack(B) ((B)->b != (B)->initb) -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; +/* +** returns a pointer to a free area with at least 'sz' bytes +*/ +LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { + lua_State *L = B->L; + if (B->size - B->n < sz) { /* not enough space? */ + char *newbuff; + size_t newsize = B->size * 2; /* double buffer size */ + if (newsize - B->n < sz) /* not bit enough? */ + newsize = B->n + sz; + if (newsize < B->n || newsize - B->n < sz) + luaL_error(L, "buffer too large"); + /* create larger buffer */ + newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char)); + /* move content to new buffer */ + memcpy(newbuff, B->b, B->n * sizeof(char)); + if (buffonstack(B)) + lua_remove(L, -2); /* remove old buffer */ + B->b = newbuff; + B->size = newsize; } -} - - -LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { - if (emptybuffer(B)) - adjuststack(B); - return B->buffer; + return &B->b[B->n]; } LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - while (l--) - luaL_addchar(B, *s++); + char *b = luaL_prepbuffsize(B, l); + memcpy(b, s, l * sizeof(char)); + luaL_addsize(B, l); } @@ -445,57 +468,72 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - emptybuffer(B); - lua_concat(B->L, B->lvl); - B->lvl = 1; + lua_State *L = B->L; + lua_pushlstring(L, B->b, B->n); + if (buffonstack(B)) + lua_remove(L, -2); /* remove old buffer */ +} + + +LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { + luaL_addsize(B, sz); + luaL_pushresult(B); } 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); - } + size_t l; + const char *s = lua_tolstring(L, -1, &l); + if (buffonstack(B)) + lua_insert(L, -2); /* put value below buffer */ + luaL_addlstring(B, s, l); + lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ } LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { B->L = L; - B->p = B->buffer; - B->lvl = 0; + B->b = B->initb; + B->n = 0; + B->size = LUAL_BUFFERSIZE; +} + + +LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { + luaL_buffinit(L, B); + return luaL_prepbuffsize(B, sz); } /* }====================================================== */ +/* +** {====================================================== +** Reference system +** ======================================================= +*/ + +/* index of free-list header */ +#define freelist 0 + + LUALIB_API int luaL_ref (lua_State *L, int t) { int ref; - t = abs_index(L, t); + t = lua_absindex(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_rawgeti(L, t, freelist); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ 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, freelist); /* (t[freelist] = t[ref]) */ } + else /* no free elements */ + ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ lua_rawseti(L, t, ref); return ref; } @@ -503,14 +541,15 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { 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] */ + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); + lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ lua_pushinteger(L, ref); - lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ + lua_rawseti(L, t, freelist); /* t[freelist] = ref */ } } +/* }====================================================== */ /* @@ -520,23 +559,27 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { */ typedef struct LoadF { - int extraline; - FILE *f; - char buff[LUAL_BUFFERSIZE]; + int n; /* number of pre-read characters */ + FILE *f; /* file being read */ + char buff[LUAL_BUFFERSIZE]; /* area for reading file */ } 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"; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ } - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); - return (*size > 0) ? lf->buff : NULL; + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; } @@ -549,12 +592,44 @@ static int errfile (lua_State *L, const char *what, int fnameindex) { } -LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { +static int skipBOM (LoadF *lf) { + const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */ + int c; + lf->n = 0; + do { + c = getc(lf->f); + if (c == EOF || c != *(unsigned char *)p++) return c; + lf->buff[lf->n++] = c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ +} + + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int skipcomment (LoadF *lf, int *cp) { + int c = *cp = skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + while ((c = getc(lf->f)) != EOF && c != '\n') ; /* skip first line */ + *cp = getc(lf->f); /* skip end-of-line */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ +} + + +LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, + const char *mode) { 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; @@ -564,21 +639,16 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *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 (skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ 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; + skipcomment(&lf, &c); /* re-read initial portion */ } - ungetc(c, lf.f); - status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + if (c != EOF) + lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); readstatus = ferror(lf.f); if (filename) fclose(lf.f); /* close file (even in case of errors) */ if (readstatus) { @@ -598,7 +668,7 @@ typedef struct LoadS { static const char *getS (lua_State *L, void *ud, size_t *size) { LoadS *ls = (LoadS *)ud; - (void)L; + (void)L; /* not used */ if (ls->size == 0) return NULL; *size = ls->size; ls->size = 0; @@ -606,27 +676,246 @@ static const char *getS (lua_State *L, void *ud, size_t *size) { } -LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, - const char *name) { +LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, + const char *name, const char *mode) { LoadS ls; ls.s = buff; ls.size = size; - return lua_load(L, getS, &ls, name); + return lua_load(L, getS, &ls, name, mode); } -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { +LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { return luaL_loadbuffer(L, s, strlen(s), s); } +/* }====================================================== */ + + + +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 = lua_absindex(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 int luaL_len (lua_State *L, int idx) { + int l; + int isnum; + lua_len(L, idx); + l = (int)lua_tointegerx(L, -1, &isnum); + if (!isnum) + luaL_error(L, "object length is not a number"); + lua_pop(L, 1); /* remove object */ + return l; +} + + +LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { + if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ + switch (lua_type(L, idx)) { + case LUA_TNUMBER: + case LUA_TSTRING: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), + lua_topointer(L, idx)); + break; + } + } + return lua_tolstring(L, -1, len); +} + + +/* +** {====================================================== +** Compatibility with 5.1 module functions +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +static const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + if (idx) 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; +} + + +/* +** Count number of elements in a luaL_Reg list. +*/ +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l && l->name; l++) size++; + return size; +} + + +/* +** Find or create a module table with a given name. The function +** first looks at the _LOADED table and, if that fails, try a +** global variable with that name. In any case, leaves on the stack +** the module table. +*/ +LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, + int sizehint) { + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */ + lua_getfield(L, -1, 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) */ + lua_pushglobaltable(L); + if (luaL_findtable(L, 0, modname, sizehint) != NULL) + luaL_error(L, "name conflict for module " LUA_QS, modname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */ + } + lua_remove(L, -2); /* remove _LOADED table */ +} + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + luaL_checkversion(L); + if (libname) { + luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ + lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ + } + if (l) + luaL_setfuncs(L, l, nup); + else + lua_pop(L, nup); /* remove upvalues */ +} +#endif /* }====================================================== */ +/* +** set functions from list 'l' into table at top - 'nup'; each +** function gets the 'nup' elements at the top as upvalues. +** Returns with only the table at the stack. +*/ +LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + +/* +** ensure that stack[idx][fname] has a table and push that table +** into the stack +*/ +LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { + lua_getfield(L, idx, fname); + if (lua_istable(L, -1)) return 1; /* table already there */ + else { + idx = lua_absindex(L, idx); + lua_pop(L, 1); /* remove previous result */ + lua_newtable(L); + lua_pushvalue(L, -1); /* copy to be left at top */ + lua_setfield(L, idx, fname); /* assign new table to field */ + return 0; /* false, because did not find table there */ + } +} + + +/* +** stripped-down 'require'. Calls 'openf' to open a module, +** registers the result in 'package.loaded' table and, if 'glb' +** is true, also registers the result in the global table. +** Leaves resulting module on the top. +*/ +LUALIB_API void luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb) { + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* open module */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_pushvalue(L, -2); /* make copy of module (call result) */ + lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ + lua_pop(L, 1); /* remove _LOADED table */ + if (glb) { + lua_pushglobaltable(L); + lua_pushvalue(L, -2); /* copy of 'mod' */ + lua_setfield(L, -2, modname); /* _G[modname] = module */ + lua_pop(L, 1); /* remove _G table */ + } +} + + +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); +} + static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; - (void)osize; + (void)ud; (void)osize; /* not used */ if (nsize == 0) { free(ptr); return NULL; @@ -637,10 +926,9 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { static int panic (lua_State *L) { - (void)L; /* to avoid warnings */ - fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1)); - return 0; + return 0; /* return to Lua to abort */ } @@ -650,3 +938,20 @@ LUALIB_API lua_State *luaL_newstate (void) { return L; } + +LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) { + const lua_Number *v = lua_version(L); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + ver, *v); + /* check conversions number -> integer types */ + lua_pushnumber(L, -(lua_Number)0x1234); + if (lua_tointeger(L, -1) != -0x1234 || + lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) + luaL_error(L, "bad conversion number->int;" + " must recompile Lua with proper settings"); + lua_pop(L, 1); +} + diff --git a/liblua/lauxlib.h b/liblua/lauxlib.h index 34258235db..ac4d15fbb9 100644 --- a/liblua/lauxlib.h +++ b/liblua/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lauxlib.h,v 1.120 2011/11/29 15:55:08 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -15,18 +15,6 @@ #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) @@ -38,14 +26,12 @@ typedef struct luaL_Reg { } luaL_Reg; +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); +#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) -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 const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); 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); @@ -57,12 +43,17 @@ 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 lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); +LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, + lua_Unsigned 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_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, 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); @@ -71,25 +62,41 @@ 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_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + 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_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); LUALIB_API lua_State *(luaL_newstate) (void); +LUALIB_API int (luaL_len) (lua_State *L, int idx); 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); +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); /* ** =============================================================== @@ -97,6 +104,12 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, ** =============================================================== */ + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + #define luaL_argcheck(L, cond,numarg,extramsg) \ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) @@ -118,56 +131,81 @@ LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + /* ** {====================================================== ** Generic Buffer manipulation ** ======================================================= */ - - typedef struct luaL_Buffer { - char *p; /* current position in buffer */ - int lvl; /* number of strings in the stack (level) */ + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ lua_State *L; - char buffer[LUAL_BUFFERSIZE]; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ } 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_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) -#define luaL_addsize(B,n) ((B)->p += (n)) +#define luaL_addsize(B,s) ((B)->n += (s)) LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); 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); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) /* }====================================================== */ -/* compatibility with ref system */ -/* pre-defined references */ -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + -#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)) +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) -#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif -#define luaL_reg luaL_Reg #endif diff --git a/liblua/lbaselib.c b/liblua/lbaselib.c index 4a97d277d3..1dfae30146 100644 --- a/liblua/lbaselib.c +++ b/liblua/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.191.1.4 2008/01/20 13:53:22 roberto Exp $ +** $Id: lbaselib.c,v 1.273 2011/11/30 13:03:24 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ @@ -20,60 +20,68 @@ #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; + size_t l; 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 */ + s = lua_tolstring(L, -1, &l); /* 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); + return luaL_error(L, + LUA_QL("tostring") " must return a string to " LUA_QL("print")); + if (i>1) luai_writestring("\t", 1); + luai_writestring(s, l); lua_pop(L, 1); /* pop result */ } - fputs("\n", stdout); + luai_writeline(); return 0; } +#define SPACECHARS " \f\n\r\t\v" + 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)); + if (lua_isnoneornil(L, 2)) { /* standard conversion */ + int isnum; + lua_Number n = lua_tonumberx(L, 1, &isnum); + if (isnum) { + lua_pushnumber(L, n); return 1; - } + } /* else not a number; must be something */ + luaL_checkany(L, 1); } else { - const char *s1 = luaL_checkstring(L, 1); - char *s2; - unsigned long n; + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *e = s + l; /* end point for 's' */ + int base = luaL_checkint(L, 2); + int neg = 0; 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); + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') { s++; neg = 1; } /* handle signal */ + else if (*s == '+') s++; + if (isalnum((unsigned char)*s)) { + lua_Number n = 0; + do { + int digit = (isdigit((unsigned char)*s)) ? *s - '0' + : toupper((unsigned char)*s) - 'A' + 10; + if (digit >= base) break; /* invalid numeral; force a fail */ + n = n * (lua_Number)base + (lua_Number)digit; + s++; + } while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + if (s == e) { /* no invalid trailing characters? */ + lua_pushnumber(L, (neg) ? -n : n); return 1; - } - } + } /* else not a number */ + } /* else not a number */ } - lua_pushnil(L); /* else not a number */ + lua_pushnil(L); /* not a number */ return 1; } @@ -107,57 +115,13 @@ static int luaB_setmetatable (lua_State *L) { 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"); + return 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); @@ -166,6 +130,15 @@ static int luaB_rawequal (lua_State *L) { } +static int luaB_rawlen (lua_State *L) { + int t = lua_type(L, 1); + luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, + "table or string expected"); + lua_pushinteger(L, lua_rawlen(L, 1)); + return 1; +} + + static int luaB_rawget (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); luaL_checkany(L, 2); @@ -184,32 +157,29 @@ static int luaB_rawset (lua_State *L) { } -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}; + "count", "step", "setpause", "setstepmul", + "setmajorinc", "isrunning", "generational", "incremental", 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); + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, + LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; + int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; int ex = luaL_optint(L, 2, 0); - int res = lua_gc(L, optsnum[o], ex); - switch (optsnum[o]) { + int res = lua_gc(L, o, ex); + switch (o) { case LUA_GCCOUNT: { int b = lua_gc(L, LUA_GCCOUNTB, 0); lua_pushnumber(L, res + ((lua_Number)b/1024)); - return 1; + lua_pushinteger(L, b); + return 2; } - case LUA_GCSTEP: { + case LUA_GCSTEP: case LUA_GCISRUNNING: { lua_pushboolean(L, res); return 1; } default: { - lua_pushnumber(L, res); + lua_pushinteger(L, res); return 1; } } @@ -223,6 +193,23 @@ static int luaB_type (lua_State *L) { } +static int pairsmeta (lua_State *L, const char *method, int iszero, + lua_CFunction iter) { + if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */ + luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */ + lua_pushcfunction(L, iter); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + if (iszero) lua_pushinteger(L, 0); /* and initial value */ + else lua_pushnil(L); + } + else { + lua_pushvalue(L, 1); /* argument 'self' to metamethod */ + lua_call(L, 1, 3); /* get 3 values from metamethod */ + } + return 3; +} + + 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 */ @@ -236,11 +223,7 @@ static int luaB_next (lua_State *L) { 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; + return pairsmeta(L, "__pairs", 0, luaB_next); } @@ -250,21 +233,17 @@ static int ipairsaux (lua_State *L) { i++; /* next value */ lua_pushinteger(L, i); lua_rawgeti(L, 1, i); - return (lua_isnil(L, -1)) ? 0 : 2; + return (lua_isnil(L, -1)) ? 1 : 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; + return pairsmeta(L, "__ipairs", 1, ipairsaux); } static int load_aux (lua_State *L, int status) { - if (status == 0) /* OK? */ + if (status == LUA_OK) return 1; else { lua_pushnil(L); @@ -274,20 +253,34 @@ static int load_aux (lua_State *L, int status) { } -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)); + const char *mode = luaL_optstring(L, 2, NULL); + int env = !lua_isnone(L, 3); /* 'env' parameter? */ + int status = luaL_loadfilex(L, fname, mode); + if (status == LUA_OK && env) { /* 'env' parameter? */ + lua_pushvalue(L, 3); + lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */ + } + return load_aux(L, status); } +/* +** {====================================================== +** Generic Read function +** ======================================================= +*/ + + +/* +** reserved slot, above all arguments, to hold a copy of the returned +** string to avoid it being collected while parsed. 'load' has four +** optional arguments (chunk, source name, mode, and environment). +*/ +#define RESERVEDSLOT 5 + + /* ** Reader for generic `load' function: `lua_load' uses the ** stack for internal stuff, so the reader cannot change the @@ -295,7 +288,7 @@ static int luaB_loadfile (lua_State *L) { ** reserved slot inside the stack. */ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - (void)ud; /* to avoid warnings */ + (void)(ud); /* not used */ luaL_checkstack(L, 2, "too many nested functions"); lua_pushvalue(L, 1); /* get function */ lua_call(L, 0, 1); /* call it */ @@ -303,58 +296,60 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { *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 */ + else if (!lua_isstring(L, -1)) + luaL_error(L, "reader function must return a string"); + lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ + return lua_tolstring(L, RESERVEDSLOT, size); } 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); + size_t l; + int top = lua_gettop(L); + const char *s = lua_tolstring(L, 1, &l); + const char *mode = luaL_optstring(L, 3, "bt"); + if (s != NULL) { /* loading a string? */ + const char *chunkname = luaL_optstring(L, 2, s); + status = luaL_loadbufferx(L, s, l, chunkname, mode); + } + else { /* loading from a reader function */ + const char *chunkname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, RESERVEDSLOT); /* create reserved slot */ + status = lua_load(L, generic_reader, NULL, chunkname, mode); + } + if (status == LUA_OK && top >= 4) { /* is there an 'env' argument */ + lua_pushvalue(L, 4); /* environment for loaded function */ + lua_setupvalue(L, -2, 1); /* set it as 1st upvalue */ + } return load_aux(L, status); } +/* }====================================================== */ + + +static int dofilecont (lua_State *L) { + return lua_gettop(L) - 1; +} + 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; + lua_settop(L, 1); + if (luaL_loadfile(L, fname) != LUA_OK) lua_error(L); + lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); + return dofilecont(L); } 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); - while (i++ < 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) == '#') { @@ -371,75 +366,50 @@ static int luaB_select (lua_State *L) { } +static int finishpcall (lua_State *L, int status) { + if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */ + lua_settop(L, 0); /* create space for return values */ + lua_pushboolean(L, 0); + lua_pushstring(L, "stack overflow"); + return 2; /* return false, msg */ + } + lua_pushboolean(L, status); /* first result (status) */ + lua_replace(L, 1); /* put first result in first slot */ + return lua_gettop(L); +} + + +static int pcallcont (lua_State *L) { + int status = lua_getctx(L, NULL); + return finishpcall(L, (status == LUA_YIELD)); +} + + 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 */ + lua_pushnil(L); + lua_insert(L, 1); /* create space for status result */ + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); + return finishpcall(L, (status == LUA_OK)); } 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 */ + int n = lua_gettop(L); + luaL_argcheck(L, n >= 2, 2, "value expected"); + lua_pushvalue(L, 1); /* exchange function... */ + lua_copy(L, 2, 1); /* ...and error handler */ + lua_replace(L, 2); + status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); + return finishpcall(L, (status == LUA_OK)); } 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); + luaL_tolstring(L, 1, NULL); return 1; } @@ -449,205 +419,40 @@ static const luaL_Reg base_funcs[] = { {"collectgarbage", luaB_collectgarbage}, {"dofile", luaB_dofile}, {"error", luaB_error}, - {"gcinfo", luaB_gcinfo}, - {"getfenv", luaB_getfenv}, {"getmetatable", luaB_getmetatable}, + {"ipairs", luaB_ipairs}, {"loadfile", luaB_loadfile}, {"load", luaB_load}, - {"loadstring", luaB_loadstring}, +#if defined(LUA_COMPAT_LOADSTRING) + {"loadstring", luaB_load}, +#endif {"next", luaB_next}, + {"pairs", luaB_pairs}, {"pcall", luaB_pcall}, {"print", luaB_print}, {"rawequal", luaB_rawequal}, + {"rawlen", luaB_rawlen}, {"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) { +LUAMOD_API int luaopen_base (lua_State *L) { /* set global _G */ - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setglobal(L, "_G"); + lua_pushglobaltable(L); + lua_pushglobaltable(L); + lua_setfield(L, -2, "_G"); /* open lib into global table */ - luaL_register(L, "_G", base_funcs); + luaL_setfuncs(L, base_funcs, 0); 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; + lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */ + return 1; } diff --git a/liblua/lbitlib.c b/liblua/lbitlib.c new file mode 100644 index 0000000000..7533b85c5a --- /dev/null +++ b/liblua/lbitlib.c @@ -0,0 +1,209 @@ +/* +** $Id: lbitlib.c,v 1.16 2011/06/20 16:35:23 roberto Exp $ +** Standard library for bitwise operations +** See Copyright Notice in lua.h +*/ + +#define lbitlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* number of bits to consider in a number */ +#if !defined(LUA_NBITS) +#define LUA_NBITS 32 +#endif + + +#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) + +/* macro to trim extra bits */ +#define trim(x) ((x) & ALLONES) + + +/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ +#define mask(n) (~((ALLONES << 1) << ((n) - 1))) + + +typedef lua_Unsigned b_uint; + + + +static b_uint andaux (lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = ~(b_uint)0; + for (i = 1; i <= n; i++) + r &= luaL_checkunsigned(L, i); + return trim(r); +} + + +static int b_and (lua_State *L) { + b_uint r = andaux(L); + lua_pushunsigned(L, r); + return 1; +} + + +static int b_test (lua_State *L) { + b_uint r = andaux(L); + lua_pushboolean(L, r != 0); + return 1; +} + + +static int b_or (lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = 0; + for (i = 1; i <= n; i++) + r |= luaL_checkunsigned(L, i); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_xor (lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = 0; + for (i = 1; i <= n; i++) + r ^= luaL_checkunsigned(L, i); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_not (lua_State *L) { + b_uint r = ~luaL_checkunsigned(L, 1); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_shift (lua_State *L, b_uint r, int i) { + if (i < 0) { /* shift right? */ + i = -i; + r = trim(r); + if (i >= LUA_NBITS) r = 0; + else r >>= i; + } + else { /* shift left */ + if (i >= LUA_NBITS) r = 0; + else r <<= i; + r = trim(r); + } + lua_pushunsigned(L, r); + return 1; +} + + +static int b_lshift (lua_State *L) { + return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2)); +} + + +static int b_rshift (lua_State *L) { + return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2)); +} + + +static int b_arshift (lua_State *L) { + b_uint r = luaL_checkunsigned(L, 1); + int i = luaL_checkint(L, 2); + if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1)))) + return b_shift(L, r, -i); + else { /* arithmetic shift for 'negative' number */ + if (i >= LUA_NBITS) r = ALLONES; + else + r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ + lua_pushunsigned(L, r); + return 1; + } +} + + +static int b_rot (lua_State *L, int i) { + b_uint r = luaL_checkunsigned(L, 1); + i &= (LUA_NBITS - 1); /* i = i % NBITS */ + r = trim(r); + r = (r << i) | (r >> (LUA_NBITS - i)); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_lrot (lua_State *L) { + return b_rot(L, luaL_checkint(L, 2)); +} + + +static int b_rrot (lua_State *L) { + return b_rot(L, -luaL_checkint(L, 2)); +} + + +/* +** get field and width arguments for field-manipulation functions, +** checking whether they are valid +*/ +static int fieldargs (lua_State *L, int farg, int *width) { + int f = luaL_checkint(L, farg); + int w = luaL_optint(L, farg + 1, 1); + luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); + luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); + if (f + w > LUA_NBITS) + luaL_error(L, "trying to access non-existent bits"); + *width = w; + return f; +} + + +static int b_extract (lua_State *L) { + int w; + b_uint r = luaL_checkunsigned(L, 1); + int f = fieldargs(L, 2, &w); + r = (r >> f) & mask(w); + lua_pushunsigned(L, r); + return 1; +} + + +static int b_replace (lua_State *L) { + int w; + b_uint r = luaL_checkunsigned(L, 1); + b_uint v = luaL_checkunsigned(L, 2); + int f = fieldargs(L, 3, &w); + int m = mask(w); + v &= m; /* erase bits outside given width */ + r = (r & ~(m << f)) | (v << f); + lua_pushunsigned(L, r); + return 1; +} + + +static const luaL_Reg bitlib[] = { + {"arshift", b_arshift}, + {"band", b_and}, + {"bnot", b_not}, + {"bor", b_or}, + {"bxor", b_xor}, + {"btest", b_test}, + {"extract", b_extract}, + {"lrotate", b_lrot}, + {"lshift", b_lshift}, + {"replace", b_replace}, + {"rrotate", b_rrot}, + {"rshift", b_rshift}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_bit32 (lua_State *L) { + luaL_newlib(L, bitlib); + return 1; +} + diff --git a/liblua/lcode.c b/liblua/lcode.c index cff626b7fa..614e452f9c 100644 --- a/liblua/lcode.c +++ b/liblua/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: lcode.c,v 2.60 2011/08/30 16:26:41 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -21,7 +21,9 @@ #include "lobject.h" #include "lopcodes.h" #include "lparser.h" +#include "lstring.h" #include "ltable.h" +#include "lvm.h" #define hasjumps(e) ((e)->t != (e)->f) @@ -34,25 +36,23 @@ static int isnumeral(expdesc *e) { void luaK_nil (FuncState *fs, int from, int n) { Instruction *previous; + int l = from + n - 1; /* last register to set nil */ 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; - } + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { + int pfrom = GETARG_A(*previous); + int pl = pfrom + GETARG_B(*previous); + if ((pfrom <= from && from <= pl + 1) || + (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ + if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) l = pl; /* l = max(l, pl) */ + SETARG_A(*previous, from); + SETARG_B(*previous, l - from); + return; } - } + } /* else go through */ } - luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ + luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ } @@ -176,6 +176,19 @@ void luaK_patchlist (FuncState *fs, int list, int target) { } +LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) { + level++; /* argument is +1 to reserve 0 as non-op */ + while (list != NO_JUMP) { + int next = getjump(fs, list); + lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && + (GETARG_A(fs->f->code[list]) == 0 || + GETARG_A(fs->f->code[list]) >= level)); + SETARG_A(fs->f->code[list], level); + list = next; + } +} + + void luaK_patchtohere (FuncState *fs, int list) { luaK_getlabel(fs); luaK_concat(fs, &fs->jpc, list); @@ -196,6 +209,55 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { } +static int luaK_code (FuncState *fs, Instruction i) { + Proto *f = fs->f; + dischargejpc(fs); /* `pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "opcodes"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "opcodes"); + f->lineinfo[fs->pc] = fs->ls->lastline; + 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); + lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); + return luaK_code(fs, CREATE_ABC(o, a, b, c)); +} + + +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); + lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, bc)); +} + + +static int codeextraarg (FuncState *fs, int a) { + lua_assert(a <= MAXARG_Ax); + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +} + + +int luaK_codek (FuncState *fs, int reg, int k) { + if (k <= MAXARG_Bx) + return luaK_codeABx(fs, OP_LOADK, reg, k); + else { + int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); + codeextraarg(fs, k); + return p; + } +} + + void luaK_checkstack (FuncState *fs, int n) { int newstack = fs->freereg + n; if (newstack > fs->f->maxstacksize) { @@ -222,42 +284,60 @@ static void freereg (FuncState *fs, int reg) { static void freeexp (FuncState *fs, expdesc *e) { if (e->k == VNONRELOC) - freereg(fs, e->u.s.info); + freereg(fs, e->u.info); } -static int addk (FuncState *fs, TValue *k, TValue *v) { - lua_State *L = fs->L; - TValue *idx = luaH_set(L, fs->h, k); +static int addk (FuncState *fs, TValue *key, TValue *v) { + lua_State *L = fs->ls->L; + TValue *idx = luaH_set(L, fs->h, key); Proto *f = fs->f; - int oldsize = f->sizek; + int k, oldsize; 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++; + lua_Number n = nvalue(idx); + lua_number2int(k, n); + if (luaV_rawequalobj(&f->k[k], v)) + return k; + /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); + go through and create a new entry for this value */ } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setnvalue(idx, cast_num(k)); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); + return k; } int luaK_stringK (FuncState *fs, TString *s) { TValue o; - setsvalue(fs->L, &o, s); + setsvalue(fs->ls->L, &o, s); return addk(fs, &o, &o); } int luaK_numberK (FuncState *fs, lua_Number r) { + int n; + lua_State *L = fs->ls->L; TValue o; setnvalue(&o, r); - return addk(fs, &o, &o); + if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ + /* use raw representation as key to avoid numeric problems */ + setsvalue(L, L->top, luaS_newlstr(L, (char *)&r, sizeof(r))); + incr_top(L); + n = addk(fs, L->top - 1, &o); + L->top--; + } + else + n = addk(fs, &o, &o); /* regular case */ + return n; } @@ -272,7 +352,7 @@ 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); + sethvalue(fs->ls->L, &k, fs->h); return addk(fs, &k, &v); } @@ -292,7 +372,7 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { 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)); + e->u.info = GETARG_A(getcode(fs, e)); } else if (e->k == VVARARG) { SETARG_B(getcode(fs, e), 2); @@ -308,19 +388,18 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { 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->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); 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); + OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ + freereg(fs, e->u.ind.idx); + if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ + freereg(fs, e->u.ind.t); + op = OP_GETTABLE; + } + e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); e->k = VRELOCABLE; break; } @@ -352,11 +431,11 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { break; } case VK: { - luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); + luaK_codek(fs, reg, e->u.info); break; } case VKNUM: { - luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); + luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); break; } case VRELOCABLE: { @@ -365,8 +444,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { break; } case VNONRELOC: { - if (reg != e->u.s.info) - luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); + if (reg != e->u.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); break; } default: { @@ -374,7 +453,7 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { return; /* nothing to do... */ } } - e->u.s.info = reg; + e->u.info = reg; e->k = VNONRELOC; } @@ -390,7 +469,7 @@ static void discharge2anyreg (FuncState *fs, expdesc *e) { 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 */ + luaK_concat(fs, &e->t, e->u.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 */ @@ -406,7 +485,7 @@ static void exp2reg (FuncState *fs, expdesc *e, int reg) { patchlistaux(fs, e->t, final, reg, p_t); } e->f = e->t = NO_JUMP; - e->u.s.info = reg; + e->u.info = reg; e->k = VNONRELOC; } @@ -422,14 +501,20 @@ void luaK_exp2nextreg (FuncState *fs, expdesc *e) { 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; + if (!hasjumps(e)) return e->u.info; /* exp is already in a register */ + if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.info); /* put value on it */ + return e->u.info; } } luaK_exp2nextreg(fs, e); /* default */ - return e->u.s.info; + return e->u.info; +} + + +void luaK_exp2anyregup (FuncState *fs, expdesc *e) { + if (e->k != VUPVAL || hasjumps(e)) + luaK_exp2anyreg(fs, e); } @@ -444,22 +529,24 @@ void luaK_exp2val (FuncState *fs, expdesc *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)); + if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */ + e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); e->k = VK; - return RKASK(e->u.s.info); + return RKASK(e->u.info); } else break; } + case VKNUM: { + e->u.info = luaK_numberK(fs, e->u.nval); + e->k = VK; + /* go through */ + } case VK: { - if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ - return RKASK(e->u.s.info); + if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ + return RKASK(e->u.info); else break; } default: break; @@ -473,22 +560,18 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { switch (var->k) { case VLOCAL: { freeexp(fs, ex); - exp2reg(fs, ex, var->u.s.info); + exp2reg(fs, ex, var->u.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); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); break; } case VINDEXED: { + OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); + luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); break; } default: { @@ -501,20 +584,20 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int func; + int ereg; luaK_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' was placed */ 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->u.info = fs->freereg; /* base register for op_self */ e->k = VNONRELOC; + luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ + luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); + freeexp(fs, key); } static void invertjump (FuncState *fs, expdesc *e) { - Instruction *pc = getjumpcontrol(fs, e->u.s.info); + Instruction *pc = getjumpcontrol(fs, e->u.info); lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && GET_OPCODE(*pc) != OP_TEST); SETARG_A(*pc, !(GETARG_A(*pc))); @@ -532,7 +615,7 @@ static int jumponcond (FuncState *fs, expdesc *e, int cond) { } discharge2anyreg(fs, e); freeexp(fs, e); - return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); + return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); } @@ -540,17 +623,13 @@ 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; + pc = e->u.info; + break; + } + case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ break; } default: { @@ -564,20 +643,16 @@ void luaK_goiftrue (FuncState *fs, expdesc *e) { } -static void luaK_goiffalse (FuncState *fs, expdesc *e) { +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 */ + case VJMP: { + pc = e->u.info; break; } - case VJMP: { - pc = e->u.s.info; + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ break; } default: { @@ -610,7 +685,7 @@ static void codenot (FuncState *fs, expdesc *e) { case VNONRELOC: { discharge2anyreg(fs, e); freeexp(fs, e); - e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); + e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); e->k = VRELOCABLE; break; } @@ -627,38 +702,28 @@ static void codenot (FuncState *fs, expdesc *e) { void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { - t->u.s.aux = luaK_exp2RK(fs, k); + lua_assert(!hasjumps(t)); + t->u.ind.t = t->u.info; + t->u.ind.idx = luaK_exp2RK(fs, k); + t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL + : check_exp(vkisinreg(t->k), VLOCAL); t->k = VINDEXED; } static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { - lua_Number v1, v2, r; + lua_Number 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 */ + if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) + return 0; /* do not attempt to divide by 0 */ + r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); e1->u.nval = r; return 1; } -static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { +static void codearith (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { if (constfolding(op, e1, e2)) return; else { @@ -672,8 +737,9 @@ static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { freeexp(fs, e2); freeexp(fs, e1); } - e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); + e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); e1->k = VRELOCABLE; + luaK_fixline(fs, line); } } @@ -689,25 +755,28 @@ static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ cond = 1; } - e1->u.s.info = condjump(fs, op, cond, o1, o2); + e1->u.info = condjump(fs, op, cond, o1, o2); e1->k = VJMP; } -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { 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); + if (isnumeral(e)) /* minus constant? */ + e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ + else { + luaK_exp2anyreg(fs, e); + codearith(fs, OP_UNM, e, &e2, line); + } 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); + codearith(fs, OP_LEN, e, &e2, line); break; } default: lua_assert(0); @@ -742,7 +811,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { } -void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { +void luaK_posfix (FuncState *fs, BinOpr op, + expdesc *e1, expdesc *e2, int line) { switch (op) { case OPR_AND: { lua_assert(e1->t == NO_JUMP); /* list must be closed */ @@ -761,29 +831,30 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { 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); + lua_assert(e1->u.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; + SETARG_B(getcode(fs, e2), e1->u.info); + e1->k = VRELOCABLE; e1->u.info = e2->u.info; } else { luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ - codearith(fs, OP_CONCAT, e1, e2); + codearith(fs, OP_CONCAT, e1, e2, line); } 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; + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); + break; + } + case OPR_EQ: case OPR_LT: case OPR_LE: { + codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2); + break; + } + case OPR_NE: case OPR_GT: case OPR_GE: { + codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2); + break; + } default: lua_assert(0); } } @@ -794,46 +865,18 @@ void luaK_fixline (FuncState *fs, int 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 { + else if (c <= MAXARG_Ax) { luaK_codeABC(fs, OP_SETLIST, base, b, 0); - luaK_code(fs, cast(Instruction, c), fs->ls->lastline); + codeextraarg(fs, c); } + else + luaX_syntaxerror(fs->ls, "constructor too long"); fs->freereg = base + 1; /* free registers with list values */ } diff --git a/liblua/lcode.h b/liblua/lcode.h index b941c60721..5a1fa9feac 100644 --- a/liblua/lcode.h +++ b/liblua/lcode.h @@ -1,5 +1,5 @@ /* -** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lcode.h,v 1.58 2011/08/30 16:26:41 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -21,13 +21,13 @@ /* -** grep "ORDER OPR" if you change these enums +** grep "ORDER OPR" if you change these enums (ORDER OP) */ 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_EQ, OPR_LT, OPR_LE, + OPR_NE, OPR_GT, OPR_GE, OPR_AND, OPR_OR, OPR_NOBINOPR } BinOpr; @@ -36,14 +36,17 @@ typedef enum 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 getcode(fs,e) ((fs)->f->code[(e)->u.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) +#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) + 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 int luaK_codek (FuncState *fs, int reg, int k); 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); @@ -52,12 +55,14 @@ 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_exp2anyregup (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_goiffalse (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); @@ -65,11 +70,13 @@ 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_patchclose (FuncState *fs, int list, int level); 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_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); 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_posfix (FuncState *fs, BinOpr op, expdesc *v1, + expdesc *v2, int line); LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); diff --git a/liblua/lcorolib.c b/liblua/lcorolib.c new file mode 100644 index 0000000000..0edde26daf --- /dev/null +++ b/liblua/lcorolib.c @@ -0,0 +1,154 @@ +/* +** $Id: lcorolib.c,v 1.3 2011/08/23 17:24:34 roberto Exp $ +** Coroutine Library +** See Copyright Notice in lua.h +*/ + + +#include + + +#define lcorolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status; + if (!lua_checkstack(co, narg)) { + lua_pushliteral(L, "too many arguments to resume"); + return -1; /* error flag */ + } + if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { + lua_pushliteral(L, "cannot resume dead coroutine"); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + status = lua_resume(co, L, narg); + if (status == LUA_OK || status == LUA_YIELD) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres + 1)) { + lua_pop(co, nres); /* remove results anyway */ + lua_pushliteral(L, "too many results to resume"); + return -1; /* error flag */ + } + 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_checktype(L, 1, LUA_TFUNCTION); + 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_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + if (L == co) lua_pushliteral(L, "running"); + else { + switch (lua_status(co)) { + case LUA_YIELD: + lua_pushliteral(L, "suspended"); + break; + case LUA_OK: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + lua_pushliteral(L, "normal"); /* it is running */ + else if (lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); /* initial state */ + break; + } + default: /* some error occurred */ + lua_pushliteral(L, "dead"); + break; + } + } + return 1; +} + + +static int luaB_corunning (lua_State *L) { + int ismain = lua_pushthread(L); + lua_pushboolean(L, ismain); + return 2; +} + + +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} +}; + + + +LUAMOD_API int luaopen_coroutine (lua_State *L) { + luaL_newlib(L, co_funcs); + return 1; +} + diff --git a/liblua/lctype.c b/liblua/lctype.c new file mode 100644 index 0000000000..55e433a5dd --- /dev/null +++ b/liblua/lctype.c @@ -0,0 +1,52 @@ +/* +** $Id: lctype.c,v 1.11 2011/10/03 16:19:23 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#define lctype_c +#define LUA_CORE + +#include "lctype.h" + +#if !LUA_USE_CTYPE /* { */ + +#include + +LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { + 0x00, /* EOZ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ + 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +#endif /* } */ diff --git a/liblua/lctype.h b/liblua/lctype.h new file mode 100644 index 0000000000..99c7d12237 --- /dev/null +++ b/liblua/lctype.h @@ -0,0 +1,95 @@ +/* +** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lctype_h +#define lctype_h + +#include "lua.h" + + +/* +** WARNING: the functions defined here do not necessarily correspond +** to the similar functions in the standard C ctype.h. They are +** optimized for the specific needs of Lua +*/ + +#if !defined(LUA_USE_CTYPE) + +#if 'A' == 65 && '0' == 48 +/* ASCII case: can use its own tables; faster and fixed */ +#define LUA_USE_CTYPE 0 +#else +/* must use standard C ctype */ +#define LUA_USE_CTYPE 1 +#endif + +#endif + + +#if !LUA_USE_CTYPE /* { */ + +#include + +#include "llimits.h" + + +#define ALPHABIT 0 +#define DIGITBIT 1 +#define PRINTBIT 2 +#define SPACEBIT 3 +#define XDIGITBIT 4 + + +#define MASK(B) (1 << (B)) + + +/* +** add 1 to char to allow index -1 (EOZ) +*/ +#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) + +/* +** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' +*/ +#define lislalpha(c) testprop(c, MASK(ALPHABIT)) +#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) +#define lisdigit(c) testprop(c, MASK(DIGITBIT)) +#define lisspace(c) testprop(c, MASK(SPACEBIT)) +#define lisprint(c) testprop(c, MASK(PRINTBIT)) +#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) + +/* +** this 'ltolower' only works for alphabetic characters +*/ +#define ltolower(c) ((c) | ('A' ^ 'a')) + + +/* two more entries for 0 and -1 (EOZ) */ +LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; + + +#else /* }{ */ + +/* +** use standard C ctypes +*/ + +#include + + +#define lislalpha(c) (isalpha(c) || (c) == '_') +#define lislalnum(c) (isalnum(c) || (c) == '_') +#define lisdigit(c) (isdigit(c)) +#define lisspace(c) (isspace(c)) +#define lisprint(c) (isprint(c)) +#define lisxdigit(c) (isxdigit(c)) + +#define ltolower(c) (tolower(c)) + +#endif /* } */ + +#endif + diff --git a/liblua/ldblib.c b/liblua/ldblib.c index 67de1222a9..3c2f159572 100644 --- a/liblua/ldblib.c +++ b/liblua/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $ +** $Id: ldblib.c,v 1.131 2011/10/24 14:54:05 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -18,6 +18,9 @@ #include "lualib.h" +#define HOOKKEY "_HKEY" + + static int db_getregistry (lua_State *L) { lua_pushvalue(L, LUA_REGISTRYINDEX); @@ -39,23 +42,28 @@ static int db_setmetatable (lua_State *L) { 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; + lua_setmetatable(L, 1); + return 1; /* return 1st argument */ } -static int db_getfenv (lua_State *L) { - lua_getfenv(L, 1); +static int db_getuservalue (lua_State *L) { + if (lua_type(L, 1) != LUA_TUSERDATA) + lua_pushnil(L); + else + lua_getuservalue(L, 1); return 1; } -static int db_setfenv (lua_State *L) { - luaL_checktype(L, 2, LUA_TTABLE); +static int db_setuservalue (lua_State *L) { + if (lua_type(L, 1) == LUA_TLIGHTUSERDATA) + luaL_argerror(L, 1, "full userdata expected, got light userdata"); + luaL_checktype(L, 1, LUA_TUSERDATA); + if (!lua_isnoneornil(L, 2)) + 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"); + lua_setuservalue(L, 1); return 1; } @@ -72,6 +80,12 @@ static void settabsi (lua_State *L, const char *i, int v) { } +static void settabsb (lua_State *L, const char *i, int v) { + lua_pushboolean(L, v); + lua_setfield(L, -2, i); +} + + static lua_State *getthread (lua_State *L, int *arg) { if (lua_isthread(L, 1)) { *arg = 1; @@ -99,7 +113,7 @@ 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"); + const char *options = luaL_optstring(L, arg+2, "flnStu"); if (lua_isnumber(L, arg+1)) { if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { lua_pushnil(L); /* level out of range */ @@ -126,38 +140,51 @@ static int db_getinfo (lua_State *L) { } if (strchr(options, 'l')) settabsi(L, "currentline", ar.currentline); - if (strchr(options, 'u')) + if (strchr(options, 'u')) { settabsi(L, "nups", ar.nups); + settabsi(L, "nparams", ar.nparams); + settabsb(L, "isvararg", ar.isvararg); + } if (strchr(options, 'n')) { settabss(L, "name", ar.name); settabss(L, "namewhat", ar.namewhat); } + if (strchr(options, 't')) + settabsb(L, "istailcall", ar.istailcall); 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); + int nvar = luaL_checkint(L, arg+2); /* local-variable index */ + if (lua_isfunction(L, arg + 1)) { /* function argument? */ + lua_pushvalue(L, arg + 1); /* push function */ + lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ return 1; } + else { /* stack-level argument */ + 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, nvar); + if (name) { + lua_xmove(L1, L, 1); /* push local value */ + lua_pushstring(L, name); /* push name */ + lua_pushvalue(L, -2); /* re-order */ + return 2; + } + else { + lua_pushnil(L); /* no name (nor value) */ + return 1; + } + } } @@ -179,7 +206,6 @@ 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); @@ -199,17 +225,42 @@ static int db_setupvalue (lua_State *L) { } +static int checkupval (lua_State *L, int argf, int argnup) { + lua_Debug ar; + int nup = luaL_checkint(L, argnup); + luaL_checktype(L, argf, LUA_TFUNCTION); + lua_pushvalue(L, argf); + lua_getinfo(L, ">u", &ar); + luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index"); + return nup; +} -static const char KEY_HOOK = 'h'; + +static int db_upvalueid (lua_State *L) { + int n = checkupval(L, 1, 2); + lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); + return 1; +} + + +static int db_upvaluejoin (lua_State *L) { + int n1 = checkupval(L, 1, 2); + int n2 = checkupval(L, 3, 4); + luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); + luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); + lua_upvaluejoin(L, 1, n1, 3, n2); + return 0; +} + + +#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY); 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); + {"call", "return", "line", "count", "tail call"}; + gethooktable(L); + lua_rawgetp(L, -1, L); if (lua_isfunction(L, -1)) { lua_pushstring(L, hooknames[(int)ar->event]); if (ar->currentline >= 0) @@ -241,19 +292,6 @@ static char *unmakemask (int mask, char *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; @@ -269,9 +307,8 @@ static int db_sethook (lua_State *L) { 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_rawsetp(L, -2, L1); /* set new hook */ lua_pop(L, 1); /* remove hook table */ lua_sethook(L1, func, mask, count); /* set hooks */ return 0; @@ -288,8 +325,7 @@ static int db_gethook (lua_State *L) { lua_pushliteral(L, "external hook"); else { gethooktable(L); - lua_pushlightuserdata(L, L1); - lua_rawget(L, -2); /* get hook */ + lua_rawgetp(L, -1, L1); /* get hook */ lua_remove(L, -2); /* remove hook table */ } lua_pushstring(L, unmakemask(mask, buff)); @@ -301,97 +337,55 @@ static int db_gethook (lua_State *L) { static int db_debug (lua_State *L) { for (;;) { char buffer[250]; - fputs("lua_debug> ", stderr); + luai_writestringerror("%s", "lua_debug> "); 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_pcall(L, 0, 0, 0)) + luai_writestringerror("%s\n", lua_tostring(L, -1)); 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 `...' */ +static int db_traceback (lua_State *L) { 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); + const char *msg = lua_tostring(L, arg + 1); + if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ + lua_pushvalue(L, arg + 1); /* return it untouched */ + else { + int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0); + luaL_traceback(L, L1, msg, level); } - lua_concat(L, lua_gettop(L) - arg); return 1; } static const luaL_Reg dblib[] = { {"debug", db_debug}, - {"getfenv", db_getfenv}, + {"getuservalue", db_getuservalue}, {"gethook", db_gethook}, {"getinfo", db_getinfo}, {"getlocal", db_getlocal}, {"getregistry", db_getregistry}, {"getmetatable", db_getmetatable}, {"getupvalue", db_getupvalue}, - {"setfenv", db_setfenv}, + {"upvaluejoin", db_upvaluejoin}, + {"upvalueid", db_upvalueid}, + {"setuservalue", db_setuservalue}, {"sethook", db_sethook}, {"setlocal", db_setlocal}, {"setmetatable", db_setmetatable}, {"setupvalue", db_setupvalue}, - {"traceback", db_errorfb}, + {"traceback", db_traceback}, {NULL, NULL} }; -LUALIB_API int luaopen_debug (lua_State *L) { - luaL_register(L, LUA_DBLIBNAME, dblib); +LUAMOD_API int luaopen_debug (lua_State *L) { + luaL_newlib(L, dblib); return 1; } diff --git a/liblua/ldebug.c b/liblua/ldebug.c index 9eac4a9b41..31b7ae4013 100644 --- a/liblua/ldebug.c +++ b/liblua/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.29.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: ldebug.c,v 2.88 2011/11/30 12:43:51 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -33,20 +33,14 @@ 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 currentpc (CallInfo *ci) { + lua_assert(isLua(ci)); + return pcRel(ci->u.l.savedpc, ci_func(ci)->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); +static int currentline (CallInfo *ci) { + return getfuncline(ci_func(ci)->p, currentpc(ci)); } @@ -58,6 +52,8 @@ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { mask = 0; func = NULL; } + if (isLua(L->ci)) + L->oldpc = L->ci->u.l.savedpc; L->hook = func; L->basehookcount = count; resethookcount(L); @@ -84,19 +80,13 @@ LUA_API int lua_gethookcount (lua_State *L) { LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { int status; CallInfo *ci; + if (level < 0) return 0; /* invalid (negative) level */ lua_lock(L); - for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { + for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) 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? */ + if (level == 0 && ci != &L->base_ci) { /* level found? */ status = 1; - ar->i_ci = 0; + ar->i_ci = ci; } else status = 0; /* no such level */ lua_unlock(L); @@ -104,43 +94,78 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { } -static Proto *getluaproto (CallInfo *ci) { - return (isLua(ci) ? ci_func(ci)->l.p : NULL); +static const char *upvalname (Proto *p, int uv) { + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); } -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 */ +static const char *findvararg (CallInfo *ci, int n, StkId *pos) { + int nparams = clLvalue(ci->func)->p->numparams; + if (n >= ci->u.l.base - ci->func - nparams) + return NULL; /* no such vararg */ 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)"; + *pos = ci->func + nparams + n; + return "(*vararg)"; /* generic name for any vararg */ + } +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n, + StkId *pos) { + const char *name = NULL; + StkId base; + if (isLua(ci)) { + if (n < 0) /* access to vararg values? */ + return findvararg(ci, -n, pos); + else { + base = ci->u.l.base; + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); + } + } + else + base = ci->func + 1; + if (name == NULL) { /* no 'standard' name? */ + StkId limit = (ci == L->ci) ? L->top : ci->next->func; + if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + name = "(*temporary)"; /* generic name for any valid slot */ else - return NULL; + return NULL; /* no name */ } + *pos = base + (n - 1); + return name; } 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); + const char *name; lua_lock(L); - if (name) - luaA_pushobject(L, ci->base + (n - 1)); + if (ar == NULL) { /* information about non-active function? */ + if (!isLfunction(L->top - 1)) /* not a Lua function? */ + name = NULL; + else /* consider live variables at function start (parameters) */ + name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); + } + else { /* active function; get information through 'ar' */ + StkId pos = 0; /* to avoid warnings */ + name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobj2s(L, L->top, pos); + api_incr_top(L); + } + } 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); + StkId pos = 0; /* to avoid warnings */ + const char *name = findlocal(L, ar->i_ci, n, &pos); lua_lock(L); if (name) - setobjs2s(L, ci->base + (n - 1), L->top - 1); + setobjs2s(L, pos, L->top - 1); L->top--; /* pop value */ lua_unlock(L); return name; @@ -148,55 +173,45 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { static void funcinfo (lua_Debug *ar, Closure *cl) { - if (cl->c.isC) { + if (cl == NULL || 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; + Proto *p = cl->l.p; + ar->source = p->source ? getstr(p->source) : "=?"; + ar->linedefined = p->linedefined; + ar->lastlinedefined = 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); + incr_top(L); } 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); + TValue v; + int *lineinfo = f->l.p->lineinfo; + Table *t = luaH_new(L); /* new table to store active lines */ + sethvalue(L, L->top, t); /* push it on stack */ + incr_top(L); + setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ + luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ } - 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': { @@ -204,15 +219,31 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, break; } case 'l': { - ar->currentline = (ci) ? currentline(L, ci) : -1; + ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; break; } case 'u': { - ar->nups = f->c.nupvalues; + ar->nups = (f == NULL) ? 0 : f->c.nupvalues; + if (f == NULL || f->c.isC) { + ar->isvararg = 1; + ar->nparams = 0; + } + else { + ar->isvararg = f->l.p->is_vararg; + ar->nparams = f->l.p->numparams; + } + break; + } + case 't': { + ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; break; } case 'n': { - ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; + /* calling function is a known Lua function? */ + if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + ar->namewhat = getfuncname(L, ci->previous, &ar->name); + else + ar->namewhat = NULL; if (ar->namewhat == NULL) { ar->namewhat = ""; /* not found */ ar->name = NULL; @@ -231,29 +262,30 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { int status; - Closure *f = NULL; - CallInfo *ci = NULL; + Closure *cl; + CallInfo *ci; + StkId func; lua_lock(L); if (*what == '>') { - StkId func = L->top - 1; - luai_apicheck(L, ttisfunction(func)); + ci = NULL; + func = L->top - 1; + api_check(L, ttisfunction(func), "function expected"); 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; + else { + ci = ar->i_ci; + func = ci->func; lua_assert(ttisfunction(ci->func)); - f = clvalue(ci->func); } - status = auxgetinfo(L, what, ar, f, ci); + cl = ttisclosure(func) ? clvalue(func) : NULL; + status = auxgetinfo(L, what, ar, cl, ci); if (strchr(what, 'f')) { - if (f == NULL) setnilvalue(L->top); - else setclvalue(L, L->top, f); + setobjs2s(L, L->top, func); incr_top(L); } if (strchr(what, 'L')) - collectvalidlines(L, f); + collectvalidlines(L, cl); lua_unlock(L); return status; } @@ -261,299 +293,218 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { /* ** {====================================================== -** Symbolic Execution and code checker +** Symbolic Execution ** ======================================================= */ -#define check(x) if (!(x)) return 0; - -#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name); -#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) - - -static int precheck (const Proto *pt) { - check(pt->maxstacksize <= MAXSTACK); - lua_assert(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); - lua_assert(!(pt->is_vararg & VARARG_NEEDSARG) || - (pt->is_vararg & VARARG_HASARG)); - check(pt->sizeupvalues <= pt->nups); - check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); - check(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; +/* +** find a "name" for the RK value 'c' +*/ +static void kname (Proto *p, int pc, int c, const char **name) { + if (ISK(c)) { /* is 'c' a constant? */ + TValue *kvalue = &p->k[INDEXK(c)]; + if (ttisstring(kvalue)) { /* literal constant? */ + *name = svalue(kvalue); /* it is its own name */ + return; } - default: return 0; /* invalid instruction after an open call */ + /* else no reasonable name found */ } -} - - -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; + else { /* 'c' is a register */ + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ + if (what && *what == 'c') { /* found a constant name? */ + return; /* 'name' already filled */ + } + /* else no reasonable name found */ } - return 1; + *name = "?"; /* no reasonable name found */ } -static Instruction symbexec (const Proto *pt, int lastpc, int reg) { +/* +** try to find last instruction before 'lastpc' that modified register 'reg' +*/ +static int findsetreg (Proto *p, 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)); + int setreg = -1; /* keep last instruction that changed 'reg' */ for (pc = 0; pc < lastpc; pc++) { - Instruction i = pt->code[pc]; + Instruction i = p->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) { - /* cannot jump to a setlist count */ - Instruction d = pt->code[dest-1]; - check(!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 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: { - check(c == 0 || pc+2 < pt->sizecode); /* check its jump */ - 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])); + int b = GETARG_B(i); + if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ + setreg = pc; 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 */ + case OP_TFORCALL: { + if (reg >= a + 2) setreg = pc; /* affect all regs above its base */ 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); + if (reg >= a) setreg = pc; /* affect all registers above base */ break; } - case OP_SETLIST: { - if (b > 0) checkreg(pt, a + b); - if (c == 0) pc++; + case OP_JMP: { + int b = GETARG_sBx(i); + int dest = pc + 1 + b; + /* jump is forward and do not skip `lastpc'? */ + if (pc < dest && dest <= lastpc) + pc += b; /* do the jump */ 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 */ + case OP_TEST: { + if (reg == a) setreg = pc; /* jumped code can change 'a' */ 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); + default: + if (testAMode(op) && reg == a) /* any instruction that set A */ + setreg = pc; 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); + return setreg; } -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, +static const char *getobjname (Proto *p, int lastpc, int reg, 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"; - } + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) { /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) { 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' */ + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ break; } + case OP_GETTABUP: case OP_GETTABLE: { int k = GETARG_C(i); /* key index */ - *name = kname(p, k); - return "field"; + int t = GETARG_B(i); /* table index */ + const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ + ? luaF_getlocalname(p, t + 1, pc) + : upvalname(p, t); + kname(p, pc, k, name); + return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; } case OP_GETUPVAL: { - int u = GETARG_B(i); /* upvalue index */ - *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; + *name = upvalname(p, GETARG_B(i)); return "upvalue"; } + case OP_LOADK: + case OP_LOADKX: { + int b = (op == OP_LOADK) ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } case OP_SELF: { int k = GETARG_C(i); /* key index */ - *name = kname(p, k); + kname(p, pc, k, name); return "method"; } - default: break; + default: break; /* go through to return NULL */ } } - return NULL; /* no useful name found */ + return NULL; /* could not find reasonable name */ } 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 */ + TMS tm; + Proto *p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: /* get function name */ + return getobjname(p, pc, GETARG_A(i), name); + case OP_TFORCALL: { /* for iterator */ + *name = "for iterator"; + return "for iterator"; + } + /* all other instructions can call only through metamethods */ + case OP_SELF: + case OP_GETTABUP: + case OP_GETTABLE: tm = TM_INDEX; break; + case OP_SETTABUP: + case OP_SETTABLE: tm = TM_NEWINDEX; break; + case OP_EQ: tm = TM_EQ; break; + case OP_ADD: tm = TM_ADD; break; + case OP_SUB: tm = TM_SUB; break; + case OP_MUL: tm = TM_MUL; break; + case OP_DIV: tm = TM_DIV; break; + case OP_MOD: tm = TM_MOD; break; + case OP_POW: tm = TM_POW; break; + case OP_UNM: tm = TM_UNM; break; + case OP_LEN: tm = TM_LEN; break; + case OP_LT: tm = TM_LT; break; + case OP_LE: tm = TM_LE; break; + case OP_CONCAT: tm = TM_CONCAT; break; + default: + return NULL; /* else no useful name can be found */ + } + *name = getstr(G(L)->tmname[tm]); + return "metamethod"; } +/* }====================================================== */ + + -/* only ANSI way to check whether a pointer points to an array */ +/* +** only ANSI way to check whether a pointer points to an array +** (used only for error messages, so efficiency is not a big concern) +*/ static int isinstack (CallInfo *ci, const TValue *o) { StkId p; - for (p = ci->base; p < ci->top; p++) + for (p = ci->u.l.base; p < ci->top; p++) if (o == p) return 1; return 0; } -void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { +static const char *getupvalname (CallInfo *ci, const TValue *o, + const char **name) { + LClosure *c = ci_func(ci); + int i; + for (i = 0; i < c->nupvalues; i++) { + if (c->upvals[i]->v == o) { + *name = upvalname(c->p, i); + return "upvalue"; + } + } + return NULL; +} + + +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + CallInfo *ci = L->ci; 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; + const char *t = objtypename(o); + const char *kind = NULL; + if (isLua(ci)) { + kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ + if (!kind && isinstack(ci, o)) /* no? try a register */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(o - ci->u.l.base), &name); + } if (kind) luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", op, kind, name, t); @@ -562,14 +513,14 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { } -void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { +l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; - lua_assert(!ttisstring(p1) && !ttisnumber(p1)); + lua_assert(!ttisstring(p1) && !ttisnumber(p2)); luaG_typeerror(L, p1, "concatenate"); } -void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { +l_noret 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 */ @@ -577,14 +528,13 @@ void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { } -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]) +l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = objtypename(p1); + const char *t2 = objtypename(p2); + if (t1 == t2) luaG_runerror(L, "attempt to compare two %s values", t1); else luaG_runerror(L, "attempt to compare %s with %s", t1, t2); - return 0; } @@ -592,27 +542,32 @@ 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); + int line = currentline(ci); + TString *src = ci_func(ci)->p->source; + if (src) + luaO_chunkid(buff, getstr(src), LUA_IDSIZE); + else { /* no source available; use "?" instead */ + buff[0] = '?'; buff[1] = '\0'; + } luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); } } -void luaG_errormsg (lua_State *L) { +l_noret 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_call(L, L->top - 2, 1, 0); /* call it */ } luaD_throw(L, LUA_ERRRUN); } -void luaG_runerror (lua_State *L, const char *fmt, ...) { +l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); addinfo(L, luaO_pushvfstring(L, fmt, argp)); diff --git a/liblua/ldebug.h b/liblua/ldebug.h index ba28a97248..fe39556b06 100644 --- a/liblua/ldebug.h +++ b/liblua/ldebug.h @@ -1,5 +1,5 @@ /* -** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ldebug.h,v 2.7 2011/10/07 20:45:19 roberto Exp $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ @@ -13,21 +13,22 @@ #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) -#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) +#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) #define resethookcount(L) (L->hookcount = L->basehookcount) +/* Active Lua function (given call info) */ +#define ci_func(ci) (clLvalue((ci)->func)) -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); + +LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2); +LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC l_noret luaG_errormsg (lua_State *L); #endif diff --git a/liblua/ldo.c b/liblua/ldo.c index 8de05f728e..26f9a6747e 100644 --- a/liblua/ldo.c +++ b/liblua/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ +** $Id: ldo.c,v 2.102 2011/11/29 15:55:08 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -14,6 +14,7 @@ #include "lua.h" +#include "lapi.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" @@ -39,6 +40,38 @@ ** ======================================================= */ +/* +** LUAI_THROW/LUAI_TRY define how Lua does exception handling. 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(LUAI_THROW) + +#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) +/* 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 + +#endif + + /* chain list of long jump buffers */ struct lua_longjmp { @@ -48,18 +81,17 @@ struct lua_longjmp { }; -void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { +static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { switch (errcode) { - case LUA_ERRMEM: { - setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); + case LUA_ERRMEM: { /* memory error? */ + setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ break; } case LUA_ERRERR: { setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); break; } - case LUA_ERRSYNTAX: - case LUA_ERRRUN: { + default: { setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ break; } @@ -68,55 +100,39 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { } -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); +l_noret luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { /* thread has an error handler? */ + L->errorJmp->status = errcode; /* set status */ + LUAI_THROW(L, L->errorJmp); /* jump to it */ } -} - - -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); + else { /* thread has no error handler */ + L->status = cast_byte(errcode); /* mark it as dead */ + if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */ + setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */ + luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */ + } + else { /* no handler at all; abort */ + if (G(L)->panic) { /* panic function? */ + lua_unlock(L); + G(L)->panic(L); /* call it (last chance to jump out) */ + } + abort(); } - exit(EXIT_FAILURE); } } int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + unsigned short oldnCcalls = L->nCcalls; struct lua_longjmp lj; - lj.status = 0; + lj.status = LUA_OK; 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 */ + L->nCcalls = oldnCcalls; return lj.status; } @@ -129,112 +145,126 @@ static void correctstack (lua_State *L, TValue *oldstack) { 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++) { + for (ci = L->ci; ci != NULL; ci = ci->previous) { ci->top = (ci->top - oldstack) + L->stack; - ci->base = (ci->base - oldstack) + L->stack; ci->func = (ci->func - oldstack) + L->stack; + if (isLua(ci)) + ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; } - L->base = (L->base - oldstack) + L->stack; } +/* some space for error handling */ +#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) + + 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; + int lim = L->stacksize; + lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); + luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); + for (; lim < newsize; lim++) + setnilvalue(L->stack + lim); /* erase new segment */ + L->stacksize = newsize; + L->stack_last = L->stack + newsize - EXTRA_STACK; 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) { + int size = L->stacksize; + if (size > LUAI_MAXSTACK) /* error after extra size? */ + luaD_throw(L, LUA_ERRERR); + else { + int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; + int newsize = 2 * size; + if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; + if (newsize < needed) newsize = needed; + if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ + luaD_reallocstack(L, ERRORSTACKSIZE); + luaG_runerror(L, "stack overflow"); + } + else + luaD_reallocstack(L, newsize); + } } -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 int stackinuse (lua_State *L) { + CallInfo *ci; + StkId lim = L->top; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + lua_assert(ci->top <= L->stack_last); + if (lim < ci->top) lim = ci->top; + } + return cast_int(lim - L->stack) + 1; /* part of stack in use */ } -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_shrinkstack (lua_State *L) { + int inuse = stackinuse(L); + int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; + if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; + if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ + goodsize >= L->stacksize) /* would grow instead of shrink? */ + condmovestack(L); /* don't change stack (change only for debugging) */ + else + luaD_reallocstack(L, goodsize); /* shrink it */ } -void luaD_callhook (lua_State *L, int event, int line) { +void luaD_hook (lua_State *L, int event, int line) { lua_Hook hook = L->hook; if (hook && L->allowhook) { + CallInfo *ci = L->ci; ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, L->ci->top); + ptrdiff_t ci_top = savestack(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); + ar.i_ci = 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); + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); L->allowhook = 0; /* cannot call hooks inside a hook */ + ci->callstatus |= CIST_HOOKED; lua_unlock(L); (*hook)(L, &ar); lua_lock(L); lua_assert(!L->allowhook); L->allowhook = 1; - L->ci->top = restorestack(L, ci_top); + ci->top = restorestack(L, ci_top); L->top = restorestack(L, top); + ci->callstatus &= ~CIST_HOOKED; } } +static void callhook (lua_State *L, CallInfo *ci) { + int hook = LUA_HOOKCALL; + ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ + if (isLua(ci->previous) && + GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { + ci->callstatus |= CIST_TAIL; + hook = LUA_HOOKTAILCALL; + } + luaD_hook(L, hook, -1); + ci->u.l.savedpc--; /* correct 'pc' */ +} + + 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 + lua_assert(actual >= nfixargs); /* 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))); + setobjs2s(L, L->top++, fixed + i); + setnilvalue(fixed + i); } return base; } @@ -256,100 +286,85 @@ static StkId tryfuncTM (lua_State *L, StkId func) { -#define inc_ci(L) \ - ((L->ci == L->end_ci) ? growCI(L) : \ - (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) +#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) +/* +** returns true if function has been executed (C function) +*/ 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 */ + lua_CFunction f; + CallInfo *ci; + int n; /* number of arguments (Lua) or returns (C) */ + ptrdiff_t funcr = savestack(L, func); + switch (ttype(func)) { + case LUA_TLCF: /* light C function */ + f = fvalue(func); + goto Cfunc; + case LUA_TCCL: { /* C closure */ + f = clCvalue(func)->f; + Cfunc: + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = restorestack(L, funcr); + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->callstatus = 0; + if (L->hookmask & LUA_MASKCALL) + luaD_hook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, L->top - n); + return 1; } - 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' */ + case LUA_TLCL: { /* Lua function: prepare its call */ + StkId base; + Proto *p = clLvalue(func)->p; + luaD_checkstack(L, p->maxstacksize); + func = restorestack(L, funcr); + n = cast_int(L->top - func) - 1; /* number of real arguments */ + for (; n < p->numparams; n++) + setnilvalue(L->top++); /* complete missing arguments */ + base = (!p->is_vararg) ? func + 1 : adjust_varargs(L, p, n); + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->u.l.base = base; + ci->top = base + p->maxstacksize; + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus = CIST_LUA; + L->top = ci->top; + if (L->hookmask & LUA_MASKCALL) + callhook(L, ci); + return 0; } - 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; + default: { /* not a function */ + func = tryfuncTM(L, func); /* retry with 'function' tag method */ + return luaD_precall(L, func, nresults); /* now it must be a function */ } } } -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--; + CallInfo *ci = L->ci; + if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { + if (L->hookmask & LUA_MASKRET) { + ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ + luaD_hook(L, LUA_HOOKRET, -1); + firstResult = restorestack(L, fr); + } + L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ + } 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 */ + L->ci = ci = ci->previous; /* back to caller */ /* move results to correct place */ for (i = wanted; i != 0 && firstResult < L->top; i--) setobjs2s(L, res++, firstResult++); @@ -365,112 +380,223 @@ int luaD_poscall (lua_State *L, StkId firstResult) { ** 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) { +*/ +void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { 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 */ + if (!allowyield) L->nny++; + if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ + luaV_execute(L); /* call it */ + if (!allowyield) L->nny--; L->nCcalls--; luaC_checkGC(L); } -static void resume (lua_State *L, void *ud) { - StkId firstArg = cast(StkId, ud); +static void finishCcall (lua_State *L) { 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 */ + int n; + lua_assert(ci->u.c.k != NULL); /* must have a continuation */ + lua_assert(L->nny == 0); + /* finish 'luaD_call' */ + L->nCcalls--; + /* finish 'lua_callk' */ + adjustresults(L, ci->nresults); + /* call continuation function */ + if (!(ci->callstatus & CIST_STAT)) /* no call status? */ + ci->u.c.status = LUA_YIELD; /* 'default' status */ + lua_assert(ci->u.c.status != LUA_OK); + ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED; + lua_unlock(L); + n = (*ci->u.c.k)(L); + lua_lock(L); + api_checknelems(L, n); + /* finish 'luaD_precall' */ + luaD_poscall(L, L->top - n); +} + + +static void unroll (lua_State *L, void *ud) { + UNUSED(ud); + for (;;) { + if (L->ci == &L->base_ci) /* stack is empty? */ + return; /* coroutine finished normally */ + if (!isLua(L->ci)) /* C function? */ + finishCcall(L); + else { /* Lua function */ + luaV_finishOp(L); /* finish interrupted instruction */ + luaV_execute(L); /* execute down to higher C 'boundary' */ } - 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)); +/* +** check whether thread has a suspended protected call +*/ +static CallInfo *findpcall (lua_State *L) { + CallInfo *ci; + for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ + if (ci->callstatus & CIST_YPCALL) + return ci; + } + return NULL; /* no pending pcall */ +} + + +static int recover (lua_State *L, int status) { + StkId oldtop; + CallInfo *ci = findpcall(L); + if (ci == NULL) return 0; /* no recovery point */ + /* "finish" luaD_pcall */ + oldtop = restorestack(L, ci->u.c.extra); + luaF_close(L, oldtop); + seterrorobj(L, status, oldtop); + L->ci = ci; + L->allowhook = ci->u.c.old_allowhook; + L->nny = 0; /* should be zero to be yieldable */ + luaD_shrinkstack(L); + L->errfunc = ci->u.c.old_errfunc; + ci->callstatus |= CIST_STAT; /* call has error status */ + ci->u.c.status = status; /* (here it is) */ + return 1; /* continue running the coroutine */ +} + + +/* +** signal an error in the call to 'resume', not in the execution of the +** coroutine itself. (Such errors should not be handled by any coroutine +** error handler and should not kill the coroutine.) +*/ +static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { + L->top = firstArg; /* remove args from the stack */ + setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ incr_top(L); - lua_unlock(L); - return LUA_ERRRUN; + luaD_throw(L, -1); /* jump back to 'lua_resume' */ } -LUA_API int lua_resume (lua_State *L, int nargs) { +/* +** do the work for 'lua_resume' in protected mode +*/ +static void resume (lua_State *L, void *ud) { + StkId firstArg = cast(StkId, ud); + CallInfo *ci = L->ci; + if (L->nCcalls >= LUAI_MAXCCALLS) + resume_error(L, "C stack overflow", firstArg); + if (L->status == LUA_OK) { /* may be starting a coroutine */ + if (ci != &L->base_ci) /* not in base level? */ + resume_error(L, "cannot resume non-suspended coroutine", firstArg); + /* coroutine is in base level; start running it */ + if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ + luaV_execute(L); /* call it */ + } + else if (L->status != LUA_YIELD) + resume_error(L, "cannot resume dead coroutine", firstArg); + else { /* resuming from previous yield */ + L->status = LUA_OK; + if (isLua(ci)) /* yielded inside a hook? */ + luaV_execute(L); /* just continue running Lua code */ + else { /* 'common' yield */ + ci->func = restorestack(L, ci->u.c.extra); + if (ci->u.c.k != NULL) { /* does it have a continuation? */ + int n; + ci->u.c.status = LUA_YIELD; /* 'default' status */ + ci->callstatus |= CIST_YIELDED; + lua_unlock(L); + n = (*ci->u.c.k)(L); /* call continuation */ + lua_lock(L); + api_checknelems(L, n); + firstArg = L->top - n; /* yield results come from continuation */ + } + L->nCcalls--; /* finish 'luaD_call' */ + luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ + } + unroll(L, NULL); + } +} + + +LUA_API int lua_resume (lua_State *L, lua_State *from, 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; + L->nCcalls = (from) ? from->nCcalls + 1 : 1; + L->nny = 0; /* allow yields */ + api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); 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; + if (status == -1) /* error calling 'lua_resume'? */ + status = LUA_ERRRUN; + else { /* yield or regular error */ + while (status != LUA_OK && status != LUA_YIELD) { /* error? */ + if (recover(L, status)) /* recover point? */ + status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ + else { /* unrecoverable error */ + L->status = cast_byte(status); /* mark thread as `dead' */ + seterrorobj(L, status, L->top); + L->ci->top = L->top; + break; + } + } + lua_assert(status == L->status); } - --L->nCcalls; + L->nny = 1; /* do not allow yields */ + L->nCcalls--; + lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); lua_unlock(L); return status; } -LUA_API int lua_yield (lua_State *L, int nresults) { +LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { + CallInfo *ci = L->ci; 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 */ + api_checknelems(L, nresults); + if (L->nny > 0) { + if (L != G(L)->mainthread) + luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); + else + luaG_runerror(L, "attempt to yield from outside a coroutine"); + } L->status = LUA_YIELD; + if (isLua(ci)) { /* inside a hook? */ + api_check(L, k == NULL, "hooks cannot continue after yielding"); + } + else { + if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ + ci->u.c.ctx = ctx; /* save context */ + ci->u.c.extra = savestack(L, ci->func); /* save current 'func' */ + ci->func = L->top - nresults - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } + lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ lua_unlock(L); - return -1; + return 0; /* return to 'luaD_hook' */ } 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); + CallInfo *old_ci = L->ci; lu_byte old_allowhooks = L->allowhook; + unsigned short old_nny = L->nny; ptrdiff_t old_errfunc = L->errfunc; L->errfunc = ef; status = luaD_rawrunprotected(L, func, u); - if (status != 0) { /* an error occurred? */ + if (status != LUA_OK) { /* 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; + luaF_close(L, oldtop); /* close possible pending closures */ + seterrorobj(L, status, oldtop); + L->ci = old_ci; L->allowhook = old_allowhooks; - restore_stack_limit(L); + L->nny = old_nny; + luaD_shrinkstack(L); } L->errfunc = old_errfunc; return status; @@ -483,35 +609,61 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, */ struct SParser { /* data to `f_parser' */ ZIO *z; - Mbuffer buff; /* buffer to be used by the scanner */ + Mbuffer buff; /* dynamic structure used by the scanner */ + Dyndata dyd; /* dynamic structures used by the parser */ + const char *mode; const char *name; }; + +static void checkmode (lua_State *L, const char *mode, const char *x) { + if (mode && strchr(mode, x[0]) == NULL) { + luaO_pushfstring(L, + "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode); + luaD_throw(L, LUA_ERRSYNTAX); + } +} + + 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); + int c = zgetc(p->z); /* read first character */ + if (c == LUA_SIGNATURE[0]) { + checkmode(L, p->mode, "binary"); + tf = luaU_undump(L, p->z, &p->buff, p->name); + } + else { + checkmode(L, p->mode, "text"); + tf = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + } + setptvalue2s(L, L->top, tf); incr_top(L); + cl = luaF_newLclosure(L, tf); + setclLvalue(L, L->top - 1, cl); + for (i = 0; i < tf->sizeupvalues; i++) /* initialize upvalues */ + cl->l.upvals[i] = luaF_newupval(L); } -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode) { struct SParser p; int status; - p.z = z; p.name = name; + L->nny++; /* cannot yield during parsing */ + p.z = z; p.name = name; p.mode = mode; + p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; + p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; + p.dyd.label.arr = NULL; p.dyd.label.size = 0; luaZ_initbuffer(L, &p.buff); status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); luaZ_freebuffer(L, &p.buff); + luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); + luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); + luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); + L->nny--; return status; } diff --git a/liblua/ldo.h b/liblua/ldo.h index 98fddac59f..27b837d999 100644 --- a/liblua/ldo.h +++ b/liblua/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ldo.h,v 2.20 2011/11/29 15:55:08 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -13,45 +13,34 @@ #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 luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ + luaD_growstack(L, n); else condmovestack(L); -#define incr_top(L) {luaD_checkstack(L,1); L->top++;} +#define incr_top(L) {L->top++; luaD_checkstack(L,0);} #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_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode); +LUAI_FUNC void luaD_hook (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 void luaD_call (lua_State *L, StkId func, int nResults, + int allowyield); 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_shrinkstack (lua_State *L); -LUAI_FUNC void luaD_throw (lua_State *L, int errcode); +LUAI_FUNC l_noret 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/liblua/ldump.c b/liblua/ldump.c index c9d3d4870f..699e1dc4e9 100644 --- a/liblua/ldump.c +++ b/liblua/ldump.c @@ -1,5 +1,5 @@ /* -** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ldump.c,v 1.19 2011/11/23 17:48:18 lhf Exp $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -24,7 +24,7 @@ typedef struct { } DumpState; #define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) +#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) static void DumpBlock(const void* b, size_t size, DumpState* D) { @@ -60,7 +60,7 @@ static void DumpVector(const void* b, int n, size_t size, DumpState* D) static void DumpString(const TString* s, DumpState* D) { - if (s==NULL || getstr(s)==NULL) + if (s==NULL) { size_t size=0; DumpVar(size,D); @@ -69,13 +69,13 @@ static void DumpString(const TString* s, DumpState* D) { size_t size=s->tsv.len+1; /* include trailing '\0' */ DumpVar(size,D); - DumpBlock(getstr(s),size,D); + DumpBlock(getstr(s),size*sizeof(char),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 DumpFunction(const Proto* f, DumpState* D); static void DumpConstants(const Proto* f, DumpState* D) { @@ -98,19 +98,28 @@ static void DumpConstants(const Proto* f, DumpState* D) 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); + for (i=0; ip[i],D); +} + +static void DumpUpvalues(const Proto* f, DumpState* D) +{ + int i,n=f->sizeupvalues; + DumpInt(n,D); + for (i=0; iupvalues[i].instack,D); + DumpChar(f->upvalues[i].idx,D); + } } static void DumpDebug(const Proto* f, DumpState* D) { int i,n; + DumpString((D->strip) ? NULL : f->source,D); n= (D->strip) ? 0 : f->sizelineinfo; DumpVector(f->lineinfo,n,sizeof(int),D); n= (D->strip) ? 0 : f->sizelocvars; @@ -123,26 +132,25 @@ static void DumpDebug(const Proto* f, DumpState* D) } n= (D->strip) ? 0 : f->sizeupvalues; DumpInt(n,D); - for (i=0; iupvalues[i],D); + for (i=0; iupvalues[i].name,D); } -static void DumpFunction(const Proto* f, const TString* p, DumpState* D) +static void DumpFunction(const Proto* f, 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); + DumpUpvalues(f,D); DumpDebug(f,D); } static void DumpHeader(DumpState* D) { - char h[LUAC_HEADERSIZE]; + lu_byte h[LUAC_HEADERSIZE]; luaU_header(h); DumpBlock(h,LUAC_HEADERSIZE,D); } @@ -159,6 +167,6 @@ int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip D.strip=strip; D.status=0; DumpHeader(&D); - DumpFunction(f,NULL,&D); + DumpFunction(f,&D); return D.status; } diff --git a/liblua/lfunc.c b/liblua/lfunc.c index 813e88f583..1a1a8bb8bd 100644 --- a/liblua/lfunc.c +++ b/liblua/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ +** $Id: lfunc.c,v 2.27 2010/06/30 14:11:17 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -20,30 +20,27 @@ -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); +Closure *luaF_newCclosure (lua_State *L, int n) { + Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeCclosure(n), NULL, 0)->cl; c->c.isC = 1; - c->c.env = e; - c->c.nupvalues = cast_byte(nelems); + c->c.nupvalues = cast_byte(n); 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); +Closure *luaF_newLclosure (lua_State *L, Proto *p) { + int n = p->sizeupvalues; + Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeLclosure(n), NULL, 0)->cl; c->l.isC = 0; - c->l.env = e; - c->l.nupvalues = cast_byte(nelems); - while (nelems--) c->l.upvals[nelems] = NULL; + c->l.p = p; + c->l.nupvalues = cast_byte(n); + while (n--) c->l.upvals[n] = NULL; return c; } UpVal *luaF_newupval (lua_State *L) { - UpVal *uv = luaM_new(L, UpVal); - luaC_link(L, obj2gco(uv), LUA_TUPVAL); + UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; uv->v = &uv->u.value; setnilvalue(uv->v); return uv; @@ -55,21 +52,20 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { GCObject **pp = &L->openupval; UpVal *p; UpVal *uv; - while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { + while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { + GCObject *o = obj2gco(p); 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 */ + if (isdead(g, o)) /* is it dead? */ + changewhite(o); /* resurrect it */ return p; } + resetoldbit(o); /* may create a newer upval after this one */ pp = &p->next; } - uv = luaM_new(L, UpVal); /* not found: create a new one */ - uv->tt = LUA_TUPVAL; - uv->marked = luaC_white(g); + /* not found: create a new one */ + uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; 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; @@ -96,41 +92,42 @@ void luaF_freeupval (lua_State *L, UpVal *uv) { 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) { + while (L->openupval != NULL && (uv = gco2uv(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); + unlinkupval(uv); /* remove upvalue from 'uvhead' list */ + setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ uv->v = &uv->u.value; /* now current value lives here */ - luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ + gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ + g->allgc = o; + luaC_checkupvalcolor(g, uv); } } } Proto *luaF_newproto (lua_State *L) { - Proto *f = luaM_new(L, Proto); - luaC_link(L, obj2gco(f), LUA_TPROTO); + Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; f->k = NULL; f->sizek = 0; f->p = NULL; f->sizep = 0; f->code = NULL; + f->cache = NULL; f->sizecode = 0; + f->lineinfo = NULL; f->sizelineinfo = 0; - f->sizeupvalues = 0; - f->nups = 0; f->upvalues = NULL; + f->sizeupvalues = 0; f->numparams = 0; f->is_vararg = 0; f->maxstacksize = 0; - f->lineinfo = NULL; - f->sizelocvars = 0; f->locvars = NULL; + f->sizelocvars = 0; f->linedefined = 0; f->lastlinedefined = 0; f->source = NULL; @@ -139,12 +136,12 @@ Proto *luaF_newproto (lua_State *L) { 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_freearray(L, f->code, f->sizecode); + luaM_freearray(L, f->p, f->sizep); + luaM_freearray(L, f->k, f->sizek); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); luaM_free(L, f); } diff --git a/liblua/lfunc.h b/liblua/lfunc.h index a68cf5151c..da18923150 100644 --- a/liblua/lfunc.h +++ b/liblua/lfunc.h @@ -1,5 +1,5 @@ /* -** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lfunc.h,v 2.6 2010/06/04 13:06:15 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -19,8 +19,8 @@ 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 Closure *luaF_newCclosure (lua_State *L, int nelems); +LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, Proto *p); 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); diff --git a/liblua/lgc.c b/liblua/lgc.c index d9e0b78294..cdd92e524e 100644 --- a/liblua/lgc.c +++ b/liblua/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lgc.c,v 2.116 2011/12/02 13:18:41 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -23,68 +23,247 @@ #include "ltm.h" -#define GCSTEPSIZE 1024u + +/* how much to allocate before next GC step */ +#define GCSTEPSIZE 1024 + +/* maximum number of elements to sweep in each single step */ #define GCSWEEPMAX 40 -#define GCSWEEPCOST 10 -#define GCFINALIZECOST 100 +/* cost of sweeping one element */ +#define GCSWEEPCOST 1 + +/* maximum number of finalizers to call in each GC step */ +#define GCFINALIZENUM 4 + +/* cost of marking the root set */ +#define GCROOTCOST 10 + +/* cost of atomic step */ +#define GCATOMICCOST 1000 + +/* basic cost to traverse one object (to be added to the links the + object may have) */ +#define TRAVCOST 5 + + +/* +** standard negative debt for GC; a reasonable "time" to wait before +** starting a new cycle +*/ +#define stddebt(g) (-cast(l_mem, gettotalbytes(g)/100) * g->gcpause) -#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) +/* +** 'makewhite' erases all color bits plus the old bit and then +** sets only the current white bit +*/ +#define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) #define makewhite(g,x) \ - ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) + (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) -#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) -#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) +#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) +#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) -#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) +#define stringmark(s) ((void)((s) && resetbits((s)->tsv.marked, WHITEBITS))) -#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) -#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) +#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) +#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) -#define KEYWEAK bitmask(KEYWEAKBIT) -#define VALUEWEAK bitmask(VALUEWEAKBIT) +#define checkconsistency(obj) \ + lua_longassert(!iscollectable(obj) || righttt(obj)) #define markvalue(g,o) { checkconsistency(o); \ - if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } + if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } -#define markobject(g,t) { if (iswhite(obj2gco(t))) \ +#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ reallymarkobject(g, obj2gco(t)); } +static void reallymarkobject (global_State *g, GCObject *o); + + +/* +** {====================================================== +** Generic functions +** ======================================================= +*/ + + +/* +** one after last element in a hash array +*/ +#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) + -#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) +/* +** link table 'h' into list pointed by 'p' +*/ +#define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) +/* +** if key is not marked, mark its entry as dead (therefore removing it +** from the table) +*/ static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); - if (iscollectable(gkey(n))) - setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ + if (valiswhite(gkey(n))) + setdeadvalue(gkey(n)); /* unused and unmarked key; remove it */ +} + + +/* +** 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 objects +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (const TValue *o) { + if (!iscollectable(o)) return 0; + else if (ttisstring(o)) { + stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ + return 0; + } + else return iswhite(gcvalue(o)); +} + + +/* +** barrier that moves collector forward, that is, mark the white object +** being pointed by a black object. +*/ +void luaC_barrier_ (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(isgenerational(g) || g->gcstate != GCSpause); + lua_assert(gch(o)->tt != LUA_TTABLE); + if (keepinvariant(g)) /* must keep invariant? */ + reallymarkobject(g, v); /* restore invariant */ + else { /* sweep phase */ + lua_assert(issweepphase(g)); + makewhite(g, o); /* mark main obj. as white to avoid other barriers */ + } +} + + +/* +** barrier that moves collector backward, that is, mark the black object +** pointing to a white object as gray again. (Current implementation +** only works for tables; access to 'gclist' is not uniform across +** different types.) +*/ +void luaC_barrierback_ (lua_State *L, GCObject *o) { + global_State *g = G(L); + lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE); + black2gray(o); /* make object gray (again) */ + gco2t(o)->gclist = g->grayagain; + g->grayagain = o; +} + + +/* +** barrier for prototypes. When creating first closure (cache is +** NULL), use a forward barrier; this may be the only closure of the +** prototype (if it is a "regular" function, with a single instance) +** and the prototype may be big, so it is better to avoid traversing +** it again. Otherwise, use a backward barrier, to avoid marking all +** possible instances. +*/ +LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { + global_State *g = G(L); + lua_assert(isblack(obj2gco(p))); + if (p->cache == NULL) { /* first time? */ + luaC_objbarrier(L, p, c); + } + else { /* use a backward barrier */ + black2gray(obj2gco(p)); /* make prototype gray (again) */ + p->gclist = g->grayagain; + g->grayagain = obj2gco(p); + } } +/* +** check color (and invariants) for an upvalue that was closed, +** i.e., moved into the 'allgc' list +*/ +void luaC_checkupvalcolor (global_State *g, UpVal *uv) { + GCObject *o = obj2gco(uv); + lua_assert(!isblack(o)); /* open upvalues are never black */ + if (isgray(o)) { + if (keepinvariant(g)) { + resetoldbit(o); /* see MOVE OLD rule */ + gray2black(o); /* it is being visited now */ + markvalue(g, uv->v); + } + else { + lua_assert(issweepphase(g)); + makewhite(g, o); + } + } +} + + +/* +** create a new collectable object (with given type and size) and link +** it to '*list'. 'offset' tells how many bytes to allocate before the +** object itself (used only by states). +*/ +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, + int offset) { + global_State *g = G(L); + GCObject *o = obj2gco(cast(char *, luaM_newobject(L, tt, sz)) + offset); + if (list == NULL) + list = &g->allgc; /* standard list for collectable objects */ + gch(o)->marked = luaC_white(g); + gch(o)->tt = tt; + gch(o)->next = *list; + *list = o; + return o; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Mark functions +** ======================================================= +*/ + + +/* +** mark an object. Userdata and closed upvalues are visited and turned +** black here. Strings remain gray (it is the same as making them +** black). Other objects are marked gray and added to appropriate list +** to be visited (and turned black) later. (Open upvalues are already +** linked in 'headuv' list.) +*/ static void reallymarkobject (global_State *g, GCObject *o) { lua_assert(iswhite(o) && !isdead(g, o)); white2gray(o); - switch (o->gch.tt) { + switch (gch(o)->tt) { case LUA_TSTRING: { - return; + return; /* for strings, gray is as good as black */ } case LUA_TUSERDATA: { Table *mt = gco2u(o)->metatable; - gray2black(o); /* udata are never gray */ - if (mt) markobject(g, mt); + markobject(g, mt); markobject(g, gco2u(o)->env); + gray2black(o); /* all pointers marked */ 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 */ + if (uv->v == &uv->u.value) /* closed? (open upvalues remain gray) */ + gray2black(o); /* make it black */ return; } case LUA_TFUNCTION: { @@ -93,8 +272,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { break; } case LUA_TTABLE: { - gco2h(o)->gclist = g->gray; - g->gray = o; + linktable(gco2t(o), &g->gray); break; } case LUA_TTHREAD: { @@ -112,117 +290,187 @@ static void reallymarkobject (global_State *g, GCObject *o) { } -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); +/* +** mark metamethods for basic types +*/ +static void markmt (global_State *g) { + int i; + for (i=0; i < LUA_NUMTAGS; i++) + markobject(g, g->mt[i]); +} + + +/* +** mark all objects in list of being-finalized +*/ +static void markbeingfnz (global_State *g) { + GCObject *o; + for (o = g->tobefnz; o != NULL; o = gch(o)->next) { + makewhite(g, o); + reallymarkobject(g, o); } } -/* 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; - } - } +/* +** mark all values stored in marked open upvalues. (See comment in +** 'lstate.h'.) +*/ +static void remarkupvals (global_State *g) { + UpVal *uv; + for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { + if (isgray(obj2gco(uv))) + markvalue(g, uv->v); } - 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 */ +/* +** mark root set and reset all gray lists, to start a new +** incremental (or full) collection +*/ +static void markroot (global_State *g) { + g->gray = g->grayagain = NULL; + g->weak = g->allweak = g->ephemeron = NULL; + markobject(g, g->mainthread); + markvalue(g, &g->l_registry); + markmt(g); + markbeingfnz(g); /* mark any finalizing object left from previous cycle */ +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Traverse functions +** ======================================================= +*/ + +static void traverseweakvalue (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + /* if there is array part, assume it may have white values (do not + traverse it just to check) */ + int hasclears = (h->sizearray > 0); + for (n = gnode(h, 0); n < limit; n++) { + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ else { lua_assert(!ttisnil(gkey(n))); - if (!weakkey) markvalue(g, gkey(n)); - if (!weakvalue) markvalue(g, gval(n)); + markvalue(g, gkey(n)); /* mark key */ + if (!hasclears && iscleared(gval(n))) /* is there a white value? */ + hasclears = 1; /* table will have to be cleared */ } } - return weakkey || weakvalue; + if (hasclears) + linktable(h, &g->weak); /* has to be cleared later */ + else /* no white values */ + linktable(h, &g->grayagain); /* no need to clean */ } -/* -** All marks are conditional because a GC may happen while the -** prototype is still being created -*/ -static void traverseproto (global_State *g, Proto *f) { +static int traverseephemeron (global_State *g, Table *h) { + int marked = 0; /* true if an object is marked in this traversal */ + int hasclears = 0; /* true if table has white keys */ + int prop = 0; /* true if table has entry "white-key -> white-value" */ + Node *n, *limit = gnodelast(h); 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]); + /* traverse array part (numeric keys are 'strong') */ + for (i = 0; i < h->sizearray; i++) { + if (valiswhite(&h->array[i])) { + marked = 1; + reallymarkobject(g, gcvalue(&h->array[i])); + } } - for (i=0; isizep; i++) { /* mark nested protos */ - if (f->p[i]) - markobject(g, f->p[i]); + /* traverse hash part */ + for (n = gnode(h, 0); n < limit; n++) { + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else if (iscleared(gkey(n))) { /* key is not marked (yet)? */ + hasclears = 1; /* table must be cleared */ + if (valiswhite(gval(n))) /* value not marked yet? */ + prop = 1; /* must propagate again */ + } + else if (valiswhite(gval(n))) { /* value not marked yet? */ + marked = 1; + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ + } } - for (i=0; isizelocvars; i++) { /* mark local-variable names */ - if (f->locvars[i].varname) - stringmark(f->locvars[i].varname); + if (prop) + linktable(h, &g->ephemeron); /* have to propagate again */ + else if (hasclears) /* does table have white keys? */ + linktable(h, &g->allweak); /* may have to clean white keys */ + else /* no white keys */ + linktable(h, &g->grayagain); /* no need to clean */ + return marked; +} + + +static void traversestrongtable (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + int i; + for (i = 0; i < h->sizearray; i++) /* traverse array part */ + markvalue(g, &h->array[i]); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + markvalue(g, gval(n)); /* mark value */ + } } } +static int traversetable (global_State *g, Table *h) { + const TValue *mode = gfasttm(g, h->metatable, TM_MODE); + markobject(g, h->metatable); + if (mode && ttisstring(mode)) { /* is there a weak mode? */ + int weakkey = (strchr(svalue(mode), 'k') != NULL); + int weakvalue = (strchr(svalue(mode), 'v') != NULL); + if (weakkey || weakvalue) { /* is really weak? */ + black2gray(obj2gco(h)); /* keep table gray */ + if (!weakkey) { /* strong keys? */ + traverseweakvalue(g, h); + return TRAVCOST + sizenode(h); + } + else if (!weakvalue) { /* strong values? */ + traverseephemeron(g, h); + return TRAVCOST + h->sizearray + sizenode(h); + } + else { + linktable(h, &g->allweak); /* nothing to traverse now */ + return TRAVCOST; + } + } /* else go through */ + } + traversestrongtable(g, h); + return TRAVCOST + h->sizearray + (2 * sizenode(h)); +} + -static void traverseclosure (global_State *g, Closure *cl) { - markobject(g, cl->c.env); +static int traverseproto (global_State *g, Proto *f) { + int i; + if (f->cache && iswhite(obj2gco(f->cache))) + f->cache = NULL; /* allow cache to be collected */ + stringmark(f->source); + for (i = 0; i < f->sizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + stringmark(f->upvalues[i].name); + for (i = 0; i < f->sizep; i++) /* mark nested protos */ + markobject(g, f->p[i]); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + stringmark(f->locvars[i].varname); + return TRAVCOST + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars; +} + + +static int traverseclosure (global_State *g, Closure *cl) { if (cl->c.isC) { int i; for (i=0; ic.nupvalues; i++) /* mark its upvalues */ @@ -230,69 +478,49 @@ static void traverseclosure (global_State *g, Closure *cl) { } else { int i; - lua_assert(cl->l.nupvalues == cl->l.p->nups); - markobject(g, cl->l.p); + lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); + markobject(g, cl->l.p); /* mark its prototype */ for (i=0; il.nupvalues; i++) /* mark its upvalues */ markobject(g, cl->l.upvals[i]); } + return TRAVCOST + cl->c.nupvalues; } -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++) +static int traversestack (global_State *g, lua_State *L) { + StkId o = L->stack; + if (o == NULL) + return 1; /* stack not completely built yet */ + for (; o < L->top; o++) markvalue(g, o); - for (; o <= lim; o++) - setnilvalue(o); - checkstacksizes(l, lim); + if (g->gcstate == GCSatomic) { /* final traversal? */ + StkId lim = L->stack + L->stacksize; /* real end of stack */ + for (; o < lim; o++) /* clear not-marked stack slice */ + setnilvalue(o); + } + return TRAVCOST + cast_int(o - L->stack); } /* -** traverse one gray object, turning it to black. -** Returns `quantity' traversed. +** traverse one gray object, turning it to black (except for threads, +** which are always gray). +** Returns number of values traversed. */ -static l_mem propagatemark (global_State *g) { +static int propagatemark (global_State *g) { GCObject *o = g->gray; lua_assert(isgray(o)); gray2black(o); - switch (o->gch.tt) { + switch (gch(o)->tt) { case LUA_TTABLE: { - Table *h = gco2h(o); + Table *h = gco2t(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); + return traversetable(g, 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); + return traverseclosure(g, cl); } case LUA_TTHREAD: { lua_State *th = gco2th(o); @@ -300,306 +528,476 @@ static l_mem propagatemark (global_State *g) { 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; + return traversestack(g, th); } 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; + return traverseproto(g, p); } 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; +static void propagateall (global_State *g) { + while (g->gray) propagatemark(g); } +static void propagatelist (global_State *g, GCObject *l) { + lua_assert(g->gray == NULL); /* no grays left */ + g->gray = l; + propagateall(g); /* traverse all elements from 'l' */ +} + /* -** 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 +** retraverse all gray lists. Because tables may be reinserted in other +** lists when traversed, traverse the original lists to avoid traversing +** twice the same table (which is not wrong, but inefficient) */ -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)))); +static void retraversegrays (global_State *g) { + GCObject *weak = g->weak; /* save original lists */ + GCObject *grayagain = g->grayagain; + GCObject *ephemeron = g->ephemeron; + g->weak = g->grayagain = g->ephemeron = NULL; + propagateall(g); /* traverse main gray list */ + propagatelist(g, grayagain); + propagatelist(g, weak); + propagatelist(g, ephemeron); +} + + +static void convergeephemerons (global_State *g) { + int changed; + do { + GCObject *w; + GCObject *next = g->ephemeron; /* get ephemeron list */ + g->ephemeron = NULL; /* tables will return to this list when traversed */ + changed = 0; + while ((w = next) != NULL) { + next = gco2t(w)->gclist; + if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ + propagateall(g); /* propagate changes */ + changed = 1; /* will have to revisit all ephemeron tables */ + } + } + } while (changed); } +/* }====================================================== */ + + +/* +** {====================================================== +** Sweep Functions +** ======================================================= +*/ + /* -** clear collected entries from weaktables +** clear entries with unmarked keys from all weaktables in list 'l' up +** to element 'f' */ -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 */ +static void clearkeys (GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && (iscleared(gkey(n)))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ } } - 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))) { + } +} + + +/* +** clear entries with unmarked values from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearvalues (GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + int i; + for (i = 0; i < h->sizearray; i++) { + TValue *o = &h->array[i]; + if (iscleared(o)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && iscleared(gval(n))) { setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* remove entry from table */ + removeentry(n); /* and remove entry from table */ } } - l = h->gclist; } } static void freeobj (lua_State *L, GCObject *o) { - switch (o->gch.tt) { + switch (gch(o)->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_TTABLE: luaH_free(L, gco2t(o)); break; + case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; + case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(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); + + +/* +** sweep the (open) upvalues of a thread and resize its stack and +** list of call-info structures. +*/ +static void sweepthread (lua_State *L, lua_State *L1) { + if (L1->stack == NULL) return; /* stack not completely built yet */ + sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ + luaE_freeCI(L1); /* free extra CallInfo slots */ + /* should not change the stack during an emergency gc cycle */ + if (G(L)->gckind != KGC_EMERGENCY) + luaD_shrinkstack(L1); +} +/* +** sweep at most 'count' elements from a list of GCObjects erasing dead +** objects, where a dead (not alive) object is one marked with the "old" +** (non current) white and not fixed. +** In non-generational mode, change all non-dead objects back to white, +** preparing for next collection cycle. +** In generational mode, keep black objects black, and also mark them as +** old; stop when hitting an old object, as all objects after that +** one will be old too. +** When object is a thread, sweep its list of open upvalues too. +*/ 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); + int ow = otherwhite(g); + int toclear, toset; /* bits to clear and to set in all live objects */ + int tostop; /* stop sweep when this is true */ + l_mem debt = g->GCdebt; /* current debt */ + if (isgenerational(g)) { /* generational mode? */ + toclear = ~0; /* clear nothing */ + toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ + tostop = bitmask(OLDBIT); /* do not sweep old generation */ + } + else { /* normal mode */ + toclear = maskcolors; /* clear all color bits + old bit */ + toset = luaC_white(g); /* make object white */ + tostop = 0; /* do not stop */ + } + while (*p != NULL && count-- > 0) { + GCObject *curr = *p; + int marked = gch(curr)->marked; + if (isdeadm(ow, marked)) { /* is 'curr' dead? */ + *p = gch(curr)->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { + if (gch(curr)->tt == LUA_TTHREAD) + sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ + if (testbits(marked, tostop)) { + static GCObject *nullp = NULL; + p = &nullp; /* stop sweeping this list */ + break; + } + /* update marks */ + gch(curr)->marked = cast_byte((marked & toclear) | toset); + p = &gch(curr)->next; /* go to next element */ } } + luaE_setdebt(g, debt); /* sweeping should not change debt */ return p; } +/* }====================================================== */ + + +/* +** {====================================================== +** Finalization +** ======================================================= +*/ 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); + if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ + int hs = g->strt.size / 2; /* half the size of the string table */ + if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ + luaS_resize(L, hs); /* halve its size */ + luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ } } -static void GCTM (lua_State *L) { +static GCObject *udata2finalize (global_State *g) { + GCObject *o = g->tobefnz; /* get first element */ + lua_assert(isfinalized(o)); + g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ + gch(o)->next = g->allgc; /* return it to 'allgc' list */ + g->allgc = o; + resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ + lua_assert(!isold(o)); /* see MOVE OLD rule */ + if (!keepinvariant(g)) /* not keeping invariant? */ + makewhite(g, o); /* "sweep" object */ + return o; +} + + +static void dothecall (lua_State *L, void *ud) { + UNUSED(ud); + luaD_call(L, L->top - 2, 0, 0); +} + + +static void GCTM (lua_State *L, int propagateerrors) { 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) { + TValue v; + setgcovalue(L, &v, udata2finalize(g)); + tm = luaT_gettmbyobj(L, &v, TM_GC); + if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ + int status; 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); + int running = g->gcrunning; + L->allowhook = 0; /* stop debug hooks during GC metamethod */ + g->gcrunning = 0; /* avoid GC steps */ + setobj2s(L, L->top, tm); /* push finalizer... */ + setobj2s(L, L->top + 1, &v); /* ... and its argument */ + L->top += 2; /* and (next line) call the finalizer */ + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); L->allowhook = oldah; /* restore hooks */ - g->GCthreshold = oldt; /* restore threshold */ + g->gcrunning = running; /* restore state */ + if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ + if (status == LUA_ERRRUN) { /* is there an error msg.? */ + luaO_pushfstring(L, "error in __gc metamethod (%s)", + lua_tostring(L, -1)); + status = LUA_ERRGCMM; /* error in __gc metamethod */ + } + luaD_throw(L, status); /* re-send error */ + } } } /* -** Call all GC tag methods +** move all unreachable objects (or 'all' objects) that need +** finalization from list 'finobj' to list 'tobefnz' (to be finalized) */ -void luaC_callGCTM (lua_State *L) { - while (G(L)->tmudata) - GCTM(L); +static void separatetobefnz (lua_State *L, int all) { + global_State *g = G(L); + GCObject **p = &g->finobj; + GCObject *curr; + GCObject **lastnext = &g->tobefnz; + /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ + while (*lastnext != NULL) + lastnext = &gch(*lastnext)->next; + while ((curr = *p) != NULL) { /* traverse all finalizable objects */ + lua_assert(!isfinalized(curr)); + lua_assert(testbit(gch(curr)->marked, SEPARATED)); + if (!(all || iswhite(curr))) /* not being collected? */ + p = &gch(curr)->next; /* don't bother with it */ + else { + l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ + *p = gch(curr)->next; /* remove 'curr' from 'finobj' list */ + gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ + *lastnext = curr; + lastnext = &gch(curr)->next; + } + } } -void luaC_freeall (lua_State *L) { +/* +** if object 'o' has a finalizer, remove it from 'allgc' list (must +** search the list to find it) and link it in 'finobj' list. +*/ +void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { 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]); + if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ + isfinalized(o) || /* ... or is finalized... */ + gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ + return; /* nothing to be done */ + else { /* move 'o' to 'finobj' list */ + GCObject **p; + for (p = &g->allgc; *p != o; p = &gch(*p)->next) ; + *p = gch(o)->next; /* remove 'o' from root list */ + gch(o)->next = g->finobj; /* link it in list 'finobj' */ + g->finobj = o; + l_setbit(gch(o)->marked, SEPARATED); /* mark it as such */ + resetoldbit(o); /* see MOVE OLD rule */ + } } +/* }====================================================== */ -static void markmt (global_State *g) { - int i; - for (i=0; imt[i]) markobject(g, g->mt[i]); -} +/* +** {====================================================== +** GC control +** ======================================================= +*/ -/* mark root set */ -static void markroot (lua_State *L) { + +#define sweepphases \ + (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) + +/* +** change GC mode +*/ +void luaC_changemode (lua_State *L, int mode) { 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; + if (mode == g->gckind) return; /* nothing to change */ + if (mode == KGC_GEN) { /* change to generational mode */ + /* make sure gray lists are consistent */ + luaC_runtilstate(L, bitmask(GCSpropagate)); + g->lastmajormem = gettotalbytes(g); + g->gckind = KGC_GEN; + } + else { /* change to incremental mode */ + /* sweep all objects to turn them back to white + (as white has not changed, nothing extra will be collected) */ + g->sweepstrgc = 0; + g->gcstate = GCSsweepstring; + g->gckind = KGC_NORMAL; + luaC_runtilstate(L, ~sweepphases); + } } -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); +/* +** call all pending finalizers +*/ +static void callallpendingfinalizers (lua_State *L, int propagateerrors) { + global_State *g = G(L); + while (g->tobefnz) { + resetoldbit(g->tobefnz); + GCTM(L, propagateerrors); } } +void luaC_freeallobjects (lua_State *L) { + global_State *g = G(L); + int i; + separatetobefnz(L, 1); /* separate all objects with finalizers */ + lua_assert(g->finobj == NULL); + callallpendingfinalizers(L, 0); + g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ + g->gckind = KGC_NORMAL; + sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ + sweepwholelist(L, &g->allgc); + for (i = 0; i < g->strt.size; i++) /* free all string lists */ + sweepwholelist(L, &g->strt.hash[i]); + lua_assert(g->strt.nuse == 0); +} + + 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; + GCObject *origweak, *origall; 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; + /* registry and global metatables may be changed by API */ + markvalue(g, &g->l_registry); + markmt(g); /* mark basic metatables */ + /* remark occasional upvalues of (maybe) dead threads */ + remarkupvals(g); + /* traverse objects caught by write barrier and by 'remarkupvals' */ + retraversegrays(g); + convergeephemerons(g); + /* at this point, all strongly accessible objects are marked. */ + /* clear values from weak tables, before checking finalizers */ + clearvalues(g->weak, NULL); + clearvalues(g->allweak, NULL); + origweak = g->weak; origall = g->allweak; + separatetobefnz(L, 0); /* separate objects to be finalized */ + markbeingfnz(g); /* mark userdata that will be finalized */ + propagateall(g); /* remark, to propagate `preserveness' */ + convergeephemerons(g); + /* at this point, all resurrected objects are marked. */ + /* remove dead objects from weak tables */ + clearkeys(g->ephemeron, NULL); /* clear keys from all ephemeron tables */ + clearkeys(g->allweak, NULL); /* clear keys from all allweak tables */ + /* clear values from resurrected weak tables */ + clearvalues(g->weak, origweak); + clearvalues(g->allweak, origall); + g->sweepstrgc = 0; /* prepare to sweep strings */ g->gcstate = GCSsweepstring; - g->estimate = g->totalbytes - udsize; /* first estimate */ + g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ + /*lua_checkmemory(L);*/ } 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; + if (!isgenerational(g)) + markroot(g); /* start a new collection */ + /* in any case, root must be marked */ + lua_assert(!iswhite(obj2gco(g->mainthread)) + && !iswhite(gcvalue(&g->l_registry))); + g->gcstate = GCSpropagate; + return GCROOTCOST; } case GCSpropagate: { if (g->gray) return propagatemark(g); else { /* no more `gray' objects */ - atomic(L); /* finish mark phase */ - return 0; + g->gcstate = GCSatomic; /* finish mark phase */ + atomic(L); + return GCATOMICCOST; } } 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; + if (g->sweepstrgc < g->strt.size) { + sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); + return GCSWEEPCOST; + } + else { /* no more strings to sweep */ + g->sweepgc = &g->finobj; /* prepare to sweep finalizable objects */ + g->gcstate = GCSsweepudata; + return 0; + } } - 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 */ + case GCSsweepudata: { + if (*g->sweepgc) { + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + return GCSWEEPMAX*GCSWEEPCOST; + } + else { + g->sweepgc = &g->allgc; /* go to next phase */ + g->gcstate = GCSsweep; + return GCSWEEPCOST; } - 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; + } + case GCSsweep: { + if (*g->sweepgc) { + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + return GCSWEEPMAX*GCSWEEPCOST; } else { - g->gcstate = GCSpause; /* end collection */ - g->gcdept = 0; - return 0; + /* sweep main thread */ + GCObject *mt = obj2gco(g->mainthread); + sweeplist(L, &mt, 1); + checkSizes(L); + g->gcstate = GCSpause; /* finish collection */ + return GCSWEEPCOST; } } default: lua_assert(0); return 0; @@ -607,105 +1005,99 @@ static l_mem singlestep (lua_State *L) { } -void luaC_step (lua_State *L) { +/* +** advances the garbage collector until it reaches a state allowed +** by 'statemask' +*/ +void luaC_runtilstate (lua_State *L, int statesmask) { 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); - } + while (!testbit(statesmask, g->gcstate)) + singlestep(L); } -void luaC_fullgc (lua_State *L) { +static void generationalcollection (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); + if (g->lastmajormem == 0) { /* signal for another major collection? */ + luaC_fullgc(L, 0); /* perform a full regular collection */ + g->lastmajormem = gettotalbytes(g); /* update control */ } - markroot(L); - while (g->gcstate != GCSpause) { - singlestep(L); + else { + luaC_runtilstate(L, ~bitmask(GCSpause)); /* run complete cycle */ + luaC_runtilstate(L, bitmask(GCSpause)); + if (gettotalbytes(g) > g->lastmajormem/100 * g->gcmajorinc) + g->lastmajormem = 0; /* signal for a major collection */ } - setthreshold(g); + luaE_setdebt(g, stddebt(g)); } -void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { +static void step (lua_State *L) { 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 */ + l_mem lim = g->gcstepmul; /* how much to work */ + do { /* always perform at least one single step */ + lim -= singlestep(L); + } while (lim > 0 && g->gcstate != GCSpause); + if (g->gcstate != GCSpause) + luaE_setdebt(g, g->GCdebt - GCSTEPSIZE); + else + luaE_setdebt(g, stddebt(g)); } -void luaC_barrierback (lua_State *L, Table *t) { +/* +** performs a basic GC step even if the collector is stopped +*/ +void luaC_forcestep (lua_State *L) { 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; + int i; + if (isgenerational(g)) generationalcollection(L); + else step(L); + for (i = 0; i < GCFINALIZENUM && g->tobefnz; i++) + GCTM(L, 1); /* Call a few pending finalizers */ } -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; +/* +** performs a basic GC step only if collector is running +*/ +void luaC_step (lua_State *L) { + if (G(L)->gcrunning) luaC_forcestep(L); } -void luaC_linkupval (lua_State *L, UpVal *uv) { +/* +** performs a full GC cycle; if "isemergency", does not call +** finalizers (which could change stack positions) +*/ +void luaC_fullgc (lua_State *L, int isemergency) { 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); - } + int origkind = g->gckind; + lua_assert(origkind != KGC_EMERGENCY); + if (!isemergency) /* do not run finalizers during emergency GC */ + callallpendingfinalizers(L, 1); + if (keepinvariant(g)) { /* marking phase? */ + /* must sweep all objects to turn them back to white + (as white has not changed, nothing will be collected) */ + g->sweepstrgc = 0; + g->gcstate = GCSsweepstring; + } + g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL; + /* finish any pending sweep phase to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpause)); + /* run entire collector */ + luaC_runtilstate(L, ~bitmask(GCSpause)); + luaC_runtilstate(L, bitmask(GCSpause)); + if (origkind == KGC_GEN) { /* generational mode? */ + /* generational mode must always start in propagate phase */ + luaC_runtilstate(L, bitmask(GCSpropagate)); } + g->gckind = origkind; + luaE_setdebt(g, stddebt(g)); + if (!isemergency) /* do not run finalizers during emergency GC */ + callallpendingfinalizers(L, 1); } +/* }====================================================== */ + + diff --git a/liblua/lgc.h b/liblua/lgc.h index 5a8dc605b3..aa5dfce212 100644 --- a/liblua/lgc.h +++ b/liblua/lgc.h @@ -1,5 +1,5 @@ /* -** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lgc.h,v 2.52 2011/10/03 17:54:25 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -9,65 +9,89 @@ #include "lobject.h" +#include "lstate.h" + +/* +** Collectable objects may have one of three colors: white, which +** means the object is not marked; gray, which means the +** object is marked, but its references may be not marked; and +** black, which means that the object and all its references are marked. +** The main invariant of the garbage collector, while marking objects, +** is that a black object can never point to a white one. Moreover, +** any gray object must be in a "gray list" (gray, grayagain, weak, +** allweak, ephemeron) so that it can be visited again before finishing +** the collection cycle. These lists have no meaning when the invariant +** is not being enforced (e.g., sweep phase). +*/ /* ** Possible states of the Garbage Collector */ -#define GCSpause 0 -#define GCSpropagate 1 +#define GCSpropagate 0 +#define GCSatomic 1 #define GCSsweepstring 2 -#define GCSsweep 3 -#define GCSfinalize 4 +#define GCSsweepudata 3 +#define GCSsweep 4 +#define GCSpause 5 +#define issweepphase(g) \ + (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) + +#define isgenerational(g) ((g)->gckind == KGC_GEN) + /* -** some userful bit tricks +** macro to tell when main invariant (white objects cannot point to black +** ones) must be kept. During a non-generational collection, the sweep +** phase may break the invariant, as objects turned white may point to +** still-black objects. The invariant is restored when sweep ends and +** all objects are white again. During a generational collection, the +** invariant must be kept all times. */ -#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))) - +#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) /* -** 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) +** some useful 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)) + + +/* Layout for bit use in `marked' field: */ +#define WHITE0BIT 0 /* object is white (type 0) */ +#define WHITE1BIT 1 /* object is white (type 1) */ +#define BLACKBIT 2 /* object is black */ +#define FINALIZEDBIT 3 /* object has been separated for finalization */ +#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ +#define FIXEDBIT 5 /* object is fixed (should not be collected) */ +#define OLDBIT 6 /* object is old (only in generational mode) */ +/* bit 7 is currently used by tests (luaL_checkmemory) */ - -#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 iswhite(x) testbits((x)->gch.marked, WHITEBITS) #define isblack(x) testbit((x)->gch.marked, BLACKBIT) -#define isgray(x) (!isblack(x) && !iswhite(x)) +#define isgray(x) /* neither white nor black */ \ + (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) + +#define isold(x) testbit((x)->gch.marked, OLDBIT) + +/* MOVE OLD rule: whenever an object is moved to the beginning of + a GC list, its old bit must be cleared */ +#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) #define otherwhite(g) (g->currentwhite ^ WHITEBITS) -#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) +#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) +#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) @@ -77,34 +101,39 @@ #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_condGC(L,c) \ + {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} +#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),gcvalue(v)); } + luaC_barrier_(L,obj2gco(p),gcvalue(v)); } -#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ - luaC_barrierback(L,t); } +#define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ + luaC_barrierback_(L,p); } #define luaC_objbarrier(L,p,o) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrierf(L,obj2gco(p),obj2gco(o)); } + luaC_barrier_(L,obj2gco(p),obj2gco(o)); } -#define luaC_objbarriert(L,t,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } +#define luaC_objbarrierback(L,p,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } -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); +#define luaC_barrierproto(L,p,c) \ + { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } +LUAI_FUNC void luaC_freeallobjects (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_forcestep (lua_State *L); +LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); +LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); +LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, + GCObject **list, int offset); +LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); +LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); +LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); +LUAI_FUNC void luaC_changemode (lua_State *L, int mode); #endif diff --git a/liblua/liblua.vcxproj b/liblua/liblua.vcxproj index 18823e31a1..a7a2efd46c 100644 --- a/liblua/liblua.vcxproj +++ b/liblua/liblua.vcxproj @@ -94,7 +94,10 @@ + + + @@ -117,15 +120,17 @@ + + - + @@ -140,8 +145,8 @@ - + @@ -153,4 +158,4 @@ - \ No newline at end of file + diff --git a/liblua/linit.c b/liblua/linit.c index c1f90dfab7..8d3aa6576f 100644 --- a/liblua/linit.c +++ b/liblua/linit.c @@ -1,10 +1,18 @@ /* -** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ -** Initialization of libraries for lua.c +** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $ +** Initialization of libraries for lua.c and other clients ** See Copyright Notice in lua.h */ +/* +** If you embed Lua in your program and need to open the standard +** libraries, call luaL_openlibs in your program. If you need a +** different set of libraries, copy this file to your project and edit +** it to suit your needs. +*/ + + #define linit_c #define LUA_LIB @@ -14,25 +22,46 @@ #include "lauxlib.h" -static const luaL_Reg lualibs[] = { - {"", luaopen_base}, +/* +** these libs are loaded by lua.c and are readily available to any Lua +** program +*/ +static const luaL_Reg loadedlibs[] = { + {"_G", luaopen_base}, {LUA_LOADLIBNAME, luaopen_package}, + {LUA_COLIBNAME, luaopen_coroutine}, {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, {LUA_OSLIBNAME, luaopen_os}, {LUA_STRLIBNAME, luaopen_string}, + {LUA_BITLIBNAME, luaopen_bit32}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_DBLIBNAME, luaopen_debug}, {NULL, NULL} }; +/* +** these libs are preloaded and must be required before used +*/ +static const luaL_Reg preloadedlibs[] = { + {NULL, NULL} +}; + + LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib = lualibs; - for (; lib->func; lib++) { + const luaL_Reg *lib; + /* call open functions from 'loadedlibs' and set results to global table */ + for (lib = loadedlibs; lib->func; lib++) { + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); /* remove lib */ + } + /* add open functions from 'preloadedlibs' into 'package.preload' table */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); + for (lib = preloadedlibs; lib->func; lib++) { lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); + lua_setfield(L, -2, lib->name); } + lua_pop(L, 1); /* remove _PRELOAD table */ } diff --git a/liblua/liolib.c b/liblua/liolib.c index e79ed1cb2e..4814aa2c2a 100644 --- a/liblua/liolib.c +++ b/liblua/liolib.c @@ -1,10 +1,20 @@ /* -** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ +** $Id: liolib.c,v 2.108 2011/11/25 12:50:03 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ +/* +** POSIX idiosyncrasy! +** This definition must come before the inclusion of 'stdio.h'; it +** should not affect non-POSIX systems +*/ +#if !defined(_FILE_OFFSET_BITS) +#define _FILE_OFFSET_BITS 64 +#endif + + #include #include #include @@ -20,48 +30,95 @@ -#define IO_INPUT 1 -#define IO_OUTPUT 2 +/* +** {====================================================== +** lua_popen spawns a new process connected to the current +** one through the file streams. +** ======================================================= +*/ + +#if !defined(lua_popen) /* { */ +#if defined(LUA_USE_POPEN) /* { */ -static const char *const fnames[] = {"input", "output"}; +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, pclose(file)) +#elif defined(LUA_WIN) /* }{ */ -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; - } -} +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, _pclose(file)) -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)); -} +#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), -1) + + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + +/* +** {====================================================== +** lua_fseek/lua_ftell: configuration for longer offsets +** ======================================================= +*/ + +#if !defined(lua_fseek) /* { */ + +#if defined(LUA_USE_POSIX) + +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t + +#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ + && defined(_MSC_VER) && (_MSC_VER >= 1400) +/* Windows (but not DDK) and Visual C++ 2005 or higher */ +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 -#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) +#else + +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long + +#endif + +#endif /* } */ + +/* }====================================================== */ + + +#define IO_PREFIX "_IO_" +#define IO_INPUT (IO_PREFIX "input") +#define IO_OUTPUT (IO_PREFIX "output") + + +typedef luaL_Stream LStream; + + +#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + +#define isclosed(p) ((p)->closef == NULL) static int io_type (lua_State *L) { - void *ud; + LStream *p; 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)) + p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); + if (p == NULL) lua_pushnil(L); /* not a file */ - else if (*((FILE **)ud) == NULL) + else if (isclosed(p)) lua_pushliteral(L, "closed file"); else lua_pushliteral(L, "file"); @@ -69,47 +126,59 @@ static int io_type (lua_State *L) { } +static int f_tostring (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", p->f); + return 1; +} + + static FILE *tofile (lua_State *L) { - FILE **f = tofilep(L); - if (*f == NULL) + LStream *p = tolstream(L); + if (isclosed(p)) luaL_error(L, "attempt to use a closed file"); - return *f; + lua_assert(p->f); + return p->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; +static LStream *newprefile (lua_State *L) { + LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); + p->closef = NULL; /* mark file handle as 'closed' */ + luaL_setmetatable(L, LUA_FILEHANDLE); + return p; } -/* -** 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; +static int aux_close (lua_State *L) { + LStream *p = tolstream(L); + lua_CFunction cf = p->closef; + p->closef = NULL; /* mark stream as closed */ + return (*cf)(L); /* close it */ } -/* -** 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); +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) /* no argument? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ + tofile(L); /* make sure argument is an open stream */ + return aux_close(L); +} + + +static int f_gc (lua_State *L) { + LStream *p = tolstream(L); + if (!isclosed(p) && p->f != NULL) + aux_close(L); /* ignore closed and incompletely open files */ + return 0; } @@ -117,103 +186,94 @@ static int io_pclose (lua_State *L) { ** 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); + LStream *p = tolstream(L); + int res = fclose(p->f); + return luaL_fileresult(L, (res == 0), NULL); } -static int io_gc (lua_State *L) { - FILE *f = *tofilep(L); - /* ignore closed files */ - if (f != NULL) - aux_close(L); - return 0; +static LStream *newfile (lua_State *L) { + LStream *p = newprefile(L); + p->f = NULL; + p->closef = &io_fclose; + return p; } -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 void opencheck (lua_State *L, const char *fname, const char *mode) { + LStream *p = newfile(L); + p->f = fopen(fname, mode); + if (p->f == NULL) + luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); } 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; + LStream *p = newfile(L); + int i = 0; + /* check whether 'mode' matches '[rwa]%+?b?' */ + if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != NULL && + (mode[i] != '+' || ++i) && /* skip if char is '+' */ + (mode[i] != 'b' || ++i) && /* skip if char is 'b' */ + (mode[i] == '\0'))) + return luaL_error(L, "invalid mode " LUA_QS + " (should match " LUA_QL("[rwa]%%+?b?") ")", mode); + p->f = fopen(filename, mode); + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; } /* -** this function has a separated environment, which defines the -** correct __close for 'popen' files +** function to close 'popen' files */ +static int io_pclose (lua_State *L) { + LStream *p = tolstream(L); + return luaL_execresult(L, lua_pclose(L, p->f)); +} + + 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; + LStream *p = newprefile(L); + p->f = lua_popen(L, filename, mode); + p->closef = &io_pclose; + return (p->f == NULL) ? luaL_fileresult(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; + LStream *p = newfile(L); + p->f = tmpfile(); + return (p->f == NULL) ? luaL_fileresult(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 FILE *getiofile (lua_State *L, const char *findex) { + LStream *p; + lua_getfield(L, LUA_REGISTRYINDEX, findex); + p = (LStream *)lua_touserdata(L, -1); + if (isclosed(p)) + luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX)); + return p->f; } -static int g_iofile (lua_State *L, int f, const char *mode) { +static int g_iofile (lua_State *L, const char *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); - } + if (filename) + opencheck(L, filename, mode); else { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); } - lua_rawseti(L, LUA_ENVIRONINDEX, f); + lua_setfield(L, LUA_REGISTRYINDEX, f); } /* return current value */ - lua_rawgeti(L, LUA_ENVIRONINDEX, f); + lua_getfield(L, LUA_REGISTRYINDEX, f); return 1; } @@ -231,35 +291,43 @@ static int io_output (lua_State *L) { static int io_readline (lua_State *L); -static void aux_lines (lua_State *L, int idx, int toclose) { - lua_pushvalue(L, idx); +static void aux_lines (lua_State *L, int toclose) { + int i; + int n = lua_gettop(L) - 1; /* number of arguments to read */ + /* ensure that arguments will fit here and into 'io_readline' stack */ + luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options"); + lua_pushvalue(L, 1); /* file handle */ + lua_pushinteger(L, n); /* number of arguments to read */ lua_pushboolean(L, toclose); /* close/not close file when finished */ - lua_pushcclosure(L, io_readline, 2); + for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */ + lua_pushcclosure(L, io_readline, 3 + n); } static int f_lines (lua_State *L) { tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 1, 0); + aux_lines(L, 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); + int toclose; + if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ + if (lua_isnil(L, 1)) { /* no file name? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ + lua_replace(L, 1); /* put it at index 1 */ + tofile(L); /* check that it's a valid file handle */ + toclose = 0; /* do not close it after iteration */ } - else { + else { /* open a new file */ 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; + opencheck(L, filename, "r"); + lua_replace(L, 1); /* put file at index 1 */ + toclose = 1; /* close it after iteration */ } + aux_lines(L, toclose); + return 1; } @@ -276,7 +344,10 @@ static int read_number (lua_State *L, FILE *f) { lua_pushnumber(L, d); return 1; } - else return 0; /* read fails */ + else { + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } } @@ -288,7 +359,7 @@ static int test_eof (lua_State *L, FILE *f) { } -static int read_line (lua_State *L, FILE *f) { +static int read_line (lua_State *L, FILE *f, int chop) { luaL_Buffer b; luaL_buffinit(L, &b); for (;;) { @@ -296,13 +367,13 @@ static int read_line (lua_State *L, FILE *f) { 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 */ + return (lua_rawlen(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_addsize(&b, l - chop); /* chop 'eol' if needed */ luaL_pushresult(&b); /* close buffer */ return 1; /* read at least an `eol' */ } @@ -310,21 +381,34 @@ static int read_line (lua_State *L, FILE *f) { } +#define MAX_SIZE_T (~(size_t)0) + +static void read_all (lua_State *L, FILE *f) { + size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + char *p = luaL_prepbuffsize(&b, rlen); + size_t nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + if (nr < rlen) break; /* eof? */ + else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ + rlen *= 2; /* double buffer size at each iteration */ + } + luaL_pushresult(&b); /* close buffer */ +} + + 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 */ + char *p; 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 */ + p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ + nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ + luaL_addsize(&b, nr); luaL_pushresult(&b); /* close buffer */ - return (n == 0 || lua_objlen(L, -1) > 0); + return (nr > 0); /* true iff read something */ } @@ -334,7 +418,7 @@ static int g_read (lua_State *L, FILE *f, int first) { int n; clearerr(f); if (nargs == 0) { /* no arguments? */ - success = read_line(L, f); + success = read_line(L, f, 1); n = first+1; /* to return 1 result */ } else { /* ensure stack space for all results and for auxlib's buffer */ @@ -353,10 +437,13 @@ static int g_read (lua_State *L, FILE *f, int first) { success = read_number(L, f); break; case 'l': /* line */ - success = read_line(L, f); + success = read_line(L, f, 1); + break; + case 'L': /* line with end-of-line */ + success = read_line(L, f, 0); break; case 'a': /* file */ - read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + read_all(L, f); /* read entire file */ success = 1; /* always success */ break; default: @@ -366,7 +453,7 @@ static int g_read (lua_State *L, FILE *f, int first) { } } if (ferror(f)) - return pushresult(L, 0, NULL); + return luaL_fileresult(L, 0, NULL); if (!success) { lua_pop(L, 1); /* remove last result */ lua_pushnil(L); /* push nil instead */ @@ -386,16 +473,24 @@ static int f_read (lua_State *L) { 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? */ + LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); + int i; + int n = (int)lua_tointeger(L, lua_upvalueindex(2)); + if (isclosed(p)) /* file is already closed? */ + return luaL_error(L, "file is already closed"); + lua_settop(L , 1); + for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ + lua_pushvalue(L, lua_upvalueindex(3 + i)); + n = g_read(L, p->f, 2); /* 'n' is number of results */ + lua_assert(n > 0); /* should return at least a nil */ + if (!lua_isnil(L, -n)) /* read at least one value? */ + return n; /* return them */ + else { /* first result is nil: EOF or error */ + if (n > 1) { /* is there error information? */ + /* 2nd result is error message */ + return luaL_error(L, "%s", lua_tostring(L, -n + 1)); + } + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ lua_settop(L, 0); lua_pushvalue(L, lua_upvalueindex(1)); aux_close(L); /* close it */ @@ -408,7 +503,7 @@ static int io_readline (lua_State *L) { static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - 1; + int nargs = lua_gettop(L) - arg; int status = 1; for (; nargs--; arg++) { if (lua_type(L, arg) == LUA_TNUMBER) { @@ -422,7 +517,8 @@ static int g_write (lua_State *L, FILE *f, int arg) { status = status && (fwrite(s, sizeof(char), l, f) == l); } } - return pushresult(L, status, NULL); + if (status) return 1; /* file handle already on stack top */ + else return luaL_fileresult(L, status, NULL); } @@ -432,7 +528,9 @@ static int io_write (lua_State *L) { static int f_write (lua_State *L) { - return g_write(L, tofile(L), 2); + FILE *f = tofile(L); + lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ + return g_write(L, f, 2); } @@ -441,12 +539,15 @@ static int f_seek (lua_State *L) { 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]); + lua_Number p3 = luaL_optnumber(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Number)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); if (op) - return pushresult(L, 0, NULL); /* error */ + return luaL_fileresult(L, 0, NULL); /* error */ else { - lua_pushinteger(L, ftell(f)); + lua_pushnumber(L, (lua_Number)l_ftell(f)); return 1; } } @@ -459,21 +560,24 @@ static int f_setvbuf (lua_State *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); + return luaL_fileresult(L, res == 0, NULL); } static int io_flush (lua_State *L) { - return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); + return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); } static int f_flush (lua_State *L) { - return pushresult(L, fflush(tofile(L)) == 0, NULL); + return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); } +/* +** functions for 'io' library +*/ static const luaL_Reg iolib[] = { {"close", io_close}, {"flush", io_flush}, @@ -490,6 +594,9 @@ static const luaL_Reg iolib[] = { }; +/* +** methods for file handles +*/ static const luaL_Reg flib[] = { {"close", io_close}, {"flush", f_flush}, @@ -498,8 +605,8 @@ static const luaL_Reg flib[] = { {"seek", f_seek}, {"setvbuf", f_setvbuf}, {"write", f_write}, - {"__gc", io_gc}, - {"__tostring", io_tostring}, + {"__gc", f_gc}, + {"__tostring", f_tostring}, {NULL, NULL} }; @@ -508,46 +615,43 @@ 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 */ + luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ + lua_pop(L, 1); /* pop new metatable */ } -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); +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + LStream *p = tolstream(L); + p->closef = &io_noclose; /* keep file opened */ + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; } -static void newfenv (lua_State *L, lua_CFunction cls) { - lua_createtable(L, 0, 1); - lua_pushcfunction(L, cls); - lua_setfield(L, -2, "__close"); +static void createstdfile (lua_State *L, FILE *f, const char *k, + const char *fname) { + LStream *p = newprefile(L); + p->f = f; + p->closef = &io_noclose; + if (k != NULL) { + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ + } + lua_setfield(L, -2, fname); /* add file to module */ } -LUALIB_API int luaopen_io (lua_State *L) { +LUAMOD_API int luaopen_io (lua_State *L) { + luaL_newlib(L, iolib); /* new module */ 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' */ + createstdfile(L, stderr, NULL, "stderr"); return 1; } diff --git a/liblua/llex.c b/liblua/llex.c index 6dc319358c..74deebb930 100644 --- a/liblua/llex.c +++ b/liblua/llex.c @@ -1,11 +1,10 @@ /* -** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: llex.c,v 2.59 2011/11/30 12:43:51 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ -#include #include #include @@ -14,6 +13,7 @@ #include "lua.h" +#include "lctype.h" #include "ldo.h" #include "llex.h" #include "lobject.h" @@ -29,35 +29,36 @@ - #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') /* ORDER RESERVED */ -const char *const luaX_tokens [] = { +static const char *const luaX_tokens [] = { "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "if", + "end", "false", "for", "function", "goto", "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 l_noret lexerror (LexState *ls, const char *msg, int token); + + static void save (LexState *ls, int c) { Mbuffer *b = ls->buff; - if (b->n + 1 > b->buffsize) { + if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { size_t newsize; - if (b->buffsize >= MAX_SIZET/2) - luaX_lexerror(ls, "lexical element too long", 0); - newsize = b->buffsize * 2; + if (luaZ_sizebuffer(b) >= MAX_SIZET/2) + lexerror(ls, "lexical element too long", 0); + newsize = luaZ_sizebuffer(b) * 2; luaZ_resizebuffer(ls->L, b, newsize); } - b->buffer[b->n++] = cast(char, c); + b->buffer[luaZ_bufflen(b)++] = cast(char, c); } @@ -66,23 +67,24 @@ void luaX_init (lua_State *L) { 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); + return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) : + luaO_pushfstring(ls->L, "char(%d)", token); + } + else { + const char *s = luaX_tokens[token - FIRST_RESERVED]; + if (token < TK_EOS) + return luaO_pushfstring(ls->L, LUA_QS, s); + else + return s; } - else - return luaX_tokens[token-FIRST_RESERVED]; } @@ -92,38 +94,54 @@ static const char *txtToken (LexState *ls, int token) { case TK_STRING: case TK_NUMBER: save(ls, '\0'); - return luaZ_buffer(ls->buff); + return luaO_pushfstring(ls->L, LUA_QS, 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); +static l_noret lexerror (LexState *ls, const char *msg, int token) { + char buff[LUA_IDSIZE]; + luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); 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)); + luaO_pushfstring(ls->L, "%s near %s", 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); +l_noret luaX_syntaxerror (LexState *ls, const char *msg) { + lexerror(ls, msg, ls->t.token); } +/* +** creates a new string and anchors it in function's table so that +** it will not be collected until the end of the function's compilation +** (by that time it should be anchored in function's prototype) +*/ 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 */ + TValue *o; /* entry for `str' */ + TString *ts = luaS_newlstr(L, str, l); /* create new string */ + setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ + o = luaH_set(L, ls->fs->h, L->top - 1); + if (ttisnil(o)) { /* not in use yet? (see 'addK') */ + /* boolean value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setbvalue(o, 1); /* t[string] = true */ + luaC_checkGC(L); + } + L->top--; /* remove string from stack */ return ts; } +/* +** increment line number and skips newline sequence (any of +** \n, \r, \n\r, or \r\n) +*/ static void inclinenumber (LexState *ls) { int old = ls->current; lua_assert(currIsNewline(ls)); @@ -135,17 +153,20 @@ static void inclinenumber (LexState *ls) { } -void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, + int firstchar) { ls->decpoint = '.'; ls->L = L; + ls->current = firstchar; ls->lookahead.token = TK_EOS; /* no look-ahead token */ ls->z = z; ls->fs = NULL; ls->linenumber = 1; ls->lastline = 1; ls->source = source; + ls->envn = luaS_new(L, LUA_ENV); /* create env name */ + luaS_fix(ls->envn); /* never collect this name */ luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ - next(ls); /* read first char */ } @@ -159,13 +180,16 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { static int check_next (LexState *ls, const char *set) { - if (!strchr(set, ls->current)) + if (ls->current == '\0' || !strchr(set, ls->current)) return 0; save_and_next(ls); return 1; } +/* +** change all characters 'from' in buffer to 'to' +*/ static void buffreplace (LexState *ls, char from, char to) { size_t n = luaZ_bufflen(ls->buff); char *p = luaZ_buffer(ls->buff); @@ -174,37 +198,48 @@ static void buffreplace (LexState *ls, char from, char to) { } +#if !defined(getlocaledecpoint) +#define getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + + +#define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e) + +/* +** in case of format error, try to change decimal point separator to +** the one defined in the current locale and check again +*/ 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)) { + ls->decpoint = getlocaledecpoint(); + buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ + if (!buff2d(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); + lexerror(ls, "malformed number", TK_NUMBER); } } /* LUA_NUMBER */ static void read_numeral (LexState *ls, SemInfo *seminfo) { - lua_assert(isdigit(ls->current)); + lua_assert(lisdigit(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); + if (check_next(ls, "EePp")) /* exponent part? */ + check_next(ls, "+-"); /* optional exponent sign */ + } while (lislalnum(ls->current) || ls->current == '.'); save(ls, '\0'); buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ - if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ + if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ trydecpoint(ls, seminfo); /* try to update decimal point separator */ } +/* +** skip a sequence '[=*[' or ']=*]' and return its number of '='s or +** -1 if sequence is malformed +*/ static int skip_sep (LexState *ls) { int count = 0; int s = ls->current; @@ -219,43 +254,23 @@ static int skip_sep (LexState *ls) { 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); + 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': { + case '\n': case '\r': { save(ls, '\n'); inclinenumber(ls); if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ @@ -273,51 +288,91 @@ static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { } +static void escerror (LexState *ls, int *c, int n, const char *msg) { + int i; + luaZ_resetbuffer(ls->buff); /* prepare error message */ + save(ls, '\\'); + for (i = 0; i < n && c[i] != EOZ; i++) + save(ls, c[i]); + lexerror(ls, msg, TK_STRING); +} + + +static int readhexaesc (LexState *ls) { + int c[3], i; /* keep input for error message */ + int r = 0; /* result accumulator */ + c[0] = 'x'; /* for error message */ + for (i = 1; i < 3; i++) { /* read two hexa digits */ + c[i] = next(ls); + if (!lisxdigit(c[i])) + escerror(ls, c, i + 1, "hexadecimal digit expected"); + r = (r << 4) + luaO_hexavalue(c[i]); + } + return r; +} + + +static int readdecesc (LexState *ls) { + int c[3], i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ + c[i] = ls->current; + r = 10*r + c[i] - '0'; + next(ls); + } + if (r > UCHAR_MAX) + escerror(ls, c, i, "decimal escape too large"); + return r; +} + + static void read_string (LexState *ls, int del, SemInfo *seminfo) { - save_and_next(ls); + save_and_next(ls); /* keep delimiter (for error messages) */ while (ls->current != del) { switch (ls->current) { case EOZ: - luaX_lexerror(ls, "unfinished string", TK_EOS); - continue; /* to avoid warnings */ + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ case '\n': case '\r': - luaX_lexerror(ls, "unfinished string", TK_STRING); - continue; /* to avoid warnings */ - case '\\': { - int c; + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': { /* escape sequences */ + int c; /* final character to be saved */ 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); + case 'a': c = '\a'; goto read_save; + case 'b': c = '\b'; goto read_save; + case 'f': c = '\f'; goto read_save; + case 'n': c = '\n'; goto read_save; + case 'r': c = '\r'; goto read_save; + case 't': c = '\t'; goto read_save; + case 'v': c = '\v'; goto read_save; + case 'x': c = readhexaesc(ls); goto read_save; + case '\n': case '\r': + inclinenumber(ls); c = '\n'; goto only_save; + case '\\': case '\"': case '\'': + c = ls->current; goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + next(ls); /* skip the 'z' */ + while (lisspace(ls->current)) { + if (currIsNewline(ls)) inclinenumber(ls); + else next(ls); } - continue; + goto no_save; + } + default: { + if (!lisdigit(ls->current)) + escerror(ls, &ls->current, 1, "invalid escape sequence"); + /* digital escape \ddd */ + c = readdecesc(ls); + goto only_save; } } - save(ls, c); - next(ls); - continue; + read_save: next(ls); /* read next character */ + only_save: save(ls, c); /* save 'c' */ + no_save: break; } default: save_and_next(ls); @@ -333,38 +388,41 @@ static int llex (LexState *ls, SemInfo *seminfo) { luaZ_resetbuffer(ls->buff); for (;;) { switch (ls->current) { - case '\n': - case '\r': { + case '\n': case '\r': { /* line breaks */ inclinenumber(ls); - continue; + break; } - case '-': { + case ' ': case '\f': case '\t': case '\v': { /* spaces */ + next(ls); + break; + } + case '-': { /* '-' or '--' (comment) */ next(ls); if (ls->current != '-') return '-'; /* else is a comment */ next(ls); - if (ls->current == '[') { + if (ls->current == '[') { /* long comment? */ 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; + read_long_string(ls, NULL, sep); /* skip long comment */ + luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ + break; } } /* else short comment */ while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); - continue; + next(ls); /* skip until end of line (or end of file) */ + break; } - case '[': { + case '[': { /* long string or simply '[' */ 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); + else lexerror(ls, "invalid long string delimiter", TK_STRING); } case '=': { next(ls); @@ -386,56 +444,52 @@ static int llex (LexState *ls, SemInfo *seminfo) { if (ls->current != '=') return '~'; else { next(ls); return TK_NE; } } - case '"': - case '\'': { + case ':': { + next(ls); + if (ls->current != ':') return ':'; + else { next(ls); return TK_DBCOLON; } + } + case '"': case '\'': { /* short literal strings */ read_string(ls, ls->current, seminfo); return TK_STRING; } - case '.': { + case '.': { /* '.', '..', '...', or number */ 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; + return TK_DOTS; /* '...' */ + else return TK_CONCAT; /* '..' */ } + else if (!lisdigit(ls->current)) return '.'; + /* else go through */ + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + 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 */ + if (lislalpha(ls->current)) { /* identifier or reserved word? */ TString *ts; do { save_and_next(ls); - } while (isalnum(ls->current) || ls->current == '_'); + } while (lislalnum(ls->current)); ts = luaX_newstring(ls, luaZ_buffer(ls->buff), luaZ_bufflen(ls->buff)); + seminfo->ts = ts; if (ts->tsv.reserved > 0) /* reserved word? */ return ts->tsv.reserved - 1 + FIRST_RESERVED; else { - seminfo->ts = ts; return TK_NAME; } } - else { + else { /* single-char tokens (+ - / ...) */ int c = ls->current; next(ls); - return c; /* single-char tokens (+ - / ...) */ + return c; } } } @@ -454,8 +508,9 @@ void luaX_next (LexState *ls) { } -void luaX_lookahead (LexState *ls) { +int luaX_lookahead (LexState *ls) { lua_assert(ls->lookahead.token == TK_EOS); ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; } diff --git a/liblua/llex.h b/liblua/llex.h index a9201cee48..9ca8a29948 100644 --- a/liblua/llex.h +++ b/liblua/llex.h @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: llex.h,v 1.72 2011/11/30 12:43:51 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -13,8 +13,6 @@ #define FIRST_RESERVED 257 -/* maximum length of a reserved word */ -#define TOKEN_LEN (sizeof("function")/sizeof(char)) /* @@ -25,21 +23,17 @@ 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_GOTO, 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 + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS, + TK_NUMBER, TK_NAME, TK_STRING }; /* 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; @@ -52,29 +46,32 @@ typedef struct Token { } Token; +/* state of the lexer plus state of the parser when shared by all + functions */ 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 FuncState *fs; /* current function (parser) */ struct lua_State *L; ZIO *z; /* input stream */ Mbuffer *buff; /* buffer for tokens */ + struct Dyndata *dyd; /* dynamic structures used by the parser */ TString *source; /* current source name */ + TString *envn; /* environment variable 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); + TString *source, int firstchar); 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 int luaX_lookahead (LexState *ls); +LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); diff --git a/liblua/llimits.h b/liblua/llimits.h index ca8dcb7224..48dc81f760 100644 --- a/liblua/llimits.h +++ b/liblua/llimits.h @@ -1,5 +1,5 @@ /* -** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: llimits.h,v 1.95 2011/12/06 16:58:36 roberto Exp $ ** Limits, basic types, and some other `installation-dependent' definitions ** See Copyright Notice in lua.h */ @@ -15,7 +15,7 @@ #include "lua.h" -typedef LUAI_UINT32 lu_int32; +typedef unsigned LUA_INT32 lu_int32; typedef LUAI_UMEM lu_mem; @@ -44,6 +44,10 @@ typedef unsigned char lu_byte; /* type to ensure maximum alignment */ +#if !defined(LUAI_USER_ALIGNMENT_T) +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } +#endif + typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; @@ -52,35 +56,74 @@ typedef LUAI_UACNUMBER l_uacNumber; /* internal assertions for in-house debugging */ -#ifdef lua_assert - +#if defined(lua_assert) #define check_exp(c,e) (lua_assert(c), (e)) -#define api_check(l,e) lua_assert(e) - +/* to avoid problems with conditions too long */ +#define lua_longassert(c) { if (!(c)) lua_assert(0); } #else - #define lua_assert(c) ((void)0) #define check_exp(c,e) (e) -#define api_check luai_apicheck +#define lua_longassert(c) ((void)0) +#endif +/* +** assertion for checking API calls +*/ +#if !defined(luai_apicheck) + +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(L,e) assert(e) +#else +#define luai_apicheck(L,e) lua_assert(e) #endif +#endif -#ifndef UNUSED +#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) + + +#if !defined(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)) +#define cast_uchar(i) cast(unsigned char, (i)) + + +/* +** non-return type +*/ +#if defined(__GNUC__) +#define l_noret void __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define l_noret void __declspec(noreturn) +#else +#define l_noret void +#endif +/* +** maximum depth for nested C calls and syntactical nested non-terminals +** in a program. (Value must fit in an unsigned short int.) +*/ +#if !defined(LUAI_MAXCCALLS) +#define LUAI_MAXCCALLS 200 +#endif + +/* +** maximum number of upvalues in a closure (both C and Lua). (Value +** must fit in an unsigned char.) +*/ +#define MAXUPVAL UCHAR_MAX + + /* ** type for virtual-machine instructions ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) @@ -95,34 +138,165 @@ typedef lu_int32 Instruction; /* minimum size for the string table (must be power of 2) */ -#ifndef MINSTRTABSIZE +#if !defined(MINSTRTABSIZE) #define MINSTRTABSIZE 32 #endif /* minimum size for string buffer */ -#ifndef LUA_MINBUFFER +#if !defined(LUA_MINBUFFER) #define LUA_MINBUFFER 32 #endif -#ifndef lua_lock -#define lua_lock(L) ((void) 0) +#if !defined(lua_lock) +#define lua_lock(L) ((void) 0) #define lua_unlock(L) ((void) 0) #endif -#ifndef luai_threadyield +#if !defined(luai_threadyield) #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} #endif +/* +** these macros allow user-specific actions on threads when you defined +** LUAI_EXTRASPACE and need to do something extra when a thread is +** created/deleted/resumed/yielded. +*/ +#if !defined(luai_userstateopen) +#define luai_userstateopen(L) ((void)L) +#endif + +#if !defined(luai_userstateclose) +#define luai_userstateclose(L) ((void)L) +#endif + +#if !defined(luai_userstatethread) +#define luai_userstatethread(L,L1) ((void)L) +#endif + +#if !defined(luai_userstatefree) +#define luai_userstatefree(L,L1) ((void)L) +#endif + +#if !defined(luai_userstateresume) +#define luai_userstateresume(L,n) ((void)L) +#endif + +#if !defined(luai_userstateyield) +#define luai_userstateyield(L,n) ((void)L) +#endif + +/* +** lua_number2int is a macro to convert lua_Number to int. +** lua_number2integer is a macro to convert lua_Number to lua_Integer. +** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned. +** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number. +** luai_hashnum is a macro to hash a lua_Number value into an integer. +** The hash must be deterministic and give reasonable values for +** both small and large values (outside the range of integers). +*/ + +#if defined(MS_ASMTRICK) /* { */ +/* trick with Microsoft assembler for X86 */ + +#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i} +#define lua_number2integer(i,n) lua_number2int(i, n) +#define lua_number2unsigned(i,n) \ + {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} + + +#elif defined(LUA_IEEE754TRICK) /* }{ */ +/* the next trick should work on any machine using IEEE754 with + a 32-bit integer type */ + +union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; + +#if !defined(LUA_IEEEENDIAN) /* { */ +#define LUAI_EXTRAIEEE \ + static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; +#define LUA_IEEEENDIAN (ieeeendian.l_p[1] == 33) +#else +#define LUAI_EXTRAIEEE /* empty */ +#endif /* } */ + +#define lua_number2int32(i,n,t) \ + { LUAI_EXTRAIEEE \ + volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ + (i) = (t)u.l_p[LUA_IEEEENDIAN]; } + +#define luai_hashnum(i,n) \ + { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \ + (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */ + +#define lua_number2int(i,n) lua_number2int32(i, n, int) +#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) +#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) + +#endif /* } */ + + +/* the following definitions always work, but may be slow */ + +#if !defined(lua_number2int) +#define lua_number2int(i,n) ((i)=(int)(n)) +#endif + +#if !defined(lua_number2integer) +#define lua_number2integer(i,n) ((i)=(lua_Integer)(n)) +#endif + +#if !defined(lua_number2unsigned) /* { */ +/* the following definition assures proper modulo behavior */ +#if defined(LUA_NUMBER_DOUBLE) +#include +#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) +#define lua_number2unsigned(i,n) \ + ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) +#else +#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) +#endif +#endif /* } */ + + +#if !defined(lua_unsigned2number) +/* on several machines, coercion from unsigned to double is slow, + so it may be worth to avoid */ +#define lua_unsigned2number(u) \ + (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) +#endif + + + +#if defined(ltable_c) && !defined(luai_hashnum) + +#include +#include + +#define luai_hashnum(i,n) { int e; \ + n = frexp(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \ + lua_number2int(i, n); i += e; } + +#endif + + + /* ** macro to control inclusion of some hard tests on stack reallocation -*/ -#ifndef HARDSTACKTESTS -#define condhardstacktests(x) ((void)0) +*/ +#if !defined(HARDSTACKTESTS) +#define condmovestack(L) ((void)0) +#else +/* realloc stack keeping its size */ +#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) +#endif + +#if !defined(HARDMEMTESTS) +#define condchangemem(L) condmovestack(L) #else -#define condhardstacktests(x) x +#define condchangemem(L) \ + ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) #endif #endif diff --git a/liblua/lmathlib.c b/liblua/lmathlib.c index 441fbf736c..b17237f0b0 100644 --- a/liblua/lmathlib.c +++ b/liblua/lmathlib.c @@ -1,5 +1,5 @@ /* -** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lmathlib.c,v 1.80 2011/07/05 12:49:35 roberto Exp $ ** Standard mathematical library ** See Copyright Notice in lua.h */ @@ -22,107 +22,127 @@ #define RADIANS_PER_DEGREE (PI/180.0) +/* macro 'l_tg' allows the addition of an 'l' or 'f' to all math operations */ +#if !defined(l_tg) +#define l_tg(x) (x) +#endif + + static int math_abs (lua_State *L) { - lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(fabs)(luaL_checknumber(L, 1))); return 1; } static int math_sin (lua_State *L) { - lua_pushnumber(L, sin(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(sin)(luaL_checknumber(L, 1))); return 1; } static int math_sinh (lua_State *L) { - lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(sinh)(luaL_checknumber(L, 1))); return 1; } static int math_cos (lua_State *L) { - lua_pushnumber(L, cos(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(cos)(luaL_checknumber(L, 1))); return 1; } static int math_cosh (lua_State *L) { - lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(cosh)(luaL_checknumber(L, 1))); return 1; } static int math_tan (lua_State *L) { - lua_pushnumber(L, tan(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(tan)(luaL_checknumber(L, 1))); return 1; } static int math_tanh (lua_State *L) { - lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(tanh)(luaL_checknumber(L, 1))); return 1; } static int math_asin (lua_State *L) { - lua_pushnumber(L, asin(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(asin)(luaL_checknumber(L, 1))); return 1; } static int math_acos (lua_State *L) { - lua_pushnumber(L, acos(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(acos)(luaL_checknumber(L, 1))); return 1; } static int math_atan (lua_State *L) { - lua_pushnumber(L, atan(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(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))); + lua_pushnumber(L, l_tg(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))); + lua_pushnumber(L, l_tg(ceil)(luaL_checknumber(L, 1))); return 1; } static int math_floor (lua_State *L) { - lua_pushnumber(L, floor(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(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))); + lua_pushnumber(L, l_tg(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_Number ip; + lua_Number fp = l_tg(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))); + lua_pushnumber(L, l_tg(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))); + lua_pushnumber(L, l_tg(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))); + lua_Number x = luaL_checknumber(L, 1); + lua_Number res; + if (lua_isnoneornil(L, 2)) + res = l_tg(log)(x); + else { + lua_Number base = luaL_checknumber(L, 2); + if (base == 10.0) res = l_tg(log10)(x); + else res = l_tg(log)(x)/l_tg(log)(base); + } + lua_pushnumber(L, res); return 1; } +#if defined(LUA_COMPAT_LOG10) static int math_log10 (lua_State *L) { - lua_pushnumber(L, log10(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(log10)(luaL_checknumber(L, 1))); return 1; } +#endif static int math_exp (lua_State *L) { - lua_pushnumber(L, exp(luaL_checknumber(L, 1))); + lua_pushnumber(L, l_tg(exp)(luaL_checknumber(L, 1))); return 1; } @@ -138,13 +158,14 @@ static int math_rad (lua_State *L) { static int math_frexp (lua_State *L) { int e; - lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); + lua_pushnumber(L, l_tg(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))); + lua_pushnumber(L, l_tg(ldexp)(luaL_checknumber(L, 1), + luaL_checkint(L, 2))); return 1; } @@ -188,16 +209,16 @@ static int math_random (lua_State *L) { 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' */ + lua_Number u = luaL_checknumber(L, 1); + luaL_argcheck(L, 1.0 <= u, 1, "interval is empty"); + lua_pushnumber(L, l_tg(floor)(r*u) + 1.0); /* int in [1, 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' */ + lua_Number l = luaL_checknumber(L, 1); + lua_Number u = luaL_checknumber(L, 2); + luaL_argcheck(L, l <= u, 2, "interval is empty"); + lua_pushnumber(L, l_tg(floor)(r*(u-l+1)) + l); /* int in [l, u] */ break; } default: return luaL_error(L, "wrong number of arguments"); @@ -207,7 +228,8 @@ static int math_random (lua_State *L) { static int math_randomseed (lua_State *L) { - srand(luaL_checkint(L, 1)); + srand(luaL_checkunsigned(L, 1)); + (void)rand(); /* discard first value to avoid undesirable correlations */ return 0; } @@ -227,7 +249,9 @@ static const luaL_Reg mathlib[] = { {"fmod", math_fmod}, {"frexp", math_frexp}, {"ldexp", math_ldexp}, +#if defined(LUA_COMPAT_LOG10) {"log10", math_log10}, +#endif {"log", math_log}, {"max", math_max}, {"min", math_min}, @@ -248,16 +272,12 @@ static const luaL_Reg mathlib[] = { /* ** Open math library */ -LUALIB_API int luaopen_math (lua_State *L) { - luaL_register(L, LUA_MATHLIBNAME, mathlib); +LUAMOD_API int luaopen_math (lua_State *L) { + luaL_newlib(L, 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/liblua/lmem.c b/liblua/lmem.c index ae7d8c965f..792deb3cfc 100644 --- a/liblua/lmem.c +++ b/liblua/lmem.c @@ -1,5 +1,5 @@ /* -** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lmem.c,v 1.83 2011/11/30 12:42:49 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -14,6 +14,7 @@ #include "ldebug.h" #include "ldo.h" +#include "lgc.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" @@ -25,12 +26,11 @@ ** 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, NULL, x, s) creates a new block of size `s' (no +** matter 'x'). ** ** * frealloc(ud, p, x, 0) frees the block `p' -** (in this specific case, frealloc must return NULL). +** (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) ** @@ -44,12 +44,12 @@ void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, - int limit, const char *errormsg) { + int limit, const char *what) { void *newblock; int newsize; if (*size >= limit/2) { /* cannot double it? */ if (*size >= limit) /* cannot grow even a little? */ - luaG_runerror(L, errormsg); + luaG_runerror(L, "too many %s (limit is %d)", what, limit); newsize = limit; /* still have at least one free place */ } else { @@ -63,9 +63,8 @@ void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, } -void *luaM_toobig (lua_State *L) { +l_noret luaM_toobig (lua_State *L) { luaG_runerror(L, "memory allocation error: block too big"); - return NULL; /* to avoid warnings */ } @@ -74,13 +73,43 @@ void *luaM_toobig (lua_State *L) { ** generic allocation routine. */ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + void *newblock; 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; + size_t realosize = (block) ? osize : 0; + lua_assert((realosize == 0) == (block == NULL)); +#if defined(HARDMEMTESTS) + if (nsize > realosize && g->gcrunning) + luaC_fullgc(L, 1); /* force a GC whenever possible */ +#endif + newblock = (*g->frealloc)(g->ud, block, osize, nsize); + if (newblock == NULL && nsize > 0) { + api_check(L, nsize > realosize, + "realloc cannot fail when shrinking a block"); + if (g->gcrunning) { + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + } + if (newblock == NULL) + luaD_throw(L, LUA_ERRMEM); + } + lua_assert((nsize == 0) == (newblock == NULL)); + g->GCdebt = (g->GCdebt + nsize) - realosize; +#if defined(TRACEMEM) + { /* auxiliary patch to monitor garbage collection. + ** To plot, gnuplot with following command: + ** plot TRACEMEM using 1:2 with lines, TRACEMEM using 1:3 with lines + */ + static unsigned long total = 0; /* our "time" */ + static FILE *f = NULL; /* output file */ + total++; /* "time" always grows */ + if ((total % 200) == 0) { + if (f == NULL) f = fopen(TRACEMEM, "w"); + fprintf(f, "%lu %u %d %d\n", total, + gettotalbytes(g), g->GCdebt, g->gcstate * 10000); + } + } +#endif + + return newblock; } diff --git a/liblua/lmem.h b/liblua/lmem.h index 7c2dcb3220..535dfe07f3 100644 --- a/liblua/lmem.h +++ b/liblua/lmem.h @@ -1,5 +1,5 @@ /* -** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lmem.h,v 1.38 2011/12/02 13:26:54 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ @@ -13,23 +13,23 @@ #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)) + ((cast(size_t, (n)+1) > MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ + (luaM_toobig(L), (void *)0) : \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e))) #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_freearray(L, b, n) luaM_reallocv(L, (b), n, 0, sizeof((b)[0])) -#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) +#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) #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_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) + #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))) @@ -37,13 +37,14 @@ #define luaM_reallocvector(L, v,oldn,n,t) \ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) +LUAI_FUNC l_noret luaM_toobig (lua_State *L); +/* not to be called directly */ 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); + const char *what); #endif diff --git a/liblua/loadlib.c b/liblua/loadlib.c index d955f3ef41..783bc12be3 100644 --- a/liblua/loadlib.c +++ b/liblua/loadlib.c @@ -1,14 +1,22 @@ /* -** $Id: loadlib.c,v 1.52.1.2 2007/12/28 14:58:43 roberto Exp $ +** $Id: loadlib.c,v 1.108 2011/12/12 16:34:03 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. +** that have dlfcn, an implementation for Windows, and a stub for other +** systems. */ +/* +** if needed, includes windows header before everything else +*/ +#if defined(_WIN32) +#include +#endif + + #include #include @@ -22,6 +30,61 @@ #include "lualib.h" +/* +** LUA_PATH and LUA_CPATH are the names of the environment +** variables that Lua check to set its paths. +*/ +#if !defined(LUA_PATH) +#define LUA_PATH "LUA_PATH" +#endif + +#if !defined(LUA_CPATH) +#define LUA_CPATH "LUA_CPATH" +#endif + +#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + +#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX +#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX + +/* +** LUA_PATH_SEP is the character that separates templates in a path. +** LUA_PATH_MARK is the string that marks the substitution points in a +** template. +** LUA_EXEC_DIR in a Windows path is replaced by the executable's +** directory. +** LUA_IGMARK is a mark to ignore all before it when building the +** luaopen_ function name. +*/ +#if !defined (LUA_PATH_SEP) +#define LUA_PATH_SEP ";" +#endif +#if !defined (LUA_PATH_MARK) +#define LUA_PATH_MARK "?" +#endif +#if !defined (LUA_EXEC_DIR) +#define LUA_EXEC_DIR "!" +#endif +#if !defined (LUA_IGMARK) +#define LUA_IGMARK "-" +#endif + + +/* +** LUA_CSUBSEP is the character that replaces dots in submodule names +** when searching for a C loader. +** LUA_LSUBSEP is the character that replaces dots in submodule names +** when searching for a Lua loader. +*/ +#if !defined(LUA_CSUBSEP) +#define LUA_CSUBSEP LUA_DIRSEP +#endif + +#if !defined(LUA_LSUBSEP) +#define LUA_LSUBSEP LUA_DIRSEP +#endif + + /* prefix for open functions in C libraries */ #define LUA_POF "luaopen_" @@ -42,13 +105,16 @@ #define setprogdir(L) ((void)0) +/* +** system-dependent functions +*/ static void ll_unloadlib (void *lib); -static void *ll_load (lua_State *L, const char *path); +static void *ll_load (lua_State *L, const char *path, int seeglb); static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); -#if defined(LUA_DL_DLOPEN) +#if defined(LUA_USE_DLOPEN) /* ** {======================================================================== ** This is an implementation of loadlib based on the dlfcn interface. @@ -65,8 +131,8 @@ static void ll_unloadlib (void *lib) { } -static void *ll_load (lua_State *L, const char *path) { - void *lib = dlopen(path, RTLD_NOW); +static void *ll_load (lua_State *L, const char *path, int seeglb) { + void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); if (lib == NULL) lua_pushstring(L, dlerror()); return lib; } @@ -89,10 +155,15 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { ** ======================================================================= */ -#include +#undef setprogdir +/* +** optional flags for LoadLibraryEx +*/ +#if !defined(LUA_LLE_FLAGS) +#define LUA_LLE_FLAGS 0 +#endif -#undef setprogdir static void setprogdir (lua_State *L) { char buff[MAX_PATH + 1]; @@ -103,7 +174,7 @@ static void setprogdir (lua_State *L) { luaL_error(L, "unable to get ModuleFileName"); else { *lb = '\0'; - luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); + luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); lua_remove(L, -2); /* remove original string */ } } @@ -113,26 +184,27 @@ 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)) + NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) lua_pushstring(L, buffer); else lua_pushfstring(L, "system error %d\n", error); } static void ll_unloadlib (void *lib) { - FreeLibrary((HINSTANCE)lib); + FreeLibrary((HMODULE)lib); } -static void *ll_load (lua_State *L, const char *path) { - HINSTANCE lib = LoadLibraryA(path); +static void *ll_load (lua_State *L, const char *path, int seeglb) { + HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); + (void)(seeglb); /* not used: symbols are 'global' by default */ 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); + lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); if (f == NULL) pusherror(L); return f; } @@ -140,88 +212,6 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { /* }====================================================== */ - -#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 /* ** {====================================================== @@ -237,19 +227,19 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { static void ll_unloadlib (void *lib) { - (void)lib; /* to avoid warnings */ + (void)(lib); /* not used */ } -static void *ll_load (lua_State *L, const char *path) { - (void)path; /* to avoid warnings */ +static void *ll_load (lua_State *L, const char *path, int seeglb) { + (void)(path); (void)(seeglb); /* not used */ 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 */ + (void)(lib); (void)(sym); /* not used */ lua_pushliteral(L, DLMSG); return NULL; } @@ -266,11 +256,10 @@ static void **ll_register (lua_State *L, const char *path) { 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); + lua_pop(L, 1); /* remove result from gettable */ plib = (void **)lua_newuserdata(L, sizeof(const void *)); *plib = NULL; - luaL_getmetatable(L, "_LOADLIB"); - lua_setmetatable(L, -2); + luaL_setmetatable(L, "_LOADLIB"); lua_pushfstring(L, "%s%s", LIBPREFIX, path); lua_pushvalue(L, -2); lua_settable(L, LUA_REGISTRYINDEX); @@ -293,15 +282,18 @@ static int gctm (lua_State *L) { 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 */ + if (*reg == NULL) *reg = ll_load(L, path, *sym == '*'); + if (*reg == NULL) return ERRLIB; /* unable to load library */ + if (*sym == '*') { /* loading only library (no function)? */ + lua_pushboolean(L, 1); /* return 'true' */ + return 0; /* no errors */ + } 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 */ + lua_pushcfunction(L, f); /* else create new function */ + return 0; /* no errors */ } } @@ -339,104 +331,137 @@ static int readable (const char *filename) { static const char *pushnexttemplate (lua_State *L, const char *path) { const char *l; - while (*path == *LUA_PATHSEP) path++; /* skip separators */ + while (*path == *LUA_PATH_SEP) path++; /* skip separators */ if (*path == '\0') return NULL; /* no more templates */ - l = strchr(path, *LUA_PATHSEP); /* find next separator */ + l = strchr(path, *LUA_PATH_SEP); /* 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 */ +static const char *searchpath (lua_State *L, const char *name, + const char *path, + const char *sep, + const char *dirsep) { + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + if (*sep != '\0') /* non-empty separator? */ + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ while ((path = pushnexttemplate(L, path)) != NULL) { - const char *filename; - filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); + const char *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 */ + luaL_addvalue(&msg); /* concatenate error msg. entry */ } + luaL_pushresult(&msg); /* create 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 ll_searchpath (lua_State *L) { + const char *f = searchpath(L, luaL_checkstring(L, 1), + luaL_checkstring(L, 2), + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); + if (f != NULL) return 1; + else { /* error message is on top of the stack */ + lua_pushnil(L); + lua_insert(L, -2); + return 2; /* return nil + error message */ + } } -static int loader_Lua (lua_State *L) { +static const char *findfile (lua_State *L, const char *name, + const char *pname, + const char *dirsep) { + const char *path; + lua_getfield(L, lua_upvalueindex(1), pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, LUA_QL("package.%s") " must be a string", pname); + return searchpath(L, name, path, ".", dirsep); +} + + +static int checkload (lua_State *L, int stat, const char *filename) { + if (stat) { /* module loaded successfully? */ + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; /* return open function and file name */ + } + else + return 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 searcher_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 */ + filename = findfile(L, name, "path", LUA_LSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); } -static const char *mkfuncname (lua_State *L, const char *modname) { +static int loadfunc (lua_State *L, const char *filename, 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; + const char *mark; + modname = luaL_gsub(L, modname, ".", LUA_OFSEP); + mark = strchr(modname, *LUA_IGMARK); + if (mark) { + int stat; + funcname = lua_pushlstring(L, modname, mark - modname); + funcname = lua_pushfstring(L, POF"%s", funcname); + stat = ll_loadfunc(L, filename, funcname); + if (stat != ERRFUNC) return stat; + modname = mark + 1; /* else go ahead and try old-style name */ + } + funcname = lua_pushfstring(L, POF"%s", modname); + return ll_loadfunc(L, filename, funcname); } -static int loader_C (lua_State *L) { - const char *funcname; +static int searcher_C (lua_State *L) { 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 */ + const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (loadfunc(L, filename, name) == 0), filename); } -static int loader_Croot (lua_State *L) { - const char *funcname; +static int searcher_Croot (lua_State *L) { 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"); + filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); 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 */ + if ((stat = loadfunc(L, filename, name)) != 0) { + if (stat != ERRFUNC) + return checkload(L, 0, filename); /* real error */ + else { /* open function not found */ + lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, + name, filename); + return 1; + } } - return 1; + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; } -static int loader_preload (lua_State *L) { +static int searcher_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, LUA_REGISTRYINDEX, "_PRELOAD"); lua_getfield(L, -1, name); if (lua_isnil(L, -1)) /* not found? */ lua_pushfstring(L, "\n\tno field package.preload['%s']", name); @@ -444,48 +469,53 @@ static int loader_preload (lua_State *L) { } -static const int sentinel_ = 0; -#define sentinel ((void *)&sentinel_) +static void findloader (lua_State *L, const char *name) { + int i; + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */ + if (!lua_istable(L, 3)) + luaL_error(L, LUA_QL("package.searchers") " must be a table"); + /* iterate over available seachers to find a loader */ + for (i = 1; ; i++) { + lua_rawgeti(L, 3, i); /* get a seacher */ + if (lua_isnil(L, -1)) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ + luaL_error(L, "module " LUA_QS " not found:%s", + name, lua_tostring(L, -1)); + } + lua_pushstring(L, name); + lua_call(L, 1, 2); /* call it */ + if (lua_isfunction(L, -2)) /* did it find a loader? */ + return; /* module loader found */ + else if (lua_isstring(L, -2)) { /* searcher returned error message? */ + lua_pop(L, 1); /* remove extra return */ + luaL_addvalue(&msg); /* concatenate error message */ + } + else + lua_pop(L, 2); /* remove both returns */ + } +} 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); + lua_getfield(L, 2, name); /* _LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ 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 */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); + lua_pushstring(L, name); /* pass name as argument to module loader */ + lua_insert(L, -2); /* name is 1st argument (before search data) */ + lua_call(L, 2, 1); /* run loader to load 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? */ + if (lua_isnil(L, -1)) { /* 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 */ @@ -502,24 +532,31 @@ static int ll_require (lua_State *L) { ** 'module' function ** ======================================================= */ - +#if defined(LUA_COMPAT_MODULE) -static void setfenv (lua_State *L) { +/* +** changes the environment variable of calling function +*/ +static void set_env (lua_State *L) { lua_Debug ar; - lua_getstack(L, 1, &ar); - lua_getinfo(L, "f", &ar); - lua_pushvalue(L, -2); - lua_setfenv(L, -2); - lua_pop(L, 1); + 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); /* copy new environment table to top */ + lua_setupvalue(L, -2, 1); + lua_pop(L, 1); /* remove function */ } 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); + if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } } } @@ -541,17 +578,8 @@ static void modinit (lua_State *L, const char *modname) { 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 */ - } + int lastarg = lua_gettop(L); /* last parameter */ + luaL_pushmodule(L, modname, 1); /* get/create module table */ /* check whether table already has a _NAME field */ lua_getfield(L, -1, "_NAME"); if (!lua_isnil(L, -1)) /* is table an initialized module? */ @@ -561,9 +589,9 @@ static int ll_module (lua_State *L) { modinit(L, modname); } lua_pushvalue(L, -1); - setfenv(L); - dooptions(L, loaded - 1); - return 0; + set_env(L); + dooptions(L, lastarg); + return 1; } @@ -574,12 +602,12 @@ static int ll_seeall (lua_State *L) { lua_pushvalue(L, -1); lua_setmetatable(L, 1); } - lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_pushglobaltable(L); lua_setfield(L, -2, "__index"); /* mt.__index = _G */ return 0; } - +#endif /* }====================================================== */ @@ -587,15 +615,30 @@ static int ll_seeall (lua_State *L) { /* 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); + +/* +** return registry.LUA_NOENV as a boolean +*/ +static int noenv (lua_State *L) { + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; +} + + +static void setpath (lua_State *L, const char *fieldname, const char *envname1, + const char *envname2, const char *def) { + const char *path = getenv(envname1); if (path == NULL) /* no environment variable? */ + path = getenv(envname2); /* try alternative name */ + if (path == NULL || noenv(L)) /* 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); + path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, + LUA_PATH_SEP AUXMARK LUA_PATH_SEP); luaL_gsub(L, path, AUXMARK, def); lua_remove(L, -2); } @@ -606,59 +649,66 @@ static void setpath (lua_State *L, const char *fieldname, const char *envname, static const luaL_Reg pk_funcs[] = { {"loadlib", ll_loadlib}, + {"searchpath", ll_searchpath}, +#if defined(LUA_COMPAT_MODULE) {"seeall", ll_seeall}, +#endif {NULL, NULL} }; static const luaL_Reg ll_funcs[] = { +#if defined(LUA_COMPAT_MODULE) {"module", ll_module}, +#endif {"require", ll_require}, {NULL, NULL} }; -static const lua_CFunction loaders[] = - {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; +static const lua_CFunction searchers[] = + {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; -LUALIB_API int luaopen_package (lua_State *L) { +LUAMOD_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]); + luaL_newlib(L, pk_funcs); + /* create 'searchers' table */ + lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); + /* fill it with pre-defined searchers */ + for (i=0; searchers[i] != NULL; i++) { + lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ + lua_pushcclosure(L, searchers[i], 1); 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' */ +#if defined(LUA_COMPAT_LOADERS) + lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ + lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ +#endif + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ + /* set field 'path' */ + setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT); + /* set field 'cpath' */ + setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT); /* store config information */ - lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" - LUA_EXECDIR "\n" LUA_IGMARK); + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" + LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); lua_setfield(L, -2, "config"); /* set field `loaded' */ - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); lua_setfield(L, -2, "loaded"); /* set field `preload' */ - lua_newtable(L); + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); 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); + lua_pushglobaltable(L); + lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ + luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ + lua_pop(L, 1); /* pop global table */ return 1; /* return 'package' table */ } diff --git a/liblua/lobject.c b/liblua/lobject.c index 4ff50732a4..cf0f75446d 100644 --- a/liblua/lobject.c +++ b/liblua/lobject.c @@ -1,10 +1,9 @@ /* -** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lobject.c,v 2.55 2011/11/30 19:30:16 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ -#include #include #include #include @@ -15,6 +14,8 @@ #include "lua.h" +#include "lctype.h" +#include "ldebug.h" #include "ldo.h" #include "lmem.h" #include "lobject.h" @@ -24,7 +25,7 @@ -const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; +LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; /* @@ -33,25 +34,25 @@ const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; ** eeeee != 0 and (xxx) otherwise. */ int luaO_int2fb (unsigned int x) { - int e = 0; /* expoent */ - while (x >= 16) { + int e = 0; /* exponent */ + if (x < 8) return x; + while (x >= 0x10) { x = (x+1) >> 1; e++; } - if (x < 8) return x; - else return ((e+1) << 3) | (cast_int(x) - 8); + return ((e+1) << 3) | (cast_int(x) - 8); } /* converts back */ int luaO_fb2int (int x) { - int e = (x >> 3) & 31; + int e = (x >> 3) & 0x1f; if (e == 0) return x; - else return ((x & 7)+8) << (e - 1); + else return ((x & 7) + 8) << (e - 1); } -int luaO_log2 (unsigned int x) { +int luaO_ceillog2 (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, @@ -62,55 +63,122 @@ int luaO_log2 (unsigned int x) { 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; + int l = 0; + x--; while (x >= 256) { l += 8; x >>= 8; } return l + log_2[x]; +} + + +lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { + switch (op) { + case LUA_OPADD: return luai_numadd(NULL, v1, v2); + case LUA_OPSUB: return luai_numsub(NULL, v1, v2); + case LUA_OPMUL: return luai_nummul(NULL, v1, v2); + case LUA_OPDIV: return luai_numdiv(NULL, v1, v2); + case LUA_OPMOD: return luai_nummod(NULL, v1, v2); + case LUA_OPPOW: return luai_numpow(NULL, v1, v2); + case LUA_OPUNM: return luai_numunm(NULL, v1); + default: lua_assert(0); return 0; + } +} + + +int luaO_hexavalue (int c) { + if (lisdigit(c)) return c - '0'; + else return ltolower(c) - 'a' + 10; +} + + +#if !defined(lua_strx2number) + +#include + + +static int isneg (const char **s) { + if (**s == '-') { (*s)++; return 1; } + else if (**s == '+') (*s)++; + return 0; +} + +static lua_Number readhexa (const char **s, lua_Number r, int *count) { + for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ + r = (r * 16.0) + cast_num(luaO_hexavalue(cast_uchar(**s))); + (*count)++; + } + return r; } -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); +/* +** convert an hexadecimal numeric string to a number, following +** C99 specification for 'strtod' +*/ +static lua_Number lua_strx2number (const char *s, char **endptr) { + lua_Number r = 0.0; + int e = 0, i = 0; + int neg = 0; /* 1 if number is negative */ + *endptr = cast(char *, s); /* nothing is valid yet */ + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); /* check signal */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + s += 2; /* skip '0x' */ + r = readhexa(&s, r, &i); /* read integer part */ + if (*s == '.') { + s++; /* skip dot */ + r = readhexa(&s, r, &e); /* read fractional part */ } + if (i == 0 && e == 0) + return 0.0; /* invalid format (no digit) */ + e *= -4; /* each fractional digit divides value by 2^-4 */ + *endptr = cast(char *, s); /* valid up to here */ + if (*s == 'p' || *s == 'P') { /* exponent part? */ + int exp1 = 0; + int neg1; + s++; /* skip 'p' */ + neg1 = isneg(&s); /* signal */ + if (!lisdigit(cast_uchar(*s))) + goto ret; /* must have at least one digit */ + while (lisdigit(cast_uchar(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + } + *endptr = cast(char *, s); /* valid up to here */ + ret: + if (neg) r = -r; + return ldexp(r, e); } +#endif + -int luaO_str2d (const char *s, lua_Number *result) { +int luaO_str2d (const char *s, size_t len, 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; + if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ + return 0; + else if (strpbrk(s, "xX")) /* hexa? */ + *result = lua_strx2number(s, &endptr); + else + *result = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* nothing recognized */ + while (lisspace(cast_uchar(*endptr))) endptr++; + return (endptr == s + len); /* OK if no trailing characters */ } -static void pushstr (lua_State *L, const char *str) { - setsvalue2s(L, L->top, luaS_new(L, str)); +static void pushstr (lua_State *L, const char *str, size_t l) { + setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); 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, ""); + int n = 0; for (;;) { const char *e = strchr(fmt, '%'); if (e == NULL) break; @@ -120,14 +188,13 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { case 's': { const char *s = va_arg(argp, char *); if (s == NULL) s = "(null)"; - pushstr(L, s); + pushstr(L, s, strlen(s)); break; } case 'c': { - char buff[2]; - buff[0] = cast(char, va_arg(argp, int)); - buff[1] = '\0'; - pushstr(L, buff); + char buff; + buff = cast(char, va_arg(argp, int)); + pushstr(L, &buff, 1); break; } case 'd': { @@ -142,29 +209,25 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { } 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); + int l = sprintf(buff, "%p", va_arg(argp, void *)); + pushstr(L, buff, l); break; } case '%': { - pushstr(L, "%"); + pushstr(L, "%", 1); break; } default: { - char buff[3]; - buff[0] = '%'; - buff[1] = *(e+1); - buff[2] = '\0'; - pushstr(L, buff); - break; + luaG_runerror(L, + "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), + *(e + 1)); } } n += 2; fmt = e+2; } - pushstr(L, fmt); - luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); - L->top -= n; + pushstr(L, fmt, strlen(fmt)); + if (n > 0) luaV_concat(L, n + 1); return svalue(L->top - 1); } @@ -179,36 +242,48 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { } +/* number of chars of a literal string without the ending \0 */ +#define LL(x) (sizeof(x)/sizeof(char) - 1) + +#define RETS "..." +#define PRE "[string \"" +#define POS "\"]" + +#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) + 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 */ + size_t l = strlen(source); + if (*source == '=') { /* 'literal' source */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* truncate it */ + addstr(out, source + 1, bufflen - 1); + *out = '\0'; + } } - 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 if (*source == '@') { /* file name */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* add '...' before rest of name */ + addstr(out, RETS, LL(RETS)); + bufflen -= LL(RETS); + memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); } - 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, "\"]"); + } + else { /* string; format as [string "source"] */ + const char *nl = strchr(source, '\n'); /* find first new line (if any) */ + addstr(out, PRE, LL(PRE)); /* add prefix */ + bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ + if (l < bufflen && nl == NULL) { /* small one-line source? */ + addstr(out, source, l); /* keep it */ } + else { + if (nl != NULL) l = nl - source; /* stop at first newline */ + if (l > bufflen) l = bufflen; + addstr(out, source, l); + addstr(out, RETS, LL(RETS)); + } + memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); } } + diff --git a/liblua/lobject.h b/liblua/lobject.h index e7199dfc68..06246bfa5e 100644 --- a/liblua/lobject.h +++ b/liblua/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lobject.h,v 2.64 2011/10/31 17:48:22 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -16,18 +16,44 @@ #include "lua.h" -/* tags for values visible from Lua */ -#define LAST_TAG LUA_TTHREAD +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO LUA_NUMTAGS +#define LUA_TUPVAL (LUA_NUMTAGS+1) +#define LUA_TDEADKEY (LUA_NUMTAGS+2) -#define NUM_TAGS (LAST_TAG+1) +/* +** number of all possible tags (including LUA_TNONE but excluding DEADKEY) +*/ +#define LUA_TOTALTAGS (LUA_TUPVAL+2) /* -** Extra tags for non-values +** tags for Tagged Values have the following use of bits: +** bits 0-3: actual tag (a LUA_T* value) +** bits 4-5: variant bits +** bit 6: whether value is collectable */ -#define LUA_TPROTO (LAST_TAG+1) -#define LUA_TUPVAL (LAST_TAG+2) -#define LUA_TDEADKEY (LAST_TAG+3) + +/* +** LUA_TFUNCTION variants: +** 0 - Lua function +** 1 - light C function +** 2 - regular C function (closure) +*/ + +/* Variant tags for functions */ +#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ +#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ +#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ + + +/* Bit mark for collectable types */ +#define BIT_ISCOLLECTABLE (1 << 6) + +/* mark a tag as collectable */ +#define ctb(t) ((t) | BIT_ISCOLLECTABLE) /* @@ -52,120 +78,166 @@ typedef struct GCheader { - /* ** Union of all Lua values */ -typedef union { - GCObject *gc; - void *p; - lua_Number n; - int b; -} Value; +typedef union Value Value; + + +#define numfield lua_Number n; /* numbers */ + /* -** Tagged Values +** Tagged Values. This is the basic representation of values in Lua, +** an actual value plus a tag with its type. */ -#define TValuefields Value value; int tt +#define TValuefields Value value_; int tt_ + +typedef struct lua_TValue TValue; + + +/* macro defining a nil value */ +#define NILCONSTANT {NULL}, LUA_TNIL + + +#define val_(o) ((o)->value_) +#define num_(o) (val_(o).n) -typedef struct lua_TValue { - TValuefields; -} TValue; + +/* raw type tag of a TValue */ +#define rttype(o) ((o)->tt_) + +/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ +#define ttype(o) (rttype(o) & 0x3F) + + +/* type tag of a TValue with no variants (bits 0-3) */ +#define ttypenv(o) (rttype(o) & 0x0F) /* 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) +#define checktag(o,t) (rttype(o) == (t)) +#define ttisnumber(o) checktag((o), LUA_TNUMBER) +#define ttisnil(o) checktag((o), LUA_TNIL) +#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) +#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) +#define ttisstring(o) checktag((o), ctb(LUA_TSTRING)) +#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) +#define ttisfunction(o) (ttypenv(o) == LUA_TFUNCTION) +#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) +#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) +#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) +#define ttislcf(o) checktag((o), LUA_TLCF) +#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) +#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) +#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) + +#define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) /* 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 nvalue(o) check_exp(ttisnumber(o), num_(o)) +#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) +#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) +#define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) #define tsvalue(o) (&rawtsvalue(o)->tsv) -#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +#define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).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 clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) +#define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) +#define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) +#define fvalue(o) check_exp(ttislcf(o), val_(o).f) +#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) +#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) +#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th) +/* a dead value may get the 'gc' field, but cannot access its contents */ +#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) #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 iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) + + +/* Macros for internal tests */ +#define righttt(obj) (ttypenv(obj) == gcvalue(obj)->gch.tt) #define checkliveness(g,obj) \ - lua_assert(!iscollectable(obj) || \ - ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) + lua_longassert(!iscollectable(obj) || \ + (righttt(obj) && !isdead(g,gcvalue(obj)))) /* Macros to set values */ -#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) +#define settt_(o,t) ((o)->tt_=(t)) #define setnvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } + { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } + +#define changenvalue(o,x) check_exp(ttisnumber(o), num_(o)=(x)) + +#define setnilvalue(obj) settt_(obj, LUA_TNIL) + +#define setfvalue(obj,x) \ + { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } #define setpvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } + { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } #define setbvalue(obj,x) \ - { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } + { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } + +#define setgcovalue(L,obj,x) \ + { TValue *io=(obj); GCObject *i_g=(x); \ + val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); } #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); } + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TSTRING)); \ + checkliveness(G(L),io); } #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); } + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \ + checkliveness(G(L),io); } #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); } + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \ + checkliveness(G(L),io); } -#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 setclLvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \ + checkliveness(G(L),io); } + +#define setclCvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \ + checkliveness(G(L),io); } #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); } + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \ + checkliveness(G(L),io); } #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); } + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TPROTO)); \ + checkliveness(G(L),io); } +#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) #define setobj(L,obj1,obj2) \ - { const TValue *o2=(obj2); TValue *o1=(obj1); \ - o1->value = o2->value; o1->tt=o2->tt; \ - checkliveness(G(L),o1); } + { const TValue *io2=(obj2); TValue *io1=(obj1); \ + io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ + checkliveness(G(L),io1); } /* -** different types of sets, according to destination +** different types of assignments, according to destination */ /* from stack to (same) stack */ @@ -183,18 +255,147 @@ typedef struct lua_TValue { #define setobj2n setobj #define setsvalue2n setsvalue -#define setttype(obj, tt) (ttype(obj) = (tt)) -#define iscollectable(o) (ttype(o) >= LUA_TSTRING) +/* +** {====================================================== +** NaN Trick +** ======================================================= +*/ + +#if defined(LUA_NANTRICK) \ + || defined(LUA_NANTRICK_LE) \ + || defined(LUA_NANTRICK_BE) + +/* +** numbers are represented in the 'd_' field. All other values have the +** value (NNMARK | tag) in 'tt__'. A number with such pattern would be +** a "signaled NaN", which is never generated by regular operations by +** the CPU (nor by 'strtod') +*/ +#if !defined(NNMARK) +#define NNMARK 0x7FF7A500 +#define NNMASK 0x7FFFFF00 +#endif + +#undef TValuefields +#undef NILCONSTANT + +#if defined(LUA_NANTRICK_LE) + +/* little endian */ +#define TValuefields \ + union { struct { Value v__; int tt__; } i; double d__; } u +#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} +/* field-access macros */ +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) + +#elif defined(LUA_NANTRICK_BE) + +/* big endian */ +#define TValuefields \ + union { struct { int tt__; Value v__; } i; double d__; } u +#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} +/* field-access macros */ +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) + +#elif !defined(TValuefields) +#error option 'LUA_NANTRICK' needs declaration for 'TValuefields' + +#endif + + +/* correspondence with standard representation */ +#undef val_ +#define val_(o) v_(o) +#undef num_ +#define num_(o) d_(o) + + +#undef numfield +#define numfield /* no such field; numbers are the entire struct */ + +/* basic check to distinguish numbers from non-numbers */ +#undef ttisnumber +#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) + +#define tag2tt(t) (NNMARK | (t)) + +#undef rttype +#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) + +#undef settt_ +#define settt_(o,t) (tt_(o) = tag2tt(t)) + +#undef setnvalue +#define setnvalue(obj,x) \ + { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } + +#undef setobj +#define setobj(L,obj1,obj2) \ + { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ + o1_->u = o2_->u; \ + checkliveness(G(L),o1_); } + + +/* +** these redefinitions are not mandatory, but these forms are more efficient +*/ + +#undef checktag +#define checktag(o,t) (tt_(o) == tag2tt(t)) + +#undef ttisequal +#define ttisequal(o1,o2) \ + (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) + + + +#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } + + +#else + +#define luai_checknum(L,o,c) { /* empty */ } + +#endif +/* }====================================================== */ + + + +/* +** {====================================================== +** types and prototypes +** ======================================================= +*/ + + +union Value { + GCObject *gc; /* collectable objects */ + void *p; /* light userdata */ + int b; /* booleans */ + lua_CFunction f; /* light C functions */ + numfield /* numbers */ +}; + + +struct lua_TValue { + TValuefields; +}; typedef TValue *StkId; /* index to stack elements */ + + /* -** String headers for string table +** Header for string value; string bytes follow the end of this structure */ typedef union TString { L_Umaxalign dummy; /* ensures maximum alignment for strings */ @@ -202,28 +403,53 @@ typedef union TString { CommonHeader; lu_byte reserved; unsigned int hash; - size_t len; + size_t len; /* number of characters in string */ } tsv; } TString; +/* get the actual string (array of bytes) from a TString */ #define getstr(ts) cast(const char *, (ts) + 1) -#define svalue(o) getstr(tsvalue(o)) +/* get the actual string (array of bytes) from a Lua value */ +#define svalue(o) getstr(rawtsvalue(o)) +/* +** Header for userdata; memory area follows the end of this structure +*/ typedef union Udata { L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ struct { CommonHeader; struct Table *metatable; struct Table *env; - size_t len; + size_t len; /* number of bytes */ } uv; } Udata; +/* +** Description of an upvalue for function prototypes +*/ +typedef struct Upvaldesc { + TString *name; /* upvalue name (for debug information) */ + lu_byte instack; /* whether it is in stack */ + lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ +} Upvaldesc; + + +/* +** Description of a local variable for function prototypes +** (used for debug information) +*/ +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + /* ** Function Prototypes @@ -233,11 +459,12 @@ typedef struct Proto { 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 *lineinfo; /* map from opcodes to source lines (debug information) */ + LocVar *locvars; /* information about local variables (debug information) */ + Upvaldesc *upvalues; /* upvalue information */ + union Closure *cache; /* last created closure with this prototype */ + TString *source; /* used for debug information */ + int sizeupvalues; /* size of 'upvalues' */ int sizek; /* size of `k' */ int sizecode; int sizelineinfo; @@ -246,31 +473,16 @@ typedef struct Proto { int linedefined; int lastlinedefined; GCObject *gclist; - lu_byte nups; /* number of upvalues */ - lu_byte numparams; + lu_byte numparams; /* number of fixed parameters */ lu_byte is_vararg; - lu_byte maxstacksize; + lu_byte maxstacksize; /* maximum stack used by this function */ } 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 +** Lua Upvalues */ - typedef struct UpVal { CommonHeader; TValue *v; /* points to stack or to its own value */ @@ -289,20 +501,19 @@ typedef struct UpVal { */ #define ClosureHeader \ - CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ - struct Table *env + CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist typedef struct CClosure { ClosureHeader; lua_CFunction f; - TValue upvalue[1]; + TValue upvalue[1]; /* list of upvalues */ } CClosure; typedef struct LClosure { ClosureHeader; struct Proto *p; - UpVal *upvals[1]; + UpVal *upvals[1]; /* list of upvalues */ } LClosure; @@ -312,8 +523,9 @@ typedef union Closure { } Closure; -#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) -#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) +#define isLfunction(o) ttisLclosure(o) + +#define getproto(o) (clLvalue(o)->p) /* @@ -337,7 +549,7 @@ typedef struct Node { typedef struct Table { CommonHeader; - lu_byte flags; /* 1<

lsizenode)) +/* +** (address of) a fixed nil value +*/ #define luaO_nilobject (&luaO_nilobject_) -LUAI_DATA const TValue luaO_nilobject_; -#define ceillog2(x) (luaO_log2((x)-1) + 1) +LUAI_DDEC const TValue luaO_nilobject_; + -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 int luaO_ceillog2 (unsigned int x); +LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2); +LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); +LUAI_FUNC int luaO_hexavalue (int c); 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, ...); diff --git a/liblua/lopcodes.c b/liblua/lopcodes.c index 4cc745230b..2e34676687 100644 --- a/liblua/lopcodes.c +++ b/liblua/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lopcodes.c,v 1.48 2011/04/19 16:22:13 roberto Exp $ ** See Copyright Notice in lua.h */ @@ -13,15 +13,16 @@ /* ORDER OP */ -const char *const luaP_opnames[NUM_OPCODES+1] = { +LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "MOVE", "LOADK", + "LOADKX", "LOADBOOL", "LOADNIL", "GETUPVAL", - "GETGLOBAL", + "GETTABUP", "GETTABLE", - "SETGLOBAL", + "SETTABUP", "SETUPVAL", "SETTABLE", "NEWTABLE", @@ -47,27 +48,29 @@ const char *const luaP_opnames[NUM_OPCODES+1] = { "RETURN", "FORLOOP", "FORPREP", + "TFORCALL", "TFORLOOP", "SETLIST", - "CLOSE", "CLOSURE", "VARARG", + "EXTRAARG", NULL }; #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) -const lu_byte luaP_opmodes[NUM_OPCODES] = { +LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { /* T A B C mode opcode */ - opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ + ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ @@ -86,17 +89,18 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = { ,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, 0, OpArgN, 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, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* 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 */ + ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ }; diff --git a/liblua/lopcodes.h b/liblua/lopcodes.h index 41224d6ee1..07d2b3f39a 100644 --- a/liblua/lopcodes.h +++ b/liblua/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lopcodes.h,v 1.142 2011/07/15 12:50:29 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -17,6 +17,7 @@ `A' : 8 bits `B' : 9 bits `C' : 9 bits + 'Ax' : 26 bits ('A', 'B', and 'C' together) `Bx' : 18 bits (`B' and `C' together) `sBx' : signed Bx @@ -28,7 +29,7 @@ ===========================================================================*/ -enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ +enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ /* @@ -38,6 +39,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ #define SIZE_B 9 #define SIZE_Bx (SIZE_C + SIZE_B) #define SIZE_A 8 +#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) #define SIZE_OP 6 @@ -46,6 +48,7 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ #define POS_C (POS_A + SIZE_A) #define POS_B (POS_C + SIZE_C) #define POS_Bx POS_C +#define POS_Ax POS_A /* @@ -61,6 +64,12 @@ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ #define MAXARG_sBx MAX_INT #endif +#if SIZE_Ax < LUAI_BITSINT-1 +#define MAXARG_Ax ((1<>POS_A) & MASK1(SIZE_A,0))) -#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ - ((cast(Instruction, u)<>pos) & MASK1(size,0))) +#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ + ((cast(Instruction, v)<>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)<= R(A) + 1 */ OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ -OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ -OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ +OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ +OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ -OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ +OP_TEST,/* A C if not (R(A) <=> 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)) */ @@ -197,39 +212,44 @@ 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_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ + +OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */ -OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ +OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */ } OpCode; -#define NUM_OPCODES (cast(int, OP_VARARG) + 1) +#define NUM_OPCODES (cast(int, OP_EXTRAARG) + 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_CALL, if (B == 0) then B = top. If (C == 0), then `top' is + set 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). + set top (like in OP_CALL with C == 0). - (*) In OP_RETURN, if (B == 0) then return up to `top' + (*) 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 + (*) In OP_SETLIST, if (B == 0) then B = `top'; if (C == 0) then next + 'instruction' is EXTRAARG(real C). + + (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG. (*) For comparisons, A specifies what condition the test should accept - (true or false). + (true or false). + + (*) All `skips' (pc++) assume that next instruction is a jump. - (*) All `skips' (pc++) assume that next instruction is a jump ===========================================================================*/ @@ -239,8 +259,8 @@ OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ ** bits 2-3: C arg mode ** bits 4-5: B arg mode ** bit 6: instruction set register A -** bit 7: operator is a test -*/ +** bit 7: operator is a test (next instruction must be a jump) +*/ enum OpArgMask { OpArgN, /* argument is not used */ @@ -249,7 +269,7 @@ enum OpArgMask { OpArgK /* argument is a constant or register/constant */ }; -LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; +LUAI_DDEC 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)) @@ -258,7 +278,7 @@ LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) -LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ +LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ /* number of list items to accumulate before a SETLIST instruction */ diff --git a/liblua/loslib.c b/liblua/loslib.c index da06a572ac..881667dac8 100644 --- a/liblua/loslib.c +++ b/liblua/loslib.c @@ -1,5 +1,5 @@ /* -** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ +** $Id: loslib.c,v 1.38 2011/11/30 12:35:05 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ @@ -20,37 +20,84 @@ #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; - } -} +/* +** list of valid conversion specifiers for the 'strftime' function +*/ +#if !defined(LUA_STRFTIMEOPTIONS) + +#if !defined(LUA_USE_POSIX) +#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } +#else +#define LUA_STRFTIMEOPTIONS { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "", \ + "E", "cCxXyY", \ + "O", "deHImMSuUVwWy" } +#endif + +#endif + + + +/* +** By default, Lua uses tmpnam except when POSIX is available, where it +** uses mkstemp. +*/ +#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); } + +#elif !defined(lua_tmpnam) + +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } + +#endif + + +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ +#if defined(LUA_USE_GMTIME_R) + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#elif !defined(l_gmtime) + +#define l_gmtime(t,r) ((void)r, gmtime(t)) +#define l_localtime(t,r) ((void)r, localtime(t)) + +#endif + static int os_execute (lua_State *L) { - lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); - return 1; + const char *cmd = luaL_optstring(L, 1, NULL); + int stat = system(cmd); + if (cmd != NULL) + return luaL_execresult(L, stat); + else { + lua_pushboolean(L, stat); /* true if there is a shell */ + return 1; + } } static int os_remove (lua_State *L) { const char *filename = luaL_checkstring(L, 1); - return os_pushresult(L, remove(filename) == 0, filename); + return luaL_fileresult(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); + return luaL_fileresult(L, rename(fromname, toname) == 0, fromname); } @@ -107,11 +154,10 @@ static int getboolfield (lua_State *L, const char *key) { static int getfield (lua_State *L, const char *key, int d) { - int res; + int res, isnum; lua_getfield(L, -1, key); - if (lua_isnumber(L, -1)) - res = (int)lua_tointeger(L, -1); - else { + res = (int)lua_tointegerx(L, -1, &isnum); + if (!isnum) { if (d < 0) return luaL_error(L, "field " LUA_QS " missing in date table", key); res = d; @@ -121,16 +167,40 @@ static int getfield (lua_State *L, const char *key, int d) { } +static const char *checkoption (lua_State *L, const char *conv, char *buff) { + static const char *const options[] = LUA_STRFTIMEOPTIONS; + unsigned int i; + for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) { + if (*conv != '\0' && strchr(options[i], *conv) != NULL) { + buff[1] = *conv; + if (*options[i + 1] == '\0') { /* one-char conversion specifier? */ + buff[2] = '\0'; /* end buffer */ + return conv + 1; + } + else if (*(conv + 1) != '\0' && + strchr(options[i + 1], *(conv + 1)) != NULL) { + buff[2] = *(conv + 1); /* valid two-char conversion specifier */ + buff[3] = '\0'; /* end buffer */ + return conv + 2; + } + } + } + luaL_argerror(L, 1, + lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ +} + + 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; + struct tm tmr, *stm; if (*s == '!') { /* UTC? */ - stm = gmtime(&t); + stm = l_gmtime(&t, &tmr); s++; /* skip `!' */ } else - stm = localtime(&t); + stm = l_localtime(&t, &tmr); if (stm == NULL) /* invalid date? */ lua_pushnil(L); else if (strcmp(s, "*t") == 0) { @@ -146,17 +216,17 @@ static int os_date (lua_State *L) { setboolfield(L, "isdst", stm->tm_isdst); } else { - char cc[3]; + char cc[4]; luaL_Buffer b; - cc[0] = '%'; cc[2] = '\0'; + cc[0] = '%'; luaL_buffinit(L, &b); - for (; *s; s++) { - if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ - luaL_addchar(&b, *s); + while (*s) { + if (*s != '%') /* 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); + s = checkoption(L, s + 1, cc); reslen = strftime(buff, sizeof(buff), cc, stm); luaL_addlstring(&b, buff, reslen); } @@ -214,9 +284,18 @@ static int os_setlocale (lua_State *L) { static int os_exit (lua_State *L) { - exit(luaL_optint(L, 1, EXIT_SUCCESS)); + int status; + if (lua_isboolean(L, 1)) + status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); + else + status = luaL_optint(L, 1, EXIT_SUCCESS); + if (lua_toboolean(L, 2)) + lua_close(L); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; } + static const luaL_Reg syslib[] = { {"clock", os_clock}, {"date", os_date}, @@ -236,8 +315,8 @@ static const luaL_Reg syslib[] = { -LUALIB_API int luaopen_os (lua_State *L) { - luaL_register(L, LUA_OSLIBNAME, syslib); +LUAMOD_API int luaopen_os (lua_State *L) { + luaL_newlib(L, syslib); return 1; } diff --git a/liblua/lparser.c b/liblua/lparser.c index 1e2a9a88b7..4d689365a9 100644 --- a/liblua/lparser.c +++ b/liblua/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: lparser.c,v 2.124 2011/12/02 13:23:56 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -27,11 +27,13 @@ -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) +/* maximum number of local variables per function (must be smaller + than 250, due to the bytecode format) */ +#define MAXVARS 200 + -#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) -#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) /* @@ -39,10 +41,11 @@ */ 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 */ + short firstlabel; /* index of first label in this block */ + short firstgoto; /* index of first pending goto in this block */ + lu_byte nactvar; /* # active locals outside the block */ lu_byte upval; /* true if some variable in the block is an upvalue */ - lu_byte isbreakable; /* true if `block' is a loop */ + lu_byte isloop; /* true if `block' is a loop */ } BlockCnt; @@ -50,11 +53,13 @@ typedef struct BlockCnt { /* ** prototypes for recursive non-terminal functions */ -static void chunk (LexState *ls); +static void statement (LexState *ls); static void expr (LexState *ls, expdesc *v); static void anchor_token (LexState *ls) { + /* last token from outer function must be EOS */ + lua_assert(ls->fs != NULL || ls->t.token == TK_EOS); 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); @@ -62,18 +67,34 @@ static void anchor_token (LexState *ls) { } -static void error_expected (LexState *ls, int token) { +/* semantic error */ +static l_noret semerror (LexState *ls, const char *msg) { + ls->t.token = 0; /* remove 'near to' from final message */ + luaX_syntaxerror(ls, msg); +} + + +static l_noret error_expected (LexState *ls, int token) { luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); + luaO_pushfstring(ls->L, "%s 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 l_noret errorlimit (FuncState *fs, int limit, const char *what) { + lua_State *L = fs->ls->L; + const char *msg; + int line = fs->f->linedefined; + const char *where = (line == 0) + ? "main function" + : luaO_pushfstring(L, "function at line %d", line); + msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", + what, limit, where); + luaX_syntaxerror(fs->ls, msg); +} + + +static void checklimit (FuncState *fs, int v, int l, const char *what) { + if (v > l) errorlimit(fs, l, what); } @@ -91,6 +112,7 @@ static void check (LexState *ls, int c) { error_expected(ls, c); } + static void checknext (LexState *ls, int c) { check(ls, c); luaX_next(ls); @@ -107,7 +129,7 @@ static void check_match (LexState *ls, int what, int who, int where) { error_expected(ls, what); else { luaX_syntaxerror(ls, luaO_pushfstring(ls->L, - LUA_QS " expected (to close " LUA_QS " at line %d)", + "%s expected (to close %s at line %d)", luaX_token2str(ls, what), luaX_token2str(ls, who), where)); } } @@ -126,7 +148,7 @@ static TString *str_checkname (LexState *ls) { static void init_exp (expdesc *e, expkind k, int i) { e->f = e->t = NO_JUMP; e->k = k; - e->u.s.info = i; + e->u.info = i; } @@ -135,7 +157,7 @@ static void codestring (LexState *ls, expdesc *e, TString *s) { } -static void checkname(LexState *ls, expdesc *e) { +static void checkname (LexState *ls, expdesc *e) { codestring(ls, e, str_checkname(ls)); } @@ -145,7 +167,7 @@ static int registerlocalvar (LexState *ls, TString *varname) { 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"); + LocVar, SHRT_MAX, "local variables"); while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; f->locvars[fs->nlocvars].varname = varname; luaC_objbarrier(ls->L, f, varname); @@ -153,14 +175,30 @@ static int registerlocalvar (LexState *ls, TString *varname) { } -#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) { + FuncState *fs = ls->fs; + Dyndata *dyd = ls->dyd; + int reg = registerlocalvar(ls, name); + checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, + MAXVARS, "local variables"); + luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, + dyd->actvar.size, Vardesc, MAX_INT, "local variables"); + dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); +} -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 new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { + new_localvar(ls, luaX_newstring(ls, name, sz)); +} + +#define new_localvarliteral(ls,v) \ + new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) + + +static LocVar *getlocvar (FuncState *fs, int i) { + int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; + lua_assert(idx < fs->nlocvars); + return &fs->f->locvars[idx]; } @@ -168,77 +206,88 @@ 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; + getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; } } -static void removevars (LexState *ls, int tolevel) { - FuncState *fs = ls->fs; +static void removevars (FuncState *fs, int tolevel) { + fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); while (fs->nactvar > tolevel) - getlocvar(fs, --fs->nactvar).endpc = fs->pc; + getlocvar(fs, --fs->nactvar)->endpc = fs->pc; } -static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { +static int searchupvalue (FuncState *fs, TString *name) { int i; + Upvaldesc *up = fs->f->upvalues; + for (i = 0; i < fs->nups; i++) { + if (eqstr(up[i].name, name)) return i; + } + return -1; /* not found */ +} + + +static int newupvalue (FuncState *fs, TString *name, expdesc *v) { 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++; + checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); + luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, + Upvaldesc, MAXUPVAL, "upvalues"); + while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; + f->upvalues[fs->nups].instack = (v->k == VLOCAL); + f->upvalues[fs->nups].idx = cast_byte(v->u.info); + f->upvalues[fs->nups].name = name; + luaC_objbarrier(fs->ls->L, f, name); + return fs->nups++; } static int searchvar (FuncState *fs, TString *n) { int i; for (i=fs->nactvar-1; i >= 0; i--) { - if (n == getlocvar(fs, i).varname) + if (eqstr(n, getlocvar(fs, i)->varname)) return i; } return -1; /* not found */ } +/* + Mark block where variable at given level was defined + (to emit close instructions later). +*/ static void markupval (FuncState *fs, int level) { BlockCnt *bl = fs->bl; - while (bl && bl->nactvar > level) bl = bl->previous; - if (bl) bl->upval = 1; + while (bl->nactvar > level) bl = bl->previous; + bl->upval = 1; } +/* + Find variable with given name 'n'. If it is an upvalue, add this + upvalue into all intermediate functions. +*/ 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; - } + if (fs == NULL) /* no more levels? */ + return VVOID; /* default is global */ else { - int v = searchvar(fs, n); /* look up at current level */ - if (v >= 0) { - init_exp(var, VLOCAL, v); + int v = searchvar(fs, n); /* look up locals at current level */ + if (v >= 0) { /* found? */ + init_exp(var, VLOCAL, v); /* variable is local */ 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 */ + else { /* not found as local at current level; try upvalues */ + int idx = searchupvalue(fs, n); /* try existing upvalues */ + if (idx < 0) { /* not found? */ + if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ + return VVOID; /* not found; is a global */ + /* else was LOCAL or UPVAL */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + } + init_exp(var, VUPVAL, idx); return VUPVAL; } } @@ -248,8 +297,13 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { 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 */ + if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ + expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ + lua_assert(var->k == VLOCAL || var->k == VUPVAL); + codestring(ls, &key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ + } } @@ -274,18 +328,118 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { static void enterlevel (LexState *ls) { - if (++ls->L->nCcalls > LUAI_MAXCCALLS) - luaX_lexerror(ls, "chunk has too many syntax levels", 0); + lua_State *L = ls->L; + ++L->nCcalls; + checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); } #define leavelevel(ls) ((ls)->L->nCcalls--) -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { - bl->breaklist = NO_JUMP; - bl->isbreakable = isbreakable; +static void closegoto (LexState *ls, int g, Labeldesc *label) { + int i; + FuncState *fs = ls->fs; + Labellist *gl = &ls->dyd->gt; + Labeldesc *gt = &gl->arr[g]; + lua_assert(eqstr(gt->name, label->name)); + if (gt->nactvar < label->nactvar) { + TString *vname = getlocvar(fs, gt->nactvar)->varname; + const char *msg = luaO_pushfstring(ls->L, + " at line %d jumps into the scope of local " LUA_QS, + getstr(gt->name), gt->line, getstr(vname)); + semerror(ls, msg); + } + luaK_patchlist(fs, gt->pc, label->pc); + /* remove goto from pending list */ + for (i = g; i < gl->n - 1; i++) + gl->arr[i] = gl->arr[i + 1]; + gl->n--; +} + + +/* +** try to close a goto with existing labels; this solves backward jumps +*/ +static int findlabel (LexState *ls, int g) { + int i; + BlockCnt *bl = ls->fs->bl; + Dyndata *dyd = ls->dyd; + Labeldesc *gt = &dyd->gt.arr[g]; + /* check labels in current block for a match */ + for (i = bl->firstlabel; i < dyd->label.n; i++) { + Labeldesc *lb = &dyd->label.arr[i]; + if (eqstr(lb->name, gt->name)) { /* correct label? */ + if (gt->nactvar > lb->nactvar && + (bl->upval || dyd->label.n > bl->firstlabel)) + luaK_patchclose(ls->fs, gt->pc, lb->nactvar); + closegoto(ls, g, lb); /* close it */ + return 1; + } + } + return 0; /* label not found; cannot close goto */ +} + + +static int newlabelentry (LexState *ls, Labellist *l, TString *name, + int line, int pc) { + int n = l->n; + luaM_growvector(ls->L, l->arr, n, l->size, + Labeldesc, SHRT_MAX, "labels/gotos"); + l->arr[n].name = name; + l->arr[n].line = line; + l->arr[n].nactvar = ls->fs->nactvar; + l->arr[n].pc = pc; + l->n++; + return n; +} + + +/* +** check whether new label 'lb' matches any pending gotos in current +** block; solves forward jumps +*/ +static void findgotos (LexState *ls, Labeldesc *lb) { + Labellist *gl = &ls->dyd->gt; + int i = ls->fs->bl->firstgoto; + while (i < gl->n) { + if (eqstr(gl->arr[i].name, lb->name)) + closegoto(ls, i, lb); + else + i++; + } +} + + +/* +** "export" pending gotos to outer level, to check them against +** outer labels; if the block being exited has upvalues, and +** the goto exits the scope of any variable (which can be the +** upvalue), close those variables being exited. +*/ +static void movegotosout (FuncState *fs, BlockCnt *bl) { + int i = bl->firstgoto; + Labellist *gl = &fs->ls->dyd->gt; + /* correct pending gotos to current block and try to close it + with visible labels */ + while (i < gl->n) { + Labeldesc *gt = &gl->arr[i]; + if (gt->nactvar > bl->nactvar) { + if (bl->upval) + luaK_patchclose(fs, gt->pc, bl->nactvar); + gt->nactvar = bl->nactvar; + } + if (!findlabel(fs->ls, i)) + i++; /* move to next one */ + } +} + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { + bl->isloop = isloop; bl->nactvar = fs->nactvar; + bl->firstlabel = fs->ls->dyd->label.n; + bl->firstgoto = fs->ls->dyd->gt.n; bl->upval = 0; bl->previous = fs->bl; fs->bl = bl; @@ -293,63 +447,100 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { } +/* +** create a label named "break" to resolve break statements +*/ +static void breaklabel (LexState *ls) { + TString *n = luaS_new(ls->L, "break"); + int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); + findgotos(ls, &ls->dyd->label.arr[l]); +} + +/* +** generates an error for an undefined 'goto'; choose appropriate +** message when label name is a reserved word (which can only be 'break') +*/ +static l_noret undefgoto (LexState *ls, Labeldesc *gt) { + const char *msg = (gt->name->tsv.reserved > 0) + ? "<%s> at line %d not inside a loop" + : "no visible label " LUA_QS " for at line %d"; + msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); + semerror(ls, msg); +} + + static void leaveblock (FuncState *fs) { BlockCnt *bl = fs->bl; + LexState *ls = fs->ls; + if (bl->previous && bl->upval) { + /* create a 'jump to here' to close upvalues */ + int j = luaK_jump(fs); + luaK_patchclose(fs, j, bl->nactvar); + luaK_patchtohere(fs, j); + } + if (bl->isloop) + breaklabel(ls); /* close pending breaks */ 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); + removevars(fs, bl->nactvar); lua_assert(bl->nactvar == fs->nactvar); fs->freereg = fs->nactvar; /* free registers */ - luaK_patchtohere(fs, bl->breaklist); + ls->dyd->label.n = bl->firstlabel; /* remove local labels */ + if (bl->previous) /* inner block? */ + movegotosout(fs, bl); /* update pending gotos to outer block */ + else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ } -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); +/* +** adds prototype being created into its parent list of prototypes +** and codes instruction to create new closure +*/ +static void codeclosure (LexState *ls, Proto *clp, expdesc *v) { + FuncState *fs = ls->fs->prev; + Proto *f = fs->f; /* prototype of function creating new closure */ + if (fs->np >= f->sizep) { + int oldsize = f->sizep; + luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, + MAXARG_Bx, "functions"); + while (oldsize < f->sizep) f->p[oldsize++] = NULL; } + f->p[fs->np++] = clp; + luaC_objbarrier(ls->L, f, clp); + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); + luaK_exp2nextreg(fs, v); /* fix it at stack top (for GC) */ } -static void open_func (LexState *ls, FuncState *fs) { +static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { lua_State *L = ls->L; - Proto *f = luaF_newproto(L); - fs->f = f; + Proto *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->lasttarget = 0; fs->jpc = NO_JUMP; fs->freereg = 0; fs->nk = 0; fs->np = 0; + fs->nups = 0; fs->nlocvars = 0; fs->nactvar = 0; + fs->firstlocal = ls->dyd->actvar.n; fs->bl = NULL; + f = luaF_newproto(L); + fs->f = f; 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); + /* anchor prototype (to avoid being collected) */ setptvalue2s(L, L->top, f); incr_top(L); + fs->h = luaH_new(L); + /* anchor table of constants (to avoid being collected) */ + sethvalue2s(L, L->top, fs->h); + incr_top(L); + enterblock(fs, bl, 0); } @@ -357,8 +548,8 @@ 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 */ + leaveblock(fs); luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); f->sizecode = fs->pc; luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); @@ -369,32 +560,28 @@ static void close_func (LexState *ls) { 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)); + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); + f->sizeupvalues = fs->nups; 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); + /* last token read was anchored in defunct function; must re-anchor it */ + anchor_token(ls); + L->top--; /* pop table of constants */ + luaC_checkGC(L); + L->top--; /* pop prototype (after possible collection) */ } -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; +/* +** opens the main function, which is a regular vararg function with an +** upvalue named LUA_ENV +*/ +static void open_mainfunc (LexState *ls, FuncState *fs, BlockCnt *bl) { + expdesc v; + open_func(ls, fs, bl); + fs->f->is_vararg = 1; /* main function is always vararg */ + init_exp(&v, VLOCAL, 0); + newupvalue(fs, ls->envn, &v); /* create environment upvalue */ } @@ -404,11 +591,39 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { /*============================================================*/ -static void field (LexState *ls, expdesc *v) { - /* field -> ['.' | ':'] NAME */ +/* +** check whether current token is in the follow set of a block. +** 'until' closes syntactical blocks, but do not close scope, +** so it handled in separate. +*/ +static int block_follow (LexState *ls, int withuntil) { + switch (ls->t.token) { + case TK_ELSE: case TK_ELSEIF: + case TK_END: case TK_EOS: + return 1; + case TK_UNTIL: return withuntil; + default: return 0; + } +} + + +static void statlist (LexState *ls) { + /* statlist -> { stat [`;'] } */ + while (!block_follow(ls, 1)) { + if (ls->t.token == TK_RETURN) { + statement(ls); + return; /* 'return' must be last statement */ + } + statement(ls); + } +} + + +static void fieldsel (LexState *ls, expdesc *v) { + /* fieldsel -> ['.' | ':'] NAME */ FuncState *fs = ls->fs; expdesc key; - luaK_exp2anyreg(fs, v); + luaK_exp2anyregup(fs, v); luaX_next(ls); /* skip the dot or colon */ checkname(ls, &key); luaK_indexed(fs, v, &key); @@ -447,7 +662,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { expdesc key, val; int rkkey; if (ls->t.token == TK_NAME) { - luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); checkname(ls, &key); } else /* ls->t.token == '[' */ @@ -456,7 +671,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { 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)); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); fs->freereg = reg; /* free registers */ } @@ -466,7 +681,7 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) { 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 */ + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ cc->tostore = 0; /* no more items pending */ } } @@ -476,27 +691,51 @@ 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); + luaK_setlist(fs, cc->t->u.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); + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); } } static void listfield (LexState *ls, struct ConsControl *cc) { + /* listfield -> exp */ expr(ls, &cc->v); - luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); cc->na++; cc->tostore++; } +static void field (LexState *ls, struct ConsControl *cc) { + /* field -> listfield | recfield */ + switch(ls->t.token) { + case TK_NAME: { /* may be 'listfield' or 'recfield' */ + if (luaX_lookahead(ls) != '=') /* expression? */ + listfield(ls, cc); + else + recfield(ls, cc); + break; + } + case '[': { + recfield(ls, cc); + break; + } + default: { + listfield(ls, cc); + break; + } + } +} + + static void constructor (LexState *ls, expdesc *t) { - /* constructor -> ?? */ + /* constructor -> '{' [ field { sep field } [sep] ] '}' + sep -> ',' | ';' */ FuncState *fs = ls->fs; int line = ls->linenumber; int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); @@ -505,30 +744,13 @@ static void constructor (LexState *ls, expdesc *t) { 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) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ 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; - } - } + field(ls, &cc); } while (testnext(ls, ',') || testnext(ls, ';')); check_match(ls, '}', '{', line); lastlistfield(fs, &cc); @@ -550,17 +772,13 @@ static void parlist (LexState *ls) { do { switch (ls->t.token) { case TK_NAME: { /* param -> NAME */ - new_localvar(ls, str_checkname(ls), nparams++); + 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; + f->is_vararg = 1; break; } default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); @@ -568,33 +786,34 @@ static void parlist (LexState *ls) { } while (!f->is_vararg && testnext(ls, ',')); } adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); + f->numparams = cast_byte(fs->nactvar); luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ } -static void body (LexState *ls, expdesc *e, int needself, int line) { - /* body -> `(' parlist `)' chunk END */ +static void body (LexState *ls, expdesc *e, int ismethod, int line) { + /* body -> `(' parlist `)' block END */ FuncState new_fs; - open_func(ls, &new_fs); + BlockCnt bl; + open_func(ls, &new_fs, &bl); new_fs.f->linedefined = line; checknext(ls, '('); - if (needself) { - new_localvarliteral(ls, "self", 0); + if (ismethod) { + new_localvarliteral(ls, "self"); /* create 'self' parameter */ adjustlocalvars(ls, 1); } parlist(ls); checknext(ls, ')'); - chunk(ls); + statlist(ls); new_fs.f->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); + codeclosure(ls, new_fs.f, e); close_func(ls); - pushclosure(ls, &new_fs, e); } -static int explist1 (LexState *ls, expdesc *v) { - /* explist1 -> expr { `,' expr } */ +static int explist (LexState *ls, expdesc *v) { + /* explist -> expr { `,' expr } */ int n = 1; /* at least one expression */ expr(ls, v); while (testnext(ls, ',')) { @@ -606,20 +825,17 @@ static int explist1 (LexState *ls, expdesc *v) { } -static void funcargs (LexState *ls, expdesc *f) { +static void funcargs (LexState *ls, expdesc *f, int line) { 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)"); + case '(': { /* funcargs -> `(' [ explist ] `)' */ luaX_next(ls); if (ls->t.token == ')') /* arg list is empty? */ args.k = VVOID; else { - explist1(ls, &args); + explist(ls, &args); luaK_setmultret(fs, &args); } check_match(ls, ')', '(', line); @@ -636,11 +852,10 @@ static void funcargs (LexState *ls, expdesc *f) { } default: { luaX_syntaxerror(ls, "function arguments expected"); - return; } } lua_assert(f->k == VNONRELOC); - base = f->u.s.info; /* base register for call */ + base = f->u.info; /* base register for call */ if (hasmultret(args.k)) nparams = LUA_MULTRET; /* open call */ else { @@ -681,7 +896,6 @@ static void prefixexp (LexState *ls, expdesc *v) { } default: { luaX_syntaxerror(ls, "unexpected symbol"); - return; } } } @@ -691,16 +905,17 @@ static void primaryexp (LexState *ls, expdesc *v) { /* primaryexp -> prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ FuncState *fs = ls->fs; + int line = ls->linenumber; prefixexp(ls, v); for (;;) { switch (ls->t.token) { - case '.': { /* field */ - field(ls, v); + case '.': { /* fieldsel */ + fieldsel(ls, v); break; } case '[': { /* `[' exp1 `]' */ expdesc key; - luaK_exp2anyreg(fs, v); + luaK_exp2anyregup(fs, v); yindex(ls, &key); luaK_indexed(fs, v, &key); break; @@ -710,12 +925,12 @@ static void primaryexp (LexState *ls, expdesc *v) { luaX_next(ls); checkname(ls, &key); luaK_self(fs, v, &key); - funcargs(ls, v); + funcargs(ls, v, line); break; } case '(': case TK_STRING: case '{': { /* funcargs */ luaK_exp2nextreg(fs, v); - funcargs(ls, v); + funcargs(ls, v, line); break; } default: return; @@ -725,7 +940,7 @@ static void primaryexp (LexState *ls, expdesc *v) { static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | + /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | constructor | FUNCTION body | primaryexp */ switch (ls->t.token) { case TK_NUMBER: { @@ -753,7 +968,6 @@ static void simpleexp (LexState *ls, expdesc *v) { 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; } @@ -811,11 +1025,11 @@ 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) */ + {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */ + {10, 9}, {5, 4}, /* ^, .. (right associative) */ + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ + {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ + {2, 2}, {1, 1} /* and, or */ }; #define UNARY_PRIORITY 8 /* priority for unary operators */ @@ -825,15 +1039,16 @@ static const struct { ** 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) { +static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { BinOpr op; UnOpr uop; enterlevel(ls); uop = getunopr(ls->t.token); if (uop != OPR_NOUNOPR) { + int line = ls->linenumber; luaX_next(ls); subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls->fs, uop, v); + luaK_prefix(ls->fs, uop, v, line); } else simpleexp(ls, v); /* expand while operators have priorities higher than `limit' */ @@ -841,11 +1056,12 @@ static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { while (op != OPR_NOBINOPR && priority[op].left > limit) { expdesc v2; BinOpr nextop; + int line = ls->linenumber; 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); + luaK_posfix(ls->fs, op, v, &v2, line); op = nextop; } leavelevel(ls); @@ -868,23 +1084,12 @@ static void expr (LexState *ls, expdesc *v) { */ -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 */ + /* block -> statlist */ FuncState *fs = ls->fs; BlockCnt bl; enterblock(fs, &bl, 0); - chunk(ls); - lua_assert(bl.breaklist == NO_JUMP); + statlist(ls); leaveblock(fs); } @@ -900,29 +1105,34 @@ struct LHS_assign { /* -** 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. +** check whether, in an assignment to an upvalue/local variable, the +** upvalue/local variable is begin used in a previous assignment to a +** table. If so, save original upvalue/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? */ + for (; lh; lh = lh->prev) { /* check all previous assignments */ + if (lh->v.k == VINDEXED) { /* assigning to a table? */ + /* table is the upvalue/local being assigned now? */ + if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { conflict = 1; - lh->v.u.s.info = extra; /* previous assignment will use safe copy */ + lh->v.u.ind.vt = VLOCAL; + lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ } - if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ + /* index is the local being assigned? (index cannot be upvalue) */ + if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { conflict = 1; - lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ } } } if (conflict) { - luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ + /* copy upvalue/local value to a temporary (in position 'extra') */ + OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, op, extra, v->u.info, 0); luaK_reserveregs(fs, 1); } } @@ -930,22 +1140,21 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { 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"); + check_condition(ls, vkisvar(lh->v.k), "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); - if (nv.v.k == VLOCAL) + if (nv.v.k != VINDEXED) check_conflict(ls, lh, &nv.v); - luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, - "variables in assignment"); + checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, + "C levels"); assignment(ls, &nv, nvars+1); } - else { /* assignment -> `=' explist1 */ + else { /* assignment -> `=' explist */ int nexps; checknext(ls, '='); - nexps = explist1(ls, &e); + nexps = explist(ls, &e); if (nexps != nvars) { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) @@ -972,19 +1181,52 @@ static int cond (LexState *ls) { } -static void breakstat (LexState *ls) { +static void gotostat (LexState *ls, int pc) { + int line = ls->linenumber; + TString *label; + int g; + if (testnext(ls, TK_GOTO)) + label = str_checkname(ls); + else { + luaX_next(ls); /* skip break */ + label = luaS_new(ls->L, "break"); + } + g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); + findlabel(ls, g); /* close it if label already defined */ +} + + +/* check for repeated labels on the same block */ +static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { + int i; + for (i = fs->bl->firstlabel; i < ll->n; i++) { + if (eqstr(label, ll->arr[i].name)) { + const char *msg = luaO_pushfstring(fs->ls->L, + "label " LUA_QS " already defined on line %d", + getstr(label), ll->arr[i].line); + semerror(fs->ls, msg); + } + } +} + + +static void labelstat (LexState *ls, TString *label, int line) { + /* label -> '::' NAME '::' */ FuncState *fs = ls->fs; - BlockCnt *bl = fs->bl; - int upval = 0; - while (bl && !bl->isbreakable) { - upval |= bl->upval; - bl = bl->previous; + Labellist *ll = &ls->dyd->label; + int l; /* index of new label being created */ + checkrepeated(fs, ll, label); /* check for repeated labels */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + /* create new entry for this label */ + l = newlabelentry(ls, ll, label, line, fs->pc); + /* skip other no-op statements */ + while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) + statement(ls); + if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ + ll->arr[l].nactvar = fs->bl->nactvar; } - 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)); + findgotos(ls, &ll->arr[l]); } @@ -1000,7 +1242,7 @@ static void whilestat (LexState *ls, int line) { enterblock(fs, &bl, 1); checknext(ls, TK_DO); block(ls); - luaK_patchlist(fs, luaK_jump(fs), whileinit); + luaK_jumpto(fs, whileinit); check_match(ls, TK_END, TK_WHILE, line); leaveblock(fs); luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ @@ -1016,30 +1258,25 @@ static void repeatstat (LexState *ls, int line) { enterblock(fs, &bl1, 1); /* loop block */ enterblock(fs, &bl2, 0); /* scope block */ luaX_next(ls); /* skip REPEAT */ - chunk(ls); + statlist(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 */ - } + if (bl2.upval) /* upvalues? */ + luaK_patchclose(fs, condexit, bl2.nactvar); + leaveblock(fs); /* finish scope */ + luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ leaveblock(fs); /* finish loop */ } static int exp1 (LexState *ls) { expdesc e; - int k; + int reg; expr(ls, &e); - k = e.k; luaK_exp2nextreg(ls->fs, &e); - return k; + lua_assert(e.k == VNONRELOC); + reg = e.u.info; + return reg; } @@ -1057,10 +1294,15 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { 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); + if (isnum) /* numeric for? */ + endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); + else { /* generic for */ + luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); + luaK_fixline(fs, line); + endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); + } + luaK_patchlist(fs, endfor, prep + 1); + luaK_fixline(fs, line); } @@ -1068,10 +1310,10 @@ 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); + new_localvarliteral(ls, "(for index)"); + new_localvarliteral(ls, "(for limit)"); + new_localvarliteral(ls, "(for step)"); + new_localvar(ls, varname); checknext(ls, '='); exp1(ls); /* initial value */ checknext(ls, ','); @@ -1079,7 +1321,7 @@ static void fornum (LexState *ls, TString *varname, int line) { if (testnext(ls, ',')) exp1(ls); /* optional step */ else { /* default step = 1 */ - luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); + luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1)); luaK_reserveregs(fs, 1); } forbody(ls, base, line, 1, 1); @@ -1087,23 +1329,25 @@ static void fornum (LexState *ls, TString *varname, int line) { static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist1 forbody */ + /* forlist -> NAME {,NAME} IN explist forbody */ FuncState *fs = ls->fs; expdesc e; - int nvars = 0; + int nvars = 4; /* gen, state, control, plus at least one declared var */ 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++); + new_localvarliteral(ls, "(for generator)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for control)"); /* create declared variables */ - new_localvar(ls, indexname, nvars++); - while (testnext(ls, ',')) - new_localvar(ls, str_checkname(ls), nvars++); + new_localvar(ls, indexname); + 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); + adjust_assign(ls, 3, explist(ls, &e), &e); luaK_checkstack(fs, 3); /* extra space to call generator */ forbody(ls, base, line, nvars - 3, 0); } @@ -1127,65 +1371,76 @@ static void forstat (LexState *ls, int line) { } -static int test_then_block (LexState *ls) { +static void test_then_block (LexState *ls, int *escapelist) { /* test_then_block -> [IF | ELSEIF] cond THEN block */ - int condexit; + BlockCnt bl; + FuncState *fs = ls->fs; + expdesc v; + int jf; /* instruction to skip 'then' code (if condition is false) */ luaX_next(ls); /* skip IF or ELSEIF */ - condexit = cond(ls); + expr(ls, &v); /* read condition */ checknext(ls, TK_THEN); - block(ls); /* `then' part */ - return condexit; + if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { + luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + gotostat(ls, v.t); /* handle goto/break */ + if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ + leaveblock(fs); + return; /* and that is it */ + } + else /* must skip over 'then' part if condition is false */ + jf = luaK_jump(fs); + } + else { /* regular case (not goto/break) */ + luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ + enterblock(fs, &bl, 0); + jf = v.f; + } + statlist(ls); /* `then' part */ + leaveblock(fs); + if (ls->t.token == TK_ELSE || + ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ + luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ + luaK_patchtohere(fs, jf); } 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) */ + int escapelist = NO_JUMP; /* exit list for finished parts */ + test_then_block(ls, &escapelist); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) + test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ + if (testnext(ls, TK_ELSE)) block(ls); /* `else' part */ - } - else - luaK_concat(fs, &escapelist, flist); - luaK_patchtohere(fs, escapelist); check_match(ls, TK_END, TK_IF, line); + luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ } static void localfunc (LexState *ls) { - expdesc v, b; + expdesc 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); + new_localvar(ls, str_checkname(ls)); /* new local variable */ + adjustlocalvars(ls, 1); /* enter its scope */ + body(ls, &b, 0, ls->linenumber); /* function created in next register */ /* debug information will only see the variable after this point! */ - getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; + getlocvar(fs, b.u.info)->startpc = fs->pc; } static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ + /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ int nvars = 0; int nexps; expdesc e; do { - new_localvar(ls, str_checkname(ls), nvars++); + new_localvar(ls, str_checkname(ls)); + nvars++; } while (testnext(ls, ',')); if (testnext(ls, '=')) - nexps = explist1(ls, &e); + nexps = explist(ls, &e); else { e.k = VVOID; nexps = 0; @@ -1196,26 +1451,26 @@ static void localstat (LexState *ls) { static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME {field} [`:' NAME] */ - int needself = 0; + /* funcname -> NAME {fieldsel} [`:' NAME] */ + int ismethod = 0; singlevar(ls, v); while (ls->t.token == '.') - field(ls, v); + fieldsel(ls, v); if (ls->t.token == ':') { - needself = 1; - field(ls, v); + ismethod = 1; + fieldsel(ls, v); } - return needself; + return ismethod; } static void funcstat (LexState *ls, int line) { /* funcstat -> FUNCTION funcname body */ - int needself; + int ismethod; expdesc v, b; luaX_next(ls); /* skip FUNCTION */ - needself = funcname(ls, &v); - body(ls, &b, needself, line); + ismethod = funcname(ls, &v); + body(ls, &b, ismethod, line); luaK_storevar(ls->fs, &v, &b); luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ } @@ -1236,15 +1491,14 @@ static void exprstat (LexState *ls) { static void retstat (LexState *ls) { - /* stat -> RETURN explist */ + /* 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 == ';') + if (block_follow(ls, 1) || ls->t.token == ';') first = nret = 0; /* return no values */ else { - nret = explist1(ls, &e); /* optional return values */ + nret = explist(ls, &e); /* optional return values */ if (hasmultret(e.k)) { luaK_setmultret(fs, &e); if (e.k == VCALL && nret == 1) { /* tail call? */ @@ -1265,37 +1519,43 @@ static void retstat (LexState *ls) { } } luaK_ret(fs, first, nret); + testnext(ls, ';'); /* skip optional semicolon */ } -static int statement (LexState *ls) { +static void statement (LexState *ls) { int line = ls->linenumber; /* may be needed for error messages */ + enterlevel(ls); switch (ls->t.token) { + case ';': { /* stat -> ';' (empty statement) */ + luaX_next(ls); /* skip ';' */ + break; + } case TK_IF: { /* stat -> ifstat */ ifstat(ls, line); - return 0; + break; } case TK_WHILE: { /* stat -> whilestat */ whilestat(ls, line); - return 0; + break; } case TK_DO: { /* stat -> DO block END */ luaX_next(ls); /* skip DO */ block(ls); check_match(ls, TK_END, TK_DO, line); - return 0; + break; } case TK_FOR: { /* stat -> forstat */ forstat(ls, line); - return 0; + break; } case TK_REPEAT: { /* stat -> repeatstat */ repeatstat(ls, line); - return 0; + break; } - case TK_FUNCTION: { - funcstat(ls, line); /* stat -> funcstat */ - return 0; + case TK_FUNCTION: { /* stat -> funcstat */ + funcstat(ls, line); + break; } case TK_LOCAL: { /* stat -> localstat */ luaX_next(ls); /* skip LOCAL */ @@ -1303,37 +1563,58 @@ static int statement (LexState *ls) { localfunc(ls); else localstat(ls); - return 0; + break; + } + case TK_DBCOLON: { /* stat -> label */ + luaX_next(ls); /* skip double colon */ + labelstat(ls, str_checkname(ls), line); + break; } case TK_RETURN: { /* stat -> retstat */ + luaX_next(ls); /* skip RETURN */ retstat(ls); - return 1; /* must be last statement */ + break; } - case TK_BREAK: { /* stat -> breakstat */ - luaX_next(ls); /* skip BREAK */ - breakstat(ls); - return 1; /* must be last statement */ + case TK_BREAK: /* stat -> breakstat */ + case TK_GOTO: { /* stat -> 'goto' NAME */ + gotostat(ls, luaK_jump(ls->fs)); + break; } - default: { + default: { /* stat -> func | assignment */ exprstat(ls); - return 0; /* to avoid warnings */ + break; } } + 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); } +/* }====================================================================== */ -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); + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar) { + LexState lexstate; + FuncState funcstate; + BlockCnt bl; + TString *tname = luaS_new(L, name); + setsvalue2s(L, L->top, tname); /* push name to protect it */ + incr_top(L); + lexstate.buff = buff; + lexstate.dyd = dyd; + dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; + luaX_setinput(L, &lexstate, z, tname, firstchar); + open_mainfunc(&lexstate, &funcstate, &bl); + luaX_next(&lexstate); /* read first token */ + statlist(&lexstate); /* main body */ + check(&lexstate, TK_EOS); + close_func(&lexstate); + L->top--; /* pop name */ + lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); + /* all scopes should be correctly finished */ + lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); + return funcstate.f; } -/* }====================================================================== */ diff --git a/liblua/lparser.h b/liblua/lparser.h index 18836afd1c..caabf46ccc 100644 --- a/liblua/lparser.h +++ b/liblua/lparser.h @@ -1,5 +1,5 @@ /* -** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lparser.h,v 1.69 2011/07/27 18:09:01 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -23,34 +23,72 @@ typedef enum { VFALSE, VK, /* info = index of constant in `k' */ VKNUM, /* nval = numerical value */ + VNONRELOC, /* info = result register */ 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') */ + VUPVAL, /* info = index of upvalue in 'upvalues' */ + VINDEXED, /* t = table register/upvalue; idx = index R/K */ VJMP, /* info = instruction pc */ VRELOCABLE, /* info = instruction pc */ - VNONRELOC, /* info = result register */ VCALL, /* info = instruction pc */ VVARARG /* info = instruction pc */ } expkind; + +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) +#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) + typedef struct expdesc { expkind k; union { - struct { int info, aux; } s; - lua_Number nval; + struct { /* for indexed variables (VINDEXED) */ + short idx; /* index (R/K) */ + lu_byte t; /* table (register or upvalue) */ + lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ + } ind; + int info; /* for generic use */ + lua_Number nval; /* for VKNUM */ } 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; +/* description of active local variable */ +typedef struct Vardesc { + short idx; /* variable index in stack */ +} Vardesc; + + +/* description of pending goto statements and label statements */ +typedef struct Labeldesc { + TString *name; /* label identifier */ + int pc; /* position in code */ + int line; /* line where it appeared */ + lu_byte nactvar; /* local level where it appears in current block */ +} Labeldesc; + + +/* list of labels or gotos */ +typedef struct Labellist { + Labeldesc *arr; /* array */ + int n; /* number of entries in use */ + int size; /* array size */ +} Labellist; + + +/* dynamic structures used by the parser */ +typedef struct Dyndata { + struct { /* list of active local variables */ + Vardesc *arr; + int n; + int size; + } actvar; + Labellist gt; /* list of pending gotos */ + Labellist label; /* list of active labels */ +} Dyndata; +/* control of blocks */ struct BlockCnt; /* defined in lparser.c */ @@ -60,23 +98,22 @@ typedef struct FuncState { 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 lasttarget; /* 'label' of last 'jump label' */ 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' */ + int firstlocal; /* index of first local var (in Dyndata array) */ + short nlocvars; /* number of elements in 'f->locvars' */ lu_byte nactvar; /* number of active local variables */ - upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ - unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ + lu_byte nups; /* number of upvalues */ + lu_byte freereg; /* first free register */ } FuncState; LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - const char *name); + Dyndata *dyd, const char *name, int firstchar); #endif diff --git a/liblua/lstate.c b/liblua/lstate.c index 4313b83a0c..6e2801c490 100644 --- a/liblua/lstate.c +++ b/liblua/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ +** $Id: lstate.c,v 2.92 2011/10/03 17:54:25 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -12,6 +12,7 @@ #include "lua.h" +#include "lapi.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" @@ -24,119 +25,203 @@ #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)) +#if !defined(LUAI_GCPAUSE) +#define LUAI_GCPAUSE 200 /* 200% */ +#endif + +#if !defined(LUAI_GCMAJOR) +#define LUAI_GCMAJOR 200 /* 200% */ +#endif + +#if !defined(LUAI_GCMUL) +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ +#endif + + +#define MEMERRMSG "not enough memory" + + +/* +** thread state + extra space +*/ +typedef struct LX { +#if defined(LUAI_EXTRASPACE) + char buff[LUAI_EXTRASPACE]; +#endif + lua_State l; +} LX; /* ** Main thread combines a thread state and the global state */ typedef struct LG { - lua_State l; + LX l; global_State g; } LG; - + + + +#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) + + +/* +** set GCdebt to a new value keeping the value (totalbytes + GCdebt) +** invariant +*/ +void luaE_setdebt (global_State *g, l_mem debt) { + g->totalbytes -= (debt - g->GCdebt); + g->GCdebt = debt; +} + + +CallInfo *luaE_extendCI (lua_State *L) { + CallInfo *ci = luaM_new(L, CallInfo); + lua_assert(L->ci->next == NULL); + L->ci->next = ci; + ci->previous = L->ci; + ci->next = NULL; + return ci; +} + + +void luaE_freeCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next = ci->next; + ci->next = NULL; + while ((ci = next) != NULL) { + next = ci->next; + luaM_free(L, ci); + } +} 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; + int i; CallInfo *ci; /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); - L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); + L1->stacksize = BASIC_STACK_SIZE; + for (i = 0; i < BASIC_STACK_SIZE; i++) + setnilvalue(L1->stack + i); /* erase new stack */ L1->top = L1->stack; - L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; + L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; /* 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; + ci = &L1->base_ci; + ci->next = ci->previous = NULL; + ci->callstatus = 0; + ci->func = L1->top; + setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ + ci->top = L1->top + LUA_MINSTACK; + L1->ci = ci; +} + + +static void freestack (lua_State *L) { + if (L->stack == NULL) + return; /* stack not completely built yet */ + L->ci = &L->base_ci; /* free the entire 'ci' list */ + luaE_freeCI(L); + luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ } -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); +/* +** Create registry table and its predefined values +*/ +static void init_registry (lua_State *L, global_State *g) { + TValue mt; + /* create registry */ + Table *registry = luaH_new(L); + sethvalue(L, &g->l_registry, registry); + luaH_resize(L, registry, LUA_RIDX_LAST, 0); + /* registry[LUA_RIDX_MAINTHREAD] = L */ + setthvalue(L, &mt, L); + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt); + /* registry[LUA_RIDX_GLOBALS] = table of globals */ + sethvalue(L, &mt, luaH_new(L)); + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt); } /* -** open parts that may cause memory-allocation errors +** open parts of the state 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 */ + init_registry(L, g); 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; + /* pre-create memory-error message */ + g->memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaS_fix(g->memerrmsg); /* it should never be collected */ + g->gcrunning = 1; /* allow gc */ } +/* +** preinitialize a state with consistent values without allocating +** any memory (to avoid errors) +*/ static void preinit_state (lua_State *L, global_State *g) { G(L) = g; L->stack = NULL; + L->ci = NULL; L->stacksize = 0; L->errorJmp = NULL; + L->nCcalls = 0; 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->nny = 1; + L->status = LUA_OK; 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 *); + luaC_freeallobjects(L); /* collect all objects */ + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); luaZ_freebuffer(L, &g->buff); - freestack(L, L); - lua_assert(g->totalbytes == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); + freestack(L); + lua_assert(gettotalbytes(g) == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ } -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); +LUA_API lua_State *lua_newthread (lua_State *L) { + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th; + setthvalue(L, L->top, L1); + api_incr_top(L); 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))); + luai_userstatethread(L, L1); + stack_init(L1, L); /* init stack */ + lua_unlock(L); return L1; } void luaE_freethread (lua_State *L, lua_State *L1) { + LX *l = fromstate(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)); + luai_userstatefree(L, L1); + freestack(L1); + luaM_free(L, l); } @@ -144,42 +229,43 @@ 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)); + LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); if (l == NULL) return NULL; - L = tostate(l); - g = &((LG *)L)->g; + L = &l->l.l; + g = &l->g; L->next = NULL; L->tt = LUA_TTHREAD; g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); L->marked = luaC_white(g); - set2bits(L->marked, FIXEDBIT, SFIXEDBIT); + g->gckind = KGC_NORMAL; 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->gcrunning = 0; /* no GC while building state */ + g->lastmajormem = 0; g->strt.size = 0; g->strt.nuse = 0; g->strt.hash = NULL; - setnilvalue(registry(L)); + setnilvalue(&g->l_registry); luaZ_initbuffer(L, &g->buff); g->panic = NULL; + g->version = lua_version(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->allgc = NULL; + g->finobj = NULL; + g->tobefnz = NULL; + g->gray = g->grayagain = NULL; + g->weak = g->ephemeron = g->allweak = NULL; g->totalbytes = sizeof(LG); + g->GCdebt = 0; g->gcpause = LUAI_GCPAUSE; + g->gcmajorinc = LUAI_GCMAJOR; g->gcstepmul = LUAI_GCMUL; - g->gcdept = 0; - for (i=0; imt[i] = NULL; - if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { + for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { /* memory allocation error: free partial state */ close_state(L); L = NULL; @@ -190,25 +276,11 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { } -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/liblua/lstate.h b/liblua/lstate.h index 3bc575b6bc..4743d74103 100644 --- a/liblua/lstate.h +++ b/liblua/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ +** $Id: lstate.h,v 2.74 2011/09/30 12:45:07 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ @@ -14,26 +14,47 @@ #include "lzio.h" +/* -struct lua_longjmp; /* defined in ldo.c */ +** Some notes about garbage-collected objects: All objects in Lua must +** be kept somehow accessible until being freed. +** +** Lua keeps most objects linked in list g->allgc. The link uses field +** 'next' of the CommonHeader. +** +** Strings are kept in several lists headed by the array g->strt.hash. +** +** Open upvalues are not subject to independent garbage collection. They +** are collected together with their respective threads. Lua keeps a +** double-linked list with all open upvalues (g->uvhead) so that it can +** mark objects referred by them. (They are always gray, so they must +** be remarked in the atomic step. Usually their contents would be marked +** when traversing the respective threads, but the thread may already be +** dead, while the upvalue is still accessible through closures.) +** +** Objects with finalizers are kept in the list g->finobj. +** +** The list g->tobefnz links all objects being finalized. +*/ -/* table of globals */ -#define gt(L) (&L->l_gt) -/* registry */ -#define registry(L) (&G(L)->l_registry) +struct lua_longjmp; /* defined in ldo.c */ + /* 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) +/* kinds of Garbage Collection */ +#define KGC_NORMAL 0 +#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ +#define KGC_GEN 2 /* generational collection */ + typedef struct stringtable { GCObject **hash; @@ -43,54 +64,83 @@ typedef struct stringtable { /* -** informations about a call +** information 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 */ + struct CallInfo *previous, *next; /* dynamic call link */ + short nresults; /* expected number of results from this function */ + lu_byte callstatus; + union { + struct { /* only for Lua functions */ + StkId base; /* base for this function */ + const Instruction *savedpc; + } l; + struct { /* only for C functions */ + int ctx; /* context info. in case of yields */ + lua_CFunction k; /* continuation in case of yields */ + ptrdiff_t old_errfunc; + ptrdiff_t extra; + lu_byte old_allowhook; + lu_byte status; + } c; + } u; } CallInfo; +/* +** Bits in CallInfo status +*/ +#define CIST_LUA (1<<0) /* call is running a Lua function */ +#define CIST_HOOKED (1<<1) /* call is running a debug hook */ +#define CIST_REENTRY (1<<2) /* call is running on same invocation of + luaV_execute of previous call */ +#define CIST_YIELDED (1<<3) /* call reentered after suspension */ +#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ +#define CIST_STAT (1<<5) /* call has an error status (pcall) */ +#define CIST_TAIL (1<<6) /* call was tail called */ + -#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)) +#define isLua(ci) ((ci)->callstatus & CIST_LUA) /* ** `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_mem totalbytes; /* number of bytes currently allocated - GCdebt */ + l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ + lu_mem lastmajormem; /* memory in use after last major collection */ + stringtable strt; /* hash table for strings */ + TValue l_registry; lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ + lu_byte gckind; /* kind of GC running */ + lu_byte gcrunning; /* true if GC is running */ int sweepstrgc; /* position of sweep in `strt' */ - GCObject *rootgc; /* list of all collectable objects */ - GCObject **sweepgc; /* position of sweep in `rootgc' */ + GCObject *allgc; /* list of all collectable objects */ + GCObject *finobj; /* list of collectable objects with finalizers */ + GCObject **sweepgc; /* current position of sweep */ 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' */ + GCObject *weak; /* list of tables with weak values */ + GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ + GCObject *allweak; /* list of all-weak tables */ + GCObject *tobefnz; /* list of userdata to be GC */ + UpVal uvhead; /* head of double-linked list of all open upvalues */ + Mbuffer buff; /* temporary buffer for string concatenation */ int gcpause; /* size of pause between successive GCs */ + int gcmajorinc; /* how much to wait for a major GC (only in gen. mode) */ 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 */ + const lua_Number *version; /* pointer to version number */ + TString *memerrmsg; /* memory-error message */ TString *tmname[TM_N]; /* array with tag-method names */ + struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ } global_State; @@ -101,29 +151,24 @@ 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 */ + const Instruction *oldpc; /* last pc traced */ 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 nny; /* number of non-yieldable calls in stack */ 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) */ + CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ }; @@ -134,7 +179,7 @@ struct lua_State { ** Union of all collectable objects */ union GCObject { - GCheader gch; + GCheader gch; /* common header */ union TString ts; union Udata u; union Closure cl; @@ -145,25 +190,31 @@ union GCObject { }; +#define gch(o) (&(o)->gch) + /* 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 gco2t(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); +/* actual number of total bytes allocated */ +#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) + +LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); +LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); +LUAI_FUNC void luaE_freeCI (lua_State *L); + #endif diff --git a/liblua/lstring.c b/liblua/lstring.c index 49113151cc..adec415e78 100644 --- a/liblua/lstring.c +++ b/liblua/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lstring.c,v 2.19 2011/05/03 16:01:57 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -20,54 +20,55 @@ 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; istrt; + /* cannot resize while GC is traversing strings */ + luaC_runtilstate(L, ~bitmask(GCSsweepstring)); + if (newsize > tb->size) { + luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); + for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; + } /* rehash */ for (i=0; isize; i++) { GCObject *p = tb->hash[i]; + tb->hash[i] = NULL; 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; + GCObject *next = gch(p)->next; /* save next */ + unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ + gch(p)->next = tb->hash[h]; /* chain it */ + tb->hash[h] = p; + resetoldbit(p); /* see MOVE OLD rule */ p = next; } } - luaM_freearray(L, tb->hash, tb->size, TString *); + if (newsize < tb->size) { + /* shrinking slice must be empty */ + lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); + luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); + } tb->size = newsize; - tb->hash = newhash; } static TString *newlstr (lua_State *L, const char *str, size_t l, unsigned int h) { + size_t totalsize; /* total size of TString object */ + GCObject **list; /* (pointer to) list where it will be inserted */ TString *ts; - stringtable *tb; + stringtable *tb = &G(L)->strt; if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) luaM_toobig(L); - ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); + if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ + totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); + list = &tb->hash[lmod(h, tb->size)]; + ts = &luaC_newobj(L, LUA_TSTRING, totalsize, list, 0)->ts; 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; } @@ -81,15 +82,22 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { 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) { + o = gch(o)->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); + if (h == ts->tsv.hash && + ts->tsv.len == l && + (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { + if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ + changewhite(o); /* resurrect it */ return ts; } } - return newlstr(L, str, l, h); /* not found */ + return newlstr(L, str, l, h); /* not found; create a new string */ +} + + +TString *luaS_new (lua_State *L, const char *str) { + return luaS_newlstr(L, str, strlen(str)); } @@ -97,15 +105,10 @@ 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 = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; 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/liblua/lstring.h b/liblua/lstring.h index 73a2ff8b38..d708a1b099 100644 --- a/liblua/lstring.h +++ b/liblua/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lstring.h,v 1.46 2010/04/05 16:26:37 roberto Exp $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -7,7 +7,6 @@ #ifndef lstring_h #define lstring_h - #include "lgc.h" #include "lobject.h" #include "lstate.h" @@ -17,15 +16,22 @@ #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) + +/* +** as all string are internalized, string equality becomes +** pointer equality +*/ +#define eqstr(a,b) ((a) == (b)) + 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); +LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); #endif diff --git a/liblua/lstrlib.c b/liblua/lstrlib.c index ca333ba168..f5d61fd859 100644 --- a/liblua/lstrlib.c +++ b/liblua/lstrlib.c @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.132.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: lstrlib.c,v 1.173 2011/11/30 18:24:56 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -20,6 +20,15 @@ #include "lualib.h" +/* +** maximum number of captures that a pattern can do during +** pattern-matching. This limit is arbitrary. +*/ +#if !defined(LUA_MAXCAPTURES) +#define LUA_MAXCAPTURES 32 +#endif + + /* macro to `unsign' a character */ #define uchar(c) ((unsigned char)(c)) @@ -28,38 +37,41 @@ static int str_len (lua_State *L) { size_t l; luaL_checklstring(L, 1, &l); - lua_pushinteger(L, l); + lua_pushinteger(L, (lua_Integer)l); return 1; } -static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { - /* relative string position: negative means back from end */ - return (pos>=0) ? pos : (ptrdiff_t)len+pos+1; +/* translate a relative string position: negative means back from end */ +static size_t posrelat (ptrdiff_t pos, size_t len) { + if (pos >= 0) return (size_t)pos; + else if (0u - (size_t)pos > len) return 0; + else return len - ((size_t)-pos) + 1; } 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); + size_t start = posrelat(luaL_checkinteger(L, 2), l); + size_t end = posrelat(luaL_optinteger(L, 3, -1), l); if (start < 1) start = 1; - if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; + if (end > l) end = l; if (start <= end) - lua_pushlstring(L, s+start-1, end-start+1); + 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; + size_t l, i; 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); + char *p = luaL_buffinitsize(L, &b, l); + for (i = 0; i < l; i++) + p[i] = s[l - i - 1]; + luaL_pushresultsize(&b, l); return 1; } @@ -69,10 +81,10 @@ static int str_lower (lua_State *L) { size_t i; luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); - luaL_buffinit(L, &b); + char *p = luaL_buffinitsize(L, &b, l); for (i=0; i> 1) + static int str_rep (lua_State *L) { - size_t l; - luaL_Buffer b; + size_t l, lsep; const char *s = luaL_checklstring(L, 1, &l); int n = luaL_checkint(L, 2); - luaL_buffinit(L, &b); - while (n-- > 0) - luaL_addlstring(&b, s, l); - luaL_pushresult(&b); + const char *sep = luaL_optlstring(L, 3, "", &lsep); + if (n <= 0) lua_pushliteral(L, ""); + else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ + return luaL_error(L, "resulting string too large"); + else { + size_t totallen = n * l + (n - 1) * lsep; + luaL_Buffer b; + char *p = luaL_buffinitsize(L, &b, totallen); + while (n-- > 1) { /* first n-1 copies (followed by separator) */ + memcpy(p, s, l * sizeof(char)); p += l; + memcpy(p, sep, lsep * sizeof(char)); p += lsep; + } + memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ + luaL_pushresultsize(&b, totallen); + } return 1; } @@ -105,15 +131,15 @@ static int str_rep (lua_State *L) { 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); + size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); + size_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 < 1) posi = 1; + if (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"); + if (posi + n <= pose) /* (size_t -> int) overflow? */ + return 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 luaL_error(ms->L, "invalid capture index %%%d", l + 1); return l; } @@ -201,16 +228,16 @@ static int capture_to_close (MatchState *ms) { static const char *classend (MatchState *ms, const char *p) { switch (*p++) { case L_ESC: { - if (*p == '\0') + if (p == ms->p_end) luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); return p+1; } case '[': { if (*p == '^') p++; do { /* look for a `]' */ - if (*p == '\0') + if (p == ms->p_end) luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); - if (*(p++) == L_ESC && *p != '\0') + if (*(p++) == L_ESC && p < ms->p_end) p++; /* skip escapes (e.g. `%]') */ } while (*p != ']'); return p+1; @@ -228,13 +255,14 @@ static int match_class (int c, int cl) { case 'a' : res = isalpha(c); break; case 'c' : res = iscntrl(c); break; case 'd' : res = isdigit(c); break; + case 'g' : res = isgraph(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; + case 'z' : res = (c == 0); break; /* deprecated option */ default: return (cl == c); } return (islower(cl) ? res : !res); @@ -279,8 +307,9 @@ 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 (p >= ms->p_end - 1) + luaL_error(ms->L, "malformed pattern " + "(missing arguments to " LUA_QL("%%b") ")"); if (*s != *p) return NULL; else { int b = *p; @@ -363,6 +392,8 @@ static const char *match_capture (MatchState *ms, const char *s, int l) { static const char *match (MatchState *ms, const char *s, const char *p) { init: /* using goto's to optimize tail recursion */ + if (p == ms->p_end) /* end of pattern? */ + return s; /* match succeeded */ switch (*p) { case '(': { /* start capture */ if (*(p+1) == ')') /* position capture? */ @@ -373,7 +404,12 @@ static const char *match (MatchState *ms, const char *s, const char *p) { case ')': { /* end capture */ return end_capture(ms, s, p+1); } - case L_ESC: { + case '$': { + if ((p+1) == ms->p_end) /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ switch (*(p+1)) { case 'b': { /* balanced string? */ s = matchbalance(ms, s, p+2); @@ -392,27 +428,19 @@ static const char *match (MatchState *ms, const char *s, const char *p) { !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': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': { /* 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) */ } + default: goto dflt; } } - 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 */ + default: dflt: { /* pattern class plus optional suffix */ const char *ep = classend(ms, p); /* points to what is next */ - int m = ssrc_end && singlematch(uchar(*s), p, ep); + int m = s < ms->src_end && singlematch(uchar(*s), p, ep); switch (*ep) { case '?': { /* optional */ const char *res; @@ -491,37 +519,56 @@ static int push_captures (MatchState *ms, const char *s, const char *e) { } +/* check whether pattern has no special characters */ +static int nospecials (const char *p, size_t l) { + size_t upto = 0; + do { + if (strpbrk(p + upto, SPECIALS)) + return 0; /* pattern has a special character */ + upto += strlen(p + upto) + 1; /* may have more after \0 */ + } while (upto <= l); + return 1; /* no special chars found */ +} + + 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? */ + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); + if (init < 1) init = 1; + else if (init > ls + 1) { /* start after string's end? */ + lua_pushnil(L); /* cannot find anything */ + return 1; + } + /* explicit request or no special characters? */ + if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { /* do a plain search */ - const char *s2 = lmemfind(s+init, l1-init, p, l2); + const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); if (s2) { - lua_pushinteger(L, s2-s+1); - lua_pushinteger(L, s2-s+l2); + lua_pushinteger(L, s2 - s + 1); + lua_pushinteger(L, s2 - s + lp); return 2; } } else { MatchState ms; - int anchor = (*p == '^') ? (p++, 1) : 0; - const char *s1=s+init; + const char *s1 = s + init - 1; + int anchor = (*p == '^'); + if (anchor) { + p++; lp--; /* skip anchor character */ + } ms.L = L; ms.src_init = s; - ms.src_end = s+l1; + ms.src_end = s + ls; + ms.p_end = p + lp; 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 */ + lua_pushinteger(L, s1 - s + 1); /* start */ + lua_pushinteger(L, res - s); /* end */ return push_captures(&ms, NULL, 0) + 2; } else @@ -546,13 +593,14 @@ static int str_match (lua_State *L) { static int gmatch_aux (lua_State *L) { MatchState ms; - size_t ls; + size_t ls, lp; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); - const char *p = lua_tostring(L, lua_upvalueindex(2)); + const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); const char *src; ms.L = L; ms.src_init = s; ms.src_end = s+ls; + ms.p_end = p + lp; for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); src <= ms.src_end; src++) { @@ -580,12 +628,6 @@ static int gmatch (lua_State *L) { } -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; @@ -595,8 +637,12 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, luaL_addchar(b, news[i]); else { i++; /* skip ESC */ - if (!isdigit(uchar(news[i]))) + if (!isdigit(uchar(news[i]))) { + if (news[i] != L_ESC) + luaL_error(ms->L, "invalid use of " LUA_QL("%c") + " in replacement string", L_ESC); luaL_addchar(b, news[i]); + } else if (news[i] == '0') luaL_addlstring(b, s, e - s); else { @@ -609,14 +655,9 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { + const char *e, int tr) { lua_State *L = ms->L; - switch (lua_type(L, 3)) { - case LUA_TNUMBER: - case LUA_TSTRING: { - add_s(ms, b, s, e); - return; - } + switch (tr) { case LUA_TFUNCTION: { int n; lua_pushvalue(L, 3); @@ -629,41 +670,49 @@ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, lua_gettable(L, 3); break; } + default: { /* LUA_TNUMBER or LUA_TSTRING */ + add_s(ms, b, s, e); + return; + } } 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_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; + size_t srcl, lp; 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; + const char *p = luaL_checklstring(L, 2, &lp); + int tr = lua_type(L, 3); + size_t max_s = luaL_optinteger(L, 4, srcl+1); + int anchor = (*p == '^'); + size_t 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); + if (anchor) { + p++; lp--; /* skip anchor character */ + } ms.L = L; ms.src_init = src; ms.src_end = src+srcl; + ms.p_end = p + lp; while (n < max_s) { const char *e; ms.level = 0; e = match(&ms, src, p); if (e) { n++; - add_value(&ms, &b, src, e); + add_value(&ms, &b, src, e, tr); } if (e && e>src) /* non empty match? */ src = e; /* skip it */ @@ -681,6 +730,49 @@ static int str_gsub (lua_State *L) { /* }====================================================== */ + +/* +** {====================================================== +** STRING FORMAT +** ======================================================= +*/ + +/* +** LUA_INTFRMLEN is the length modifier for integer conversions in +** 'string.format'; LUA_INTFRM_T is the integer type corresponding to +** the previous length +*/ +#if !defined(LUA_INTFRMLEN) /* { */ +#if defined(LUA_USE_LONGLONG) + +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long + +#else + +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +#endif +#endif /* } */ + +#define MAX_UINTFRM ((lua_Number)(~(unsigned LUA_INTFRM_T)0)) +#define MAX_INTFRM ((lua_Number)((~(unsigned LUA_INTFRM_T)0)/2)) +#define MIN_INTFRM (-(lua_Number)((~(unsigned LUA_INTFRM_T)0)/2) - 1) + +/* +** LUA_FLTFRMLEN is the length modifier for float conversions in +** 'string.format'; LUA_FLTFRM_T is the float type corresponding to +** the previous length +*/ +#if !defined(LUA_FLTFRMLEN) + +#define LUA_FLTFRMLEN "" +#define LUA_FLTFRM_T double + +#endif + + /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ #define MAX_ITEM 512 /* valid flags in a format specification */ @@ -697,25 +789,20 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { 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; - } + if (*s == '"' || *s == '\\' || *s == '\n') { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); } + else if (*s == '\0' || iscntrl(uchar(*s))) { + char buff[10]; + if (!isdigit(uchar(*(s+1)))) + sprintf(buff, "\\%d", (int)uchar(*s)); + else + sprintf(buff, "\\%03d", (int)uchar(*s)); + luaL_addstring(b, buff); + } + else + luaL_addchar(b, *s); s++; } luaL_addchar(b, '"'); @@ -724,7 +811,7 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { 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)) + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) luaL_error(L, "invalid format (repeated flags)"); if (isdigit(uchar(*p))) p++; /* skip width */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ @@ -736,23 +823,28 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { if (isdigit(uchar(*p))) luaL_error(L, "invalid format (width or precision too long)"); *(form++) = '%'; - strncpy(form, strfrmt, p - strfrmt + 1); + memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); form += p - strfrmt + 1; *form = '\0'; return p; } -static void addintlen (char *form) { +/* +** add length modifier into formats +*/ +static void addlenmod (char *form, const char *lenmod) { size_t l = strlen(form); + size_t lm = strlen(lenmod); 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'; + strcpy(form + l - 1, lenmod); + form[l + lm - 1] = spec; + form[l + lm] = '\0'; } static int str_format (lua_State *L) { + int top = lua_gettop(L); int arg = 1; size_t sfl; const char *strfrmt = luaL_checklstring(L, arg, &sfl); @@ -766,45 +858,57 @@ static int str_format (lua_State *L) { 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++; + char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ + int nb = 0; /* number of bytes in added item */ + if (++arg > top) + luaL_argerror(L, arg, "no value"); strfrmt = scanformat(L, strfrmt, form); switch (*strfrmt++) { case 'c': { - sprintf(buff, form, (int)luaL_checknumber(L, arg)); + nb = sprintf(buff, form, luaL_checkint(L, arg)); break; } case 'd': case 'i': { - addintlen(form); - sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); + lua_Number n = luaL_checknumber(L, arg); + luaL_argcheck(L, (MIN_INTFRM - 1) < n && n < (MAX_INTFRM + 1), arg, + "not a number in proper range"); + addlenmod(form, LUA_INTFRMLEN); + nb = sprintf(buff, form, (LUA_INTFRM_T)n); break; } case 'o': case 'u': case 'x': case 'X': { - addintlen(form); - sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); + lua_Number n = luaL_checknumber(L, arg); + luaL_argcheck(L, 0 <= n && n < (MAX_UINTFRM + 1), arg, + "not a non-negative number in proper range"); + addlenmod(form, LUA_INTFRMLEN); + nb = sprintf(buff, form, (unsigned LUA_INTFRM_T)n); break; } case 'e': case 'E': case 'f': +#if defined(LUA_USE_AFORMAT) + case 'a': case 'A': +#endif case 'g': case 'G': { - sprintf(buff, form, (double)luaL_checknumber(L, arg)); + addlenmod(form, LUA_FLTFRMLEN); + nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); break; } case 'q': { addquoted(L, &b, arg); - continue; /* skip the 'addsize' at the end */ + break; } case 's': { size_t l; - const char *s = luaL_checklstring(L, arg, &l); + const char *s = luaL_tolstring(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 */ + break; } else { - sprintf(buff, form, s); + nb = sprintf(buff, form, s); + lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ break; } } @@ -813,13 +917,15 @@ static int str_format (lua_State *L) { LUA_QL("format"), *(strfrmt - 1)); } } - luaL_addlstring(&b, buff, strlen(buff)); + luaL_addsize(&b, nb); } } luaL_pushresult(&b); return 1; } +/* }====================================================== */ + static const luaL_Reg strlib[] = { {"byte", str_byte}, @@ -827,7 +933,6 @@ static const luaL_Reg strlib[] = { {"dump", str_dump}, {"find", str_find}, {"format", str_format}, - {"gfind", gfind_nodef}, {"gmatch", gmatch}, {"gsub", str_gsub}, {"len", str_len}, @@ -842,13 +947,13 @@ static const luaL_Reg strlib[] = { static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* create metatable for strings */ + lua_createtable(L, 0, 1); /* table to be metatable for strings */ lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); - lua_setmetatable(L, -2); /* set string metatable */ + lua_pushvalue(L, -2); /* copy table */ + lua_setmetatable(L, -2); /* set table as metatable for strings */ lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* string library... */ - lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ + lua_pushvalue(L, -2); /* get string library */ + lua_setfield(L, -2, "__index"); /* metatable.__index = string */ lua_pop(L, 1); /* pop metatable */ } @@ -856,12 +961,8 @@ static void createmetatable (lua_State *L) { /* ** 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 +LUAMOD_API int luaopen_string (lua_State *L) { + luaL_newlib(L, strlib); createmetatable(L); return 1; } diff --git a/liblua/ltable.c b/liblua/ltable.c index ec84f4fabc..9581add915 100644 --- a/liblua/ltable.c +++ b/liblua/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ +** $Id: ltable.c,v 2.67 2011/11/30 12:41:45 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -18,7 +18,6 @@ ** Hence even when the load factor reaches 100%, performance remains good. */ -#include #include #define ltable_c @@ -32,14 +31,16 @@ #include "lmem.h" #include "lobject.h" #include "lstate.h" +#include "lstring.h" #include "ltable.h" +#include "lvm.h" /* ** max size of array part is 2^MAXBITS */ -#if LUAI_BITSINT > 26 -#define MAXBITS 26 +#if LUAI_BITSINT >= 32 +#define MAXBITS 30 #else #define MAXBITS (LUAI_BITSINT-2) #endif @@ -48,7 +49,7 @@ #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) @@ -63,18 +64,13 @@ #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_) +#define isdummy(n) ((n) == dummynode) + static const Node dummynode_ = { - {{NULL}, LUA_TNIL}, /* value */ - {{{NULL}, LUA_TNIL, NULL}} /* key */ + {NILCONSTANT}, /* value */ + {{NILCONSTANT, NULL}} /* key */ }; @@ -82,13 +78,14 @@ static const Node dummynode_ = { ** 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]); + luai_hashnum(i, n); + if (i < 0) { + if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */ + i = 0; /* handle INT_MIN */ + i = -i; /* must be a positive value */ + } + return hashmod(t, i); } @@ -107,6 +104,8 @@ static Node *mainposition (const Table *t, const TValue *key) { return hashboolean(t, bvalue(key)); case LUA_TLIGHTUSERDATA: return hashpointer(t, pvalue(key)); + case LUA_TLCF: + return hashpointer(t, fvalue(key)); default: return hashpointer(t, gcvalue(key)); } @@ -132,7 +131,7 @@ static int arrayindex (const TValue *key) { /* ** 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. +** beginning of a traversal is signaled by -1. */ static int findindex (lua_State *L, Table *t, StkId key) { int i; @@ -142,19 +141,19 @@ static int findindex (lua_State *L, Table *t, StkId key) { 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 */ + for (;;) { /* 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))) { + if (luaV_rawequalobj(gkey(n), key) || + (ttisdeadkey(gkey(n)) && iscollectable(key) && + deadvalue(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 */ + if (n == NULL) + luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ + } } } @@ -170,7 +169,7 @@ int luaH_next (lua_State *L, Table *t, StkId key) { } 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, gkey(gnode(t, i))); setobj2s(L, key+1, gval(gnode(t, i))); return 1; } @@ -211,7 +210,7 @@ static int computesizes (int nums[], int *narray) { 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 */ + nums[luaO_ceillog2(k)]++; /* count as such */ return 1; } else @@ -251,7 +250,7 @@ static int numusehash (const Table *t, int *nums, int *pnasize) { while (i--) { Node *n = &t->node[i]; if (!ttisnil(gval(n))) { - ause += countint(key2tval(n), nums); + ause += countint(gkey(n), nums); totaluse++; } } @@ -277,7 +276,7 @@ static void setnodevector (lua_State *L, Table *t, int size) { } else { int i; - lsize = ceillog2(size); + lsize = luaO_ceillog2(size); if (lsize > MAXBITS) luaG_runerror(L, "table overflow"); size = twoto(lsize); @@ -294,7 +293,7 @@ static void setnodevector (lua_State *L, Table *t, int size) { } -static void resize (lua_State *L, Table *t, int nasize, int nhsize) { +void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { int i; int oldasize = t->sizearray; int oldhsize = t->lsizenode; @@ -302,13 +301,13 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) { if (nasize > oldasize) /* array part must grow? */ setarrayvector(L, t, nasize); /* create new hash part with appropriate size */ - setnodevector(L, t, nhsize); + 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]); + luaH_setint(L, t, i + 1, &t->array[i]); } /* shrink array */ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); @@ -316,23 +315,26 @@ static void resize (lua_State *L, Table *t, int nasize, int nhsize) { /* 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 (!ttisnil(gval(old))) { + /* doesn't need barrier/invalidate cache, as entry was + already present in the table */ + setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); + } } - if (nold != dummynode) - luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ + if (!isdummy(nold)) + luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* 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); + int nsize = isdummy(t->node) ? 0 : sizenode(t); + luaH_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 nums[MAXBITS+1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */ int i; int totaluse; for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ @@ -345,7 +347,7 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) { /* compute new size for array part */ na = computesizes(nums, &nasize); /* resize the table to new computed sizes */ - resize(L, t, nasize, totaluse - na); + luaH_resize(L, t, nasize, totaluse - na); } @@ -355,32 +357,28 @@ static void rehash (lua_State *L, Table *t, const TValue *ek) { */ -Table *luaH_new (lua_State *L, int narray, int nhash) { - Table *t = luaM_new(L, Table); - luaC_link(L, obj2gco(t), LUA_TTABLE); +Table *luaH_new (lua_State *L) { + Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h; 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); + setnodevector(L, t, 0); 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); + if (!isdummy(t->node)) + luaM_freearray(L, t->node, cast(size_t, sizenode(t))); + luaM_freearray(L, t->array, t->sizearray); luaM_free(L, t); } static Node *getfreepos (Table *t) { - while (t->lastfree-- > t->node) { + while (t->lastfree > t->node) { + t->lastfree--; if (ttisnil(gkey(t->lastfree))) return t->lastfree; } @@ -390,23 +388,28 @@ static Node *getfreepos (Table *t) { /* -** 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. +** 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) { +TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp; + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) + luaG_runerror(L, "table index is NaN"); + mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ 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 */ + /* whatever called 'newkey' take care of TM cache and GC barrier */ + return luaH_set(L, t, key); /* insert key into grown table */ } - lua_assert(n != dummynode); - othern = mainposition(t, key2tval(mp)); + lua_assert(!isdummy(n)); + othern = mainposition(t, gkey(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 */ @@ -422,8 +425,8 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { mp = n; } } - gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; - luaC_barriert(L, t, key); + setobj2t(L, gkey(mp), key); + luaC_barrierback(L, obj2gco(t), key); lua_assert(ttisnil(gval(mp))); return gval(mp); } @@ -432,7 +435,7 @@ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { /* ** search function for integers */ -const TValue *luaH_getnum (Table *t, int key) { +const TValue *luaH_getint (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]; @@ -455,7 +458,7 @@ const TValue *luaH_getnum (Table *t, int key) { 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) + if (ttisstring(gkey(n)) && eqstr(rawtsvalue(gkey(n)), key)) return gval(n); /* that's it */ else n = gnext(n); } while (n); @@ -467,7 +470,7 @@ const TValue *luaH_getstr (Table *t, TString *key) { ** main search function */ const TValue *luaH_get (Table *t, const TValue *key) { - switch (ttype(key)) { + switch (ttypenv(key)) { case LUA_TNIL: return luaO_nilobject; case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); case LUA_TNUMBER: { @@ -475,13 +478,13 @@ const TValue *luaH_get (Table *t, const TValue *key) { 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 */ + return luaH_getint(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)) + if (luaV_rawequalobj(gkey(n), key)) return gval(n); /* that's it */ else n = gnext(n); } while (n); @@ -491,41 +494,29 @@ const TValue *luaH_get (Table *t, const TValue *key) { } +/* +** beware: when using this function you probably need to check a GC +** barrier and invalidate the TM cache. +*/ 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); - } + else return luaH_newkey(L, t, key); } -TValue *luaH_setnum (lua_State *L, Table *t, int key) { - const TValue *p = luaH_getnum(t, key); +void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { + const TValue *p = luaH_getint(t, key); + TValue *cell; if (p != luaO_nilobject) - return cast(TValue *, p); + cell = 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); + cell = luaH_newkey(L, t, &k); } + setobj2t(L, cell, value); } @@ -533,20 +524,20 @@ 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))) { + while (!ttisnil(luaH_getint(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++; + while (!ttisnil(luaH_getint(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; + if (ttisnil(luaH_getint(t, m))) j = m; else i = m; } return i; @@ -570,7 +561,7 @@ int luaH_getn (Table *t) { return i; } /* else must find a boundary in hash part */ - else if (t->node == dummynode) /* hash part is empty? */ + else if (isdummy(t->node)) /* hash part is empty? */ return j; /* that is easy... */ else return unbound_search(t, j); } @@ -583,6 +574,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) { return mainposition(t, key); } -int luaH_isdummy (Node *n) { return n == dummynode; } +int luaH_isdummy (Node *n) { return isdummy(n); } #endif diff --git a/liblua/ltable.h b/liblua/ltable.h index f5b9d5ead0..2f6f5c2dc8 100644 --- a/liblua/ltable.h +++ b/liblua/ltable.h @@ -1,5 +1,5 @@ /* -** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ltable.h,v 2.16 2011/08/17 20:26:47 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -11,20 +11,21 @@ #define gnode(t,i) (&(t)->node[i]) -#define gkey(n) (&(n)->i_key.nk) +#define gkey(n) (&(n)->i_key.tvk) #define gval(n) (&(n)->i_val) #define gnext(n) ((n)->i_key.nk.next) -#define key2tval(n) (&(n)->i_key.tvk) +#define invalidateTMcache(t) ((t)->flags = 0) -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_getint (Table *t, int key); +LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value); 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_newkey (lua_State *L, 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 Table *luaH_new (lua_State *L); +LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize); 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); diff --git a/liblua/ltablib.c b/liblua/ltablib.c index 7838bc3838..a52add03da 100644 --- a/liblua/ltablib.c +++ b/liblua/ltablib.c @@ -1,5 +1,5 @@ /* -** $Id: ltablib.c,v 1.38.1.2 2007/12/28 15:32:23 roberto Exp $ +** $Id: ltablib.c,v 1.63 2011/11/28 17:26:30 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ @@ -16,43 +16,11 @@ #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; -} +#define aux_getn(L,n) \ + (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n)) +#if defined(LUA_COMPAT_MAXN) static int maxn (lua_State *L) { lua_Number max = 0; luaL_checktype(L, 1, LUA_TTABLE); @@ -67,24 +35,7 @@ static int maxn (lua_State *L) { 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) { @@ -109,7 +60,6 @@ static int tinsert (lua_State *L) { 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; } @@ -119,8 +69,7 @@ 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 */ + return 0; /* nothing to remove */ lua_rawgeti(L, 1, pos); /* result = t[pos] */ for ( ;pos 0) { /* at least one element? */ + int i; + lua_pushvalue(L, 1); + lua_rawseti(L, -2, 1); /* insert first element */ + lua_replace(L, 1); /* move table into index 1 */ + for (i = n; i >= 2; i--) /* assign other elements */ + lua_rawseti(L, 1, i); + } + return 1; /* return table */ +} + + +static int 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_len(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; +} + +/* }====================================================== */ + + /* ** {====================================================== ** Quicksort ** (based on `Algorithms in MODULA-3', Robert Sedgewick; ** Addison-Wesley, 1993.) +** ======================================================= */ @@ -179,77 +178,10 @@ static int sort_comp (lua_State *L, int a, int b) { return res; } else /* a < b? */ - return lua_lessthan(L, a, b); -} - -static int call_comp (lua_State *L) -{ - int res; - lua_pushvalue(L, 2); - lua_pushvalue(L, -2); - lua_pushvalue(L, -4); - lua_call(L, 2, 1); - res = lua_toboolean(L, -1); - lua_pop(L, 1); - return res; -} - -#define compare(L, c) (c ? call_comp(L) : lua_lessthan(L, -1, -2)) - -static int partition (lua_State *L, int p, int r, int c) -{ - int i = p - 1, j; - lua_rawgeti(L, 1, r); - /* for r - p = 1 */ - if (p - r == 1) - { - lua_rawgeti(L, 1, p); - if (!compare(L, c)) - { - lua_rawseti(L, 1, r); - lua_rawseti(L, 1, p); - } - else - lua_pop(L, 2); - return i + 1; - } - for (j = p; j < r; j++) - { - lua_rawgeti(L, 1, j); - if (compare(L, c)) - { - i++; - lua_rawgeti(L, 1, i); - lua_pushvalue(L, -2); - lua_rawseti(L, 1, i); - lua_rawseti(L, 1, j); - } - lua_pop(L, 1); - } - lua_pop(L, 1); - i++; - lua_rawgeti(L, 1, r); - lua_rawgeti(L, 1, i); - lua_rawseti(L, 1, r); - lua_rawseti(L, 1, i); - return i; -} - -static void quicksort (lua_State *L, int p, int r, int c) -{ - if (p < r) - { - int q = partition(L, p, r, c); - quicksort(L, p, q - 1, c); - quicksort(L, q + 1, r, c); - } + return lua_compare(L, a, b, LUA_OPLT); } -static int calls = 0; static void auxsort (lua_State *L, int l, int u) { - calls++; - if (calls > 20) - printf("calls = %d; l = %d; u = %d;\n", calls, l, u); while (l < u) { /* for tail recursion */ int i, j; /* sort elements a[l], a[(l+u)/2] and a[u] */ @@ -283,12 +215,12 @@ static void auxsort (lua_State *L, int l, int u) { for (;;) { /* invariant: a[l..i] <= P <= a[j..u] */ /* repeat ++i until a[i] >= P */ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i>u) luaL_error(L, "invalid order function for sorting"); + 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 (jmetatable; break; @@ -68,7 +70,7 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) { mt = uvalue(o)->metatable; break; default: - mt = G(L)->mt[ttype(o)]; + mt = G(L)->mt[ttypenv(o)]; } return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); } diff --git a/liblua/ltm.h b/liblua/ltm.h index 64343b781b..89bdc19a1e 100644 --- a/liblua/ltm.h +++ b/liblua/ltm.h @@ -1,5 +1,5 @@ /* -** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: ltm.h,v 2.11 2011/02/28 17:32:10 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ @@ -20,6 +20,7 @@ typedef enum { TM_NEWINDEX, TM_GC, TM_MODE, + TM_LEN, TM_EQ, /* last tag method with `fast' access */ TM_ADD, TM_SUB, @@ -28,7 +29,6 @@ typedef enum { TM_MOD, TM_POW, TM_UNM, - TM_LEN, TM_LT, TM_LE, TM_CONCAT, @@ -43,7 +43,10 @@ typedef enum { #define fasttm(l,et,e) gfasttm(G(l), et, e) -LUAI_DATA const char *const luaT_typenames[]; +#define ttypename(x) luaT_typenames_[(x) + 1] +#define objtypename(x) ttypename(ttypenv(x)) + +LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); diff --git a/liblua/lua.c b/liblua/lua.c index 3a46609328..e20ab86d27 100644 --- a/liblua/lua.c +++ b/liblua/lua.c @@ -1,5 +1,5 @@ /* -** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $ +** $Id: lua.c,v 1.203 2011/12/12 16:34:03 roberto Exp $ ** Lua stand-alone interpreter ** See Copyright Notice in lua.h */ @@ -18,6 +18,72 @@ #include "lualib.h" +#if !defined(LUA_PROMPT) +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " +#endif + +#if !defined(LUA_PROGNAME) +#define LUA_PROGNAME "lua" +#endif + +#if !defined(LUA_MAXINPUT) +#define LUA_MAXINPUT 512 +#endif + +#if !defined(LUA_INIT) +#define LUA_INIT "LUA_INIT" +#endif + +#define LUA_INITVERSION \ + LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +/* +** lua_stdin_is_tty detects whether the standard input is a 'tty' (that +** is, whether we're running lua interactively). +*/ +#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_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. +*/ +#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_rawlen(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)) + +#elif !defined(lua_readline) + +#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 + + + static lua_State *globalL = NULL; @@ -39,77 +105,87 @@ static void laction (int i) { } -static void print_usage (void) { - fprintf(stderr, - "usage: %s [options] [script [args]].\n" +static void print_usage (const char *badoption) { + luai_writestringerror("%s: ", progname); + if (badoption[1] == 'e' || badoption[1] == 'l') + luai_writestringerror("'%s' needs argument\n", badoption); + else + luai_writestringerror("unrecognized option '%s'\n", badoption); + luai_writestringerror( + "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" + " -l name require library " LUA_QL("name") "\n" " -v show version information\n" + " -E ignore environment variables\n" " -- stop handling options\n" - " - execute stdin and stop handling options\n" + " - stop handling options and execute stdin\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); + if (pname) luai_writestringerror("%s: ", pname); + luai_writestringerror("%s\n", msg); } static int report (lua_State *L, int status) { - if (status && !lua_isnil(L, -1)) { + if (status != LUA_OK && !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); + /* force a complete garbage collection in case of errors */ + lua_gc(L, LUA_GCCOLLECT, 0); } 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)) { +/* the next function is called unprotected, so it must avoid errors */ +static void finalreport (lua_State *L, int status) { + if (status != LUA_OK) { + const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1) + : NULL; + if (msg == NULL) msg = "(error object is not a string)"; + l_message(progname, msg); lua_pop(L, 1); - return 1; } - lua_getfield(L, -1, "traceback"); - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); - return 1; +} + + +static int traceback (lua_State *L) { + const char *msg = lua_tostring(L, 1); + if (msg) + luaL_traceback(L, L, msg, 1); + else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ + if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ + lua_pushliteral(L, "(no error message)"); } - 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) { +static int docall (lua_State *L, int narg, int nres) { 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 */ + globalL = L; /* to be available to 'laction' */ signal(SIGINT, laction); - status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); + status = lua_pcall(L, narg, nres, 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); + luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); + luai_writeline(); } @@ -132,40 +208,53 @@ static int getargs (lua_State *L, char **argv, int n) { static int dofile (lua_State *L, const char *name) { - int status = luaL_loadfile(L, name) || docall(L, 0, 1); + int status = luaL_loadfile(L, name); + if (status == LUA_OK) status = docall(L, 0, 0); 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); + int status = luaL_loadbuffer(L, s, strlen(s), name); + if (status == LUA_OK) status = docall(L, 0, 0); return report(L, status); } static int dolibrary (lua_State *L, const char *name) { - lua_getglobal(L, "require"); + int status; + lua_pushglobaltable(L); + lua_getfield(L, -1, "require"); lua_pushstring(L, name); - return report(L, docall(L, 1, 1)); + status = docall(L, 1, 1); + if (status == LUA_OK) { + lua_setfield(L, -2, name); /* global[name] = require return */ + lua_pop(L, 1); /* remove global table */ + } + else + lua_remove(L, -2); /* remove global table (below error msg.) */ + return report(L, status); } static const char *get_prompt (lua_State *L, int firstline) { const char *p; - lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); + lua_getglobal(L, 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; } +/* mark in error messages for incomplete statements */ +#define EOFMARK "" +#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) 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) { + if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { lua_pop(L, 1); return 1; } @@ -199,7 +288,9 @@ static int loadline (lua_State *L) { 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"); + size_t l; + const char *line = lua_tolstring(L, 1, &l); + status = luaL_loadbuffer(L, line, l, "=stdin"); if (!incomplete(L, status)) break; /* cannot try to add lines? */ if (!pushline(L, 0)) /* no more input? */ return -1; @@ -218,20 +309,20 @@ static void dotty (lua_State *L) { const char *oldprogname = progname; progname = NULL; while ((status = loadline(L)) != -1) { - if (status == 0) status = docall(L, 0, 0); + if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET); report(L, status); - if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ + if (status == LUA_OK && lua_gettop(L) > 0) { /* any result to print? */ + luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); lua_getglobal(L, "print"); lua_insert(L, 1); - if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) + if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK) 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); + luai_writeline(); progname = oldprogname; } @@ -242,49 +333,63 @@ static int handle_script (lua_State *L, char **argv, int n) { int narg = getargs(L, argv, n); /* collect arguments */ lua_setglobal(L, "arg"); fname = argv[n]; - if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) + 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); + if (status == LUA_OK) + status = docall(L, narg, LUA_MULTRET); else - lua_pop(L, narg); + 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;} +#define noextrachars(x) {if ((x)[2] != '\0') return -1;} + + +/* indices of various argument indicators in array args */ +#define has_i 0 /* -i */ +#define has_v 1 /* -v */ +#define has_e 2 /* -e */ +#define has_E 3 /* -E */ +#define num_has 4 /* number of 'has_*' */ -static int collectargs (char **argv, int *pi, int *pv, int *pe) { + +static int collectargs (char **argv, int *args) { 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]); + noextrachars(argv[i]); return (argv[i+1] != NULL ? i+1 : 0); case '\0': return i; + case 'E': + args[has_E] = 1; + break; case 'i': - notail(argv[i]); - *pi = 1; /* go through */ + noextrachars(argv[i]); + args[has_i] = 1; /* go through */ case 'v': - notail(argv[i]); - *pv = 1; + noextrachars(argv[i]); + args[has_v] = 1; break; case 'e': - *pe = 1; /* go through */ - case 'l': - if (argv[i][2] == '\0') { - i++; - if (argv[i] == NULL) return -1; + args[has_e] = 1; /* go through */ + case 'l': /* both options need an argument */ + if (argv[i][2] == '\0') { /* no concatenated argument? */ + i++; /* try next 'argv' */ + if (argv[i] == NULL || argv[i][0] == '-') + return -(i - 1); /* no next argument or it is another option */ } break; - default: return -1; /* invalid option */ + default: /* invalid option; return its index... */ + return -i; /* ...as a negative value */ } } return 0; @@ -294,99 +399,103 @@ static int collectargs (char **argv, int *pi, int *pv, int *pe) { 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; + if (dostring(L, chunk, "=(command line)") != LUA_OK) + return 0; 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 */ + if (dolibrary(L, filename) != LUA_OK) + return 0; /* stop if file fails */ break; } default: break; } } - return 0; + return 1; } static int handle_luainit (lua_State *L) { - const char *init = getenv(LUA_INIT); - if (init == NULL) return 0; /* status OK */ + const char *name = "=" LUA_INITVERSION; + const char *init = getenv(name + 1); + if (init == NULL) { + name = "=" LUA_INIT; + init = getenv(name + 1); /* try alternative name */ + } + if (init == NULL) return LUA_OK; else if (init[0] == '@') return dofile(L, init+1); else - return dostring(L, init, "=" LUA_INIT); + return dostring(L, init, name); } -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 argc = (int)lua_tointeger(L, 1); + char **argv = (char **)lua_touserdata(L, 2); int script; - int has_i = 0, has_v = 0, has_e = 0; - globalL = L; + int args[num_has]; + args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0; if (argv[0] && argv[0][0]) progname = argv[0]; + script = collectargs(argv, args); + if (script < 0) { /* invalid arg? */ + print_usage(argv[-script]); + return 0; + } + if (args[has_v]) print_version(); + if (args[has_E]) { /* option '-E'? */ + lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + } + /* open standard libraries */ + luaL_checkversion(L); 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) + if (!args[has_E] && handle_luainit(L) != LUA_OK) + return 0; /* error running LUA_INIT */ + /* execute arguments -e and -l */ + if (!runargs(L, argv, (script > 0) ? script : argc)) return 0; + /* execute main script (if there is one) */ + if (script && handle_script(L, argv, script) != LUA_OK) return 0; + if (args[has_i]) /* -i option? */ dotty(L); - else if (script == 0 && !has_e && !has_v) { + else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */ if (lua_stdin_is_tty()) { print_version(); dotty(L); } else dofile(L, NULL); /* executes stdin as a file */ } - return 0; + lua_pushboolean(L, 1); /* signal no errors */ + return 1; } int main (int argc, char **argv) { - int status; - struct Smain s; - lua_State *L = lua_open(); /* create state */ + int status, result; + lua_State *L = luaL_newstate(); /* 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); + /* call 'pmain' in protected mode */ + lua_pushcfunction(L, &pmain); + lua_pushinteger(L, argc); /* 1st argument */ + lua_pushlightuserdata(L, argv); /* 2nd argument */ + status = lua_pcall(L, 2, 1, 0); + result = lua_toboolean(L, -1); /* get result */ + finalreport(L, status); lua_close(L); - return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; + return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/liblua/lua.h b/liblua/lua.h index 5bc97b746f..1fafa45e4c 100644 --- a/liblua/lua.h +++ b/liblua/lua.h @@ -1,6 +1,6 @@ /* -** $Id: lua.h,v 1.218.1.4 2008/01/03 15:41:15 roberto Exp $ -** Lua - An Extensible Extension Language +** $Id: lua.h,v 1.282 2011/11/29 15:55:08 roberto Exp $ +** Lua - A Scripting Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file */ @@ -16,35 +16,39 @@ #include "luaconf.h" -#define LUA_VERSION "Lua 5.1" -#define LUA_RELEASE "Lua 5.1.3" -#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" +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "2" +#define LUA_VERSION_NUM 502 +#define LUA_VERSION_RELEASE "0" +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2011 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' */ +/* 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)) +#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) -/* thread status; 0 is OK */ +/* thread status */ +#define LUA_OK 0 #define LUA_YIELD 1 #define LUA_ERRRUN 2 #define LUA_ERRSYNTAX 3 #define LUA_ERRMEM 4 -#define LUA_ERRERR 5 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 typedef struct lua_State lua_State; @@ -81,18 +85,18 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); #define LUA_TUSERDATA 7 #define LUA_TTHREAD 8 +#define LUA_NUMTAGS 9 + /* 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 +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS /* type of numbers in Lua */ @@ -102,6 +106,18 @@ typedef LUA_NUMBER lua_Number; /* type for integer functions */ typedef LUA_INTEGER lua_Integer; +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + /* @@ -114,15 +130,20 @@ LUA_API lua_State *(lua_newthread) (lua_State *L); LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); +LUA_API const lua_Number *(lua_version) (lua_State *L); + + /* ** basic stack manipulation */ +LUA_API int (lua_absindex) (lua_State *L, int idx); 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 void (lua_copy) (lua_State *L, int fromidx, int toidx); LUA_API int (lua_checkstack) (lua_State *L, int sz); LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); @@ -139,29 +160,49 @@ 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 lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); 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 size_t (lua_rawlen) (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); +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPDIV 3 +#define LUA_OPMOD 4 +#define LUA_OPPOW 5 +#define LUA_OPUNM 6 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + /* ** 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 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_pushunsigned) (lua_State *L, lua_Unsigned n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API const char *(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, ...); @@ -174,35 +215,47 @@ LUA_API int (lua_pushthread) (lua_State *L); /* ** get functions (Lua -> stack) */ +LUA_API void (lua_getglobal) (lua_State *L, const char *var); 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_rawgetp) (lua_State *L, int idx, const void *p); 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); +LUA_API void (lua_getuservalue) (lua_State *L, int idx); /* ** set functions (stack -> Lua) */ +LUA_API void (lua_setglobal) (lua_State *L, const char *var); 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 void (lua_rawsetp) (lua_State *L, int idx, const void *p); LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -LUA_API int (lua_setfenv) (lua_State *L, int idx); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); /* -** `load' and `call' functions (load and run Lua code) +** '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 void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, + lua_CFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_getctx) (lua_State *L, int *ctx); + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + int ctx, lua_CFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname); + const char *chunkname, + const char *mode); LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); @@ -210,8 +263,10 @@ 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_yieldk) (lua_State *L, int nresults, int ctx, + lua_CFunction k); +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); LUA_API int (lua_status) (lua_State *L); /* @@ -226,6 +281,10 @@ LUA_API int (lua_status) (lua_State *L); #define LUA_GCSTEP 5 #define LUA_GCSETPAUSE 6 #define LUA_GCSETSTEPMUL 7 +#define LUA_GCSETMAJORINC 8 +#define LUA_GCISRUNNING 9 +#define LUA_GCGEN 10 +#define LUA_GCINC 11 LUA_API int (lua_gc) (lua_State *L, int what, int data); @@ -239,18 +298,23 @@ 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 void (lua_len) (lua_State *L, int idx); LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); -/* +/* ** =============================================================== ** some useful macros ** =============================================================== */ +#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) +#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) + #define lua_pop(L,n) lua_settop(L, -(n)-1) #define lua_newtable(L) lua_createtable(L, 0, 0) @@ -259,8 +323,6 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); #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) @@ -273,31 +335,13 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); #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_pushglobaltable(L) \ + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) #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 @@ -312,7 +356,7 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to); #define LUA_HOOKRET 1 #define LUA_HOOKLINE 2 #define LUA_HOOKCOUNT 3 -#define LUA_HOOKTAILRET 4 +#define LUA_HOOKTAILCALL 4 /* @@ -326,43 +370,50 @@ LUA_API void lua_setlevel (lua_State *from, lua_State *to); typedef struct lua_Debug lua_Debug; /* activation record */ -/* Functions to be called by the debuger in specific events */ +/* Functions to be called by the debugger 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_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 void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); -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); +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 *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) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ char short_src[LUA_IDSIZE]; /* (S) */ /* private part */ - int i_ci; /* active function */ + struct CallInfo *i_ci; /* active function */ }; /* }====================================================================== */ /****************************************************************************** -* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. +* Copyright (C) 1994-2011 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 diff --git a/liblua/lua.hpp b/liblua/lua.hpp new file mode 100644 index 0000000000..ec417f5946 --- /dev/null +++ b/liblua/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/liblua/luac.c b/liblua/luac.c index d07017391b..5081836d4c 100644 --- a/liblua/luac.c +++ b/liblua/luac.c @@ -1,5 +1,5 @@ /* -** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $ +** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $ ** Lua compiler (saves bytecodes to files; also list bytecodes) ** See Copyright Notice in lua.h */ @@ -15,16 +15,15 @@ #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 "lstate.h" #include "lundump.h" +static void PrintFunction(const Proto* f, int full); +#define luaU_print PrintFunction + #define PROGNAME "luac" /* default program name */ -#define OUTPUT PROGNAME ".out" /* default output file */ +#define OUTPUT PROGNAME ".out" /* default output file */ static int listing=0; /* list bytecodes? */ static int dumping=1; /* dump bytecodes? */ @@ -52,20 +51,20 @@ static void usage(const char* 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); + "usage: %s [options] [filenames]\n" + "Available options are:\n" + " -l list (use -l -l for full listing)\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" + " - stop handling options and process stdin\n" + ,progname,Output); exit(EXIT_FAILURE); } -#define IS(s) (strcmp(argv[i],s)==0) +#define IS(s) (strcmp(argv[i],s)==0) static int doargs(int argc, char* argv[]) { @@ -89,7 +88,8 @@ static int doargs(int argc, char* argv[]) else if (IS("-o")) /* output file */ { output=argv[++i]; - if (output==NULL || *output==0) usage(LUA_QL("-o") " needs argument"); + if (output==NULL || *output==0 || (*output=='-' && output[1]!=0)) + usage(LUA_QL("-o") " needs argument"); if (IS("-")) output=NULL; } else if (IS("-p")) /* parse only */ @@ -108,13 +108,30 @@ static int doargs(int argc, char* argv[]) } if (version) { - printf("%s %s\n",LUA_RELEASE,LUA_COPYRIGHT); + printf("%s\n",LUA_COPYRIGHT); if (version==argc-1) exit(EXIT_SUCCESS); } return i; } -#define toproto(L,i) (clvalue(L->top+(i))->l.p) +#define FUNCTION "(function()end)();" + +static const char* reader(lua_State *L, void *ud, size_t *size) +{ + UNUSED(L); + if ((*(int*)ud)--) + { + *size=sizeof(FUNCTION)-1; + return FUNCTION; + } + else + { + *size=0; + return NULL; + } +} + +#define toproto(L,i) getproto(L->top+(i)) static const Proto* combine(lua_State* L, int n) { @@ -122,24 +139,16 @@ static const Proto* combine(lua_State* L, int n) 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; + Proto* f; + int i=n; + if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); + f=toproto(L,-1); 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); + if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; } - f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); + f->sizelineinfo=0; return f; } } @@ -150,23 +159,17 @@ static int writer(lua_State* L, const void* p, size_t size, void* u) 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; + int argc=(int)lua_tointeger(L,1); + char** argv=(char**)lua_touserdata(L,2); const Proto* f; int i; if (!lua_checkstack(L,argc)) fatal("too many input files"); for (i=0; i1); @@ -186,15 +189,244 @@ static int pmain(lua_State* L) 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)); + L=luaL_newstate(); + if (L==NULL) fatal("cannot create state: not enough memory"); + lua_pushcfunction(L,&pmain); + lua_pushinteger(L,argc); + lua_pushlightuserdata(L,argv); + if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); lua_close(L); return EXIT_SUCCESS; } + +/* +** $Id: print.c,v 1.68 2011/09/30 10:21:20 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" + +#define VOID(p) ((const void*)(p)) + +static void PrintString(const TString* ts) +{ + const char* s=getstr(ts); + size_t i,n=ts->tsv.len; + printf("%c",'"'); + 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; + } +} + +#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") +#define MYK(x) (-1-(x)) + +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) ? (MYK(INDEXK(b))) : b); + if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); + break; + case iABx: + printf("%d",a); + if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); + if (getBMode(o)==OpArgU) printf(" %d",bx); + break; + case iAsBx: + printf("%d %d",a,sbx); + break; + case iAx: + printf("%d",MYK(ax)); + break; + } + switch (o) + { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s",UPVALNAME(b)); + break; + case OP_GETTABUP: + printf("\t; %s",UPVALNAME(b)); + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABUP: + printf("\t; %s",UPVALNAME(a)); + if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + 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: + case OP_TFORLOOP: + 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; + case OP_EXTRAARG: + printf("\t; "); PrintConstant(f,ax); + break; + default: + break; + } + printf("\n"); + } +} + +#define SS(x) ((x==1)?"":"s") +#define S(x) (int)(x),SS(x) + +static void PrintHeader(const Proto* f) +{ + const char* s=f->source ? 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 at %p)\n", + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),VOID(f)); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->sizeupvalues)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +static void PrintDebug(const Proto* f) +{ + int i,n; + 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); + } + n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + for (i=0; iupvalues[i].instack,f->upvalues[i].idx); + } +} + +static void PrintFunction(const Proto* f, int full) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); + if (full) PrintDebug(f); + for (i=0; ip[i],full); +} diff --git a/liblua/luaconf.h b/liblua/luaconf.h index 0e593f61f4..bab401e9a9 100644 --- a/liblua/luaconf.h +++ b/liblua/luaconf.h @@ -1,5 +1,5 @@ /* -** $Id: luaconf.h,v 1.82.1.6 2008/01/18 17:07:48 roberto Exp $ +** $Id: luaconf.h,v 1.170 2011/12/06 16:58:36 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ @@ -24,30 +24,44 @@ ** CHANGE it (define it) if you want Lua to avoid the use of any ** non-ansi feature or library. */ -#if defined(__STRICT_ANSI__) +#if !defined(LUA_ANSI) && defined(__STRICT_ANSI__) #define LUA_ANSI #endif -#if !defined(LUA_ANSI) && defined(_WIN32) -#define LUA_WIN +#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_WIN /* enable goodies for regular Windows platforms */ #endif +#if defined(LUA_WIN) +#define LUA_DL_DLL +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#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 */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ #endif #if defined(LUA_USE_MACOSX) #define LUA_USE_POSIX -#define LUA_DL_DYLD /* does not need extra library */ +#define LUA_USE_DLOPEN /* does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hexa formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ #endif /* -@@ LUA_USE_POSIX includes all functionallity listed as X/Open System +@@ LUA_USE_POSIX includes all functionality listed as X/Open System @* Interfaces Extension (XSI). ** CHANGE it (define it) if your system is XSI compatible. */ @@ -56,20 +70,10 @@ #define LUA_USE_ISATTY #define LUA_USE_POPEN #define LUA_USE_ULONGJMP +#define LUA_USE_GMTIME_R #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 @@ -80,7 +84,7 @@ ** hierarchy or if you want to install your libraries in ** non-conventional directories. */ -#if defined(_WIN32) +#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. @@ -88,21 +92,23 @@ #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" + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" #define LUA_CPATH_DEFAULT \ - ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" -#else +#else /* }{ */ + +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" #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_LDIR LUA_ROOT "share/lua/" LUA_VDIR +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR #define LUA_PATH_DEFAULT \ - "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" #define LUA_CPATH_DEFAULT \ - "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" -#endif + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ /* @@ -118,79 +124,67 @@ /* -@@ 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.) +@@ LUA_ENV is the name of the variable that holds the current +@@ environment, used to access global names. +** CHANGE it if you do not like this name. */ -#define LUA_INTEGER ptrdiff_t +#define LUA_ENV "_ENV" /* @@ LUA_API is a mark for all core API functions. -@@ LUALIB_API is a mark for all standard library functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening 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_BUILD_AS_DLL) /* { */ -#if defined(LUA_CORE) || defined(LUA_LIB) +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ #define LUA_API __declspec(dllexport) -#else +#else /* }{ */ #define LUA_API __declspec(dllimport) -#endif +#endif /* } */ -#else +#else /* }{ */ #define LUA_API extern -#endif +#endif /* } */ + /* more often than not the libs go together with the core */ #define LUALIB_API LUA_API +#define LUAMOD_API LUALIB_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. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables +@* that are not to be exported to outside modules (LUAI_DDEF for +@* definitions and LUAI_DDEC for declarations). ** 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__) +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ #define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DATA LUAI_FUNC +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ -#else +#else /* }{ */ #define LUAI_FUNC extern -#define LUAI_DATA extern -#endif +#define LUAI_DDEC extern +#define LUAI_DDEF /* empty */ +#endif /* } */ @@ -211,175 +205,101 @@ /* -** {================================================================== -** 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. +@@ luai_writestring/luai_writeline define how 'print' prints its results. +** They are only used in libraries and the stand-alone program. (The #if +** avoids including 'stdio.h' everywhere.) */ -#if defined(LUA_USE_ISATTY) -#include -#define lua_stdin_is_tty() isatty(0) -#elif defined(LUA_WIN) -#include +#if defined(LUA_LIB) || defined(lua_c) #include -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) -#else -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) #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.) +@@ luai_writestringerror defines how to print error messages. +** (A format string with one argument is enough for Lua...) */ -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " +#define luai_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) -/* -@@ 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). +** {================================================================== +** Compatibility with previous versions +** =================================================================== */ -#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. +@@ LUA_COMPAT_ALL controls all compatibility options. +** You can define it to get all options, or change specific options +** to fit your specific needs. */ -#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ - +#if defined(LUA_COMPAT_ALL) /* { */ /* -@@ 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. +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. */ -#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ - - +#define LUA_COMPAT_UNPACK /* -@@ 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. +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. */ -#undef LUA_COMPAT_GETN +#define LUA_COMPAT_LOADERS /* -@@ 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'). +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). */ -#undef LUA_COMPAT_LOADLIB +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) -/* -@@ 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'. +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. */ -#define LUA_COMPAT_MOD +#define LUA_COMPAT_LOG10 /* -@@ 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 [[...]]. +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. */ -#define LUA_COMPAT_LSTR 1 +#define LUA_COMPAT_LOADSTRING /* -@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. -** CHANGE it to undefined as soon as you rename 'string.gfind' to -** 'string.gmatch'. +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. */ -#define LUA_COMPAT_GFIND +#define LUA_COMPAT_MAXN /* -@@ 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' +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. */ -#define LUA_COMPAT_OPENLIB +#define lua_strlen(L,i) lua_rawlen(L, (i)) +#define lua_objlen(L,i) lua_rawlen(L, (i)) +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) /* -@@ 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. +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). */ -#if defined(LUA_USE_APICHECK) -#include -#define luai_apicheck(L,o) { (void)L; assert(o); } -#else -#define luai_apicheck(L,o) { (void)L; } -#endif +#define LUA_COMPAT_MODULE + +#endif /* } */ + +/* }================================================================== */ + /* @@ -388,106 +308,62 @@ ** your machine. Probably you do not need to change this. */ /* avoid overflows in comparison */ -#if INT_MAX-20 < 32760 +#if INT_MAX-20 < 32760 /* { */ #define LUAI_BITSINT 16 -#elif INT_MAX > 2147483640L +#elif INT_MAX > 2147483640L /* }{ */ /* int has at least 32 bits */ #define LUAI_BITSINT 32 -#else +#else /* }{ */ #error "you must define LUA_BITSINT with number of bits in an integer" -#endif +#endif /* } */ /* -@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. -@@ LUAI_INT32 is an signed integer with at least 32 bits. +@@ LUA_INT32 is an signed integer with exactly 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. +** good enough for your machine. 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 +#if LUAI_BITSINT >= 32 /* { */ +#define LUA_INT32 int #define LUAI_UMEM size_t #define LUAI_MEM ptrdiff_t -#else +#else /* }{ */ /* 16-bit ints */ -#define LUAI_UINT32 unsigned long -#define LUAI_INT32 long -#define LUAI_MAXINT32 LONG_MAX +#define LUA_INT32 long #define LUAI_UMEM unsigned long #define LUAI_MEM long -#endif +#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. +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua to consume unlimited stack +** space (and to reserve some numbers for pseudo-indices). */ -#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. -*/ -#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 - +#if LUAI_BITSINT >= 32 +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif -/* -@@ LUAI_MAXVARS is the maximum number of local variables per function -@* (must be smaller than 250). -*/ -#define LUAI_MAXVARS 200 +/* reserve some space for error handling */ +#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) -/* -@@ 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. +** CHANGE it if it uses too much C-stack space. */ #define LUAL_BUFFERSIZE BUFSIZ -/* }================================================================== */ - @@ -515,237 +391,128 @@ @@ 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. +@@ lua_str2number converts a decimal numeric string to a number. +@@ lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' do both conversions. C89, however, has no function +** to convert floating hexadecimal strings to numbers. For these +** systems, you can leave 'lua_strx2number' undefined and Lua will +** provide its own implementation. */ -#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))) +#define lua_str2number(s,p) strtod((s), (p)) + +#if defined(LUA_USE_STRTODHEX) +#define lua_strx2number(s,p) strtod((s), (p)) #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. +@@ The luai_num* macros define the primitive operations over numbers. */ -/* 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) - +/* the following operations need the math library */ +#if defined(lobject_c) || defined(lvm_c) +#include +#define luai_nummod(L,a,b) ((a) - floor((a)/(b))*(b)) +#define luai_numpow(L,a,b) (pow(a,b)) #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)) - +/* these are quite standard operations */ +#if defined(LUA_CORE) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numdiv(L,a,b) ((a)/(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(L,a,b) ((a)<(b)) +#define luai_numle(L,a,b) ((a)<=(b)) +#define luai_numisnan(L,a) (!luai_numeq((a), (a))) #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. +@@ 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 LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } - +#define LUA_INTEGER ptrdiff_t /* -@@ 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. +@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. +** It must have at least 32 bits. */ -#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 +#define LUA_UNSIGNED unsigned LUA_INT32 -/* -@@ 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 - +#if defined(LUA_CORE) /* { */ -/* -@@ 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_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ -#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); } +/* On a Microsoft compiler on a Pentium, use assembler to avoid clashes + with a DirectX idiosyncrasy */ +#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ -#else -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } -#endif +#define MS_ASMTRICK -#endif +#else /* }{ */ +/* the next definition uses a trick that should work on any machine + using IEEE754 with a 32-bit integer type */ +#define LUA_IEEE754TRICK /* -@@ 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. +@@ LUA_IEEEENDIAN is the endianness of doubles in your machine +** (0 for little endian, 1 for big endian); if not defined, Lua will +** check it dynamically. */ -#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) - +/* check for known architectures */ +#if defined(__i386__) || defined(__i386) || defined(__X86__) || \ + defined (__x86_64) +#define LUA_IEEEENDIAN 0 +#elif defined(__POWERPC__) || defined(__ppc__) +#define LUA_IEEEENDIAN 1 #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 +#endif /* } */ -#if defined(LUA_WIN) -#define LUA_DL_DLL -#endif +#endif /* } */ +#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. +@@ LUA_NANTRICK_LE/LUA_NANTRICK_BE controls the use of a trick to +** pack all types into a single double value, using NaN values to +** represent non-number values. The trick only works on 32-bit machines +** (ints and pointers are 32-bit values) with numbers represented as +** IEEE 754-2008 doubles with conventional endianess (12345678 or +** 87654321), in CPUs that do not produce signaling NaN values (all NaNs +** are quiet). */ +#if defined(LUA_CORE) && \ + defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ -#if defined(LUA_USELONGLONG) +/* little-endian architectures that satisfy those conditions */ +#if defined(__i386__) || defined(__i386) || defined(__X86__) || \ + defined(_M_IX86) -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long +#define LUA_NANTRICK_LE -#else +#endif -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long +#endif /* } */ -#endif diff --git a/liblua/lualib.h b/liblua/lualib.h index 469417f670..9fd126bf78 100644 --- a/liblua/lualib.h +++ b/liblua/lualib.h @@ -1,5 +1,5 @@ /* -** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lualib.h,v 1.43 2011/12/08 12:11:37 roberto Exp $ ** Lua standard libraries ** See Copyright Notice in lua.h */ @@ -11,41 +11,43 @@ #include "lua.h" -/* Key to file-handle type */ -#define LUA_FILEHANDLE "FILE*" +LUAMOD_API int (luaopen_base) (lua_State *L); #define LUA_COLIBNAME "coroutine" -LUALIB_API int (luaopen_base) (lua_State *L); +LUAMOD_API int (luaopen_coroutine) (lua_State *L); #define LUA_TABLIBNAME "table" -LUALIB_API int (luaopen_table) (lua_State *L); +LUAMOD_API int (luaopen_table) (lua_State *L); #define LUA_IOLIBNAME "io" -LUALIB_API int (luaopen_io) (lua_State *L); +LUAMOD_API int (luaopen_io) (lua_State *L); #define LUA_OSLIBNAME "os" -LUALIB_API int (luaopen_os) (lua_State *L); +LUAMOD_API int (luaopen_os) (lua_State *L); #define LUA_STRLIBNAME "string" -LUALIB_API int (luaopen_string) (lua_State *L); +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (lua_State *L); #define LUA_MATHLIBNAME "math" -LUALIB_API int (luaopen_math) (lua_State *L); +LUAMOD_API int (luaopen_math) (lua_State *L); #define LUA_DBLIBNAME "debug" -LUALIB_API int (luaopen_debug) (lua_State *L); +LUAMOD_API int (luaopen_debug) (lua_State *L); #define LUA_LOADLIBNAME "package" -LUALIB_API int (luaopen_package) (lua_State *L); +LUAMOD_API int (luaopen_package) (lua_State *L); /* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); +LUALIB_API void (luaL_openlibs) (lua_State *L); -#ifndef lua_assert +#if !defined(lua_assert) #define lua_assert(x) ((void)0) #endif diff --git a/liblua/lundump.c b/liblua/lundump.c index 731c064553..80c7aa39b3 100644 --- a/liblua/lundump.c +++ b/liblua/lundump.c @@ -1,5 +1,5 @@ /* -** $Id: lundump.c,v 2.7.1.2 2008/01/18 16:39:11 roberto Exp $ +** $Id: lundump.c,v 1.71 2011/12/07 10:39:12 lhf Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -27,29 +27,24 @@ typedef struct { 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); + luaO_pushfstring(S->L,"%s: %s 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 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) +#if !defined(luai_verifycode) +#define luai_verifycode(L,b,f) (f) +#endif + static void LoadBlock(LoadState* S, void* b, size_t size) { - size_t r=luaZ_read(S->Z,b,size); - UNUSED(r); - IF (r!=0, "unexpected end"); + if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated"); } static int LoadChar(LoadState* S) @@ -63,7 +58,7 @@ static int LoadInt(LoadState* S) { int x; LoadVar(S,x); - IF (x<0, "bad integer"); + if (x<0) error(S,"corrupted"); return x; } @@ -83,7 +78,7 @@ static TString* LoadString(LoadState* S) else { char* s=luaZ_openspace(S->L,S->b,size); - LoadBlock(S,s,size); + LoadBlock(S,s,size*sizeof(char)); return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ } } @@ -96,7 +91,7 @@ static void LoadCode(LoadState* S, Proto* f) LoadVector(S,f->code,n,sizeof(Instruction)); } -static Proto* LoadFunction(LoadState* S, TString* p); +static Proto* LoadFunction(LoadState* S); static void LoadConstants(LoadState* S, Proto* f) { @@ -112,10 +107,10 @@ static void LoadConstants(LoadState* S, Proto* f) switch (t) { case LUA_TNIL: - setnilvalue(o); + setnilvalue(o); break; case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)); + setbvalue(o,LoadChar(S)); break; case LUA_TNUMBER: setnvalue(o,LoadNumber(S)); @@ -123,21 +118,33 @@ static void LoadConstants(LoadState* S, Proto* f) 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); + for (i=0; ip[i]=LoadFunction(S); +} + +static void LoadUpvalues(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->upvalues=luaM_newvector(S->L,n,Upvaldesc); + f->sizeupvalues=n; + for (i=0; iupvalues[i].name=NULL; + for (i=0; iupvalues[i].instack=LoadByte(S); + f->upvalues[i].idx=LoadByte(S); + } } static void LoadDebug(LoadState* S, Proto* f) { int i,n; + f->source=LoadString(S); n=LoadInt(S); f->lineinfo=luaM_newvector(S->L,n,int); f->sizelineinfo=n; @@ -153,38 +160,43 @@ static void LoadDebug(LoadState* S, Proto* f) 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); + for (i=0; iupvalues[i].name=LoadString(S); } -static Proto* LoadFunction(LoadState* S, TString* p) +static Proto* LoadFunction(LoadState* S) { Proto* 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); + LoadUpvalues(S,f); LoadDebug(S,f); - IF (!luaG_checkcode(f), "bad code"); S->L->top--; return f; } +/* the code below must be consistent with the code in luaU_header */ +#define N0 LUAC_HEADERSIZE +#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char)) +#define N2 N1+2 +#define N3 N2+6 + static void LoadHeader(LoadState* S) { - char h[LUAC_HEADERSIZE]; - char s[LUAC_HEADERSIZE]; + lu_byte h[LUAC_HEADERSIZE]; + lu_byte s[LUAC_HEADERSIZE]; luaU_header(h); - LoadBlock(S,s,LUAC_HEADERSIZE); - IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); + memcpy(s,h,sizeof(char)); /* first char already read */ + LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char)); + if (memcmp(h,s,N0)==0) return; + if (memcmp(h,s,N1)!=0) error(S,"not a"); + if (memcmp(h,s,N2)!=0) error(S,"version mismatch in"); + if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted"); } /* @@ -203,23 +215,30 @@ Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) S.Z=Z; S.b=buff; LoadHeader(&S); - return LoadFunction(&S,luaS_newliteral(L,"=?")); + return luai_verifycode(L,buff,LoadFunction(&S)); } +#define MYINT(s) (s[0]-'0') +#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR) +#define FORMAT 0 /* this is the official format */ + /* -* make header +* make header for precompiled chunks +* if you change the code below be sure to update LoadHeader and FORMAT above +* and LUAC_HEADERSIZE in lundump.h */ -void luaU_header (char* h) +void luaU_header (lu_byte* 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? */ + memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char)); + h+=sizeof(LUA_SIGNATURE)-sizeof(char); + *h++=cast_byte(VERSION); + *h++=cast_byte(FORMAT); + *h++=cast_byte(*(char*)&x); /* endianness */ + *h++=cast_byte(sizeof(int)); + *h++=cast_byte(sizeof(size_t)); + *h++=cast_byte(sizeof(Instruction)); + *h++=cast_byte(sizeof(lua_Number)); + *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ + memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char)); } diff --git a/liblua/lundump.h b/liblua/lundump.h index c80189dbff..b63993ffe5 100644 --- a/liblua/lundump.h +++ b/liblua/lundump.h @@ -1,5 +1,5 @@ /* -** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lundump.h,v 1.44 2011/05/06 13:35:17 lhf Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -14,23 +14,15 @@ 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); +LUAI_FUNC void luaU_header (lu_byte* 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 +/* data to catch conversion errors */ +#define LUAC_TAIL "\x19\x93\r\n\x1a\n" -/* size of header of binary files */ -#define LUAC_HEADERSIZE 12 +/* size in bytes of header of binary files */ +#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) #endif diff --git a/liblua/lvm.c b/liblua/lvm.c index ee3256ab94..694971b116 100644 --- a/liblua/lvm.c +++ b/liblua/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: lvm.c,v 2.147 2011/12/07 14:43:55 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -35,7 +35,7 @@ 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)) { + if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) { setnvalue(n, num); return n; } @@ -50,58 +50,52 @@ int luaV_tostring (lua_State *L, StkId obj) { else { char s[LUAI_MAXNUMBER2STR]; lua_Number n = nvalue(obj); - lua_number2str(s, n); - setsvalue2s(L, obj, luaS_new(L, s)); + int l = lua_number2str(s, n); + setsvalue2s(L, obj, luaS_newlstr(L, s, l)); return 1; } } -static void traceexec (lua_State *L, const Instruction *pc) { +static void traceexec (lua_State *L) { + CallInfo *ci = L->ci; 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); + luaD_hook(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); + Proto *p = ci_func(ci)->p; + int npc = pcRel(ci->u.l.savedpc, p); + int newline = getfuncline(p, npc); + if (npc == 0 || /* call linehook when enter a new function, */ + ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ + newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ + luaD_hook(L, LUA_HOOKLINE, newline); + } + L->oldpc = ci->u.l.savedpc; + if (L->status == LUA_YIELD) { /* did hook yield? */ + ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ + luaD_throw(L, LUA_YIELD); } } -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); + const TValue *p2, TValue *p3, int hasres) { + ptrdiff_t result = savestack(L, p3); + setobj2s(L, L->top++, f); /* push function */ + setobj2s(L, L->top++, p1); /* 1st argument */ + setobj2s(L, L->top++, p2); /* 2nd argument */ + if (!hasres) /* no result? 'p3' is third argument */ + setobj2s(L, L->top++, p3); /* 3rd argument */ + luaD_checkstack(L, 0); + /* metamethod may yield only when called from Lua code */ + luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); + if (hasres) { /* if has result, move it to its place */ + p3 = restorestack(L, result); + setobjs2s(L, p3, --L->top); + } } @@ -112,7 +106,7 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { 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? */ + if (!ttisnil(res) || /* result is not nil? */ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ setobj2s(L, val, res); return; @@ -122,10 +116,10 @@ void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) luaG_typeerror(L, t, "index"); if (ttisfunction(tm)) { - callTMres(L, val, tm, t, key); + callTM(L, tm, t, key, val, 1); return; } - t = tm; /* else repeat with `tm' */ + t = tm; /* else repeat with 'tm' */ } luaG_runerror(L, "loop in gettable"); } @@ -137,22 +131,34 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { 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); + TValue *oldval = cast(TValue *, luaH_get(h, key)); + /* if previous value is not nil, there must be a previous entry + in the table; moreover, a metamethod has no relevance */ + if (!ttisnil(oldval) || + /* previous value is nil; must check the metamethod */ + ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && + /* no metamethod; is there a previous entry in the table? */ + (oldval != luaO_nilobject || + /* no previous entry; must create one. (The next test is + always true; we only need the assignment.) */ + (oldval = luaH_newkey(L, h, key), 1)))) { + /* no metamethod and (now) there is an entry with given key */ + setobj2t(L, oldval, val); /* assign new value to that entry */ + invalidateTMcache(h); + luaC_barrierback(L, obj2gco(h), val); return; } - /* else will try the tag method */ + /* else will try the metamethod */ } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_typeerror(L, t, "index"); + else /* not a table; check metamethod */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + /* there is a metamethod */ if (ttisfunction(tm)) { - callTM(L, tm, t, key, val); + callTM(L, tm, t, key, val, 0); return; } - t = tm; /* else repeat with `tm' */ + t = tm; /* else repeat with 'tm' */ } luaG_runerror(L, "loop in settable"); } @@ -164,12 +170,12 @@ static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, if (ttisnil(tm)) tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ if (ttisnil(tm)) return 0; - callTMres(L, res, tm, p1, p2); + callTM(L, tm, p1, p2, res, 1); return 1; } -static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, +static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2, TMS event) { const TValue *tm1 = fasttm(L, mt1, event); const TValue *tm2; @@ -177,7 +183,7 @@ static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, 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? */ + if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ return tm1; return NULL; } @@ -185,14 +191,10 @@ static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, 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); + if (!call_binTM(L, p1, p2, L->top, event)) + return -1; /* no metamethod */ + else + return !l_isfalse(L->top); } @@ -220,125 +222,259 @@ static int l_strcmp (const TString *ls, const TString *rs) { 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)) + if (ttisnumber(l) && ttisnumber(r)) + return luai_numlt(L, nvalue(l), nvalue(r)); + else if (ttisstring(l) && ttisstring(r)) 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); + else if ((res = call_orderTM(L, l, r, TM_LT)) < 0) + luaG_ordererror(L, l, r); + return res; } -static int lessequal (lua_State *L, const TValue *l, const TValue *r) { +int luaV_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)) + if (ttisnumber(l) && ttisnumber(r)) + return luai_numle(L, nvalue(l), nvalue(r)); + else if (ttisstring(l) && ttisstring(r)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; - else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* 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); + else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ + luaG_ordererror(L, l, r); + return !res; } -int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { +/* +** equality of Lua values. L == NULL means raw equality (no metamethods) +*/ +int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { const TValue *tm; - lua_assert(ttype(t1) == ttype(t2)); + lua_assert(ttisequal(t1, 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_TLCF: return fvalue(t1) == fvalue(t2); + case LUA_TSTRING: return eqstr(rawtsvalue(t1), rawtsvalue(t2)); case LUA_TUSERDATA: { if (uvalue(t1) == uvalue(t2)) return 1; - tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, - TM_EQ); + else if (L == NULL) return 0; + tm = get_equalTM(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); + else if (L == NULL) return 0; + tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); break; /* will try TM */ } - default: return gcvalue(t1) == gcvalue(t2); + default: + lua_assert(iscollectable(t1)); + return gcvalue(t1) == gcvalue(t2); } if (tm == NULL) return 0; /* no TM? */ - callTMres(L, L->top, tm, t1, t2); /* call TM */ + callTM(L, tm, t1, t2, L->top, 1); /* call TM */ return !l_isfalse(L->top); } -void luaV_concat (lua_State *L, int total, int last) { +void luaV_concat (lua_State *L, int total) { + lua_assert(total >= 2); do { - StkId top = L->base + last + 1; + StkId top = L->top; 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 if (tsvalue(top-1)->len == 0) /* second operand is empty? */ + (void)tostring(L, top - 2); /* result is first operand */ + else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { + setsvalue2s(L, top-2, rawtsvalue(top-1)); /* result is second op. */ + } else { - /* at least two string values; get as many as possible */ + /* at least two non-empty 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"); + for (i = 1; i < total && tostring(L, top-i-1); i++) { + size_t l = tsvalue(top-i-1)->len; + if (l >= (MAX_SIZET/sizeof(char)) - 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 */ + n = i; + do { /* concat all strings */ size_t l = tsvalue(top-i)->len; - memcpy(buffer+tl, svalue(top-i), l); + memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); tl += l; - } + } while (--i > 0); setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); } - total -= n-1; /* got `n' strings to create 1 new */ - last -= n-1; + total -= n-1; /* got 'n' strings to create 1 new */ + L->top -= n-1; /* popped 'n' strings and pushed one */ } 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) { +void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { + const TValue *tm; + switch (ttypenv(rb)) { + case LUA_TTABLE: { + Table *h = hvalue(rb); + tm = fasttm(L, h->metatable, TM_LEN); + if (tm) break; /* metamethod? break switch to call it */ + setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */ + return; + } + case LUA_TSTRING: { + setnvalue(ra, cast_num(tsvalue(rb)->len)); + return; + } + default: { /* try metamethod */ + tm = luaT_gettmbyobj(L, rb, TM_LEN); + if (ttisnil(tm)) /* no metamethod? */ + luaG_typeerror(L, rb, "get length of"); + break; + } + } + callTM(L, tm, rb, rb, ra, 1); +} + + +void luaV_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; - } + lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c)); + setnvalue(ra, res); } else if (!call_binTM(L, rb, rc, ra, op)) luaG_aritherror(L, rb, rc); } +/* +** check whether cached closure in prototype 'p' may be reused, that is, +** whether there is a cached closure with the same upvalues needed by +** new closure to be created. +*/ +static Closure *getcached (Proto *p, UpVal **encup, StkId base) { + Closure *c = p->cache; + if (c != NULL) { /* is there a cached closure? */ + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ + TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; + if (c->l.upvals[i]->v != v) + return NULL; /* wrong upvalue; cannot reuse closure */ + } + } + return c; /* return cached closure (or NULL if no cached closure) */ +} + + +/* +** create a new Lua closure, push it in the stack, and initialize +** its upvalues. Note that the call to 'luaC_barrierproto' must come +** before the assignment to 'p->cache', as the function needs the +** original value of that field. +*/ +static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, + StkId ra) { + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + Closure *ncl = luaF_newLclosure(L, p); + setclLvalue(L, ra, ncl); /* anchor new closure in stack */ + for (i = 0; i < nup; i++) { /* fill in its upvalues */ + if (uv[i].instack) /* upvalue refers to local variable? */ + ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); + else /* get upvalue from enclosing function */ + ncl->l.upvals[i] = encup[uv[i].idx]; + } + luaC_barrierproto(L, p, ncl); + p->cache = ncl; /* save it on cache for reuse */ +} + + +/* +** finish execution of an opcode interrupted by an yield +*/ +void luaV_finishOp (lua_State *L) { + CallInfo *ci = L->ci; + StkId base = ci->u.l.base; + Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ + OpCode op = GET_OPCODE(inst); + switch (op) { /* finish its execution */ + case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: + case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: + case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { + setobjs2s(L, base + GETARG_A(inst), --L->top); + break; + } + case OP_LE: case OP_LT: case OP_EQ: { + int res = !l_isfalse(L->top - 1); + L->top--; + /* metamethod should not be called when operand is K */ + lua_assert(!ISK(GETARG_B(inst))); + if (op == OP_LE && /* "<=" using "<" instead? */ + ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) + res = !res; /* invert result */ + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + if (res != GETARG_A(inst)) /* condition failed? */ + ci->u.l.savedpc++; /* skip jump instruction */ + break; + } + case OP_CONCAT: { + StkId top = L->top - 1; /* top when 'call_binTM' was called */ + int b = GETARG_B(inst); /* first element to concatenate */ + int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ + setobj2s(L, top - 2, top); /* put TM result in proper position */ + if (total > 1) { /* are there elements to concat? */ + L->top = top - 1; /* top is one after last element (at top-2) */ + luaV_concat(L, total); /* concat them (may yield again) */ + } + /* move final result to final position */ + setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); + L->top = ci->top; /* restore top */ + break; + } + case OP_TFORCALL: { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); + L->top = ci->top; /* correct top */ + break; + } + case OP_CALL: { + if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ + L->top = ci->top; /* adjust results */ + break; + } + case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: + break; + default: lua_assert(0); + } +} + + /* ** some macros for common tasks in `luaV_execute' */ -#define runtime_check(L, c) { if (!(c)) break; } +#if !defined luai_runtimecheck +#define luai_runtimecheck(L, c) /* void */ +#endif + #define RA(i) (base+GETARG_A(i)) /* to be used after possible stack reallocation */ @@ -348,13 +484,23 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb, 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 KBx(i) \ + (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) -#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} +/* execute a jump instruction */ +#define dojump(ci,i,e) \ + { int a = GETARG_A(i); \ + if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \ + ci->u.l.savedpc += GETARG_sBx(i) + e; } +/* for test instructions, execute the jump instruction that follows it */ +#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } -#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } + +#define Protect(x) { {x;}; base = ci->u.l.base; } + +#define checkGC(L,c) Protect(luaC_condGC(L, c); luai_threadyield(L);) #define arith_op(op,tm) { \ @@ -362,401 +508,356 @@ static void Arith (lua_State *L, StkId ra, const TValue *rb, TValue *rc = RKC(i); \ if (ttisnumber(rb) && ttisnumber(rc)) { \ lua_Number nb = nvalue(rb), nc = nvalue(rc); \ - setnvalue(ra, op(nb, nc)); \ + setnvalue(ra, op(L, nb, nc)); \ } \ - else \ - Protect(Arith(L, ra, rb, rc, tm)); \ - } + else { Protect(luaV_arith(L, ra, rb, rc, tm)); } } +#define vmdispatch(o) switch(o) +#define vmcase(l,b) case l: {b} break; +#define vmcasenb(l,b) case l: {b} /* nb = no break */ -void luaV_execute (lua_State *L, int nexeccalls) { +void luaV_execute (lua_State *L) { + CallInfo *ci = L->ci; 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; + StkId base; + newframe: /* reentry point when frame changes (call/return) */ + lua_assert(ci == L->ci); + cl = clLvalue(ci->func); k = cl->p->k; + base = ci->u.l.base; /* main loop of interpreter */ for (;;) { - const Instruction i = *pc++; + Instruction i = *(ci->u.l.savedpc++); 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; + Protect(traceexec(L)); } - /* warning!! several calls may realloc the stack and invalidate `ra' */ + /* 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: { + lua_assert(base == ci->u.l.base); + lua_assert(base <= L->top && L->top < L->stack + L->stacksize); + vmdispatch (GET_OPCODE(i)) { + vmcase(OP_MOVE, setobjs2s(L, ra, RB(i)); - continue; - } - case OP_LOADK: { - setobj2s(L, ra, KBx(i)); - continue; - } - case OP_LOADBOOL: { + ) + vmcase(OP_LOADK, + TValue *rb = k + GETARG_Bx(i); + setobj2s(L, ra, rb); + ) + vmcase(OP_LOADKX, + TValue *rb; + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + rb = k + GETARG_Ax(*ci->u.l.savedpc++); + setobj2s(L, ra, rb); + ) + vmcase(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); + if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ + ) + vmcase(OP_LOADNIL, + int b = GETARG_B(i); do { - setnilvalue(rb--); - } while (rb >= ra); - continue; - } - case OP_GETUPVAL: { + setnilvalue(ra++); + } while (b--); + ) + vmcase(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: { + ) + vmcase(OP_GETTABUP, + int b = GETARG_B(i); + Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); + ) + vmcase(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: { + ) + vmcase(OP_SETTABUP, + int a = GETARG_A(i); + Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); + ) + vmcase(OP_SETUPVAL, UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); luaC_barrier(L, uv, ra); - continue; - } - case OP_SETTABLE: { + ) + vmcase(OP_SETTABLE, Protect(luaV_settable(L, ra, RKB(i), RKC(i))); - continue; - } - case OP_NEWTABLE: { + ) + vmcase(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: { + Table *t = luaH_new(L); + sethvalue(L, ra, t); + if (b != 0 || c != 0) + luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); + checkGC(L, + L->top = ra + 1; /* limit of live values */ + luaC_step(L); + L->top = ci->top; /* restore top */ + ) + ) + vmcase(OP_SELF, StkId rb = RB(i); setobjs2s(L, ra+1, rb); Protect(luaV_gettable(L, rb, RKC(i), ra)); - continue; - } - case OP_ADD: { + ) + vmcase(OP_ADD, arith_op(luai_numadd, TM_ADD); - continue; - } - case OP_SUB: { + ) + vmcase(OP_SUB, arith_op(luai_numsub, TM_SUB); - continue; - } - case OP_MUL: { + ) + vmcase(OP_MUL, arith_op(luai_nummul, TM_MUL); - continue; - } - case OP_DIV: { + ) + vmcase(OP_DIV, arith_op(luai_numdiv, TM_DIV); - continue; - } - case OP_MOD: { + ) + vmcase(OP_MOD, arith_op(luai_nummod, TM_MOD); - continue; - } - case OP_POW: { + ) + vmcase(OP_POW, arith_op(luai_numpow, TM_POW); - continue; - } - case OP_UNM: { + ) + vmcase(OP_UNM, TValue *rb = RB(i); if (ttisnumber(rb)) { lua_Number nb = nvalue(rb); - setnvalue(ra, luai_numunm(nb)); + setnvalue(ra, luai_numunm(L, nb)); } else { - Protect(Arith(L, ra, rb, rb, TM_UNM)); + Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); } - continue; - } - case OP_NOT: { - int res = l_isfalse(RB(i)); /* next assignment may change this value */ + ) + vmcase(OP_NOT, + TValue *rb = RB(i); + int res = l_isfalse(rb); /* 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: { + ) + vmcase(OP_LEN, + Protect(luaV_objlen(L, ra, RB(i))); + ) + vmcase(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: { + StkId rb; + L->top = base + c + 1; /* mark the end of concat operands */ + Protect(luaV_concat(L, c - b + 1)); + ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */ + rb = b + base; + setobjs2s(L, ra, rb); + checkGC(L, + L->top = (ra >= rb ? ra + 1 : rb); /* limit of live values */ + luaC_step(L); + ) + L->top = ci->top; /* restore top */ + ) + vmcase(OP_JMP, + dojump(ci, i, 0); + ) + vmcase(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)); + if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); ) - pc++; - continue; - } - case OP_LT: { + ) + vmcase(OP_LT, Protect( - if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); + if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); ) - pc++; - continue; - } - case OP_LE: { + ) + vmcase(OP_LE, Protect( - if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) - dojump(L, pc, GETARG_sBx(*pc)); + if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); ) - pc++; - continue; - } - case OP_TEST: { - if (l_isfalse(ra) != GETARG_C(i)) - dojump(L, pc, GETARG_sBx(*pc)); - pc++; - continue; - } - case OP_TESTSET: { + ) + vmcase(OP_TEST, + if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + vmcase(OP_TESTSET, TValue *rb = RB(i); - if (l_isfalse(rb) != GETARG_C(i)) { + if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) + ci->u.l.savedpc++; + else { setobjs2s(L, ra, rb); - dojump(L, pc, GETARG_sBx(*pc)); + donextjump(ci); } - pc++; - continue; - } - case OP_CALL: { + ) + vmcase(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 */ - } + if (luaD_precall(L, ra, nresults)) { /* C function? */ + if (nresults >= 0) L->top = ci->top; /* adjust results */ + base = ci->u.l.base; } - } - case OP_TAILCALL: { + else { /* Lua function */ + ci = L->ci; + ci->callstatus |= CIST_REENTRY; + goto newframe; /* restart luaV_execute over new Lua function */ + } + ) + vmcase(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 */ - } + if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ + base = ci->u.l.base; + else { + /* tail call: put called frame (n) in place of caller one (o) */ + CallInfo *nci = L->ci; /* called frame */ + CallInfo *oci = nci->previous; /* caller frame */ + StkId nfunc = nci->func; /* called function */ + StkId ofunc = oci->func; /* caller function */ + /* last stack slot filled by 'precall' */ + StkId lim = nci->u.l.base + getproto(nfunc)->numparams; + int aux; + /* close all upvalues from previous call */ + if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); + /* move new frame into old one */ + for (aux = 0; nfunc + aux < lim; aux++) + setobjs2s(L, ofunc + aux, nfunc + aux); + oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ + oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ + oci->u.l.savedpc = nci->u.l.savedpc; + oci->callstatus |= CIST_TAIL; /* function was tail called */ + ci = L->ci = oci; /* remove new frame */ + lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); + goto newframe; /* restart luaV_execute over new Lua function */ } - } - case OP_RETURN: { + ) + vmcasenb(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; + if (cl->p->sizep > 0) luaF_close(L, base); 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; + if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ + return; /* external invocation: return */ + else { /* invocation via reentry: continue execution */ + ci = L->ci; + if (b) L->top = ci->top; + lua_assert(isLua(ci)); + lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); + goto newframe; /* restart luaV_execute over new Lua function */ } - } - case OP_FORLOOP: { + ) + vmcase(OP_FORLOOP, lua_Number step = nvalue(ra+2); - lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ + lua_Number idx = luai_numadd(L, 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 */ + if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) + : luai_numle(L, limit, idx)) { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ setnvalue(ra, idx); /* update internal index... */ setnvalue(ra+3, idx); /* ...and external index */ } - continue; - } - case OP_FORPREP: { + ) + vmcase(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: { + setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); + ci->u.l.savedpc += GETARG_sBx(i); + ) + vmcasenb(OP_TFORCALL, 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 */ + L->top = cb + 3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i), 1)); + L->top = ci->top; + i = *(ci->u.l.savedpc++); /* go to next instruction */ + ra = RA(i); + lua_assert(GET_OPCODE(i) == OP_TFORLOOP); + goto l_tforloop; + ) + vmcase(OP_TFORLOOP, + l_tforloop: + if (!ttisnil(ra + 1)) { /* continue loop? */ + setobjs2s(L, ra, ra + 1); /* save control variable */ + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ } - pc++; - continue; - } - case OP_SETLIST: { + ) + vmcase(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 (n == 0) n = cast_int(L->top - ra) - 1; + if (c == 0) { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + c = GETARG_Ax(*ci->u.l.savedpc++); } - if (c == 0) c = cast_int(*pc++); - runtime_check(L, ttistable(ra)); + luai_runtimecheck(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 */ + luaH_resizearray(L, h, last); /* pre-allocate it at once */ for (; n > 0; n--) { TValue *val = ra+n; - setobj2t(L, luaH_setnum(L, h, last--), val); - luaC_barriert(L, h, val); + luaH_setint(L, h, last--, val); + luaC_barrierback(L, obj2gco(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: { + L->top = ci->top; /* correct top (in case of previous open call) */ + ) + vmcase(OP_CLOSURE, + Proto *p = cl->p->p[GETARG_Bx(i)]; + Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */ + if (ncl == NULL) /* no match? */ + pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ + else + setclLvalue(L, ra, ncl); /* push cashed closure */ + checkGC(L, + L->top = ra + 1; /* limit of live values */ + luaC_step(L); + L->top = ci->top; /* restore top */ + ) + ) + vmcase(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) { + int n = cast_int(base - ci->func) - cl->p->numparams - 1; + if (b < 0) { /* B == 0? */ + b = n; /* get all var. arguments */ 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); + setobjs2s(L, ra + j, base - n + j); } else { setnilvalue(ra + j); } } - continue; - } + ) + vmcase(OP_EXTRAARG, + lua_assert(0); + ) } } } diff --git a/liblua/lvm.h b/liblua/lvm.h index bfe4f5678d..ec35822406 100644 --- a/liblua/lvm.h +++ b/liblua/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lvm.h,v 2.17 2011/05/31 18:27:56 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -13,24 +13,33 @@ #include "ltm.h" -#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) +#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) -#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ - (((o) = luaV_tonumber(o,n)) != NULL)) +#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) -#define equalobj(L,o1,o2) \ - (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) +#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) + +#define luaV_rawequalobj(t1,t2) \ + (ttisequal(t1,t2) && luaV_equalobj_(NULL,t1,t2)) + + +/* not to called directly */ +LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2); 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 int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); 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); +LUAI_FUNC void luaV_finishOp (lua_State *L); +LUAI_FUNC void luaV_execute (lua_State *L); +LUAI_FUNC void luaV_concat (lua_State *L, int total); +LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op); +LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); #endif diff --git a/liblua/lzio.c b/liblua/lzio.c index 293edd59b0..354f94e7c5 100644 --- a/liblua/lzio.c +++ b/liblua/lzio.c @@ -1,5 +1,5 @@ /* -** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lzio.c,v 1.34 2011/07/15 12:35:32 roberto Exp $ ** a generic input stream interface ** See Copyright Notice in lua.h */ @@ -25,23 +25,11 @@ int luaZ_fill (ZIO *z) { lua_unlock(L); buff = z->reader(L, z->data, &size); lua_lock(L); - if (buff == NULL || size == 0) return EOZ; - z->n = size - 1; + if (buff == NULL || size == 0) + return EOZ; + z->n = size - 1; /* discount char being returned */ 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); + return cast_uchar(*(z->p++)); } @@ -58,8 +46,14 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { 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 */ + if (z->n == 0) { /* no bytes in buffer? */ + if (luaZ_fill(z) == EOZ) /* try to read more */ + return n; /* no more input; return number of missing bytes */ + else { + z->n++; /* luaZ_fill consumed first byte; put it back */ + z->p--; + } + } m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ memcpy(b, z->p, m); z->n -= m; diff --git a/liblua/lzio.h b/liblua/lzio.h index 51d695d8c1..08682301e8 100644 --- a/liblua/lzio.h +++ b/liblua/lzio.h @@ -1,5 +1,5 @@ /* -** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lzio.h,v 1.26 2011/07/15 12:48:03 roberto Exp $ ** Buffered streams ** See Copyright Notice in lua.h */ @@ -17,9 +17,8 @@ typedef struct Zio ZIO; -#define char2int(c) cast(int, cast(unsigned char, (c))) +#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) -#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) typedef struct Mbuffer { char *buffer; @@ -47,7 +46,6 @@ 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); @@ -56,7 +54,7 @@ LUAI_FUNC int luaZ_lookahead (ZIO *z); struct Zio { size_t n; /* bytes still unread */ const char *p; /* current position in buffer */ - lua_Reader reader; + lua_Reader reader; /* reader function */ void* data; /* additional data */ lua_State *L; /* Lua state (for reader) */ }; diff --git a/liblua/print.c b/liblua/print.c deleted file mode 100644 index e240cfc3c6..0000000000 --- a/liblua/print.c +++ /dev/null @@ -1,227 +0,0 @@ -/* -** $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/nse_binlib.cc b/nse_binlib.cc index e1c8f4e35f..5ba9b09988 100644 --- a/nse_binlib.cc +++ b/nse_binlib.cc @@ -397,7 +397,7 @@ static int l_pack(lua_State *L) /** pack(f,...) */ return 1; } -static const luaL_reg binlib[] = +static const luaL_Reg binlib[] = { {"pack", l_pack}, {"unpack", l_unpack}, @@ -408,7 +408,7 @@ static const luaL_reg binlib[] = ** Open bin library */ LUALIB_API int luaopen_binlib (lua_State *L) { - luaL_register(L, NSE_BINLIBNAME, binlib); + luaL_newlib(L, binlib); return 1; } diff --git a/nse_bit.cc b/nse_bit.cc index 740befa904..716fb7fe99 100644 --- a/nse_bit.cc +++ b/nse_bit.cc @@ -56,7 +56,7 @@ TDYADIC(rshift, >>, luaL_checkubit, luaL_checkubit) TDYADIC(arshift, >>, luaL_checkbit, luaL_checkubit) DYADIC(mod, %) -static const struct luaL_reg bitlib[] = { +static const struct luaL_Reg bitlib[] = { {"bnot", bit_bnot}, {"band", bit_band}, {"bor", bit_bor}, @@ -69,7 +69,7 @@ static const struct luaL_reg bitlib[] = { }; LUALIB_API int luaopen_bit(lua_State *L) { - luaL_register(L, BITLIBNAME, bitlib); + luaL_newlib(L, bitlib); return 1; } diff --git a/nse_debug.cc b/nse_debug.cc index 3c03c3642a..f15f88fdce 100644 --- a/nse_debug.cc +++ b/nse_debug.cc @@ -10,50 +10,49 @@ extern "C" { /* Print a Lua table. depth_limit is the limit on recursive printing of subtables. */ -static void table_dump (lua_State *L, int i, int depth_limit) +static void table_dump (lua_State *L, int idx, int depth_limit) { - assert(lua_type(L, i) == LUA_TTABLE); + idx = lua_absindex(L, idx); + assert(lua_type(L, idx) == LUA_TTABLE); printf("{ "); - lua_pushvalue(L, i); - lua_pushnil(L); - while (lua_next(L, -2) != 0) { + for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) + { value_dump(L, -2, depth_limit - 1); printf(" = "); value_dump(L, -1, depth_limit - 1); printf(", "); - lua_pop(L, 1); } - lua_pop(L, 1); printf("}"); } /* Print a Lua value. depth_limit controls the depth to which tables will be printed recursively (0 for no recursion). */ -void value_dump (lua_State *L, int i, int depth_limit) +void value_dump (lua_State *L, int idx, int depth_limit) { - int t = lua_type(L, i); + idx = lua_absindex(L, idx); + int t = lua_type(L, idx); switch (t) { case LUA_TSTRING: /* strings */ - printf("'%s'", lua_tostring(L, i)); + printf("'%s'", lua_tostring(L, idx)); break; case LUA_TBOOLEAN: /* booleans */ - printf(lua_toboolean(L, i) ? "true" : "false"); + printf(lua_toboolean(L, idx) ? "true" : "false"); break; case LUA_TNUMBER: /* numbers */ - printf("%g", lua_tonumber(L, i)); + printf("%g", lua_tonumber(L, idx)); break; case LUA_TTABLE: if (depth_limit > 0) - table_dump(L, i, depth_limit); + table_dump(L, idx, depth_limit); else - printf("table: %p", lua_topointer(L, i)); + printf("table: %p", lua_topointer(L, idx)); break; case LUA_TTHREAD: case LUA_TFUNCTION: case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA: - printf("%s: %p", lua_typename(L, t), lua_topointer(L, i)); + printf("%s: %p", lua_typename(L, t), lua_topointer(L, idx)); break; default: /* other values */ printf("%s", lua_typename(L, t)); @@ -83,7 +82,9 @@ void lua_state_dump (lua_State *L) stack_dump(L); printf("=== GLOBALS\n"); - table_dump(L, LUA_GLOBALSINDEX, 0); + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); + table_dump(L, -1, 0); + lua_pop(L, 1); /* LUA_RIDX_GLOBALS */ printf("\n"); printf("=== REGISTRY\n"); @@ -94,8 +95,8 @@ void lua_state_dump (lua_State *L) lua_getglobal(L, "nmap"); lua_getfield(L, -1, "registry"); table_dump(L, -1, 1); - printf("\n"); lua_pop(L, 2); + printf("\n"); assert(lua_gettop(L) == top); } diff --git a/nse_dnet.cc b/nse_dnet.cc index d750118e3f..56abf893c5 100644 --- a/nse_dnet.cc +++ b/nse_dnet.cc @@ -21,14 +21,12 @@ extern "C" { extern NmapOps o; -/* Map of dnet userdata to ethernet device userdata */ -#define ETH_CACHE_DNET_ETH 0 -/* Map of ethernet device string identifier to ethernet device userdata */ -#define ETH_CACHE_DEVICE_ETH 1 - -/* metatable entries in the registry */ -#define DNET_METATABLE "DNET_METATABLE" -#define DNET_ETH_METATABLE "DNET_ETH_METATABLE" +enum { + DNET_METATABLE = lua_upvalueindex(1), + DNET_ETHERNET_METATABLE = lua_upvalueindex(2), + CACHE_DNET_ETHERNET = lua_upvalueindex(3), /* Map of dnet userdata to ethernet device userdata */ + CACHE_DEVICE_ETHERNET = lua_upvalueindex(4), /* Map of ethernet device string identifier to ethernet device userdata */ +}; typedef struct nse_dnet_udata { @@ -36,12 +34,12 @@ typedef struct nse_dnet_udata int sock; /* raw ip socket */ } nse_dnet_udata; -LUALIB_API int l_dnet_new (lua_State *L) +static int l_dnet_new (lua_State *L) { nse_dnet_udata *udata; udata = (nse_dnet_udata *) lua_newuserdata(L, sizeof(nse_dnet_udata)); - luaL_getmetatable(L, DNET_METATABLE); + lua_pushvalue(L, DNET_METATABLE); lua_setmetatable(L, -2); udata->eth = NULL; udata->sock = -1; @@ -49,27 +47,24 @@ LUALIB_API int l_dnet_new (lua_State *L) return 1; } -LUALIB_API int l_dnet_get_interface_info (lua_State *L) +static int l_dnet_get_interface_info (lua_State *L) { char ipstr[INET6_ADDRSTRLEN]; struct addr src, bcast; struct interface_info *ii = getInterfaceByName(luaL_checkstring(L, 1), o.af()); - if (ii == NULL) { - lua_pushnil(L); - lua_pushstring(L, "failed to find interface"); - return 2; - } + if (ii == NULL) + return nseU_safeerror(L, "failed to find interface"); memset(ipstr, 0, INET6_ADDRSTRLEN); memset(&src, 0, sizeof(src)); memset(&bcast, 0, sizeof(bcast)); lua_newtable(L); - setsfield(L, -1, "device", ii->devfullname); - setsfield(L, -1, "shortname", ii->devname); - setnfield(L, -1, "netmask", ii->netmask_bits); + nseU_setsfield(L, -1, "device", ii->devfullname); + nseU_setsfield(L, -1, "shortname", ii->devname); + nseU_setnfield(L, -1, "netmask", ii->netmask_bits); if (ii->addr.ss_family == AF_INET) inet_ntop(AF_INET, &((struct sockaddr_in *)&ii->addr)->sin_addr, @@ -80,11 +75,11 @@ LUALIB_API int l_dnet_get_interface_info (lua_State *L) else luaL_error(L, "unknown protocol"); - setsfield(L, -1, "address", ipstr); + nseU_setsfield(L, -1, "address", ipstr); switch (ii->device_type) { case devt_ethernet: - setsfield(L, -1, "link", "ethernet"); + nseU_setsfield(L, -1, "link", "ethernet"); lua_pushlstring(L, (const char *) ii->mac, 6); lua_setfield(L, -2, "mac"); @@ -96,67 +91,66 @@ LUALIB_API int l_dnet_get_interface_info (lua_State *L) addr_bcast(&src, &bcast); memset(ipstr, 0, INET6_ADDRSTRLEN); if (addr_ntop(&bcast, ipstr, INET6_ADDRSTRLEN) != NULL) - setsfield(L, -1, "broadcast", ipstr); + nseU_setsfield(L, -1, "broadcast", ipstr); } break; case devt_loopback: - setsfield(L, -1, "link", "loopback"); + nseU_setsfield(L, -1, "link", "loopback"); break; case devt_p2p: - setsfield(L, -1, "link", "p2p"); + nseU_setsfield(L, -1, "link", "p2p"); break; case devt_other: default: - setsfield(L, -1, "link", "other"); + nseU_setsfield(L, -1, "link", "other"); } - setsfield(L, -1, "up", (ii->device_up ? "up" : "down")); - setnfield(L, -1, "mtu", ii->mtu); + nseU_setsfield(L, -1, "up", (ii->device_up ? "up" : "down")); + nseU_setnfield(L, -1, "mtu", ii->mtu); return 1; } static int close_eth (lua_State *L) { - eth_t **eth = (eth_t **) luaL_checkudata(L, 1, DNET_ETH_METATABLE); + eth_t **eth = (eth_t **) nseU_checkudata(L, 1, DNET_ETHERNET_METATABLE, "ethernet"); assert(*eth != NULL); eth_close(*eth); *eth = NULL; - return success(L); + return nseU_success(L); } static eth_t *open_eth_cached (lua_State *L, int dnet_index, const char *device) { eth_t **eth; - lua_rawgeti(L, LUA_ENVIRONINDEX, ETH_CACHE_DNET_ETH); - lua_rawgeti(L, LUA_ENVIRONINDEX, ETH_CACHE_DEVICE_ETH); - lua_getfield(L, -1, device); + lua_getfield(L, CACHE_DEVICE_ETHERNET, device); if (!lua_isuserdata(L, -1)) { + lua_pop(L, 1); eth = (eth_t **) lua_newuserdata(L, sizeof(eth_t *)); *eth = eth_open(device); if (*eth == NULL) luaL_error(L, "unable to open dnet on ethernet interface %s", device); - luaL_getmetatable(L, DNET_ETH_METATABLE); + lua_pushvalue(L, DNET_ETHERNET_METATABLE); lua_setmetatable(L, -2); lua_pushvalue(L, -1); - lua_setfield(L, -4, device); - lua_replace(L, -2); /* replace nil */ + lua_setfield(L, CACHE_DEVICE_ETHERNET, device); } eth = (eth_t **) lua_touserdata(L, -1); lua_pushvalue(L, dnet_index); lua_pushvalue(L, -2); /* eth_t userdata */ - lua_rawset(L, -5); /* add to ETH_CACHE_DNET_ETH */ - lua_pop(L, 3); /* ETH_CACHE_DNET_ETH, ETH_CACHE_DEVICE_ETH, eth_t userdata */ + lua_rawset(L, CACHE_DNET_ETHERNET); + + lua_pop(L, 1); /* eth_t userdata */ return *eth; } static int ethernet_open (lua_State *L) { - nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE); + nse_dnet_udata *udata = (nse_dnet_udata *) nseU_checkudata(L, 1, DNET_METATABLE, "dnet"); const char *interface_name = luaL_checkstring(L, 2); struct interface_info *ii = getInterfaceByName(interface_name, o.af()); @@ -165,35 +159,34 @@ static int ethernet_open (lua_State *L) udata->eth = open_eth_cached(L, 1, interface_name); - return success(L); + return nseU_success(L); } static int ethernet_close (lua_State *L) { - nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE); + nse_dnet_udata *udata = (nse_dnet_udata *) nseU_checkudata(L, 1, DNET_METATABLE, "dnet"); udata->eth = NULL; - lua_rawgeti(L, LUA_ENVIRONINDEX, ETH_CACHE_DNET_ETH); lua_pushvalue(L, 1); lua_pushnil(L); - lua_rawset(L, -3); + lua_rawset(L, CACHE_DNET_ETHERNET); - return success(L); + return nseU_success(L); } static int ethernet_send (lua_State *L) { - nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE); + nse_dnet_udata *udata = (nse_dnet_udata *) nseU_checkudata(L, 1, DNET_METATABLE, "dnet"); if (udata->eth == NULL) return luaL_error(L, "dnet ethernet interface is not open"); - eth_send(udata->eth, luaL_checkstring(L, 2), lua_objlen(L, 2)); - return success(L); + eth_send(udata->eth, luaL_checkstring(L, 2), lua_rawlen(L, 2)); + return nseU_success(L); } static int ip_open (lua_State *L) { - nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE); + nse_dnet_udata *udata = (nse_dnet_udata *) nseU_checkudata(L, 1, DNET_METATABLE, "dnet"); udata->sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (udata->sock == -1) return luaL_error(L, "failed to open raw socket: %s (errno %d)", @@ -202,23 +195,23 @@ static int ip_open (lua_State *L) #ifndef WIN32 sethdrinclude(udata->sock); #endif - return success(L); + return nseU_success(L); } static int ip_close (lua_State *L) { - nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE); + nse_dnet_udata *udata = (nse_dnet_udata *) nseU_checkudata(L, 1, DNET_METATABLE, "dnet"); if (udata->sock == -1) - return safe_error(L, "raw socket already closed"); + return nseU_safeerror(L, "raw socket already closed"); close(udata->sock); udata->sock = -1; - return success(L); + return nseU_success(L); } static int ip_send (lua_State *L) { struct abstract_ip_hdr hdr; - nse_dnet_udata *udata = (nse_dnet_udata *) luaL_checkudata(L, 1, DNET_METATABLE); + nse_dnet_udata *udata = (nse_dnet_udata *) nseU_checkudata(L, 1, DNET_METATABLE, "dnet"); const char *packet; size_t packetlen; unsigned int payloadlen; @@ -281,25 +274,25 @@ static int ip_send (lua_State *L) udata->eth = eth.ethsd = open_eth_cached(L, 1, route.ii.devname); - ret = send_ip_packet(udata->sock, ð, &hdr.dst, (u8 *) packet, lua_objlen(L, 2)); + ret = send_ip_packet(udata->sock, ð, &hdr.dst, (u8 *) packet, lua_rawlen(L, 2)); } else { usesock: #ifdef WIN32 if (strlen(dev) > 0) win32_fatal_raw_sockets(dev); #endif - ret = send_ip_packet(udata->sock, NULL, &hdr.dst, (u8 *) packet, lua_objlen(L, 2)); + ret = send_ip_packet(udata->sock, NULL, &hdr.dst, (u8 *) packet, lua_rawlen(L, 2)); } if (ret == -1) - return safe_error(L, "error while sending: %s (errno %d)", + return nseU_safeerror(L, "error while sending: %s (errno %d)", socket_strerror(socket_errno()), socket_errno()); - return success(L); + return nseU_success(L); } static int gc (lua_State *L) { - luaL_checkudata(L, 1, DNET_METATABLE); + nseU_checkudata(L, 1, DNET_METATABLE, "dnet"); lua_pushcfunction(L, ip_close); lua_pushvalue(L, 1); @@ -313,7 +306,7 @@ static int gc (lua_State *L) LUALIB_API int luaopen_dnet (lua_State *L) { - static const luaL_reg l_dnet[] = { + static const luaL_Reg l_dnet_metatable[] = { {"ethernet_open", ethernet_open}, {"ethernet_close", ethernet_close}, {"ethernet_send", ethernet_send}, @@ -323,25 +316,44 @@ LUALIB_API int luaopen_dnet (lua_State *L) {NULL, NULL} }; - lua_createtable(L, 2, 0); - lua_replace(L, LUA_ENVIRONINDEX); - weak_table(L, 0, 0, "k"); /* dnet udata weak, eth device strong */ - lua_rawseti(L, LUA_ENVIRONINDEX, ETH_CACHE_DNET_ETH); - weak_table(L, 0, 0, "v"); /* eth_device weak */ - lua_rawseti(L, LUA_ENVIRONINDEX, ETH_CACHE_DEVICE_ETH); - - luaL_newmetatable(L, DNET_METATABLE); - lua_createtable(L, 0, 5); - luaL_register(L, NULL, l_dnet); - lua_setfield(L, -2, "__index"); + static const luaL_Reg l_dnet[] = { + {"new", l_dnet_new}, + {"get_interface_info", l_dnet_get_interface_info}, + {NULL, NULL} + }; + int i; + int top = lua_gettop(L); + + /* Create the library upvalues: + DNET_METATABLE = lua_upvalueindex(1), + DNET_ETHERNET_METATABLE = lua_upvalueindex(2), + CACHE_DNET_ETHERNET = lua_upvalueindex(3), + CACHE_DEVICE_ETHERNET = lua_upvalueindex(4), + */ + lua_newtable(L); + lua_newtable(L); + nseU_weaktable(L, 0, 0, "k"); /* dnet udata weak, eth device strong */ + nseU_weaktable(L, 0, 0, "v"); /* eth_device weak */ + + luaL_newlibtable(L, l_dnet_metatable); + for (i = top+1; i < top+1+4; i++) lua_pushvalue(L, i); + luaL_setfuncs(L, l_dnet_metatable, 4); + lua_setfield(L, top+1, "__index"); + lua_newtable(L); + lua_setfield(L, top+1, "__metatable"); + for (i = top+1; i < top+1+4; i++) lua_pushvalue(L, i); + lua_pushcclosure(L, gc, 4); + lua_setfield(L, top+1, "__gc"); + lua_newtable(L); - lua_setfield(L, -2, "__metatable"); - lua_pushcfunction(L, gc); - lua_setfield(L, -2, "__gc"); + lua_setfield(L, top+2, "__metatable"); + for (i = top+1; i < top+1+4; i++) lua_pushvalue(L, i); + lua_pushcclosure(L, close_eth, 4); + lua_setfield(L, top+2, "__gc"); - luaL_newmetatable(L, DNET_ETH_METATABLE); - lua_pushcfunction(L, close_eth); - lua_setfield(L, -2, "__gc"); + luaL_newlibtable(L, l_dnet); /* external interface */ + for (i = top+1; i < top+1+4; i++) lua_pushvalue(L, i); + luaL_setfuncs(L, l_dnet, 4); - return 0; + return 1; } diff --git a/nse_dnet.h b/nse_dnet.h index 588702a7fd..0e08f4cea3 100644 --- a/nse_dnet.h +++ b/nse_dnet.h @@ -1,8 +1,6 @@ #ifndef NMAP_LUA_DNET_H #define NMAP_LUA_DNET_H -LUALIB_API int l_dnet_new (lua_State *); -LUALIB_API int l_dnet_get_interface_info (lua_State *); LUALIB_API int luaopen_dnet (lua_State *L); #endif diff --git a/nse_fs.cc b/nse_fs.cc index 9552deb12a..4746e0f527 100644 --- a/nse_fs.cc +++ b/nse_fs.cc @@ -6,6 +6,7 @@ extern "C" { #include "nmap.h" #include "nse_fs.h" +#include "nse_utility.h" #include "nmap_error.h" #include "NmapOps.h" @@ -14,12 +15,14 @@ extern "C" { #include +enum { + DIR_METATABLE = lua_upvalueindex(1), +}; + #ifndef WIN32 #include "dirent.h" #endif -#define DIR_METATABLE "dir" - #ifndef MAXPATHLEN # define MAXPATHLEN 2048 #endif @@ -115,12 +118,12 @@ static int nse_fetch (lua_State *L, int (*fetch)(char *, size_t, const char *)) return 2; } -int fetchscript (lua_State *L) +static int l_fetchscript (lua_State *L) { return nse_fetch(L, nse_fetchscript); } -int fetchfile_absolute (lua_State *L) +static int l_fetchfile_absolute (lua_State *L) { return nse_fetch(L, nse_fetchfile_absolute); } @@ -157,7 +160,7 @@ static int dir_iter (lua_State *L) { #else struct dirent *entry; #endif - dir_data *d = (dir_data *)luaL_checkudata(L, 1, DIR_METATABLE); + dir_data *d = (dir_data *) nseU_checkudata(L, 1, DIR_METATABLE, "directory"); luaL_argcheck(L, !d->closed, 1, "closed directory"); #ifdef WIN32 if (d->hFile == 0L) { /* first entry */ @@ -197,7 +200,7 @@ static int dir_iter (lua_State *L) { ** Closes directory iterators */ static int dir_close (lua_State *L) { - dir_data *d = (dir_data *)lua_touserdata(L, 1); + dir_data *d = (dir_data *) nseU_checkudata(L, 1, DIR_METATABLE, "directory"); #ifdef WIN32 if (!d->closed && d->hFile) { _findclose(d->hFile); @@ -215,7 +218,7 @@ static int dir_close (lua_State *L) { /* ** Factory of directory iterators */ -int nse_readdir (lua_State *L) { +static int l_readdir (lua_State *L) { const char *dirname = luaL_checkstring(L, 1); dir_data *d; lua_pushcfunction(L, dir_iter); @@ -223,14 +226,14 @@ int nse_readdir (lua_State *L) { d->closed = 0; #ifdef WIN32 d->hFile = 0L; - luaL_getmetatable(L, DIR_METATABLE); + lua_pushvalue(L, DIR_METATABLE); lua_setmetatable(L, -2); if (strlen(dirname) > MAX_DIR_LENGTH) luaL_error(L, "%s: Path too long '%s'.", SCRIPT_ENGINE, dirname); else Snprintf(d->pattern, MAX_DIR_LENGTH, "%s/*", dirname); #else - luaL_getmetatable(L, DIR_METATABLE); + lua_pushvalue(L, DIR_METATABLE); lua_setmetatable(L, -2); d->dir = opendir(dirname); if (d->dir == NULL) @@ -239,22 +242,34 @@ int nse_readdir (lua_State *L) { return 2; } -int luaopen_fs(lua_State *L) +LUALIB_API int luaopen_fs(lua_State *L) { - /* create the dir metatable */ - luaL_newmetatable(L, DIR_METATABLE); - lua_pushstring(L, "__index"); - lua_newtable(L); - lua_pushstring(L, "next"); - lua_pushcfunction(L, dir_iter); - lua_settable(L, -3); - lua_pushstring (L, "close"); - lua_pushcfunction (L, dir_close); - lua_settable(L, -3); - lua_settable(L, -3); - lua_pushstring(L, "__gc"); - lua_pushcfunction (L, dir_close); - lua_settable(L, -3); - lua_pop(L, 1); - return 0; + static const luaL_Reg metatable_index[] = { + {"next", dir_iter}, + {"close", dir_close}, + {NULL, NULL} + }; + + static const luaL_Reg lib[] = { + {"fetchscript", l_fetchscript}, + {"fetchfile_absolute", l_fetchfile_absolute}, + {"readdir", l_readdir}, + {NULL, NULL} + }; + + int top = lua_gettop(L); + lua_newtable(L); /* DIR_METATABLE */ + + luaL_newlibtable(L, metatable_index); + lua_pushvalue(L, top+1); + luaL_setfuncs(L, metatable_index, 1); + lua_getfield(L, -1, "close"); + lua_setfield(L, top+1, "__gc"); + lua_setfield(L, top+1, "__index"); + + luaL_newlibtable(L, lib); + lua_pushvalue(L, top+1); + luaL_setfuncs(L, lib, 1); + + return 1; } diff --git a/nse_fs.h b/nse_fs.h index c9ae45dbe0..3957e95f30 100644 --- a/nse_fs.h +++ b/nse_fs.h @@ -1,12 +1,6 @@ #ifndef NSE_FS #define NSE_FS -int fetchscript (lua_State *L); - -int fetchfile_absolute (lua_State *L); - -int nse_readdir (lua_State *L); - -int luaopen_fs (lua_State *L); +LUALIB_API int luaopen_fs (lua_State *L); #endif diff --git a/nse_main.cc b/nse_main.cc index 3c64b4e146..a93d456c18 100644 --- a/nse_main.cc +++ b/nse_main.cc @@ -21,7 +21,6 @@ #include "nse_debug.h" #define NSE_MAIN "NSE_MAIN" /* the main function */ -#define NSE_TRACEBACK "NSE_TRACEBACK" /* Script Scan phases */ #define NSE_PRE_SCAN "NSE_PRE_SCAN" @@ -48,14 +47,14 @@ static ScriptResults script_scan_results; static int timedOut (lua_State *L) { - Target *target = get_target(L, 1); + Target *target = nseU_gettarget(L, 1); lua_pushboolean(L, target->timedOut(NULL)); return 1; } static int startTimeOutClock (lua_State *L) { - Target *target = get_target(L, 1); + Target *target = nseU_gettarget(L, 1); if (!target->timeOutClockRunning()) target->startTimeOutClock(NULL); return 0; @@ -63,7 +62,7 @@ static int startTimeOutClock (lua_State *L) static int stopTimeOutClock (lua_State *L) { - Target *target = get_target(L, 1); + Target *target = nseU_gettarget(L, 1); if (target->timeOutClockRunning()) target->stopTimeOutClock(NULL); return 0; @@ -90,7 +89,7 @@ static int ports (lua_State *L) PORT_UNFILTERED, PORT_HIGHEST_STATE /* last one marks end */ }; - Target *target = get_target(L, 1); + Target *target = nseU_gettarget(L, 1); PortList *plist = &(target->ports); Port *current = NULL; Port port; @@ -122,7 +121,7 @@ static int script_set_output (lua_State *L) static int host_set_output (lua_State *L) { ScriptResult sr; - Target *target = get_target(L, 1); + Target *target = nseU_gettarget(L, 1); sr.set_id(luaL_checkstring(L, 2)); sr.set_output(luaL_checkstring(L, 3)); target->scriptResults.push_back(sr); @@ -134,29 +133,15 @@ static int port_set_output (lua_State *L) Port *p; Port port; ScriptResult sr; - Target *target = get_target(L, 1); - p = get_port(L, target, &port, 2); + Target *target = nseU_gettarget(L, 1); + p = nseU_getport(L, target, &port, 2); sr.set_id(luaL_checkstring(L, 3)); sr.set_output(luaL_checkstring(L, 4)); target->ports.addScriptResult(p->portno, p->proto, sr); - /* increment host port script results*/ target->ports.numscriptresults++; return 0; } -/* This must call the l_nsock_loop function defined in nse_nsock.cc. - * That closure is created in luaopen_nsock in order to allow - * l_nsock_loop to have access to the nsock library environment. - */ -static int nsock_loop (lua_State *L) -{ - lua_settop(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, NSE_NSOCK_LOOP); - lua_pushvalue(L, 1); - lua_call(L, 1, 0); - return 0; -} - static int key_was_pressed (lua_State *L) { lua_pushboolean(L, keyWasPressed()); @@ -219,11 +204,8 @@ static int l_xml_start_tag(lua_State *L) lua_replace(L, 2); } - lua_pushnil(L); - while (lua_next(L, 2)) { + for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) xml_attribute(luaL_checkstring(L, -2), "%s", luaL_checkstring(L, -1)); - lua_pop(L, 1); - } xml_close_start_tag(); @@ -257,10 +239,6 @@ static int l_xml_newline(lua_State *L) static void open_cnse (lua_State *L) { static const luaL_Reg nse[] = { - {"fetchfile_absolute", fetchfile_absolute}, - {"fetchscript", fetchscript}, - {"dir", nse_readdir}, - {"nsock_loop", nsock_loop}, {"key_was_pressed", key_was_pressed}, {"scan_progress_meter", scan_progress_meter}, {"timedOut", timedOut}, @@ -278,20 +256,19 @@ static void open_cnse (lua_State *L) {NULL, NULL} }; - /* create dir metatable */ - luaopen_fs(L); - - lua_newtable(L); - luaL_register(L, NULL, nse); + luaL_newlib(L, nse); /* Add some other fields */ - setbfield(L, -1, "default", o.script == 1); - setbfield(L, -1, "scriptversion", o.scriptversion == 1); - setbfield(L, -1, "scriptupdatedb", o.scriptupdatedb == 1); - setbfield(L, -1, "scripthelp", o.scripthelp); - setsfield(L, -1, "script_dbpath", SCRIPT_ENGINE_DATABASE); - setsfield(L, -1, "scriptargs", o.scriptargs); - setsfield(L, -1, "scriptargsfile", o.scriptargsfile); - setsfield(L, -1, "NMAP_URL", NMAP_URL); + nseU_setbfield(L, -1, "default", o.script == 1); + nseU_setbfield(L, -1, "scriptversion", o.scriptversion == 1); + nseU_setbfield(L, -1, "scriptupdatedb", o.scriptupdatedb == 1); + nseU_setbfield(L, -1, "scripthelp", o.scripthelp); + nseU_setsfield(L, -1, "script_dbpath", SCRIPT_ENGINE_DATABASE); + nseU_setsfield(L, -1, "scriptargs", o.scriptargs); + nseU_setsfield(L, -1, "scriptargsfile", o.scriptargsfile); + nseU_setsfield(L, -1, "NMAP_URL", NMAP_URL); + + luaL_requiref(L, "fs", luaopen_fs, 0); + lua_setfield(L, -2, "fs"); } void ScriptResult::set_output (const char *out) @@ -333,32 +310,20 @@ static int panic (lua_State *L) static void set_nmap_libraries (lua_State *L) { static const luaL_Reg libs[] = { - {NSE_PCRELIBNAME, luaopen_pcrelib}, // pcre library - {NSE_NMAPLIBNAME, luaopen_nmap}, // nmap bindings + {NSE_PCRELIBNAME, luaopen_pcrelib}, + {NSE_NMAPLIBNAME, luaopen_nmap}, {NSE_BINLIBNAME, luaopen_binlib}, - {BITLIBNAME, luaopen_bit}, // bit library + {BITLIBNAME, luaopen_bit}, #ifdef HAVE_OPENSSL - {OPENSSLLIBNAME, luaopen_openssl}, // openssl bindings + {OPENSSLLIBNAME, luaopen_openssl}, #endif - {NSE_STDNSELIBNAME, luaopen_stdnse_c}, {NULL, NULL} }; - /* Put our libraries in the package.preload */ - lua_getglobal(L, "require"); /* the require function */ - lua_getglobal(L, LUA_LOADLIBNAME); - lua_getfield(L, -1, "preload"); - for (int i = 0; libs[i].name != NULL; i++) - { - lua_pushstring(L, libs[i].name); - lua_pushcclosure(L, libs[i].func, 0); - lua_settable(L, -3); /* set package.preload */ - - lua_pushvalue(L, -3); /* the require function */ - lua_pushstring(L, libs[i].name); - lua_call(L, 1, 0); /* explicitly require it */ + for (int i = 0; libs[i].name; i++) { + luaL_requiref(L, libs[i].name, libs[i].func, 1); + lua_pop(L, 1); } - lua_pop(L, 3); /* require, package, package.preload */ } static int init_main (lua_State *L) @@ -374,15 +339,6 @@ static int init_main (lua_State *L) lua_newtable(L); lua_setfield(L, LUA_REGISTRYINDEX, NSE_CURRENT_HOSTS); - /* Load debug.traceback for collecting any error tracebacks */ - lua_settop(L, 0); /* clear the stack */ - lua_getglobal(L, "debug"); - lua_getfield(L, -1, "traceback"); - lua_replace(L, 1); // debug.traceback stack position 1 - lua_pushvalue(L, 1); - lua_setfield(L, LUA_REGISTRYINDEX, NSE_TRACEBACK); /* save copy */ - - /* Load main Lua code, stack position 2 */ if (nmap_fetchfile(path, sizeof(path), "nse_main.lua") != 1) luaL_error(L, "could not locate nse_main.lua"); if (luaL_loadfile(L, path) != 0) @@ -392,21 +348,16 @@ static int init_main (lua_State *L) * library table which exposes certain necessary C functions to * the Lua engine. */ - open_cnse(L); // stack index 3 + open_cnse(L); /* first argument */ /* The second argument is the script rules, including the * files/directories/categories passed as the userdata to this function. */ - lua_createtable(L, rules->size(), 0); // stack index 4 - for (std::vector::iterator si = rules->begin(); - si != rules->end(); si++) - { - lua_pushstring(L, si->c_str()); - lua_rawseti(L, 4, lua_objlen(L, 4) + 1); - } + lua_createtable(L, rules->size(), 0); /* second argument */ + for (std::vector::iterator si = rules->begin(); si != rules->end(); si++) + nseU_appendfstr(L, -1, "%s", si->c_str()); - /* Get Lua main function */ - if (lua_pcall(L, 2, 1, 1) != 0) lua_error(L); /* we wanted a traceback */ + lua_call(L, 2, 1); /* returns the NSE main function */ lua_setfield(L, LUA_REGISTRYINDEX, NSE_MAIN); return 0; @@ -417,69 +368,64 @@ static int run_main (lua_State *L) std::vector *targets = (std::vector *) lua_touserdata(L, 1); - lua_settop(L, 0); - /* New host group */ lua_newtable(L); lua_setfield(L, LUA_REGISTRYINDEX, NSE_CURRENT_HOSTS); - lua_getfield(L, LUA_REGISTRYINDEX, NSE_TRACEBACK); /* index 1 */ - - lua_getfield(L, LUA_REGISTRYINDEX, NSE_MAIN); /* index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, NSE_MAIN); assert(lua_isfunction(L, -1)); - /* The first and only argument to main is the list of targets. - * This has all the target names, 1-N, in a list. + /* The first argument to the NSE main function is the list of targets. This + * has all the target names, 1-N, in a list. */ - lua_createtable(L, targets->size(), 0); // stack index 3 - lua_getfield(L, LUA_REGISTRYINDEX, NSE_CURRENT_HOSTS); /* index 4 */ - for (std::vector::iterator ti = targets->begin(); - ti != targets->end(); ti++) + lua_createtable(L, targets->size(), 0); + int targets_table = lua_gettop(L); + lua_getfield(L, LUA_REGISTRYINDEX, NSE_CURRENT_HOSTS); + int current_hosts = lua_gettop(L); + for (std::vector::iterator ti = targets->begin(); ti != targets->end(); ti++) { Target *target = (Target *) *ti; const char *TargetName = target->TargetName(); const char *targetipstr = target->targetipstr(); lua_newtable(L); set_hostinfo(L, target); - lua_rawseti(L, 3, lua_objlen(L, 3) + 1); + lua_rawseti(L, targets_table, lua_rawlen(L, targets_table) + 1); if (TargetName != NULL && strcmp(TargetName, "") != 0) lua_pushstring(L, TargetName); else lua_pushstring(L, targetipstr); lua_pushlightuserdata(L, target); - lua_rawset(L, 4); /* add to NSE_CURRENT_HOSTS */ + lua_rawset(L, current_hosts); /* add to NSE_CURRENT_HOSTS */ } - lua_pop(L, 1); /* pop NSE_CURRENT_HOSTS */ + lua_settop(L, targets_table); - /* push script scan type phase */ + /* Push script scan phase type. Second argument to NSE main function */ switch (o.current_scantype) { case SCRIPT_PRE_SCAN: - lua_pushstring(L, NSE_PRE_SCAN); + lua_pushliteral(L, NSE_PRE_SCAN); break; case SCRIPT_SCAN: - lua_pushstring(L, NSE_SCAN); + lua_pushliteral(L, NSE_SCAN); break; case SCRIPT_POST_SCAN: - lua_pushstring(L, NSE_POST_SCAN); + lua_pushliteral(L, NSE_POST_SCAN); break; default: fatal("%s: failed to set the script scan phase.\n", SCRIPT_ENGINE); } - if (lua_pcall(L, 2, 0, 1) != 0) lua_error(L); /* we wanted a traceback */ + lua_call(L, 2, 0); + return 0; } -/* Lua 5.2 compatibility macro */ -#define lua_yieldk(L,n,ctx,k) lua_yield(L,n) - -/* int nse_yield (lua_State *L) [-?, +?, e] +/* int nse_yield (lua_State *L, int ctx, lua_CFunction k) [-?, +?, e] * * This function will yield the running thread back to NSE, even across script * auxiliary coroutines. All NSE initiated yields must use this function. The * correct and only way to call is as a tail call: - * return nse_yield(L); + * return nse_yield(L, 0, NULL); */ int nse_yield (lua_State *L, int ctx, lua_CFunction k) { @@ -601,17 +547,14 @@ void open_nse (void) if ((L_NSE = luaL_newstate()) == NULL) fatal("%s: failed to open a Lua state!", SCRIPT_ENGINE); lua_atpanic(L_NSE, panic); + lua_settop(L_NSE, 0); -#if 0 - /* Lua 5.2 */ + lua_pushcfunction(L_NSE, nseU_traceback); lua_pushcfunction(L_NSE, init_main); lua_pushlightuserdata(L_NSE, &o.chosenScripts); - if (lua_pcall(L_NSE, 1, 0, 0)) -#else - if (lua_cpcall(L_NSE, init_main, &o.chosenScripts)) -#endif - fatal("%s: failed to initialize the script engine:\n%s\n", SCRIPT_ENGINE, - lua_tostring(L_NSE, -1)); + if (lua_pcall(L_NSE, 1, 0, 1)) + fatal("%s: failed to initialize the script engine:\n%s\n", SCRIPT_ENGINE, lua_tostring(L_NSE, -1)); + lua_settop(L_NSE, 0); } } @@ -622,16 +565,13 @@ void script_scan (std::vector &targets, stype scantype) assert(L_NSE != NULL); lua_settop(L_NSE, 0); /* clear the stack */ -#if 0 - /* Lua 5.2 */ + lua_pushcfunction(L_NSE, nseU_traceback); lua_pushcfunction(L_NSE, run_main); lua_pushlightuserdata(L_NSE, &targets); - if (lua_pcall(L_NSE, 1, 0, 0)) -#else - if (lua_cpcall(L_NSE, run_main, &targets)) -#endif + if (lua_pcall(L_NSE, 1, 0, 1)) error("%s: Script Engine Scan Aborted.\nAn error was thrown by the " "engine: %s", SCRIPT_ENGINE, lua_tostring(L_NSE, -1)); + lua_settop(L_NSE, 0); } void close_nse (void) diff --git a/nse_main.lua b/nse_main.lua index 8fd4aab1fc..e44cb378f7 100644 --- a/nse_main.lua +++ b/nse_main.lua @@ -57,14 +57,16 @@ local NSE_SCRIPT_RULES = { postrule = "postrule", }; +local cnse, rules = ...; -- The NSE C library and Script Rules + local _G = _G; local assert = assert; local collectgarbage = collectgarbage; local error = error; local ipairs = ipairs; +local load = load; local loadfile = loadfile; -local loadstring = loadstring; local next = next; local pairs = pairs; local pcall = pcall; @@ -72,12 +74,10 @@ local rawget = rawget; local rawset = rawset; local require = require; local select = select; -local setfenv = setfenv; local setmetatable = setmetatable; local tonumber = tonumber; local tostring = tostring; local type = type; -local unpack = unpack; local coroutine = require "coroutine"; local create = coroutine.create; @@ -91,6 +91,7 @@ local traceback = debug.traceback; local _R = debug.getregistry(); local io = require "io"; +local lines = io.lines; local open = io.open; local math = require "math"; @@ -112,33 +113,37 @@ local concat = table.concat; local insert = table.insert; local remove = table.remove; local sort = table.sort; - -local nmap = require "nmap"; - -local cnse, rules = ...; -- The NSE C library and Script Rules +local unpack = table.unpack; do -- Add loader to look in nselib/?.lua (nselib/ can be in multiple places) local function loader (lib) lib = lib:gsub("%.", "/"); -- change Lua "module seperator" to directory separator local name = "nselib/"..lib..".lua"; - local type, path = cnse.fetchfile_absolute(name); + local type, path = cnse.fs.fetchfile_absolute(name); if type == "file" then return loadfile(path); else return "\n\tNSE failed to find "..name.." in search paths."; end end - insert(package.loaders, 1, loader); + insert(package.searchers, 1, loader); end -local script_database_type, script_database_path = - cnse.fetchfile_absolute(cnse.script_dbpath); -local script_database_update = cnse.scriptupdatedb; -local script_help = cnse.scripthelp; +local nmap = require "nmap"; + +local socket = require "nmap.socket"; +local loop = socket.loop; local stdnse = require "stdnse"; -(require "strict")() -- strict global checking +local strict = require "strict"; +assert(_ENV == _G); +strict(_ENV); + +local script_database_type, script_database_path = + cnse.fs.fetchfile_absolute(cnse.script_dbpath); +local script_database_update = cnse.scriptupdatedb; +local script_help = cnse.scripthelp; -- NSE_YIELD_VALUE -- This is the table C uses to yield a thread with a unique value to @@ -205,6 +210,21 @@ local function table_size (t) local n = 0; for _ in pairs(t) do n = n + 1; end return n; end +local function loadscript (filename) + local source = "@"..filename; + local function ld () + -- header for scripts to allow setting the environment + yield [[return function (_ENV) return function (...)]]; + for line in lines(filename, "*L") do + yield(line); + end + -- footer... + yield [[ end end]]; + return nil; + end + return assert(load(wrap(ld), source, "t"))(); +end + -- recursively copy a table, for host/port tables -- not very rigorous, but it doesn't need to be local function tcopy (t) @@ -333,7 +353,7 @@ do function Script:new_thread (rule, ...) local script_type = assert(NSE_SCRIPT_RULES[rule]); if not self[rule] then return nil end -- No rule for this script? - local file_closure = self.file_closure; + local script_closure_generator = self.script_closure_generator; -- Rebuild the environment for the running thread. local env = { SCRIPT_PATH = self.filename, @@ -341,18 +361,16 @@ do SCRIPT_TYPE = script_type, }; setmetatable(env, {__index = _G}); - setfenv(file_closure, env); + local script_closure = script_closure_generator(env); local unique_value = {}; -- to test valid yield - local function main (...) - file_closure(); -- loads script globals - return env.action(yield(unique_value, env[rule](...))); + local function main (_ENV, ...) + script_closure(); -- loads script globals + return action(yield(unique_value, _ENV[rule](...))); end - setfenv(main, env); -- This thread allows us to load the script's globals in the -- same Lua thread the action and rule functions will execute in. local co = create(main); - local s, value, rule_return = resume(co, ...); - setfenv(file_closure, _G); -- reset the environment + local s, value, rule_return = resume(co, env, ...); if s and value ~= unique_value then print_debug(1, "A thread for %s yielded unexpectedly in the file or %s function:\n%s\n", @@ -426,7 +444,7 @@ do script_params.selection and script_params.selection or "(unknown)", script_params.forced and " and forced to run" or ""); - local file_closure = assert(loadfile(filename)); + local script_closure_generator = loadscript(filename); -- Give the closure its own environment, with global access local env = { SCRIPT_PATH = filename, @@ -434,8 +452,8 @@ do dependencies = {}, }; setmetatable(env, {__index = _G}); - setfenv(file_closure, env); - local co = create(file_closure); -- Create a garbage thread + local script_closure = script_closure_generator(env); + local co = create(script_closure); -- Create a garbage thread local status, e = resume(co); -- Get the globals it loads in env if not status then log_error("Failed to load %s:\n%s", filename, traceback(co, e)); @@ -484,7 +502,7 @@ do basename = basename, short_basename = short_basename, id = match(filename, "^.-[/\\]([^\\/]-)%.nse$") or short_basename, - file_closure = file_closure, + script_closure_generator = script_closure_generator, prerule = prerule, hostrule = hostrule, portrule = portrule, @@ -524,7 +542,8 @@ end local function get_chosen_scripts (rules) check_rules(rules); - local db_closure = assert(loadfile(script_database_path), + local db_env = {Entry = nil}; + local db_closure = assert(loadfile(script_database_path, "t", db_env), "database appears to be corrupt or out of date;\n".. "\tplease update using: nmap --script-updatedb"); @@ -571,7 +590,8 @@ local function get_chosen_scripts (rules) local globalized_rule = gsub(rule, "[\033-\039\042-\043\045-\058\060-\126]+", globalize); -- Precompile the globalized rule - local compiled_rule, err = loadstring("return "..globalized_rule, "rule"); + local env = {m = nil}; + local compiled_rule, err = load("return "..globalized_rule, "rule", "t", env); if not compiled_rule then err = err:match("rule\"]:%d+:(.+)$"); -- remove (luaL_)where in code error("Bad script rule:\n\t"..original_rule.." -> "..err); @@ -580,12 +600,13 @@ local function get_chosen_scripts (rules) entry_rules[globalized_rule] = { original_rule = rule, compiled_rule = compiled_rule, + env = env, }; end -- Checks if a given script, script_entry, should be loaded. A script_entry -- should be in the form: { filename = "name.nse", categories = { ... } } - local function entry (script_entry) + function db_env.Entry (script_entry) local categories, filename = script_entry.categories, script_entry.filename; assert(type(categories) == "table" and type(filename) == "string", "script database appears corrupt, try `nmap --script-updatedb`"); @@ -625,12 +646,12 @@ local function get_chosen_scripts (rules) return false; end - local env = {m = m}; for globalized_rule, rule_table in pairs(entry_rules) do -- Clear and set the environment of the compiled script rule - local compiled_rule = setfenv(rule_table.compiled_rule, env) - local status, found = pcall(compiled_rule) + rule_table.env.m = m; + local status, found = pcall(rule_table.compiled_rule) + rule_table.env.m = nil; if not status then error("Bad script rule:\n\t"..rule_table.original_rule.. " -> script rule expression not supported."); @@ -639,7 +660,7 @@ local function get_chosen_scripts (rules) if found then used_rules[rule_table.original_rule] = true; script_params.forced = not not forced_rules[rule_table.original_rule]; - local t, path = cnse.fetchscript(filename); + local t, path = cnse.fs.fetchscript(filename); if t == "file" then if not files_loaded[path] then local script = Script.new(path, script_params) @@ -655,7 +676,6 @@ local function get_chosen_scripts (rules) end end - setfenv(db_closure, {Entry = entry}); db_closure(); -- Load the scripts -- Now load any scripts listed by name rather than by category. @@ -663,9 +683,9 @@ local function get_chosen_scripts (rules) if not loaded then -- attempt to load the file/directory local script_params = {}; script_params.forced = not not forced_rules[rule]; - local t, path = cnse.fetchscript(rule); + local t, path = cnse.fs.fetchscript(rule); if t == nil then -- perhaps omitted the extension? - t, path = cnse.fetchscript(rule..".nse"); + t, path = cnse.fs.fetchscript(rule..".nse"); end if t == nil then error("'"..rule.."' did not match a category, filename, or directory"); @@ -676,7 +696,7 @@ local function get_chosen_scripts (rules) chosen_scripts[#chosen_scripts+1] = script; files_loaded[path] = true; elseif t == "directory" then - for f in cnse.dir(path) do + for f in cnse.fs.readdir(path) do local file = path .."/".. f if find(f, "%.nse$") and not files_loaded[file] then script_params.selection = "directory"; @@ -914,7 +934,7 @@ local function run (threads_iter, hosts) current = nil; end - cnse.nsock_loop(50); -- Allow nsock to perform any pending callbacks + loop(50); -- Allow nsock to perform any pending callbacks -- Move pending threads back to running. for co, thread in pairs(pending) do pending[co], running[co] = nil, thread; @@ -955,9 +975,9 @@ local function script_help_xml(chosen_scripts) cnse.xml_newline(); local t, scripts_dir, nselib_dir - t, scripts_dir = cnse.fetchfile_absolute("scripts/") + t, scripts_dir = cnse.fs.fetchfile_absolute("scripts/") assert(t == 'directory', 'could not locate scripts directory'); - t, nselib_dir = cnse.fetchfile_absolute("nselib/") + t, nselib_dir = cnse.fs.fetchfile_absolute("nselib/") assert(t == 'directory', 'could not locate nselib directory'); cnse.xml_start_tag("directory", { name = "scripts", path = scripts_dir }); cnse.xml_end_tag(); @@ -1057,7 +1077,7 @@ do -- Load script arguments (--script-args) nmap.registry.args = parse_table("{"..args.."}", 1); -- Check if user wants to read scriptargs from a file if cnse.scriptargsfile ~= nil then --scriptargsfile path/to/file - local t, path = cnse.fetchfile_absolute(cnse.scriptargsfile) + local t, path = cnse.fs.fetchfile_absolute(cnse.scriptargsfile) assert(t == 'file', format("%s is not a file", path)) local argfile = assert(open(path, 'r')); local argstring = argfile:read("*a") @@ -1078,12 +1098,12 @@ end if script_database_update then log_write("stdout", "Updating rule database."); - local t, path = cnse.fetchfile_absolute('scripts/'); -- fetch script directory + local t, path = cnse.fs.fetchfile_absolute('scripts/'); -- fetch script directory assert(t == 'directory', 'could not locate scripts directory'); script_database_path = path.."script.db"; local db = assert(open(script_database_path, 'w')); local scripts = {}; - for f in cnse.dir(path) do + for f in cnse.fs.readdir(path) do if match(f, '%.nse$') then scripts[#scripts+1] = path.."/"..f; end diff --git a/nse_nmaplib.cc b/nse_nmaplib.cc index 60913fe4ad..0f27101359 100644 --- a/nse_nmaplib.cc +++ b/nse_nmaplib.cc @@ -32,26 +32,24 @@ static const int NSE_PROTOCOL[] = {IPPROTO_TCP, IPPROTO_UDP, IPPROTO_SCTP}; void set_version (lua_State *L, const struct serviceDeductions *sd) { - size_t i; - - setsfield(L, -1, "name", sd->name); - setnfield(L, -1, "name_confidence", sd->name_confidence); - setsfield(L, -1, "product", sd->product); - setsfield(L, -1, "version", sd->version); - setsfield(L, -1, "extrainfo", sd->extrainfo); - setsfield(L, -1, "hostname", sd->hostname); - setsfield(L, -1, "ostype", sd->ostype); - setsfield(L, -1, "devicetype", sd->devicetype); - setsfield(L, -1, "service_tunnel", + nseU_setsfield(L, -1, "name", sd->name); + nseU_setnfield(L, -1, "name_confidence", sd->name_confidence); + nseU_setsfield(L, -1, "product", sd->product); + nseU_setsfield(L, -1, "version", sd->version); + nseU_setsfield(L, -1, "extrainfo", sd->extrainfo); + nseU_setsfield(L, -1, "hostname", sd->hostname); + nseU_setsfield(L, -1, "ostype", sd->ostype); + nseU_setsfield(L, -1, "devicetype", sd->devicetype); + nseU_setsfield(L, -1, "service_tunnel", sd->service_tunnel == SERVICE_TUNNEL_NONE ? "none" : sd->service_tunnel == SERVICE_TUNNEL_SSL ? "ssl" : NULL); - setsfield(L, -1, "service_fp", sd->service_fp); - setsfield(L, -1, "service_dtype", + nseU_setsfield(L, -1, "service_fp", sd->service_fp); + nseU_setsfield(L, -1, "service_dtype", sd->dtype == SERVICE_DETECTION_TABLE ? "table" : sd->dtype == SERVICE_DETECTION_PROBED ? "probed" : NULL); - setsfield(L, -1, "rpc_status", + nseU_setsfield(L, -1, "rpc_status", sd->rpc_status == RPC_STATUS_UNTESTED ? "untested" : sd->rpc_status == RPC_STATUS_UNKNOWN ? "unknown" : sd->rpc_status == RPC_STATUS_GOOD_PROG ? "good_prog" : @@ -59,13 +57,13 @@ void set_version (lua_State *L, const struct serviceDeductions *sd) NULL); if (sd->rpc_status == RPC_STATUS_GOOD_PROG) { - setnfield(L, -1, "rpc_program", sd->rpc_program); - setnfield(L, -1, "rpc_lowver", sd->rpc_lowver); - setnfield(L, -1, "rpc_highver", sd->rpc_highver); + nseU_setnfield(L, -1, "rpc_program", sd->rpc_program); + nseU_setnfield(L, -1, "rpc_lowver", sd->rpc_lowver); + nseU_setnfield(L, -1, "rpc_highver", sd->rpc_highver); } lua_newtable(L); - for (i = 0; i < sd->cpe.size(); i++) { + for (size_t i = 0; i < sd->cpe.size(); i++) { lua_pushstring(L, sd->cpe[i]); lua_rawseti(L, -2, i+1); } @@ -81,11 +79,11 @@ void set_portinfo (lua_State *L, const Target *target, const Port *port) target->ports.getServiceDeductions(port->portno, port->proto, &sd); - setnfield(L, -1, "number", port->portno); - setsfield(L, -1, "service", sd.name); - setsfield(L, -1, "protocol", IPPROTO2STR(port->proto)); - setsfield(L, -1, "state", statenum2str(port->state)); - setsfield(L, -1, "reason", reason_str(port->reason.reason_id, 1)); + nseU_setnfield(L, -1, "number", port->portno); + nseU_setsfield(L, -1, "service", sd.name); + nseU_setsfield(L, -1, "protocol", IPPROTO2STR(port->proto)); + nseU_setsfield(L, -1, "state", statenum2str(port->state)); + nseU_setsfield(L, -1, "reason", reason_str(port->reason.reason_id, 1)); lua_newtable(L); set_version(L, &sd); lua_setfield(L, -2, "version"); @@ -163,11 +161,11 @@ static void push_osmatch_table(lua_State *L, const FingerMatch *match, * points to nil! * */ void set_hostinfo(lua_State *L, Target *currenths) { - setsfield(L, -1, "ip", currenths->targetipstr()); - setsfield(L, -1, "name", currenths->HostName()); - setsfield(L, -1, "targetname", currenths->TargetName()); + nseU_setsfield(L, -1, "ip", currenths->targetipstr()); + nseU_setsfield(L, -1, "name", currenths->HostName()); + nseU_setsfield(L, -1, "targetname", currenths->TargetName()); if (currenths->directlyConnectedOrUnset() != -1) - setbfield(L, -1, "directly_connected", currenths->directlyConnected()); + nseU_setbfield(L, -1, "directly_connected", currenths->directlyConnected()); if (currenths->MACAddress()) { lua_pushlstring(L, (const char *) currenths->MACAddress() , 6); @@ -183,8 +181,8 @@ void set_hostinfo(lua_State *L, Target *currenths) { lua_pushlstring(L, (const char *) currenths->SrcMACAddress(), 6); lua_setfield(L, -2, "mac_addr_src"); } - setsfield(L, -1, "interface", currenths->deviceName()); - setnfield(L, -1, "interface_mtu", currenths->MTU()); + nseU_setsfield(L, -1, "interface", currenths->deviceName()); + nseU_setnfield(L, -1, "interface_mtu", currenths->MTU()); push_bin_ip(L, currenths->TargetSockAddr()); lua_setfield(L, -2, "bin_ip"); @@ -192,9 +190,9 @@ void set_hostinfo(lua_State *L, Target *currenths) { lua_setfield(L, -2, "bin_ip_src"); lua_newtable(L); - setnfield(L, -1, "srtt", (lua_Number) currenths->to.srtt / 1000000.0); - setnfield(L, -1, "rttvar", (lua_Number) currenths->to.rttvar / 1000000.0); - setnfield(L, -1, "timeout", (lua_Number) currenths->to.timeout / 1000000.0); + nseU_setnfield(L, -1, "srtt", (lua_Number) currenths->to.srtt / 1000000.0); + nseU_setnfield(L, -1, "rttvar", (lua_Number) currenths->to.rttvar / 1000000.0); + nseU_setnfield(L, -1, "timeout", (lua_Number) currenths->to.timeout / 1000000.0); lua_setfield(L, -2, "times"); lua_newtable(L); @@ -212,14 +210,14 @@ void set_hostinfo(lua_State *L, Target *currenths) { /* fill the table if the hop has not timed out, otherwise an empty table * is inserted */ if (!it->timedout) { - setsfield(L, -1, "ip", inet_ntop_ez(&it->addr, sizeof(it->addr))); + nseU_setsfield(L, -1, "ip", inet_ntop_ez(&it->addr, sizeof(it->addr))); if (!it->name.empty()) - setsfield(L, -1, "name", it->name.c_str()); + nseU_setsfield(L, -1, "name", it->name.c_str()); lua_newtable(L); - setnfield(L, -1, "srtt", it->rtt / 1000.0); + nseU_setnfield(L, -1, "srtt", it->rtt / 1000.0); lua_setfield(L, -2, "times"); } - lua_rawseti(L, -2, lua_objlen(L, -2)+1); + lua_rawseti(L, -2, lua_rawlen(L, -2)+1); } lua_setfield(L, -2, "traceroute"); } @@ -289,11 +287,11 @@ static int aux_mutex (lua_State *L) return 0; } lua_pushthread(L); - lua_rawseti(L, lua_upvalueindex(1), lua_objlen(L, lua_upvalueindex(1))+1); + lua_rawseti(L, lua_upvalueindex(1), lua_rawlen(L, lua_upvalueindex(1))+1); return nse_yield(L, 0, NULL); case DONE: lua_pushthread(L); - if (!lua_equal(L, -1, lua_upvalueindex(2))) + if (!lua_rawequal(L, -1, lua_upvalueindex(2))) luaL_error(L, "%s", "do not have a lock on this mutex"); /* remove destructor */ lua_pushvalue(L, lua_upvalueindex(3)); @@ -385,10 +383,10 @@ static int aux_condvar (lua_State *L) { case WAIT: lua_pushthread(L); - lua_rawseti(L, lua_upvalueindex(1), lua_objlen(L, lua_upvalueindex(1))+1); + lua_rawseti(L, lua_upvalueindex(1), lua_rawlen(L, lua_upvalueindex(1))+1); return nse_yield(L, 0, NULL); case SIGNAL: - n = lua_objlen(L, lua_upvalueindex(1)); + n = lua_rawlen(L, lua_upvalueindex(1)); if (n == 0) n = 1; break; @@ -397,7 +395,7 @@ static int aux_condvar (lua_State *L) break; } lua_pushvalue(L, lua_upvalueindex(1)); - for (i = lua_objlen(L, -1); i >= n; i--) + for (i = lua_rawlen(L, -1); i >= n; i--) { lua_rawgeti(L, -1, i); /* get the thread */ if (lua_isthread(L, -1)) @@ -456,12 +454,12 @@ static int l_get_ports (lua_State *L) PORT_CLOSED, PORT_OPENFILTERED, PORT_CLOSEDFILTERED}; Port *p = NULL; Port port; /* dummy Port for nextPort */ - Target *target = get_target(L, 1); + Target *target = nseU_gettarget(L, 1); int protocol = NSE_PROTOCOL[luaL_checkoption(L, 3, NULL, NSE_PROTOCOL_OP)]; int state = states[luaL_checkoption(L, 4, NULL, state_op)]; if (!lua_isnil(L, 2)) - p = get_port(L, target, &port, 2); + p = nseU_getport(L, target, &port, 2); if (!(p = target->ports.nextPort(p, &port, protocol, state))) { lua_pushnil(L); @@ -487,8 +485,8 @@ static int l_get_port_state (lua_State *L) Target *target; Port *p; Port port; /* dummy Port */ - target = get_target(L, 1); - p = get_port(L, target, &port, 2); + target = nseU_gettarget(L, 1); + p = nseU_getport(L, target, &port, 2); if (p == NULL) lua_pushnil(L); else @@ -523,8 +521,8 @@ static int l_set_port_state (lua_State *L) Target *target; Port *p; Port port; - target = get_target(L, 1); - if ((p = get_port(L, target, &port, 2)) != NULL) + target = nseU_gettarget(L, 1); + if ((p = nseU_getport(L, target, &port, 2)) != NULL) { switch (opstate[luaL_checkoption(L, 3, NULL, op)]) { @@ -568,8 +566,8 @@ static int l_set_port_version (lua_State *L) enum serviceprobestate probestate = opversion[luaL_checkoption(L, 3, "hardmatched", ops)]; - target = get_target(L, 1); - if ((p = get_port(L, target, &port, 2)) == NULL) + target = nseU_gettarget(L, 1); + if ((p = nseU_getport(L, target, &port, 2)) == NULL) return 0; /* invalid port */ lua_settop(L, 3); @@ -745,13 +743,10 @@ static int l_get_dns_servers (lua_State *L) { std::list servs2 = get_dns_servers(); std::list::iterator servI2; - int i = 1; lua_newtable(L); - for(servI2 = servs2.begin(); servI2 != servs2.end(); servI2++) { - lua_pushstring(L, servI2->c_str()); - lua_rawseti(L, -2, i++); - } + for (servI2 = servs2.begin(); servI2 != servs2.end(); servI2++) + nseU_appendfstr(L, -1, "%s", servI2->c_str()); return 1; } @@ -770,30 +765,25 @@ static int l_resolve(lua_State *L) static const int fams[] = { AF_INET, AF_INET6, AF_UNSPEC }; struct sockaddr_storage ss; struct addrinfo *addr, *addrs; - int i; const char *host = luaL_checkstring(L, 1); int af = fams[luaL_checkoption(L, 2, "unspec", fam_op)]; addrs = resolve_all(host, af); - if (!addrs) { - lua_pushboolean(L, false); - lua_pushstring(L, "Failed to resolve"); - return 2; - } + if (!addrs) + return nseU_safeerror(L, "Failed to resolve"); lua_pushboolean(L, true); lua_newtable(L); - for (addr = addrs, i = 1; addr != NULL; addr = addr->ai_next) { + for (addr = addrs; addr != NULL; addr = addr->ai_next) { if (af != AF_UNSPEC && addr->ai_family != af) continue; if (addr->ai_addrlen > sizeof(ss)) continue; memcpy(&ss, addr->ai_addr, addr->ai_addrlen); - lua_pushstring(L, inet_socktop(&ss)); - lua_rawseti(L, -2, i++); + nseU_appendfstr(L, -1, "%s", inet_socktop(&ss)); } if (addrs != NULL) @@ -805,9 +795,9 @@ static int l_resolve(lua_State *L) static int l_address_family(lua_State *L) { if (o.af() == AF_INET) - lua_pushstring(L, "inet"); + lua_pushliteral(L, "inet"); else - lua_pushstring(L, "inet6"); + lua_pushliteral(L, "inet6"); return 1; } @@ -840,9 +830,7 @@ static int l_list_interfaces (lua_State *L) int i; if (iflist==NULL || numifs<=0) { - lua_pushnil(L); - lua_pushstring(L, errstr); - return 2; + return nseU_safeerror(L, "%s", errstr); } else { memset(ipstr, 0, INET6_ADDRSTRLEN); memset(&src, 0, sizeof(src)); @@ -851,15 +839,15 @@ static int l_list_interfaces (lua_State *L) for(i=0; i< numifs; i++) { lua_newtable(L); //interface table - setsfield(L, -1, "device", iflist[i].devfullname); - setsfield(L, -1, "shortname", iflist[i].devname); - setnfield(L, -1, "netmask", iflist[i].netmask_bits); - setsfield(L, -1, "address", inet_ntop_ez(&(iflist[i].addr), + nseU_setsfield(L, -1, "device", iflist[i].devfullname); + nseU_setsfield(L, -1, "shortname", iflist[i].devname); + nseU_setnfield(L, -1, "netmask", iflist[i].netmask_bits); + nseU_setsfield(L, -1, "address", inet_ntop_ez(&(iflist[i].addr), sizeof(iflist[i].addr) )); switch (iflist[i].device_type){ case devt_ethernet: - setsfield(L, -1, "link", "ethernet"); + nseU_setsfield(L, -1, "link", "ethernet"); lua_pushlstring(L, (const char *) iflist[i].mac, 6); lua_setfield(L, -2, "mac"); @@ -871,22 +859,22 @@ static int l_list_interfaces (lua_State *L) addr_bcast(&src, &bcast); memset(ipstr, 0, INET6_ADDRSTRLEN); if (addr_ntop(&bcast, ipstr, INET6_ADDRSTRLEN) != NULL) - setsfield(L, -1, "broadcast", ipstr); + nseU_setsfield(L, -1, "broadcast", ipstr); } break; case devt_loopback: - setsfield(L, -1, "link", "loopback"); + nseU_setsfield(L, -1, "link", "loopback"); break; case devt_p2p: - setsfield(L, -1, "link", "p2p"); + nseU_setsfield(L, -1, "link", "p2p"); break; case devt_other: default: - setsfield(L, -1, "link", "other"); + nseU_setsfield(L, -1, "link", "other"); } - setsfield(L, -1, "up", (iflist[i].device_up ? "up" : "down")); - setnfield(L, -1, "mtu", iflist[i].mtu); + nseU_setsfield(L, -1, "up", (iflist[i].device_up ? "up" : "down")); + nseU_setnfield(L, -1, "mtu", iflist[i].mtu); /* After setting the fields, add the interface table to the base table */ lua_rawseti(L, -2, i); @@ -923,14 +911,12 @@ static int l_get_payload_length(lua_State *L) int luaopen_nmap (lua_State *L) { - static const luaL_reg nmaplib [] = { + static const luaL_Reg nmaplib [] = { {"get_port_state", l_get_port_state}, {"get_ports", l_get_ports}, {"set_port_state", l_set_port_state}, {"set_port_version", l_set_port_version}, {"port_is_excluded", l_port_is_excluded}, - {"new_socket", l_nsock_new}, - {"new_dnet", l_dnet_new}, {"clock_ms", l_clock_ms}, {"clock", l_clock}, {"log_write", l_log_write}, @@ -947,50 +933,47 @@ int luaopen_nmap (lua_State *L) {"resolve", l_resolve}, {"address_family", l_address_family}, {"get_interface", l_get_interface}, - {"get_interface_info", l_dnet_get_interface_info}, {"list_interfaces", l_list_interfaces}, {"get_ttl", l_get_ttl}, {"get_payload_length",l_get_payload_length}, + {"new_dnet", nseU_placeholder}, /* deprecated, placeholder */ + {"get_interface_info", nseU_placeholder}, /* deprecated, placeholder */ + {"new_socket", nseU_placeholder}, /* deprecated, placeholder */ + {"sleep", nseU_placeholder}, /* placeholder */ + {"mutex", nseU_placeholder}, /* placeholder */ + {"condvar", nseU_placeholder}, /* placeholder */ {NULL, NULL} }; - lua_settop(L, 0); // clear stack - luaL_register(L, "nmap", nmaplib); + luaL_newlib(L, nmaplib); + int nmap_idx = lua_gettop(L); - weak_table(L, 0, 0, "v"); /* allow closures to be collected (see l_mutex) */ + nseU_weaktable(L, 0, 0, "v"); /* allow closures to be collected (see l_mutex) */ lua_pushcclosure(L, l_mutex, 1); /* mutex function */ - lua_setfield(L, -2, "mutex"); + lua_setfield(L, nmap_idx, "mutex"); - weak_table(L, 0, 0, "v"); /* allow closures to be collected (see l_condvar) */ - lua_pushcclosure(L, l_condvar, 1); // condvar function - lua_setfield(L, -2, "condvar"); + nseU_weaktable(L, 0, 0, "v"); /* allow closures to be collected (see l_condvar) */ + lua_pushcclosure(L, l_condvar, 1); /* condvar function */ + lua_setfield(L, nmap_idx, "condvar"); lua_newtable(L); - lua_setfield(L, -2, "registry"); - - lua_pushcclosure(L, luaopen_nsock, 0); - lua_pushliteral(L, "nsock"); - lua_call(L, 1, 0); - - lua_pushcclosure(L, luaopen_dnet, 0); - lua_pushliteral(L, "dnet"); - lua_call(L, 1, 0); - - lua_settop(L, 1); // just nmap lib on stack - - return 1; -} - -/* Register C functions that belong in the stdnse namespace. They are loaded - from here in stdnse.lua. */ -int luaopen_stdnse_c (lua_State *L) -{ - static const luaL_reg stdnse_clib [] = { - {"sleep", l_nsock_sleep}, - {NULL, NULL} - }; - - luaL_register(L, "stdnse.c", stdnse_clib); + lua_setfield(L, nmap_idx, "registry"); + + luaL_requiref(L, "nmap.socket", luaopen_nsock, 0); + lua_getfield(L, -1, "new"); + lua_setfield(L, nmap_idx, "new_socket"); /* deprecated alias */ + lua_getfield(L, -1, "sleep"); + lua_setfield(L, nmap_idx, "sleep"); /* permanent alias */ + lua_setfield(L, nmap_idx, "socket"); + + luaL_requiref(L, "nmap.dnet", luaopen_dnet, 0); + lua_getfield(L, -1, "new"); + lua_setfield(L, nmap_idx, "new_dnet"); /* deprecated alias */ + lua_getfield(L, -1, "get_interface_info"); + lua_setfield(L, nmap_idx, "get_interface_info"); /* deprecated alias */ + lua_setfield(L, nmap_idx, "dnet"); + + lua_settop(L, nmap_idx); return 1; } diff --git a/nse_nmaplib.h b/nse_nmaplib.h index 56013344eb..12628833b8 100644 --- a/nse_nmaplib.h +++ b/nse_nmaplib.h @@ -8,7 +8,6 @@ class Target; class Port; int luaopen_nmap(lua_State* l); -int luaopen_stdnse_c (lua_State *L); void set_hostinfo(lua_State* l, Target* currenths); void set_portinfo(lua_State* l, const Target *target, const Port* port); diff --git a/nse_nsock.cc b/nse_nsock.cc index c7abc40587..0f5d0ea9a8 100644 --- a/nse_nsock.cc +++ b/nse_nsock.cc @@ -24,15 +24,17 @@ #include #include -#define NMAP_NSOCK_SOCKET "NMAP_NSOCK_SOCKET" -#define NMAP_NSOCK_PCAP_SOCKET "NMAP_NSOCK_PCAP_SOCKET" - #define DEFAULT_TIMEOUT 30000 -/* Integer keys in Nsock function environments */ -#define THREAD_SOCKETS 1 /* */ -#define CONNECT_WAITING 2 /* Threads waiting to lock */ -#define KEY_PCAP 3 /* keys to pcap sockets */ +/* Upvalues for library variables */ +enum { + NSOCK_POOL = lua_upvalueindex(1), + NSOCK_SOCKET = lua_upvalueindex(2), /* nsock socket metatable */ + PCAP_SOCKET = lua_upvalueindex(3), /* pcap socket metatable */ + THREAD_SOCKETS = lua_upvalueindex(4), /* */ + CONNECT_WAITING = lua_upvalueindex(5), /* Threads waiting to lock */ + KEY_PCAP = lua_upvalueindex(6) /* Keys to pcap sockets */ +}; /* Integer keys in the Nsock userdata environments */ #define THREAD_I 1 /* The thread that yielded */ @@ -65,8 +67,6 @@ typedef struct nse_nsock_udata } nse_nsock_udata; -static int NSOCK_POOL = 0xac1dba11; - static int gc_pool (lua_State *L) { nsock_pool *nsp = (nsock_pool *) lua_touserdata(L, 1); @@ -81,25 +81,20 @@ static nsock_pool new_pool (lua_State *L) nsock_pool nsp = nsp_new(NULL); nsock_pool *nspp; nsp_setbroadcast(nsp, true); - lua_pushlightuserdata(L, &NSOCK_POOL); nspp = (nsock_pool *) lua_newuserdata(L, sizeof(nsock_pool)); *nspp = nsp; lua_newtable(L); lua_pushcfunction(L, gc_pool); lua_setfield(L, -2, "__gc"); lua_setmetatable(L, -2); - lua_rawset(L, LUA_REGISTRYINDEX); return nsp; } static nsock_pool get_pool (lua_State *L) { nsock_pool *nsp; - lua_pushlightuserdata(L, &NSOCK_POOL); - lua_rawget(L, LUA_REGISTRYINDEX); - nsp = (nsock_pool *) lua_touserdata(L, -1); + nsp = (nsock_pool *) lua_touserdata(L, NSOCK_POOL); assert(*nsp != NULL); - lua_pop(L, 1); return *nsp; } @@ -157,21 +152,18 @@ static std::string hexify (const unsigned char *str, size_t len) */ #define MAX_PARALLELISM 20 -/* The Lua 5.2 socket_lock function */ -#if 0 /* int socket_lock (lua_State *L) * * This function is called by l_connect to get a "lock" on a socket. * When connect calls this function, it expects socket_lock to yield forcing * connect to be restarted when resumed or it succeeds returning normally. */ -static void socket_lock (lua_State *L, int idx) +static int socket_lock (lua_State *L, int idx) { unsigned p = o.max_parallelism == 0 ? MAX_PARALLELISM : o.max_parallelism; int top = lua_gettop(L); - lua_rawgeti(L, LUA_ENVIRONINDEX, THREAD_SOCKETS); nse_base(L); - lua_rawget(L, -2); + lua_rawget(L, THREAD_SOCKETS); if (lua_istable(L, -1)) { /* Thread already has a "lock" with open sockets. Place the new socket @@ -179,74 +171,25 @@ static void socket_lock (lua_State *L, int idx) lua_pushvalue(L, idx); lua_pushboolean(L, true); lua_rawset(L, -3); - } else if (table_length(L, top+2) <= p) + } else if (nseU_tablen(L, THREAD_SOCKETS) <= p) { /* There is room for this thread to open sockets */ nse_base(L); - weak_table(L, 0, 0, "k"); /* weak socket references */ + nseU_weaktable(L, 0, 0, "k"); /* weak socket references */ lua_pushvalue(L, idx); /* socket */ lua_pushboolean(L, true); lua_rawset(L, -3); /* add to sockets table */ - lua_rawset(L, top+2); /* add new Pair - * to THREAD_SOCKETS */ + lua_rawset(L, THREAD_SOCKETS); /* add new Pair + * to THREAD_SOCKETS */ } else { - /* Too many threads have sockets open. Add thread to waiting. The caller - * is expected to yield. (see the connect function in luaopen_nsock) */ - lua_rawgeti(L, LUA_ENVIRONINDEX, CONNECT_WAITING); nse_base(L); lua_pushboolean(L, true); - lua_settable(L, -3); + lua_rawset(L, CONNECT_WAITING); lua_settop(L, top); /* restore stack to original condition for l_connect */ - return nse_yield(L, 0, NULL); + return 0; } lua_settop(L, top); /* restore stack to original condition for l_connect */ -} -#endif - -/* int socket_lock (lua_State *L) - * - * Arguments - * socket A socket to "lock". - * - * This function is called by Lua to get a "lock" on a socket. - * See the connect function (in Lua) in luaopen_nsock. - */ -static int socket_lock (lua_State *L) -{ - unsigned p = o.max_parallelism == 0 ? MAX_PARALLELISM : o.max_parallelism; - lua_settop(L, 1); - lua_rawgeti(L, LUA_ENVIRONINDEX, THREAD_SOCKETS); - nse_base(L); - lua_rawget(L, -2); - if (lua_istable(L, -1)) - { - /* Thread already has a "lock" with open sockets. Place the new socket - * in its sockets table */ - lua_pushvalue(L, 1); - lua_pushboolean(L, true); - lua_rawset(L, -3); - } else if (table_length(L, 2) <= p) - { - /* There is room for this thread to open sockets */ - nse_base(L); - weak_table(L, 0, 0, "k"); /* weak socket references */ - lua_pushvalue(L, 1); /* socket */ - lua_pushboolean(L, true); - lua_rawset(L, -3); /* add to sockets table */ - lua_rawset(L, 2); /* add new Pair - * to THREAD_SOCKETS */ - } else - { - /* Too many threads have sockets open. Add thread to waiting. The caller - * is expected to yield. (see the connect function in luaopen_nsock) */ - lua_rawgeti(L, LUA_ENVIRONINDEX, CONNECT_WAITING); - nse_base(L); - lua_pushboolean(L, true); - lua_settable(L, -3); - return nse_yield(L, 0, NULL); - } - lua_pushboolean(L, true); return 1; } @@ -256,19 +199,15 @@ static void socket_unlock (lua_State *L) lua_gc(L, LUA_GCSTOP, 0); /* don't collect threads during iteration */ - lua_rawgeti(L, LUA_ENVIRONINDEX, THREAD_SOCKETS); - lua_pushnil(L); - while (lua_next(L, -2) != 0) + for (lua_pushnil(L); lua_next(L, THREAD_SOCKETS); lua_pop(L, 1)) { unsigned open = 0; if (lua_status(lua_tothread(L, -2)) == LUA_YIELD) { - lua_pushnil(L); - while (lua_next(L, -2) != 0) /* for each socket */ + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) /* for each socket */ { - lua_pop(L, 1); /* pop garbage boolean */ - if (((nse_nsock_udata *) lua_touserdata(L, -1))->nsiod != NULL) + if (((nse_nsock_udata *) lua_touserdata(L, -2))->nsiod != NULL) open++; } } @@ -276,33 +215,25 @@ static void socket_unlock (lua_State *L) if (open == 0) /* thread has no open sockets? */ { /* close all of its sockets */ - lua_pushnil(L); - while (lua_next(L, -2) != 0) /* for each socket */ + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) /* for each socket */ { - lua_pop(L, 1); /* pop garbage boolean */ - lua_getfield(L, -1, "close"); - lua_pushvalue(L, -2); + lua_getfield(L, -2, "close"); + lua_pushvalue(L, -3); lua_call(L, 1, 0); } lua_pushvalue(L, -2); /* thread key */ lua_pushnil(L); - lua_rawset(L, top+1); /* THREADS_SOCKETS */ + lua_rawset(L, THREAD_SOCKETS); - lua_rawgeti(L, LUA_ENVIRONINDEX, CONNECT_WAITING); - lua_pushnil(L); - while (lua_next(L, -2) != 0) + for (lua_pushnil(L); lua_next(L, CONNECT_WAITING); lua_pop(L, 1)) { - lua_pop(L, 1); /* pop garbage boolean */ - nse_restore(lua_tothread(L, -1), 0); - lua_pushvalue(L, -1); + nse_restore(lua_tothread(L, -2), 0); + lua_pushvalue(L, -2); lua_pushnil(L); - lua_rawset(L, -4); /* remove thread from waiting */ + lua_rawset(L, CONNECT_WAITING); } - lua_pop(L, 1); /* CONNECT_WAITING */ } - - lua_pop(L, 1); /* pop sockets table */ } lua_gc(L, LUA_GCRESTART, 0); @@ -415,7 +346,7 @@ static void callback (nsock_pool nsp, nsock_event nse, void *ud) static int yield (lua_State *L, nse_nsock_udata *nu, const char *action, const char *direction, int ctx, lua_CFunction k) { - lua_getfenv(L, 1); + lua_getuservalue(L, 1); lua_pushthread(L); lua_rawseti(L, -2, THREAD_I); lua_pop(L, 1); /* nsock udata environment */ @@ -427,8 +358,7 @@ static int yield (lua_State *L, nse_nsock_udata *nu, const char *action, static nse_nsock_udata *check_nsock_udata (lua_State *L, int idx, int open) { - nse_nsock_udata *nu = - (nse_nsock_udata *) luaL_checkudata(L, idx, NMAP_NSOCK_SOCKET); + nse_nsock_udata *nu = (nse_nsock_udata *) nseU_checkudata(L, idx, NSOCK_SOCKET, "nsock"); if (open && nu->nsiod == NULL) { /* The socket hasn't been connected or setup yet. Try doing a setup, or @@ -461,16 +391,15 @@ static nse_nsock_udata *check_nsock_udata (lua_State *L, int idx, int open) return nu; } -static int loop (lua_State *L) +static int l_loop (lua_State *L) { nsock_pool nsp = get_pool(L); int tout = luaL_checkint(L, 1); - /* clean up old socket locks */ - socket_unlock(L); + socket_unlock(L); /* clean up old socket locks */ if (nsock_loop(nsp, tout) == NSOCK_LOOP_ERROR) - luaL_error(L, "a fatal error occurred in nsock_loop"); + return luaL_error(L, "a fatal error occurred in nsock_loop"); return 0; } @@ -481,7 +410,7 @@ static int l_reconnect_ssl (lua_State *L) #ifndef HAVE_OPENSSL if (1) - return safe_error(L, "sorry, you don't have OpenSSL"); + return nseU_safeerror(L, "sorry, you don't have OpenSSL"); #endif nsock_reconnect_ssl(nsp, nu->nsiod, callback, nu->timeout, @@ -497,9 +426,9 @@ static int l_connect (lua_State *L) nsock_pool nsp = get_pool(L); nse_nsock_udata *nu = check_nsock_udata(L, 1, 0); - const char *addr, *targetname; check_target(L, 2, &addr, &targetname); + const char *addr, *targetname; nseU_checktarget(L, 2, &addr, &targetname); const char *default_proto = NULL; - unsigned short port = check_port(L, 3, &default_proto); + unsigned short port = nseU_checkport(L, 3, &default_proto); if (default_proto == NULL) { switch (nu->proto) { case IPPROTO_TCP: @@ -517,25 +446,20 @@ static int l_connect (lua_State *L) struct addrinfo *dest; int error_id; - /* Lua 5.2 */ -#if 0 - /* either socket_lock yields and this function is resumed (and restarted) - * or it succeeds and we continue. - */ - socket_lock(L); -#endif + if (!socket_lock(L, 1)) /* we cannot get a socket lock */ + return nse_yield(L, 0, l_connect); /* restart on continuation */ #ifndef HAVE_OPENSSL if (what == SSL) - return safe_error(L, "sorry, you don't have OpenSSL"); + return nseU_safeerror(L, "sorry, you don't have OpenSSL"); #endif error_id = getaddrinfo(addr, NULL, NULL, &dest); if (error_id) - return safe_error(L, gai_strerror(error_id)); + return nseU_safeerror(L, gai_strerror(error_id)); if (dest == NULL) - return safe_error(L, "getaddrinfo returned success but no addresses"); + return nseU_safeerror(L, "getaddrinfo returned success but no addresses"); nu->nsiod = nsi_new(nsp, NULL); if (nu->source_addr.ss_family != AF_UNSPEC) { @@ -596,19 +520,19 @@ static int l_sendto (lua_State *L) nsock_pool nsp = get_pool(L); nse_nsock_udata *nu = check_nsock_udata(L, 1, 1); size_t size; - const char *addr, *targetname; check_target(L, 2, &addr, &targetname); + const char *addr, *targetname; nseU_checktarget(L, 2, &addr, &targetname); const char *default_proto = NULL; - unsigned short port = check_port(L, 3, &default_proto); + unsigned short port = nseU_checkport(L, 3, &default_proto); const char *string = luaL_checklstring(L, 4, &size); int error_id; struct addrinfo *dest; error_id = getaddrinfo(addr, NULL, NULL, &dest); if (error_id) - return safe_error(L, gai_strerror(error_id)); + return nseU_safeerror(L, gai_strerror(error_id)); if (dest == NULL) - return safe_error(L, "getaddrinfo returned success but no addresses"); + return nseU_safeerror(L, "getaddrinfo returned success but no addresses"); nsock_sendto(nsp, nu->nsiod, callback, nu->timeout, nu, dest->ai_addr, dest->ai_addrlen, port, string, size); trace(nu->nsiod, hexify((unsigned char *) string, size).c_str(), TO); @@ -660,14 +584,12 @@ static int l_receive_bytes (lua_State *L) return yield(L, nu, "RECEIVE BYTES", FROM, 0, NULL); } -#if 0 -/* Lua 5.2 */ static int l_receive_buf (lua_State *L) { nsock_pool nsp = get_pool(L); nse_nsock_udata *nu = check_nsock_udata(L, 1, 1); /* 1 */ if (!(lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TSTRING)) - luaL_typeerror(L, 2, "function/string"); + nseU_typeerror(L, 2, "function/string"); luaL_checktype(L, 3, LUA_TBOOLEAN); /* 3 */ if (lua_getctx(L, NULL) == LUA_OK) @@ -710,14 +632,14 @@ static int l_receive_buf (lua_State *L) if (lua_isnumber(L, -2) && lua_isnumber(L, -1)) /* found end? */ { lua_Integer l = lua_tointeger(L, -2), r = lua_tointeger(L, -1); - if (l > r || r > (lua_Integer) lua_objlen(L, 5)) + if (l > r || r > (lua_Integer) lua_rawlen(L, 5)) return luaL_error(L, "invalid indices for match"); lua_pushboolean(L, 1); if (lua_toboolean(L, 3)) lua_pushlstring(L, lua_tostring(L, 5), r); else lua_pushlstring(L, lua_tostring(L, 5), l-1); - lua_pushlstring(L, lua_tostring(L, 5)+r, lua_objlen(L, 5)-r); + lua_pushlstring(L, lua_tostring(L, 5)+r, lua_rawlen(L, 5)-r); lua_rawseti(L, 4, BUFFER_I); return 2; } @@ -728,7 +650,6 @@ static int l_receive_buf (lua_State *L) return yield(L, nu, "RECEIVE BUF", FROM, 0, l_receive_buf); } } -#endif static int l_get_info (lua_State *L) { @@ -758,7 +679,7 @@ static int l_set_timeout (lua_State *L) nu->timeout = luaL_checkint(L, 2); if ((int) nu->timeout < -1) /* -1 is no timeout */ return luaL_error(L, "Negative timeout: %d", nu->timeout); - return success(L); + return nseU_success(L); } static void sleep_callback (nsock_pool nsp, nsock_event nse, void *ud) @@ -769,7 +690,7 @@ static void sleep_callback (nsock_pool nsp, nsock_event nse, void *ud) nse_restore(L, 0); } -LUALIB_API int l_nsock_sleep (lua_State *L) +static int l_sleep (lua_State *L) { nsock_pool nsp = get_pool(L); double secs = luaL_checknumber(L, 1); @@ -829,12 +750,12 @@ static int l_bind (lua_State *L) rc = getaddrinfo(addr_str, port_str, &hints, &results); if (rc != 0) - return safe_error(L, gai_strerror(rc)); + return nseU_safeerror(L, gai_strerror(rc)); if (results == NULL) - return safe_error(L, "getaddrinfo: no results found"); + return nseU_safeerror(L, "getaddrinfo: no results found"); if (results->ai_addrlen > sizeof(nu->source_addr)) { freeaddrinfo(results); - return safe_error(L, "getaddrinfo: result is too big"); + return nseU_safeerror(L, "getaddrinfo: result is too big"); } /* We ignore any results after the first. */ @@ -843,7 +764,7 @@ static int l_bind (lua_State *L) nu->source_addrlen = results->ai_addrlen; memcpy(&nu->source_addr, results->ai_addr, nu->source_addrlen); - return success(L); + return nseU_success(L); } static const char *default_af_string(int af) @@ -861,7 +782,7 @@ static void initialize (lua_State *L, int idx, nse_nsock_udata *nu, lua_createtable(L, 2, 0); /* room for thread in array */ lua_pushliteral(L, ""); lua_rawseti(L, -2, BUFFER_I); - lua_setfenv(L, idx); + lua_setuservalue(L, idx); nu->nsiod = NULL; nu->proto = proto; nu->af = af; @@ -874,7 +795,7 @@ static void initialize (lua_State *L, int idx, nse_nsock_udata *nu, nu->direction = nu->action = NULL; } -LUALIB_API int l_nsock_new (lua_State *L) +static int l_new (lua_State *L) { static const char *proto_strings[] = { "tcp", "udp", NULL }; int proto_map[] = { IPPROTO_TCP, IPPROTO_UDP }; @@ -889,7 +810,7 @@ LUALIB_API int l_nsock_new (lua_State *L) lua_settop(L, 0); nu = (nse_nsock_udata *) lua_newuserdata(L, sizeof(nse_nsock_udata)); - luaL_getmetatable(L, NMAP_NSOCK_SOCKET); + lua_pushvalue(L, NSOCK_SOCKET); lua_setmetatable(L, -2); initialize(L, 1, nu, proto, af); @@ -900,7 +821,7 @@ static int l_close (lua_State *L) { nse_nsock_udata *nu = check_nsock_udata(L, 1, 0); if (nu->nsiod == NULL) - return safe_error(L, "socket already closed"); + return nseU_safeerror(L, "socket already closed"); trace(nu->nsiod, "CLOSE", TO); #ifdef HAVE_OPENSSL if (nu->ssl_session) @@ -909,7 +830,7 @@ static int l_close (lua_State *L) if (!nu->is_pcap) /* pcap sockets are closed by pcap_gc */ nsi_delete(nu->nsiod, NSOCK_PENDING_NOTIFY); initialize(L, 1, nu, nu->proto, nu->af); - return success(L); + return nseU_success(L); } static int nsock_gc (lua_State *L) @@ -969,25 +890,22 @@ static int l_pcap_open (lua_State *L) if (nu->nsiod) luaL_argerror(L, 1, "socket is already open"); - if (lua_objlen(L, 6) == 0) + if (lua_rawlen(L, 6) == 0) luaL_argerror(L, 2, "bad device name"); - lua_rawgeti(L, LUA_ENVIRONINDEX, KEY_PCAP); lua_pushvalue(L, 7); - lua_rawget(L, -2); + lua_rawget(L, KEY_PCAP); nsock_iod *nsiod = (nsock_iod *) lua_touserdata(L, -1); if (nsiod == NULL) /* does not exist */ { nsiod = (nsock_iod *) lua_newuserdata(L, sizeof(nsock_iod)); - luaL_getmetatable(L, NMAP_NSOCK_PCAP_SOCKET); + lua_pushvalue(L, PCAP_SOCKET); lua_setmetatable(L, -2); *nsiod = nsi_new(nsp, nu); - lua_rawgeti(L, LUA_ENVIRONINDEX, KEY_PCAP); lua_pushvalue(L, 7); /* the pcap socket key */ lua_pushvalue(L, -2); /* the pcap socket nsiod */ - lua_rawset(L, -3); /* _ENV[KEY_PCAP]["dev|snap|promis|bpf"] = pcap_nsiod */ - lua_pop(L, 1); /* KEY_PCAP */ - lua_getfenv(L, 1); /* the socket user value */ + lua_rawset(L, KEY_PCAP); /* KEY_PCAP["dev|snap|promis|bpf"] = pcap_nsiod */ + lua_getuservalue(L, 1); /* the socket user value */ lua_pushvalue(L, -2); /* the pcap socket nsiod */ lua_pushboolean(L, 1); /* dummy variable */ lua_rawset(L, -3); @@ -1038,66 +956,30 @@ static int l_pcap_receive (lua_State *L) LUALIB_API int luaopen_nsock (lua_State *L) { -/* These two functions can be implemented in C in Lua 5.2 */ - - /* nsock:connect(socket, ...) - * This Lua function is a wrapper around the actual l_nsock_connect. The - * connect function must get a lock through socket_lock (C function above). - * Once it has the lock, it can (tail call) return the actual connect - * function. - */ - static const char connect[] = -"local connect, socket_lock = ...;\n" -"return function(socket, ...)\n" -" repeat until socket_lock(socket) == true;\n" -" return connect(socket, ...);\n" -"end\n"; - static const char receive_buf[] = -"local function receive_buf (socket, fstr, keep)\n" -" local i, j;\n" -" local socket_uservalue = debug.getfenv(socket);\n" -" local buf = socket_uservalue[2];\n" -" if type(fstr) == 'function' then\n" -" i, j = fstr(buf);\n" -" elseif type(fstr) == 'string' then\n" -" i, j = string.find(buf, fstr)\n" -" end\n" -" if type(i) == 'number' and type(j) == 'number' then\n" -" if i > j or j > #buf then\n" -" error('invalid indices for match');\n" -" else\n" -" socket_uservalue[2] = string.sub(buf, j+1);\n" -" if keep then\n" -" return true, string.sub(buf, 1, j);\n" -" else\n" -" return true, string.sub(buf, 1, i-1);\n" -" end\n" -" end\n" -" else\n" -" local status, result = socket:receive();\n" -" if not status then return status, result end\n" -" socket_uservalue[2] = socket_uservalue[2]..result;\n" -" return receive_buf(socket, fstr, keep);\n" -" end\n" -"end\n" -"return receive_buf;\n"; - - static const luaL_Reg l_nsock[] = { + static const luaL_Reg metatable_index[] = { {"bind", l_bind}, - {"send", l_send}, - {"sendto", l_sendto}, - {"receive", l_receive}, - {"receive_lines", l_receive_lines}, - {"receive_bytes", l_receive_bytes}, - /* {"receive_buf", l_receive_buf}, Lua 5.2 */ - {"get_info", l_get_info}, {"close", l_close}, - {"set_timeout", l_set_timeout}, - {"reconnect_ssl", l_reconnect_ssl}, + {"connect", l_connect}, + {"get_info", l_get_info}, {"get_ssl_certificate", l_get_ssl_certificate}, {"pcap_open", l_pcap_open}, {"pcap_close", l_close}, {"pcap_receive", l_pcap_receive}, + {"send", l_send}, + {"sendto", l_sendto}, + {"receive", l_receive}, + {"receive_buf", l_receive_buf}, + {"receive_bytes", l_receive_bytes}, + {"receive_lines", l_receive_lines}, + {"reconnect_ssl", l_reconnect_ssl}, + {"set_timeout", l_set_timeout}, + {NULL, NULL} + }; + + static const luaL_Reg l_nsock[] = { + {"loop", l_loop}, + {"new", l_new}, + {"sleep", l_sleep}, {NULL, NULL} }; @@ -1106,58 +988,42 @@ LUALIB_API int luaopen_nsock (lua_State *L) * CONNECT_WAITING tables. * These values are accessed at the Lua pseudo-index LUA_ENVIRONINDEX. */ - lua_createtable(L, 3, 0); - lua_replace(L, LUA_ENVIRONINDEX); - - weak_table(L, 0, MAX_PARALLELISM, "k"); - lua_rawseti(L, LUA_ENVIRONINDEX, THREAD_SOCKETS); - - weak_table(L, 0, 1000, "k"); - lua_rawseti(L, LUA_ENVIRONINDEX, CONNECT_WAITING); - - weak_table(L, 0, 0, "v"); - lua_rawseti(L, LUA_ENVIRONINDEX, KEY_PCAP); - - lua_pushcfunction(L, loop); - lua_setfield(L, LUA_REGISTRYINDEX, NSE_NSOCK_LOOP); + int i; + int top = lua_gettop(L); - /* Load the connect function */ - if (luaL_loadstring(L, connect) != 0) - assert(0); - lua_pushcfunction(L, l_connect); - lua_pushcfunction(L, socket_lock); - lua_call(L, 2, 1); // leave connect function on stack... + /* library upvalues */ + nsock_pool nsp = new_pool(L); /* NSOCK_POOL */ + lua_newtable(L); /* NSOCK_SOCKET */ + lua_newtable(L); /* PCAP_SOCKET */ + nseU_weaktable(L, 0, MAX_PARALLELISM, "k"); /* THREAD_SOCKETS */ + nseU_weaktable(L, 0, 1000, "k"); /* CONNECT_WAITING */ + nseU_weaktable(L, 0, 0, "v"); /* KEY_PCAP */ /* Create the nsock metatable for sockets */ - luaL_newmetatable(L, NMAP_NSOCK_SOCKET); - lua_createtable(L, 0, 23); - luaL_register(L, NULL, l_nsock); - lua_pushvalue(L, -3); // connect function - lua_setfield(L, -2, "connect"); - if (luaL_dostring(L, receive_buf)) - assert(0); - lua_pushvalue(L, LUA_GLOBALSINDEX); - lua_setfenv(L, -2); - lua_setfield(L, -2, "receive_buf"); + lua_pushvalue(L, top+2); /* NSOCK_SOCKET */ + luaL_newlibtable(L, metatable_index); + for (i = top+1; i < top+1+6; i++) lua_pushvalue(L, i); + luaL_setfuncs(L, metatable_index, 6); lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, nsock_gc); + for (i = top+1; i < top+1+6; i++) lua_pushvalue(L, i); + lua_pushcclosure(L, nsock_gc, 6); lua_setfield(L, -2, "__gc"); lua_newtable(L); - lua_setfield(L, -2, "__metatable"); // protect metatable - lua_pop(L, 1); // nsock metatable + lua_setfield(L, -2, "__metatable"); /* protect metatable */ + lua_pop(L, 1); /* NSOCK_SOCKET */ /* Create the nsock pcap metatable */ - luaL_newmetatable(L, NMAP_NSOCK_PCAP_SOCKET); - lua_pushcfunction(L, pcap_gc); - lua_setfield(L, -2, "__gc"); - lua_pop(L, 1); + lua_pushvalue(L, top+3); /* PCAP_SOCKET */ + for (i = top+1; i < top+1+6; i++) lua_pushvalue(L, i); + lua_pushcclosure(L, pcap_gc, 6); + lua_setfield(L, top+3, "__gc"); + lua_pop(L, 1); /* PCAP_SOCKET */ #if HAVE_OPENSSL /* Set up the SSL certificate userdata code in nse_ssl_cert.cc. */ nse_nsock_init_ssl_cert(L); #endif - nsock_pool nsp = new_pool(L); if (o.scriptTrace()) nsp_settrace(nsp, NULL, NSOCK_TRACE_LEVEL, o.getStartTime()); #if HAVE_OPENSSL @@ -1165,5 +1031,9 @@ LUALIB_API int luaopen_nsock (lua_State *L) nsp_ssl_init_max_speed(nsp); #endif - return 0; + luaL_newlibtable(L, l_nsock); + for (i = top+1; i < top+1+6; i++) lua_pushvalue(L, i); + luaL_setfuncs(L, l_nsock, 6); + + return 1; } diff --git a/nse_nsock.h b/nse_nsock.h index 0193af1dcd..7cf2d69831 100644 --- a/nse_nsock.h +++ b/nse_nsock.h @@ -4,10 +4,5 @@ #include "nse_main.h" LUALIB_API int luaopen_nsock (lua_State *); -LUALIB_API int l_nsock_new (lua_State *); -LUALIB_API int l_nsock_sleep (lua_State *); - -#define NSE_NSOCK_LOOP "NSOCK_LOOP" #endif - diff --git a/nse_openssl.cc b/nse_openssl.cc index eaebe2051f..8ae596235b 100644 --- a/nse_openssl.cc +++ b/nse_openssl.cc @@ -472,7 +472,7 @@ static int l_DES_string_to_key(lua_State *L) /** DES_string_to_key( string data return 1; } -static const struct luaL_reg bignum_methods[] = { +static const struct luaL_Reg bignum_methods[] = { { "num_bits", l_bignum_num_bits }, { "num_bytes", l_bignum_num_bytes }, { "tobin", l_bignum_bn2bin }, @@ -486,7 +486,7 @@ static const struct luaL_reg bignum_methods[] = { { NULL, NULL } }; -static const struct luaL_reg openssllib[] = { +static const struct luaL_Reg openssllib[] = { { "bignum_num_bits", l_bignum_num_bits }, { "bignum_num_bytes", l_bignum_num_bytes }, { "bignum_set_bit", l_bignum_set_bit }, @@ -523,7 +523,7 @@ LUALIB_API int luaopen_openssl(lua_State *L) { OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); - luaL_register(L, OPENSSLLIBNAME, openssllib); + luaL_newlib(L, openssllib); // create metatable for bignum luaL_newmetatable( L, "BIGNUM" ); @@ -531,7 +531,7 @@ LUALIB_API int luaopen_openssl(lua_State *L) { lua_pushvalue( L, -1 ); lua_setfield( L, -2, "__index" ); // register methods - luaL_register( L, NULL, bignum_methods ); + luaL_setfuncs(L, bignum_methods, 0); lua_pop( L, 1 ); // BIGNUM diff --git a/nse_pcrelib.cc b/nse_pcrelib.cc index 4dd7daab05..2b37a4a88a 100644 --- a/nse_pcrelib.cc +++ b/nse_pcrelib.cc @@ -373,7 +373,7 @@ static int Lpcre_get_flags (lua_State *L) { return get_flags(L, pcre_flags); } -static const luaL_reg pcremeta[] = { +static const luaL_Reg pcremeta[] = { {"exec", Lpcre_exec}, {"match", Lpcre_match}, {"gmatch", Lpcre_gmatch}, @@ -383,7 +383,7 @@ static const luaL_reg pcremeta[] = { }; /* Open the library */ -static const luaL_reg pcrelib[] = { +static const luaL_Reg pcrelib[] = { {"new", Lpcre_comp}, {"flags", Lpcre_get_flags}, {"version", Lpcre_vers}, @@ -394,11 +394,11 @@ LUALIB_API int luaopen_pcrelib(lua_State *L) { luaL_newmetatable(L, pcre_handle); lua_pushliteral(L, "__index"); - lua_pushvalue(L, -2); + luaL_newlib(L, pcremeta); lua_rawset(L, -3); - luaL_register(L, NULL, pcremeta); lua_pop(L, 1); - luaL_register(L, NSE_PCRELIBNAME, pcrelib); + + luaL_newlib(L, pcrelib); return 1; } diff --git a/nse_ssl_cert.cc b/nse_ssl_cert.cc index c638856461..9156fd3703 100644 --- a/nse_ssl_cert.cc +++ b/nse_ssl_cert.cc @@ -149,7 +149,7 @@ static int ssl_cert_digest(lua_State *L) /* These are the contents of the table that is pointed to by the table that has ssl_cert_methods_index_ref as a reference. */ -static struct luaL_reg ssl_cert_methods[] = { +static struct luaL_Reg ssl_cert_methods[] = { { "digest", ssl_cert_digest }, { NULL, NULL }, }; @@ -173,7 +173,7 @@ static void obj_to_key(lua_State *L, const ASN1_OBJECT *obj) while ((n = OBJ_obj2txt(buf, size, obj, 1)) < 0 || (unsigned) n >= size) { size = size * 2; buf = (char *) lua_newuserdata(L, size); - memcpy(lua_touserdata(L, -1), lua_touserdata(L, -2), lua_objlen(L, -2)); + memcpy(lua_touserdata(L, -1), lua_touserdata(L, -2), lua_rawlen(L, -2)); lua_replace(L, -2); } @@ -495,7 +495,7 @@ void nse_nsock_init_ssl_cert(lua_State *L) global shared table of certificate functions. */ lua_newtable(L); lua_newtable(L); - luaL_register(L, NULL, ssl_cert_methods); + luaL_setfuncs(L, ssl_cert_methods, 0); lua_setfield(L, -2, "__index"); ssl_cert_methods_index_ref = luaL_ref(L, LUA_REGISTRYINDEX); } diff --git a/nse_utility.cc b/nse_utility.cc index 540b489342..50e1c92ea0 100644 --- a/nse_utility.cc +++ b/nse_utility.cc @@ -7,58 +7,68 @@ #include "nse_main.h" #include "nse_utility.h" -/* size_t table_length (lua_State *L, int index) - * - * Returns the length of the table at index index. - * This length is the number of elements, not just array elements. - */ -size_t table_length (lua_State *L, int index) +int nseU_traceback (lua_State *L) { - size_t len = 0; + if (lua_isstring(L, 1)) + luaL_traceback(L, L, lua_tostring(L, 1), 1); + return 1; +} - lua_pushvalue(L, index); +int nseU_placeholder (lua_State *L) +{ lua_pushnil(L); - while (lua_next(L, -2)) - { + return lua_error(L); +} + +size_t nseU_tablen (lua_State *L, int idx) +{ + size_t len = 0; + idx = lua_absindex(L, idx); + + for (lua_pushnil(L); lua_next(L, idx); lua_pop(L, 1)) len++; - lua_pop(L, 1); - } - lua_pop(L, 1); return len; } -void setsfield (lua_State *L, int idx, const char *field, const char *what) +void nseU_setsfield (lua_State *L, int idx, const char *field, const char *what) { - lua_pushvalue(L, idx); + idx = lua_absindex(L, idx); lua_pushstring(L, what); /* what can be NULL */ - lua_setfield(L, -2, field); - lua_pop(L, 1); + lua_setfield(L, idx, field); } -void setnfield (lua_State *L, int idx, const char *field, lua_Number n) +void nseU_setnfield (lua_State *L, int idx, const char *field, lua_Number n) { - lua_pushvalue(L, idx); + idx = lua_absindex(L, idx); lua_pushnumber(L, n); - lua_setfield(L, -2, field); - lua_pop(L, 1); + lua_setfield(L, idx, field); } -void setbfield (lua_State *L, int idx, const char *field, int b) +void nseU_setbfield (lua_State *L, int idx, const char *field, int b) { - lua_pushvalue(L, idx); + idx = lua_absindex(L, idx); lua_pushboolean(L, b); - lua_setfield(L, -2, field); - lua_pop(L, 1); + lua_setfield(L, idx, field); } -int success (lua_State *L) +void nseU_appendfstr (lua_State *L, int idx, const char *fmt, ...) +{ + va_list va; + idx = lua_absindex(L, idx); + va_start(va, fmt); + lua_pushvfstring(L, fmt, va); + va_end(va); + lua_rawseti(L, idx, lua_rawlen(L, idx)+1); +} + +int nseU_success (lua_State *L) { lua_pushboolean(L, true); return 1; } -int safe_error (lua_State *L, const char *fmt, ...) +int nseU_safeerror (lua_State *L, const char *fmt, ...) { va_list va; lua_pushboolean(L, false); @@ -68,7 +78,7 @@ int safe_error (lua_State *L, const char *fmt, ...) return 2; } -void weak_table (lua_State *L, int narr, int nrec, const char *mode) +void nseU_weaktable (lua_State *L, int narr, int nrec, const char *mode) { lua_createtable(L, narr, nrec); lua_createtable(L, 0, 1); @@ -77,14 +87,26 @@ void weak_table (lua_State *L, int narr, int nrec, const char *mode) lua_setmetatable(L, -2); } -/* const char *check_target (lua_State *L, int idx) - * - * Check for a valid target specification at index idx. - * This function checks for a string at idx or a table containing - * the typical host table fields, 'ip' and 'targetname' in particular. - */ -void check_target (lua_State *L, int idx, const char **address, const char **targetname) +void nseU_typeerror (lua_State *L, int idx, const char *type) +{ + const char *msg = lua_pushfstring(L, "%s expected, got %s", type, luaL_typename(L, idx)); + luaL_argerror(L, idx, msg); +} + +void *nseU_checkudata (lua_State *L, int idx, int upvalue, const char *name) +{ + idx = lua_absindex(L, idx); + + lua_getmetatable(L, idx); + if (!(lua_isuserdata(L, idx) && lua_rawequal(L, -1, upvalue))) + nseU_typeerror(L, idx, name); + lua_pop(L, 1); + return lua_touserdata(L, idx); +} + +void nseU_checktarget (lua_State *L, int idx, const char **address, const char **targetname) { + idx = lua_absindex(L, idx); if (lua_istable(L, idx)) { lua_getfield(L, idx, "ip"); *address = lua_tostring(L, -1); @@ -99,41 +121,34 @@ void check_target (lua_State *L, int idx, const char **address, const char **tar } } -/* unsigned short check_port (lua_State *L, int idx) - * - * Check for a valid port specification at index idx. - */ -unsigned short check_port (lua_State *L, int idx, const char **protocol) +uint16_t nseU_checkport (lua_State *L, int idx, const char **protocol) { - unsigned short port; + uint16_t port; + idx = lua_absindex(L, idx); if (lua_istable(L, idx)) { lua_getfield(L, idx, "number"); if (!lua_isnumber(L, -1)) luaL_argerror(L, idx, "port table lacks numeric 'number' field"); - port = (unsigned short) lua_tointeger(L, -1); + port = (uint16_t) lua_tointeger(L, -1); lua_getfield(L, idx, "protocol"); - *protocol = lua_tostring(L, -1); + if (lua_isstring(L, -1)) + *protocol = lua_tostring(L, -1); lua_pop(L, 2); } else { - port = (unsigned short) luaL_checkint(L, idx); + port = (uint16_t) luaL_checkint(L, idx); } return port; } -/* Target *get_target (lua_State *L, int index) - * - * This function checks the value at index for a valid host table. It locates - * the associated Target (C++) class object associated with the host and - * returns it. If the Target is not being scanned then an error will be raised. - */ -Target *get_target (lua_State *L, int index) +Target *nseU_gettarget (lua_State *L, int idx) { int top = lua_gettop(L); Target *target; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "targetname"); - lua_getfield(L, index, "ip"); + idx = lua_absindex(L, idx); + luaL_checktype(L, idx, LUA_TTABLE); + lua_getfield(L, idx, "targetname"); + lua_getfield(L, idx, "ip"); if (!(lua_isstring(L, -2) || lua_isstring(L, -1))) luaL_error(L, "host table does not have a 'ip' or 'targetname' field"); if (lua_isstring(L, -2)) /* targetname */ @@ -154,21 +169,16 @@ Target *get_target (lua_State *L, int index) return target; } -/* Target *get_port (lua_State *L, Target *target, Port *port, int index) - * - * This function checks the value at index for a valid port table. It locates - * the associated Port (C++) class object associated with the host and - * returns it. - */ -Port *get_port (lua_State *L, Target *target, Port *port, int index) +Port *nseU_getport (lua_State *L, Target *target, Port *port, int idx) { Port *p = NULL; int portno, protocol; - luaL_checktype(L, index, LUA_TTABLE); - lua_getfield(L, index, "number"); + idx = lua_absindex(L, idx); + luaL_checktype(L, idx, LUA_TTABLE); + lua_getfield(L, idx, "number"); if (!lua_isnumber(L, -1)) luaL_error(L, "port 'number' field must be a number"); - lua_getfield(L, index, "protocol"); + lua_getfield(L, idx, "protocol"); if (!lua_isstring(L, -1)) luaL_error(L, "port 'protocol' field must be a string"); portno = (int) lua_tointeger(L, -2); diff --git a/nse_utility.h b/nse_utility.h index b8d0d76819..9ff2d039d8 100644 --- a/nse_utility.h +++ b/nse_utility.h @@ -1,19 +1,138 @@ #ifndef NMAP_NSE_UTILITY_H #define NMAP_NSE_UTILITY_H -size_t table_length (lua_State *, int); -void setsfield (lua_State *, int, const char *, const char *); -void setnfield (lua_State *, int, const char *, lua_Number); -void setbfield (lua_State *, int, const char *, int); -void weak_table (lua_State *, int, int, const char *); +#include "portlist.h" -int success (lua_State *); -int safe_error (lua_State *, const char *, ...); +#include -void check_target (lua_State *, int, const char **, const char **); -unsigned short check_port (lua_State *, int, const char **); +/* int nseU_traceback (lua_State *L) + * + * Traceback C Lua function. + */ +int nseU_traceback (lua_State *L); -Target *get_target (lua_State *, int); -Port *get_port (lua_State *, Target *, Port *, int); +/* int nseU_placeholder (lua_State *L) + * + * Placeholder C Lua function that simply throws a nil error. + */ +int nseU_placeholder (lua_State *L); + +/* void nseU_tablen (lua_State *L, int idx) [-0, +0, -] + * + * Calculates the number of entries in the table by iterating over + * each key/value pair. + */ +size_t nseU_tablen (lua_State *L, int idx); + +/* void nseU_setsfield (lua_State *L, int idx, [-0, +0, e] + * const char *field, const char *value) + * + * Sets the field for table at index idx to string value. + * (t[field] = value). + */ +void nseU_setsfield (lua_State *L, int idx, const char *field, const char *value); + +/* void nseU_setnfield (lua_State *L, int idx, [-0, +0, e] + * const char *field, lua_Number value) + * + * Sets the field for table at index idx to numerical value. + * (t[field] = value). + */ +void nseU_setnfield (lua_State *L, int idx, const char *field, lua_Number value); + +/* void nseU_setbfield (lua_State *L, int idx, [-0, +0, e] + * const char *field, int value) + * + * Sets the field for table at index idx to boolean value. + * (t[field] = value). + */ +void nseU_setbfield (lua_State *L, int idx, const char *field, int value); + +/* void nseU_appendfstr (lua_State *L, int idx, [-0, +0, m] + * const char *fmt, ...) + * + * Appends the formatted string to the table at index idx. + */ +void nseU_appendfstr (lua_State *L, int idx, const char *fmt, ...); + +/* void nseU_weaktable (lua_State *L, int narr, int nrec, [-0, +1, e] + * const char *mode) + * + * Creates a table using lua_createtable with sizes narr and nrec. Creates + * a metatable with its __mode field set to mode. + */ +void nseU_weaktable (lua_State *L, int narr, int nrec, const char *mode); + +/* int nseU_success (lua_State *L) [-0, +1, -] + * + * Indicates successful return of the running function by pushing + * boolean true and returning 1. Use as a tail call: + * return nseU_success(L); + */ +int nseU_success (lua_State *L); + +/* int nseU_safeerror (lua_State *L, const char *fmt, ...) [-0, +1, -] + * + * Indicates unsuccessful return of the running function by pushing + * boolean false and and a formatted error message. Use as a tail call: + * return nseU_safeerror(L, "%s", "a generic error"); + */ +int nseU_safeerror (lua_State *L, const char *fmt, ...); + +/* void nseU_typeerror (lua_State *L, int idx, [-0, +1, v] + * const char *err) + * + * Raises a type error. Same as Lua 5.1. + */ +void nseU_typeerror (lua_State *L, int idx, const char *err); + +/* void *nseU_checkudata (lua_State *L, int idx, [-0, +0, v] + * int upvalue, const char *name) + * + * Checks that value at index idx is a full userdata which a metatable + * equal to upvalue. name is the name of your object for error message + * purposes. + */ +void *nseU_checkudata (lua_State *L, int idx, int upvalue, const char *name); + +/* void nseU_checktarget (lua_State *L, int idx, [-0, +0, v] + * const char **address, + * const char **targetname) + * + * Check for a valid target specification at index idx. This function checks + * for a string at idx or a table containing the typical host table fields, + * 'ip' and 'targetname' in particular. + * + * The address and targetname string pointers are only valid if the target + * specification persists. + */ +void nseU_checktarget (lua_State *L, int idx, const char **address, const char **targetname); + +/* uint16_t nseU_checkport (lua_State *L, int idx, [-0, +0, v] + * const char **protocol) + * + * Check for a valid port specification at index idx. + * + * The protocol string pointer is only valid if the port specification + * persists. + */ +uint16_t nseU_checkport (lua_State *L, int idx, const char **protocol); + +/* Target *nseU_gettarget (lua_State *L, int idx) [-0, +0, v] + * + * This function checks the value at index for a valid host table. It locates + * the associated Target (C++) class object associated with the host and + * returns it. If the Target is not being scanned then an error will be raised. + */ +Target *nseU_gettarget (lua_State *L, int idx); + +/* Port *nseU_getport (lua_State *L, Target *target, [-0, +0, v] + * Port *port, int idx) + * + * This function checks the value at index for a valid port table. It locates + * the associated Port (C++) class object associated with the host and + * returns it. + */ +Port *nseU_getport (lua_State *L, Target *target, Port *port, int idx); #endif diff --git a/nselib/afp.lua b/nselib/afp.lua index df114e32f4..75cf0f7224 100644 --- a/nselib/afp.lua +++ b/nselib/afp.lua @@ -111,7 +111,15 @@ -- Revised 04/03/2011 - v0.6 - add support for getting file- sizes, dates and Unix ACLs -- - moved afp.username & afp.password arguments to library -module(... or "afp",package.seeall) +local bin = require "bin" +local bit = require "bit" +local nmap = require "nmap" +local openssl = require "openssl" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("afp", stdnse.seeall); local HAVE_SSL = false @@ -805,7 +813,7 @@ Proto = { local data_offset = 0 local flags = 1 -- Default User local uid = 0 - local bitmap = afp.USER_BITMAP.UserId + local bitmap = USER_BITMAP.UserId local result = {} local data = bin.pack( "CCI>S", COMMAND.FPGetUserInfo, flags, uid, bitmap ) @@ -1359,7 +1367,7 @@ Helper = { return false, "Socket connection failed" end - self.proto = afp.Proto:new( { socket=self.socket} ) + self.proto = Proto:new( { socket=self.socket} ) response = self.proto:dsi_open_session(self.socket) if response:getErrorCode() ~= ERROR.FPNoErr then @@ -1432,11 +1440,11 @@ Helper = { WalkDirTree = function( self, str_path ) local status, response, path local elements = stdnse.strsplit( "/", str_path ) - local f_bm = afp.FILE_BITMAP.NodeId + afp.FILE_BITMAP.ParentDirId + afp.FILE_BITMAP.LongName - local d_bm = afp.DIR_BITMAP.NodeId + afp.DIR_BITMAP.ParentDirId + afp.DIR_BITMAP.LongName + local f_bm = FILE_BITMAP.NodeId + FILE_BITMAP.ParentDirId + FILE_BITMAP.LongName + local d_bm = DIR_BITMAP.NodeId + DIR_BITMAP.ParentDirId + DIR_BITMAP.LongName local item = { DirectoryId = 2 } - response = self.proto:fp_open_vol( afp.VOL_BITMAP.ID, elements[1] ) + response = self.proto:fp_open_vol( VOL_BITMAP.ID, elements[1] ) if response:getErrorCode() ~= ERROR.FPNoErr then return false, response:getErrorMessage() end @@ -1445,7 +1453,7 @@ Helper = { item.DirectoryName = str_path for i=2, #elements do - path = { ['type']=afp.PATH_TYPE.LongName, name=elements[i], len=elements[i]:len() } + path = { ['type']=PATH_TYPE.LongName, name=elements[i], len=elements[i]:len() } response = self.proto:fp_get_file_dir_parms( item.VolumeId, item.DirectoryId, f_bm, d_bm, path ) if response:getErrorCode() ~= ERROR.FPNoErr then return false, response:getErrorMessage() @@ -1476,9 +1484,9 @@ Helper = { vol_id = response.VolumeId did = response.DirectoryId - path = { ['type']=afp.PATH_TYPE.LongName, name=p.file, len=p.file:len() } + path = { ['type']=PATH_TYPE.LongName, name=p.file, len=p.file:len() } - response = self.proto:fp_open_fork(0, vol_id, did, 0, afp.ACCESS_MODE.Read, path ) + response = self.proto:fp_open_fork(0, vol_id, did, 0, ACCESS_MODE.Read, path ) if response:getErrorCode() ~= ERROR.FPNoErr then return false, response:getErrorMessage() end @@ -1523,7 +1531,7 @@ Helper = { return false, response end - path = { ['type']=afp.PATH_TYPE.LongName, name=p.file, len=p.file:len() } + path = { ['type']=PATH_TYPE.LongName, name=p.file, len=p.file:len() } status, response = self.proto:fp_create_file( 0, vol_id, did, path ) if not status then @@ -1532,7 +1540,7 @@ Helper = { end end - response = self.proto:fp_open_fork( 0, vol_id, did, 0, afp.ACCESS_MODE.Write, path ) + response = self.proto:fp_open_fork( 0, vol_id, did, 0, ACCESS_MODE.Write, path ) if response:getErrorCode() ~= ERROR.FPNoErr then return false, response:getErrorMessage() end @@ -1601,9 +1609,9 @@ Helper = { local depth = depth or 1 local options = options or { max_depth = 1 } local response, records - local f_bm = afp.FILE_BITMAP.NodeId + afp.FILE_BITMAP.ParentDirId + afp.FILE_BITMAP.LongName - local d_bm = afp.DIR_BITMAP.NodeId + afp.DIR_BITMAP.ParentDirId + afp.DIR_BITMAP.LongName - local path = { ['type']=afp.PATH_TYPE.LongName, name="", len=0 } + local f_bm = FILE_BITMAP.NodeId + FILE_BITMAP.ParentDirId + FILE_BITMAP.LongName + local d_bm = DIR_BITMAP.NodeId + DIR_BITMAP.ParentDirId + DIR_BITMAP.LongName + local path = { ['type']=PATH_TYPE.LongName, name="", len=0 } local TYPE_DIR = 0x80 @@ -1685,14 +1693,14 @@ Helper = { GetSharePermissions = function( self, vol_name ) local status, response, vol_id, acls - response = self.proto:fp_open_vol( afp.VOL_BITMAP.ID, vol_name ) + response = self.proto:fp_open_vol( VOL_BITMAP.ID, vol_name ) if response:getErrorCode() == ERROR.FPNoErr then local vol_id local path = {} vol_id = response.result.volume_id - path.type = afp.PATH_TYPE.LongName + path.type = PATH_TYPE.LongName path.name = "" path.len = path.name:len() @@ -1720,14 +1728,14 @@ Helper = { -- eg: drwx------ -- @return err string (on failure) containing the error message GetFileUnixPermissions = function(self, vol_name, str_path) - local response = self.proto:fp_open_vol( afp.VOL_BITMAP.ID, vol_name ) + local response = self.proto:fp_open_vol( VOL_BITMAP.ID, vol_name ) if ( response:getErrorCode() ~= ERROR.FPNoErr ) then return false, response:getErrorMessage() end local vol_id = response.result.volume_id - local path = { type = afp.PATH_TYPE.LongName, name = str_path, len = #str_path } + local path = { type = PATH_TYPE.LongName, name = str_path, len = #str_path } response = self.proto:fp_get_file_dir_parms( vol_id, 2, FILE_BITMAP.UnixPrivileges, DIR_BITMAP.UnixPrivileges, path ) if ( response:getErrorCode() ~= ERROR.FPNoErr ) then return false, response:getErrorMessage() @@ -1752,14 +1760,14 @@ Helper = { -- @return size containing the size of the file in bytes -- @return err string (on failure) containing the error message GetFileSize = function( self, vol_name, str_path ) - local response = self.proto:fp_open_vol( afp.VOL_BITMAP.ID, vol_name ) + local response = self.proto:fp_open_vol( VOL_BITMAP.ID, vol_name ) if ( response:getErrorCode() ~= ERROR.FPNoErr ) then return false, response:getErrorMessage() end local vol_id = response.result.volume_id - local path = { type = afp.PATH_TYPE.LongName, name = str_path, len = #str_path } + local path = { type = PATH_TYPE.LongName, name = str_path, len = #str_path } response = self.proto:fp_get_file_dir_parms( vol_id, 2, FILE_BITMAP.ExtendedDataForkSize, 0, path ) if ( response:getErrorCode() ~= ERROR.FPNoErr ) then return false, response:getErrorMessage() @@ -1781,14 +1789,14 @@ Helper = { -- backup - Date of last backup -- @return err string (on failure) containing the error message GetFileDates = function( self, vol_name, str_path ) - local response = self.proto:fp_open_vol( afp.VOL_BITMAP.ID, vol_name ) + local response = self.proto:fp_open_vol( VOL_BITMAP.ID, vol_name ) if ( response:getErrorCode() ~= ERROR.FPNoErr ) then return false, response:getErrorMessage() end local vol_id = response.result.volume_id - local path = { type = afp.PATH_TYPE.LongName, name = str_path, len = #str_path } + local path = { type = PATH_TYPE.LongName, name = str_path, len = #str_path } local f_bm = FILE_BITMAP.CreationDate + FILE_BITMAP.ModificationDate + FILE_BITMAP.BackupDate local d_bm = DIR_BITMAP.CreationDate + DIR_BITMAP.ModificationDate + DIR_BITMAP.BackupDate response = self.proto:fp_get_file_dir_parms( vol_id, 2, f_bm, d_bm, path ) @@ -1814,7 +1822,7 @@ Helper = { CreateDir = function( self, str_path ) local status, response, vol_id, did local p = Util.SplitPath( str_path ) - local path = { ['type']=afp.PATH_TYPE.LongName, name=p.file, len=p.file:len() } + local path = { ['type']=PATH_TYPE.LongName, name=p.file, len=p.file:len() } status, response = self:WalkDirTree( p.dir ) @@ -1881,15 +1889,15 @@ Util = local acl_table = {} - if bit.band( acls, afp.ACLS.OwnerSearch ) == afp.ACLS.OwnerSearch then + if bit.band( acls, ACLS.OwnerSearch ) == ACLS.OwnerSearch then table.insert( acl_table, "Search") end - if bit.band( acls, afp.ACLS.OwnerRead ) == afp.ACLS.OwnerRead then + if bit.band( acls, ACLS.OwnerRead ) == ACLS.OwnerRead then table.insert( acl_table, "Read") end - if bit.band( acls, afp.ACLS.OwnerWrite ) == afp.ACLS.OwnerWrite then + if bit.band( acls, ACLS.OwnerWrite ) == ACLS.OwnerWrite then table.insert( acl_table, "Write") end @@ -1908,8 +1916,8 @@ Util = local everyone = Util.acl_group_to_long_string( bit.band( bit.rshift(acls, 16), 255 ) ) local user = Util.acl_group_to_long_string( bit.band( bit.rshift(acls, 24), 255 ) ) - local blank = bit.band( acls, afp.ACLS.BlankAccess ) == afp.ACLS.BlankAccess and "Blank" or nil - local isowner = bit.band( acls, afp.ACLS.UserIsOwner ) == afp.ACLS.UserIsOwner and "IsOwner" or nil + local blank = bit.band( acls, ACLS.BlankAccess ) == ACLS.BlankAccess and "Blank" or nil + local isowner = bit.band( acls, ACLS.UserIsOwner ) == ACLS.UserIsOwner and "IsOwner" or nil local options = {} @@ -2111,3 +2119,5 @@ Util = + +return _ENV; diff --git a/nselib/ajp.lua b/nselib/ajp.lua index fb5318a5c4..cd9a2f3469 100644 --- a/nselib/ajp.lua +++ b/nselib/ajp.lua @@ -1,15 +1,20 @@ +local base64 = require "base64" +local bin = require "bin" +local http = require "http" +local match = require "match" +local nmap = require "nmap" +local package = require "package" +local stdnse = require "stdnse" +local table = require "table" +local url = require "url" +_ENV = stdnse.module("ajp", stdnse.seeall) + --- -- A basic AJP 1.3 implementation based on documentation available from Apache -- mod_proxy_ajp; http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html -- -- @author "Patrik Karlsson " -- -module(... or "ajp",package.seeall) - -local bin = require('bin') -local http = require('http') -local match = require('match') -local url = require('url') AJP = { @@ -515,4 +520,4 @@ Helper = { return self.comm:close() end, -} \ No newline at end of file +} diff --git a/nselib/amqp.lua b/nselib/amqp.lua index 745e41f83a..17f2d6d84b 100644 --- a/nselib/amqp.lua +++ b/nselib/amqp.lua @@ -23,10 +23,13 @@ -- Created 05/04/2011 - v0.1 - created by Sebastian Dragomir -module(... or "amqp", package.seeall) +local bin = require "bin" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("amqp", stdnse.seeall); -require "bin" -require "stdnse" AMQP = { @@ -396,3 +399,5 @@ AMQPSocket = return self.Socket:send( data ) end, } + +return _ENV; diff --git a/nselib/asn1.lua b/nselib/asn1.lua index e96956b793..113a8a6d3f 100644 --- a/nselib/asn1.lua +++ b/nselib/asn1.lua @@ -15,9 +15,13 @@ -- o Each script or library should now create it's own Encoder and Decoder instance -- -module(... or "asn1",package.seeall) - -require("bit") +local bin = require "bin" +local bit = require "bit" +local math = require "math" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("asn1", stdnse.seeall) BERCLASS = { Universal = 0, @@ -471,3 +475,5 @@ function intToBER( i ) end + +return _ENV; diff --git a/nselib/base64.lua b/nselib/base64.lua index bef7eceb93..706a1082a7 100644 --- a/nselib/base64.lua +++ b/nselib/base64.lua @@ -6,9 +6,11 @@ -- thanks to Patrick Donnelly for some optimizations -module(... or "base64",package.seeall) - -require 'bin' +local bin = require "bin" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("base64", stdnse.seeall) -- todo: make metatable/index --> '' for b64dctable @@ -176,3 +178,5 @@ function dec(b64data) return concat(bdataBuf) end + +return _ENV; diff --git a/nselib/bitcoin.lua b/nselib/bitcoin.lua index cdb414ed7b..11084abfcb 100644 --- a/nselib/bitcoin.lua +++ b/nselib/bitcoin.lua @@ -32,11 +32,15 @@ -- - changed version/verack handling to support -- February 20th 2012 bitcoin protocol switchover -module(... or "bitcoin", package.seeall) - -require 'ipOps' +local bin = require "bin" +local ipOps = require "ipOps" +local nmap = require "nmap" +local openssl = require "openssl" +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" stdnse.silent_require('openssl') - +_ENV = stdnse.module("bitcoin", stdnse.seeall) -- A class that supports the BitCoin network address structure NetworkAddress = { @@ -623,3 +627,5 @@ Helper = { return self.socket:close() end } + +return _ENV; diff --git a/nselib/bittorrent.lua b/nselib/bittorrent.lua index b8435080a6..a10be34a93 100644 --- a/nselib/bittorrent.lua +++ b/nselib/bittorrent.lua @@ -88,15 +88,20 @@ -- structure is not supported by Lua, so I had to use lists to represent -- the dictionaries as well which made accessing the keys a bit quirky -module(... or "bittorrent", package.seeall) - -require "nmap" -require "stdnse" -require "http" -require "openssl" -require "url" -require "bit" -require "bin" +local bin = require "bin" +local bit = require "bit" +local coroutine = require "coroutine" +local http = require "http" +local io = require "io" +local math = require "math" +local nmap = require "nmap" +local openssl = require "openssl" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local url = require "url" +_ENV = stdnse.module("bittorrent", stdnse.seeall) --- Given a buffer and a starting position in the buffer, this function decodes -- a bencoded string there and returns it as a normal lua string, as well as @@ -1237,3 +1242,5 @@ Torrent = } + +return _ENV; diff --git a/nselib/brute.lua b/nselib/brute.lua index 6a1dc9466d..b2d3062e2b 100644 --- a/nselib/brute.lua +++ b/nselib/brute.lua @@ -191,10 +191,15 @@ -- as password per default, as suggested by the -- documentation. -module(... or "brute", package.seeall) -require 'unpwdb' -require 'datafiles' -require 'creds' +local coroutine = require "coroutine" +local creds = require "creds" +local io = require "io" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" +local unpwdb = require "unpwdb" +_ENV = stdnse.module("brute", stdnse.seeall) -- Engine options that can be set by scripts -- Supported options are: @@ -911,3 +916,5 @@ Iterators = { end, } + +return _ENV; diff --git a/nselib/citrixxml.lua b/nselib/citrixxml.lua index 5060204bdc..3f366ec287 100644 --- a/nselib/citrixxml.lua +++ b/nselib/citrixxml.lua @@ -17,9 +17,12 @@ -- -require 'http' -module(... or "citrixxml",package.seeall) +local http = require "http" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("citrixxml", stdnse.seeall) --- Decodes html-entities to chars eg. => -- @@ -35,7 +38,7 @@ function decode_xml_document(xmldata) local newstr = xmldata - for m in xmldata:gmatch("(\&\#%d+;)") do + for m in xmldata:gmatch("(&#%d+;)") do hexval = m:match("(%d+)") if ( hexval ) then @@ -96,7 +99,7 @@ function parse_server_farm_data_response( response ) local farms = {} response = response:gsub("\r?\n","") - for farm in response:gmatch("([^\<]+)") do + for farm in response:gmatch("([^<]+)") do table.insert(farms, farm) end @@ -333,7 +336,7 @@ function parse_server_data_response(response) local servers = {} response = response:gsub("\r?\n","") - for s in response:gmatch("([^\<]+)") do + for s in response:gmatch("([^<]+)") do table.insert(servers, s) end @@ -403,7 +406,7 @@ function parse_capabilities_response(response) local servers = {} response = response:gsub("\r?\n","") - for s in response:gmatch("([^\<]+)") do + for s in response:gmatch("([^<]+)") do table.insert(servers, s) end @@ -532,3 +535,5 @@ function request_reconnect_session_data(host, port, params) end + +return _ENV; diff --git a/nselib/comm.lua b/nselib/comm.lua index 52e055c6b6..625b8a3672 100644 --- a/nselib/comm.lua +++ b/nselib/comm.lua @@ -20,10 +20,9 @@ -- @author Kris Katterjohn 04/2008 -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "comm", package.seeall) - -require 'nsedebug' -require 'datafiles' +local nmap = require "nmap" +local stdnse = require "stdnse" +_ENV = stdnse.module("comm", stdnse.seeall) -- Makes sure that opts exists and the default proto is there local initopts = function(opts) @@ -269,3 +268,5 @@ function tryssl(host, port, data, opts) if not sd then best = "none" end return sd, response, best, early_resp end + +return _ENV; diff --git a/nselib/creds.lua b/nselib/creds.lua index 120ce3f6d1..de74971a63 100644 --- a/nselib/creds.lua +++ b/nselib/creds.lua @@ -92,10 +92,15 @@ -- * added saveToFile function for saving credential -- * table to file in CSV or text formats -module(... or "creds", package.seeall) +local bit = require "bit" +local coroutine = require "coroutine" +local io = require "io" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("creds", stdnse.seeall) -require('ipOps') -require('bit') -- Table containing the different account states State = { @@ -423,3 +428,5 @@ Credentials = { end, } + +return _ENV; diff --git a/nselib/cvs.lua b/nselib/cvs.lua index 4cf9efe37b..76f6fa9261 100644 --- a/nselib/cvs.lua +++ b/nselib/cvs.lua @@ -9,7 +9,11 @@ -- Created 07/13/2011 - v0.1 - created by Patrik Karlsson -module(... or "cvs", package.seeall) +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("cvs", stdnse.seeall) Helper = { @@ -90,3 +94,5 @@ Util = { end } + +return _ENV; diff --git a/nselib/datafiles.lua b/nselib/datafiles.lua index 7b1b950ac4..d88149df76 100644 --- a/nselib/datafiles.lua +++ b/nselib/datafiles.lua @@ -10,9 +10,11 @@ -- @author jah 08/2008 -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "datafiles", package.seeall) - +local io = require "io" +local nmap = require "nmap" local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("datafiles", stdnse.seeall) --- @@ -167,7 +169,7 @@ function parse_file(filename, ...) if not status then return false, ret[#ret] end end - return true, unpack( ret ) + return true, table.unpack( ret ) end @@ -305,3 +307,5 @@ get_assoc_array = function(lines, i_pattern, v_pattern) end return ret end + +return _ENV; diff --git a/nselib/dhcp.lua b/nselib/dhcp.lua index 33d0169c6b..19654179c1 100644 --- a/nselib/dhcp.lua +++ b/nselib/dhcp.lua @@ -14,12 +14,15 @@ -- o Added possibility to ovverride transaction id -- o Added WPAD action -module(... or "dhcp", package.seeall) +local bin = require "bin" +local ipOps = require "ipOps" +local math = require "math" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("dhcp", stdnse.seeall) -require 'bin' -require 'bit' -require 'ipOps' -require 'stdnse' request_types = { @@ -652,3 +655,5 @@ function make_request(target, request_type, ip_address, mac_address, options, re return true, parsed end + +return _ENV; diff --git a/nselib/dhcp6.lua b/nselib/dhcp6.lua index c8e84b86fa..65ff26db90 100644 --- a/nselib/dhcp6.lua +++ b/nselib/dhcp6.lua @@ -20,11 +20,16 @@ -- -- @author "Patrik Karlsson " -- -module(... or "dhcp6", package.seeall) -require 'bin' -require 'bit' -require 'ipOps' +local bin = require "bin" +local bit = require "bit" +local ipOps = require "ipOps" +local math = require "math" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("dhcp6", stdnse.seeall) DHCP6 = {} @@ -616,3 +621,5 @@ Helper = { end, } + +return _ENV; diff --git a/nselib/dns.lua b/nselib/dns.lua index 237bb4de18..8fa8965f9c 100644 --- a/nselib/dns.lua +++ b/nselib/dns.lua @@ -29,15 +29,19 @@ -- -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "dns", package.seeall) -require("bit") -require("ipOps") -require("stdnse") +local bin = require "bin" +local bit = require "bit" +local coroutine = require "coroutine" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("dns", stdnse.seeall) get_servers = nmap.get_dns_servers - --- -- Table of DNS resource types. -- @name types @@ -1475,3 +1479,5 @@ function update(dname, options) end return false end + +return _ENV; diff --git a/nselib/dnsbl.lua b/nselib/dnsbl.lua index f97e7fb8cf..5f403c5d28 100644 --- a/nselib/dnsbl.lua +++ b/nselib/dnsbl.lua @@ -18,10 +18,16 @@ -- @author "Patrik Karlsson " -- -module(... or "dnsbl", package.seeall) +local bit = require "bit" +local coroutine = require "coroutine" +local dns = require "dns" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("dnsbl", stdnse.seeall) -require 'bit' -require 'ipOps' -- The services table contains a list of valid DNSBL providers -- Providers are categorized in categories that should contain services that @@ -453,7 +459,7 @@ SERVICES = { return end - local octet1, octet2, octet3, octet4 = unpack(parts) + local octet1, octet2, octet3, octet4 = table.unpack(parts) if ( octet1 ~= 127 ) then -- This should'nt happen :P @@ -719,3 +725,5 @@ Helper = { end, } + +return _ENV; diff --git a/nselib/dnssd.lua b/nselib/dnssd.lua index fcc8898ed7..a4ff45da21 100644 --- a/nselib/dnssd.lua +++ b/nselib/dnssd.lua @@ -37,11 +37,15 @@ -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -- -module(... or "dnssd", package.seeall) - -require 'dns' -require 'target' -require 'ipOps' +local coroutine = require "coroutine" +local dns = require "dns" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" +_ENV = stdnse.module("dnssd", stdnse.seeall) Util = { @@ -387,4 +391,6 @@ Helper = { return true, result end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/drda.lua b/nselib/drda.lua index a896d3201f..e1a5de09c0 100644 --- a/nselib/drda.lua +++ b/nselib/drda.lua @@ -58,9 +58,13 @@ -- x Apache Derby -- x IBM Informix Dynamic Server -module(... or "drda", package.seeall) - -require "bin" +local bin = require "bin" +local bit = require "bit" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("drda", stdnse.seeall) -- CodePoint constants CodePoint = { @@ -887,3 +891,5 @@ StringUtil = return str end, } + +return _ENV; diff --git a/nselib/eap.lua b/nselib/eap.lua index 97553c07c5..a7586cff20 100644 --- a/nselib/eap.lua +++ b/nselib/eap.lua @@ -31,15 +31,16 @@ -- @author "Riccardo Cecolin " -- -module(... or "eap", package.seeall) +local bin = require "bin" +local math = require "math" +local nmap = require "nmap" +local package = require "package" +local packet = require "packet" +local stdnse = require "stdnse" +_ENV = stdnse.module("eap", stdnse.seeall) -- Created 02/23/2012 - v0.1 -require 'nmap' -require 'packet' -require 'bin' - - local ETHER_BROADCAST = "01:80:c2:00:00:03" local ETHER_TYPE_EAPOL_N = 0x888E local ETHER_TYPE_EAPOL = bin.pack(">S",ETHER_TYPE_EAPOL_N) @@ -246,7 +247,7 @@ send_identity_response = function (iface, id, identity) end local dnet = nmap.new_dnet() - local tb = {src = iface.mac, type = eap.eapol_t.PACKET} + local tb = {src = iface.mac, type = eapol_t.PACKET} local response = make_eap{header = tb, code = code_t.RESPONSE, type = eap_t.IDENTITY, id = id, payload = identity} dnet:ethernet_open(iface.device) @@ -262,7 +263,7 @@ send_nak_response = function (iface, id, auth) end local dnet = nmap.new_dnet() - local tb = {src = iface.mac, type = eap.eapol_t.PACKET} + local tb = {src = iface.mac, type = eapol_t.PACKET} local response = make_eap{header = tb, code = code_t.RESPONSE, type = eap_t.NAK, id = id, payload = bin.pack("C",auth)} dnet:ethernet_open(iface.device) @@ -279,10 +280,12 @@ send_start = function (iface) end local dnet = nmap.new_dnet() - local start = make_eapol{type = eap.eapol_t.START, src = iface.mac} + local start = make_eapol{type = eapol_t.START, src = iface.mac} dnet:ethernet_open(iface.device) dnet:ethernet_send(start) dnet:ethernet_close() end + +return _ENV; diff --git a/nselib/ftp.lua b/nselib/ftp.lua index 3d0e7c5d68..f8bfe92b23 100644 --- a/nselib/ftp.lua +++ b/nselib/ftp.lua @@ -3,10 +3,10 @@ -- -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "ftp", package.seeall) - -local comm = require 'comm' -local stdnse = require 'stdnse' +local comm = require "comm" +local stdnse = require "stdnse" +local string = require "string" +_ENV = stdnse.module("ftp", stdnse.seeall) local ERROR_MESSAGES = { ["EOF"] = "connection closed", @@ -77,3 +77,5 @@ function read_reply(buffer) return nil, string.format("Unparseable response: %q", line) end + +return _ENV; diff --git a/nselib/giop.lua b/nselib/giop.lua index eb68be1593..277a8fb97a 100644 --- a/nselib/giop.lua +++ b/nselib/giop.lua @@ -57,7 +57,12 @@ -- Created 08/07/2010 - v0.1 - created by Patrik Karlsson -- -module(... or "giop", package.seeall) +local bin = require "bin" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("giop", stdnse.seeall) -- A bunch of constants Constants = { @@ -695,4 +700,6 @@ Helper = { return true end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/gps.lua b/nselib/gps.lua index be56d85bdf..1266666ccc 100644 --- a/nselib/gps.lua +++ b/nselib/gps.lua @@ -1,3 +1,10 @@ +local bit = require "bit" +local os = require "os" +local package = require "package" +local stdnse = require "stdnse" +local string = require "string" +_ENV = stdnse.module("gps", stdnse.seeall) + --- -- A smallish gps parsing module. -- Currently does GPRMC NMEA decoding @@ -6,10 +13,6 @@ -- -- -module(... or "gps", package.seeall) - -local bit = require('bit') - NMEA = { -- Parser for the RMC sentence diff --git a/nselib/http.lua b/nselib/http.lua index ff45a61b0e..e37b40615f 100644 --- a/nselib/http.lua +++ b/nselib/http.lua @@ -98,16 +98,18 @@ -- Implement cache system for http pipelines -- -local coroutine = require "coroutine"; -local table = require "table"; -local base64 = require "base64"; -local nmap = require "nmap"; -local url = require "url"; -local stdnse = require "stdnse"; -local comm = require "comm"; - -module(... or "http",package.seeall) +local base64 = require "base64" +local comm = require "comm" +local coroutine = require "coroutine" +local nmap = require "nmap" +local openssl = require "openssl" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local url = require "url" +_ENV = stdnse.module("http", stdnse.seeall) ---Use ssl if we have it local have_ssl = (nmap.have_ssl() and pcall(require, "openssl")) @@ -1920,7 +1922,7 @@ function can_use_head(host, port, result_404, path) end -- Perform a HEAD request and see what happens. - local data = http.head( host, port, path ) + local data = head( host, port, path ) if data then if data.status and data.status == 302 and data.header and data.header.location then stdnse.print_debug(1, "HTTP: Warning: Host returned 302 and not 200 when performing HEAD.") @@ -2030,7 +2032,7 @@ function identify_404(host, port) local URL_404_2 = '/NmapUpperCheck' .. os.time(os.date('*t')) local URL_404_3 = '/Nmap/folder/check' .. os.time(os.date('*t')) - data = http.get(host, port, URL_404_1) + data = get(host, port, URL_404_1) if(data == nil) then stdnse.print_debug(1, "HTTP: Failed while testing for 404 status code") @@ -2048,8 +2050,8 @@ function identify_404(host, port) -- Clean up the body (for example, remove the URI). This makes it easier to validate later if(data.body) then -- Obtain a couple more 404 pages to test different conditions - local data2 = http.get(host, port, URL_404_2) - local data3 = http.get(host, port, URL_404_3) + local data2 = get(host, port, URL_404_2) + local data3 = get(host, port, URL_404_3) if(data2 == nil or data3 == nil) then stdnse.print_debug(1, "HTTP: Failed while testing for extra 404 error messages") return false, "Failed while testing for extra 404 error messages" @@ -2283,7 +2285,7 @@ function parse_url(url) result['querystring'] = {} local values = stdnse.strsplit('&', result['raw_querystring']) for i, v in ipairs(values) do - local name, value = unpack(stdnse.strsplit('=', v)) + local name, value = table.unpack(stdnse.strsplit('=', v)) result['querystring'][name] = value end end @@ -2407,3 +2409,5 @@ local function get_default_timeout( nmap_timing ) return timeout end + +return _ENV; diff --git a/nselib/httpspider.lua b/nselib/httpspider.lua index b0302a7bb1..e910a7ccef 100644 --- a/nselib/httpspider.lua +++ b/nselib/httpspider.lua @@ -55,10 +55,13 @@ -- @args httpspider.noblacklist if set, doesn't load the default blacklist -- -module(... or "httpspider", package.seeall) - -require 'url' -require 'http' +local coroutine = require "coroutine" +local http = require "http" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +local url = require "url" +_ENV = stdnse.module("httpspider", stdnse.seeall) local LIBRARY_NAME = "httpspider" local PREFETCH_SIZE = 5 @@ -303,7 +306,7 @@ LinkExtractor = { end for _, pattern in ipairs(patterns) do - for l in self.html:gfind(pattern) do + for l in self.html:gmatch(pattern) do local link = l if ( not(LinkExtractor.isAbsolute(l)) ) then link = LinkExtractor.createAbsolute(self.url, l, base_href) @@ -361,7 +364,7 @@ URL = { parse = function(self) self.proto, self.host, self.port, self.file = self.raw:match("^(http[s]?)://([^:/]*)[:]?(%d*)") if ( self.proto and self.host ) then - self.file = self.raw:match("^http[s]?://[^:/]*[:]?%d*(/[^\#]*)") or '/' + self.file = self.raw:match("^http[s]?://[^:/]*[:]?%d*(/[^#]*)") or '/' self.port = tonumber(self.port) if ( not(self.port) ) then if ( self.proto:match("https") ) then @@ -810,7 +813,7 @@ Crawler = { if ( #self.response_queue == 0 ) then return false, { err = false, msg = "No more urls" } else - return unpack(table.remove(self.response_queue, 1)) + return table.unpack(table.remove(self.response_queue, 1)) end end, @@ -825,3 +828,5 @@ Crawler = { condvar "wait" end } + +return _ENV; diff --git a/nselib/iax2.lua b/nselib/iax2.lua index 2c0ccf56d0..57a82c9902 100644 --- a/nselib/iax2.lua +++ b/nselib/iax2.lua @@ -4,7 +4,16 @@ -- -- @author "Patrik Karlsson " -- -module(... or "iax2", package.seeall) + +local bin = require "bin" +local bit = require "bit" +local math = require "math" +local nmap = require "nmap" +local openssl = require "openssl" +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("iax2", stdnse.seeall) IAX2 = { @@ -329,4 +338,6 @@ Helper = { end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/imap.lua b/nselib/imap.lua index 708a1e3a93..7112bdb96c 100644 --- a/nselib/imap.lua +++ b/nselib/imap.lua @@ -24,12 +24,13 @@ -- added support for LOGIN and AUTHENTICATE -- -module(... or "imap", package.seeall) +local base64 = require "base64" +local comm = require "comm" +local sasl = require "sasl" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("imap", stdnse.seeall) -require 'stdnse' -require 'comm' -require 'base64' -require 'sasl' IMAP = { @@ -145,7 +146,7 @@ IMAP = { -- All mechanisms expect username and pass -- add the otheronce for those who need them local mech_params = { username, pass, data, "imap" } - auth_data = sasl.Helper:new(mech):encode(unpack(mech_params)) + auth_data = sasl.Helper:new(mech):encode(table.unpack(mech_params)) auth_data = base64.enc(auth_data) .. "\r\n" status, data = self.socket:send(auth_data) @@ -275,3 +276,5 @@ Helper = { end, } + +return _ENV; diff --git a/nselib/informix.lua b/nselib/informix.lua index 5b5691aa79..3d9d70da73 100644 --- a/nselib/informix.lua +++ b/nselib/informix.lua @@ -75,7 +75,11 @@ -- queries -- -module(... or "informix", package.seeall) +local bin = require "bin" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("informix", stdnse.seeall) -- A bunch of constants Constants = @@ -1387,4 +1391,6 @@ Helper = { return self.socket:close() end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/ipOps.lua b/nselib/ipOps.lua index 8e6bc31c09..77303c32fa 100644 --- a/nselib/ipOps.lua +++ b/nselib/ipOps.lua @@ -3,19 +3,19 @@ -- -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html +local bin = require "bin" +local bit = require "bit" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" local type = type local table = table local string = string local ipairs = ipairs local tonumber = tonumber -local stdnse = require "stdnse" -local bit = require "bit" -local bin = require "bin" - -module ( "ipOps" ) - +_ENV = stdnse.module("ipOps", stdnse.seeall) --- -- Checks to see if the supplied IP address is part of a non-routable @@ -337,7 +337,7 @@ expand_ip = function( ip, family ) if not ip:match( ":" ) then -- ipv4: missing octets should be "0" appended - if ip:match( "[^\.0-9]" ) then + if ip:match( "[^%.0-9]" ) then return nil, err4 end local octets = {} @@ -363,7 +363,7 @@ expand_ip = function( ip, family ) return nil, "Error in ipOps.expand_ip: Cannot convert IPv6 address to IPv4" end - if ip:match( "[^\.:%x]" ) then + if ip:match( "[^%.:%x]" ) then return nil, ( err4:gsub( "IPv4", "IPv6" ) ) end @@ -372,16 +372,16 @@ expand_ip = function( ip, family ) -- get a table of each hexadectet local hexadectets = {} - for hdt in string.gmatch( ip, "[\.z%x]+" ) do + for hdt in string.gmatch( ip, "[%.z%x]+" ) do hexadectets[#hexadectets+1] = hdt end -- deal with IPv4in6 (last hexadectet only) local t = {} - if hexadectets[#hexadectets]:match( "[\.]+" ) then + if hexadectets[#hexadectets]:match( "[%.]+" ) then hexadectets[#hexadectets], err = expand_ip( hexadectets[#hexadectets] ) if err then return nil, ( err:gsub( "IPv4", "IPv4in6" ) ) end - t = stdnse.strsplit( "[\.]+", hexadectets[#hexadectets] ) + t = stdnse.strsplit( "[%.]+", hexadectets[#hexadectets] ) for i, v in ipairs( t ) do t[i] = tonumber( v, 10 ) end @@ -392,7 +392,7 @@ expand_ip = function( ip, family ) -- deal with :: and check for invalid address local z_done = false for index, value in ipairs( hexadectets ) do - if value:match( "[\.]+" ) then + if value:match( "[%.]+" ) then -- shouldn't have dots at this point return nil, ( err4:gsub( "IPv4", "IPv6" ) ) elseif value == "z" and z_done then @@ -442,9 +442,9 @@ get_ips_from_range = function( range ) local first, last, prefix if range:match( "/" ) then - first, prefix = range:match( "([%x%d:\.]+)/(%d+)" ) + first, prefix = range:match( "([%x%d:%.]+)/(%d+)" ) elseif range:match( "-" ) then - first, last = range:match( "([%x%d:\.]+)%s*\-%s*([%x%d:\.]+)" ) + first, last = range:match( "([%x%d:%.]+)%s*%.%s*([%x%d:%.]+)" ) end local err = {} @@ -652,3 +652,5 @@ hex_to_bin = function( hex ) return table.concat( t ) end + +return _ENV; diff --git a/nselib/ipp.lua b/nselib/ipp.lua index 9cdf9b9c42..d3e5743836 100644 --- a/nselib/ipp.lua +++ b/nselib/ipp.lua @@ -1,14 +1,19 @@ +local bin = require "bin" +local http = require "http" +local nmap = require "nmap" +local os = require "os" +local package = require "package" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" +_ENV = stdnse.module("ipp", stdnse.seeall) + --- -- -- A small CUPS ipp library implementation -- -- -module(... or "ipp", package.seeall) - -local bin = require('bin') -local tba = require('tab') - -- The IPP layer IPP = { @@ -252,9 +257,9 @@ IPP = { if ( group ) then table.insert(resp.attrib_groups, group) - group = ipp.IPP.AttributeGroup:new(tag) + group = IPP.AttributeGroup:new(tag) else - group = ipp.IPP.AttributeGroup:new(tag) + group = IPP.AttributeGroup:new(tag) end else pos = pos - 1 @@ -291,7 +296,7 @@ HTTP = { return false, "Unexpected response from server" end - local response = ipp.IPP.Response.parse(http_resp.body) + local response = IPP.Response.parse(http_resp.body) if ( not(response) ) then return false, "Failed to parse response" end @@ -320,11 +325,11 @@ Helper = { getPrinters = function(self) local attribs = { - IPP.Attribute:new(ipp.IPP.Attribute.IPP_TAG_CHARSET, "attributes-charset", "utf-8" ), - IPP.Attribute:new(ipp.IPP.Attribute.IPP_TAG_LANGUAGE, "attributes-natural-language", "en"), + IPP.Attribute:new(IPP.Attribute.IPP_TAG_CHARSET, "attributes-charset", "utf-8" ), + IPP.Attribute:new(IPP.Attribute.IPP_TAG_LANGUAGE, "attributes-natural-language", "en"), } - local ag = IPP.AttributeGroup:new(ipp.IPP.Attribute.IPP_TAG_OPERATION, attribs) + local ag = IPP.AttributeGroup:new(IPP.Attribute.IPP_TAG_OPERATION, attribs) local request = IPP.Request:new(IPP.OperationID.CUPS_GET_PRINTERS, 1) request:addAttributeGroup(ag) @@ -335,7 +340,7 @@ Helper = { local printers = {} - for _, ag in ipairs(response:getAttributeGroups(ipp.IPP.Attribute.IPP_TAG_PRINTER)) do + for _, ag in ipairs(response:getAttributeGroups(IPP.Attribute.IPP_TAG_PRINTER)) do local attrib = { ["printer-name"] = "name", ["printer-location"] = "location", @@ -360,26 +365,26 @@ Helper = { local uri = uri or ("ipp://%s/"):format(self.host.ip) local attribs = { - IPP.Attribute:new(ipp.IPP.Attribute.IPP_TAG_CHARSET, "attributes-charset", "utf-8" ), - IPP.Attribute:new(ipp.IPP.Attribute.IPP_TAG_LANGUAGE, "attributes-natural-language", "en-us"), - IPP.Attribute:new(ipp.IPP.Attribute.IPP_TAG_URI, "printer-uri", uri), - IPP.Attribute:new(ipp.IPP.Attribute.IPP_TAG_KEYWORD, "requested-attributes", { - -- { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "job-originating-host-name"}, - { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "com.apple.print.JobInfo.PMJobName"}, - { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "com.apple.print.JobInfo.PMJobOwner"}, - { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "job-id" }, - { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "job-k-octets" }, - { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "job-name" }, - { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "job-state" }, - { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "printer-uri" }, - -- { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "job-originating-user-name" }, - -- { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "job-printer-state-message" }, - -- { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "job-printer-uri" }, - { tag = ipp.IPP.Attribute.IPP_TAG_KEYWORD, val = "time-at-creation" } } ), - IPP.Attribute:new(ipp.IPP.Attribute.IPP_TAG_KEYWORD, "which-jobs", "not-completed" ) + IPP.Attribute:new(IPP.Attribute.IPP_TAG_CHARSET, "attributes-charset", "utf-8" ), + IPP.Attribute:new(IPP.Attribute.IPP_TAG_LANGUAGE, "attributes-natural-language", "en-us"), + IPP.Attribute:new(IPP.Attribute.IPP_TAG_URI, "printer-uri", uri), + IPP.Attribute:new(IPP.Attribute.IPP_TAG_KEYWORD, "requested-attributes", { + -- { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-originating-host-name"}, + { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "com.apple.print.JobInfo.PMJobName"}, + { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "com.apple.print.JobInfo.PMJobOwner"}, + { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-id" }, + { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-k-octets" }, + { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-name" }, + { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-state" }, + { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "printer-uri" }, + -- { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-originating-user-name" }, + -- { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-printer-state-message" }, + -- { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "job-printer-uri" }, + { tag = IPP.Attribute.IPP_TAG_KEYWORD, val = "time-at-creation" } } ), + IPP.Attribute:new(IPP.Attribute.IPP_TAG_KEYWORD, "which-jobs", "not-completed" ) } - local ag = IPP.AttributeGroup:new(ipp.IPP.Attribute.IPP_TAG_OPERATION, attribs) + local ag = IPP.AttributeGroup:new(IPP.Attribute.IPP_TAG_OPERATION, attribs) local request = IPP.Request:new(IPP.OperationID.IPP_GET_JOBS, 1) request:addAttributeGroup(ag) @@ -389,7 +394,7 @@ Helper = { end local results = {} - for _, ag in ipairs(response:getAttributeGroups(ipp.IPP.Attribute.IPP_TAG_JOB)) do + for _, ag in ipairs(response:getAttributeGroups(IPP.Attribute.IPP_TAG_JOB)) do local uri = ag:getAttributeValue("printer-uri") local printer = uri:match(".*/(.*)$") or "Unknown" -- some jobs have mutlitple state attributes, so far the ENUM ones have been correct diff --git a/nselib/iscsi.lua b/nselib/iscsi.lua index b55d42fb17..cf6b7f9b93 100644 --- a/nselib/iscsi.lua +++ b/nselib/iscsi.lua @@ -35,10 +35,17 @@ -- Revised 2010/11/28 - v0.2 - improved error handling, fixed discovery issues -- with multiple addresses -module(... or "iscsi",package.seeall) -require("bin") -require("ipOps") +local bin = require "bin" +local bit = require "bit" +local ipOps = require "ipOps" +local nmap = require "nmap" +local openssl = require "openssl" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("iscsi", stdnse.seeall) + Packet = { @@ -788,3 +795,5 @@ Helper = { + +return _ENV; diff --git a/nselib/json.lua b/nselib/json.lua index 5f283e823a..233122b96d 100644 --- a/nselib/json.lua +++ b/nselib/json.lua @@ -23,24 +23,27 @@ -- Modified 02/27/2010 - v0.4 Added unicode handling (written by David Fifield). Renamed toJson -- and fromJson intogenerate() and parse(), implemented more proper numeric parsing and added some more error checking. -module("json", package.seeall) -require("bit") -require("nsedebug") - +local bit = require "bit" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("json", stdnse.seeall) + --Some local shortcuts local function dbg(str,...) - stdnse.print_debug("Json:"..str, unpack(arg)) + stdnse.print_debug("Json:"..str, table.unpack(arg)) end local function d4(str,...) - if nmap.debugging() > 3 then dbg(str,unpack(arg)) end + if nmap.debugging() > 3 then dbg(str,table.unpack(arg)) end end local function d3(str,...) - if nmap.debugging() > 2 then dbg(str,unpack(arg)) end + if nmap.debugging() > 2 then dbg(str,table.unpack(arg)) end end --local dbg =stdnse.print_debug local function dbg_err(str,...) - stdnse.print_debug("json-ERR:"..str, unpack(arg)) + stdnse.print_debug("json-ERR:"..str, table.unpack(arg)) end -- Javascript null representation, see explanation above @@ -535,3 +538,5 @@ function test() end end end + +return _ENV; diff --git a/nselib/ldap.lua b/nselib/ldap.lua index 8a0f292f17..72f25c59f0 100644 --- a/nselib/ldap.lua +++ b/nselib/ldap.lua @@ -16,9 +16,15 @@ -- Revised 10/30/2011 - v0.6 - Added support for the ldap extensibleMatch filter type for searches -- -module("ldap", package.seeall) - -require("asn1") +local asn1 = require "asn1" +local bin = require "bin" +local io = require "io" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("ldap", stdnse.seeall) local ldapMessageId = 1 @@ -538,9 +544,9 @@ function searchResultToTable( searchEntries ) local _, o1, o2, o3, o4, o5, o6, o7, o8, o9, oa, ob, oc, od, oe, of = bin.unpack("C16", attrib[i] ) table.insert( attribs, string.format( "%s: %x%x%x%x-%x%x-%x%x-%x%x-%x%x%x%x%x", attrib[1], o4, o3, o2, o1, o5, o6, o7, o8, o9, oa, ob, oc, od, oe, of ) ) elseif ( attrib[1] == "lastLogon" or attrib[1] == "lastLogonTimestamp" or attrib[1] == "pwdLastSet" or attrib[1] == "accountExpires" or attrib[1] == "badPasswordTime" ) then - table.insert( attribs, string.format( "%s: %s", attrib[1], ldap.convertADTimeStamp(attrib[i]) ) ) + table.insert( attribs, string.format( "%s: %s", attrib[1], convertADTimeStamp(attrib[i]) ) ) elseif ( attrib[1] == "whenChanged" or attrib[1] == "whenCreated" or attrib[1] == "dSCorePropagationData" ) then - table.insert( attribs, string.format( "%s: %s", attrib[1], ldap.convertZuluTimeStamp(attrib[i]) ) ) + table.insert( attribs, string.format( "%s: %s", attrib[1], convertZuluTimeStamp(attrib[i]) ) ) else table.insert( attribs, string.format( "%s: %s", attrib[1], attrib[i] ) ) end @@ -623,10 +629,10 @@ function searchResultToFile( searchEntries, filename ) host_table[string.format("%s", v.objectName)].attributes[attrib[1]] = string.format( "%x%x%x%x-%x%x-%x%x-%x%x-%x%x%x%x%x", o4, o3, o2, o1, o5, o6, o7, o8, o9, oa, ob, oc, od, oe, of ) elseif ( attrib[1] == "lastLogon" or attrib[1] == "lastLogonTimestamp" or attrib[1] == "pwdLastSet" or attrib[1] == "accountExpires" or attrib[1] == "badPasswordTime" ) then - host_table[string.format("%s", v.objectName)].attributes[attrib[1]] = ldap.convertADTimeStamp(attrib[i]) + host_table[string.format("%s", v.objectName)].attributes[attrib[1]] = convertADTimeStamp(attrib[i]) elseif ( attrib[1] == "whenChanged" or attrib[1] == "whenCreated" or attrib[1] == "dSCorePropagationData" ) then - host_table[string.format("%s", v.objectName)].attributes[attrib[1]] = ldap.convertZuluTimeStamp(attrib[i]) + host_table[string.format("%s", v.objectName)].attributes[attrib[1]] = convertZuluTimeStamp(attrib[i]) else host_table[v.objectName].attributes[attrib[1]] = string.format( "%s", attrib[i] ) @@ -756,3 +762,5 @@ function copyTable(targetTable) end return setmetatable(temp, getmetatable(targetTable)) end + +return _ENV; diff --git a/nselib/listop.lua b/nselib/listop.lua index c38a58515b..d30ea26610 100644 --- a/nselib/listop.lua +++ b/nselib/listop.lua @@ -9,7 +9,9 @@ -- function applying a given function to each element of a list. -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "listop", package.seeall) +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("listop", stdnse.seeall) --[[ -- @@ -71,7 +73,7 @@ end -- @param l A list. -- @return Results from f. function apply(f, l) - return f(unpack(l)) + return f(table.unpack(l)) end --- Returns a list containing only those elements for which a predicate @@ -106,7 +108,7 @@ end -- @param l The list. -- @return Elements after the first. function cdr(l) - return {unpack(l, 2)} + return {table.unpack(l, 2)} end --- Fetch element at index x from l. @@ -124,7 +126,7 @@ end -- @return Elements after index x or after index 1 if -- x is not given. function ncdr(l, x) - return {unpack(l, x or 2)}; + return {table.unpack(l, x or 2)}; end --- Prepend a value or list to another value or list. @@ -132,7 +134,7 @@ end -- @param v2 value or list. -- @return New list. function cons(v1, v2) - return{ is_list(v1) and {unpack(v1)} or v1, is_list(v2) and {unpack(v2)} or v2} + return{ is_list(v1) and {table.unpack(v1)} or v1, is_list(v2) and {table.unpack(v2)} or v2} end --- Concatenate two lists and return the result. @@ -140,7 +142,7 @@ end -- @param l2 List. -- @return List. function append(l1, l2) - local results = {unpack(l1)} + local results = {table.unpack(l1)} for _, v in ipairs(l2) do results[#results+1] = v; @@ -178,3 +180,5 @@ function flatten(l) end return flat({}, l) end + +return _ENV; diff --git a/nselib/match.lua b/nselib/match.lua index 0224724cd7..f12a793a29 100644 --- a/nselib/match.lua +++ b/nselib/match.lua @@ -5,8 +5,9 @@ -- nmap.receive_buf function in the Network I/O API (which see). -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "match", package.seeall) -require "pcre" +local pcre = require "pcre" +local stdnse = require "stdnse" +_ENV = stdnse.module("match", stdnse.seeall) --various functions for use with nse's nsock:receive_buf - function @@ -54,3 +55,5 @@ numbytes = function(num) end end + +return _ENV; diff --git a/nselib/membase.lua b/nselib/membase.lua index e38bdae8c7..e0f759404f 100644 --- a/nselib/membase.lua +++ b/nselib/membase.lua @@ -7,11 +7,13 @@ -- -module(... or "membase", package.seeall) - -require 'match' -require 'sasl' - +local bin = require "bin" +local match = require "match" +local nmap = require "nmap" +local sasl = require "sasl" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("membase", stdnse.seeall) -- A minimalistic implementation of the Couchbase Membase TAP protocol TAP = { @@ -116,7 +118,7 @@ TAP = { __tostring = function(self) if ( self.mech == "PLAIN" ) then local mech_params = { self.username, self.password } - local auth_data = sasl.Helper:new(self.mech):encode(unpack(mech_params)) + local auth_data = sasl.Helper:new(self.mech):encode(table.unpack(mech_params)) self.header.keylen = #self.mech self.header.total_body = #auth_data + #self.mech @@ -328,3 +330,5 @@ Helper = { } + +return _ENV; diff --git a/nselib/mobileme.lua b/nselib/mobileme.lua index 52986cf05b..c5b1d255f2 100644 --- a/nselib/mobileme.lua +++ b/nselib/mobileme.lua @@ -1,13 +1,16 @@ +local http = require "http" +local json = require "json" +local package = require "package" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("mobileme", stdnse.seeall) + --- -- A MobileMe web service client that allows discovering Apple devices -- using the "find my iPhone" functionality. -- -- @author "Patrik Karlsson " -- -module(... or "mobileme", package.seeall) - -local http = require('http') -local json = require('json') MobileMe = { @@ -220,4 +223,4 @@ Helper = { return self.mm:sendMessage(...) end -} \ No newline at end of file +} diff --git a/nselib/mongodb.lua b/nselib/mongodb.lua index 428e31507d..acd43bd648 100644 --- a/nselib/mongodb.lua +++ b/nselib/mongodb.lua @@ -11,9 +11,13 @@ -- Created 01/13/2010 - v0.1 - created by Martin Holst Swende -- Revised 01/03/2012 - v0.2 - added authentication support -module("mongodb", package.seeall) -require("bin") -stdnse.silent_require "openssl" +local bin = require "bin" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local openssl = stdnse.silent_require "openssl" +_ENV = stdnse.module("mongodb", stdnse.seeall) -- this is not yet widely implemented but at least used for authentication @@ -24,7 +28,7 @@ local arg_DB = stdnse.get_script_args("mongodb.db") -- Some lazy shortcuts local function dbg(str,...) - stdnse.print_debug(3, "MngoDb:"..str, unpack(arg)) + stdnse.print_debug(3, "MngoDb:"..str, table.unpack(arg)) end --local dbg =stdnse.print_debug @@ -51,7 +55,7 @@ local err =stdnse.print_debug --module("bson", package.seeall) --require("bin") local function dbg_err(str,...) - stdnse.print_debug("Bson-ERR:"..str, unpack(arg)) + stdnse.print_debug("Bson-ERR:"..str, table.unpack(arg)) end --local err =stdnse.log_error @@ -600,7 +604,7 @@ function login(socket, db, username, password) local query = { getnonce = 1 } local status, packet = createQuery(collectionName, query) local response - status, response = mongodb.query(socket, packet) + status, response = query(socket, packet) if ( not(status) or not(response.nonce) ) then return false, "Failed to retrieve nonce" end @@ -613,7 +617,7 @@ function login(socket, db, username, password) query._cmd = { authenticate = 1 } local status, packet = createQuery(collectionName, query) - status, response = mongodb.query(socket, packet) + status, response = query(socket, packet) if ( not(status) ) then return status, response elseif ( response.errmsg == "auth fails" ) then @@ -679,3 +683,5 @@ end -- end --test() + +return _ENV; diff --git a/nselib/msrpc.lua b/nselib/msrpc.lua index f85d4c8ac5..838bda3d34 100644 --- a/nselib/msrpc.lua +++ b/nselib/msrpc.lua @@ -47,14 +47,18 @@ --@author Ron Bowes --@copyright Same as Nmap--See http://nmap.org/book/man-legal.html ----------------------------------------------------------------------- -module(... or "msrpc", package.seeall) -require 'bit' -require 'bin' -require 'msrpctypes' -require 'netbios' -require 'smb' -require 'stdnse' +local bin = require "bin" +local bit = require "bit" +local math = require "math" +local msrpctypes = require "msrpctypes" +local netbios = require "netbios" +local os = require "os" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("msrpc", stdnse.seeall) -- The path, UUID, and version for SAMR SAMR_PATH = "\\samr" @@ -3727,85 +3731,85 @@ local function get_domain_info(host, domain) local status, smbstate, bind_result, connect4_result, lookupdomain_result, opendomain_result, enumdomainusers_result -- Create the SMB session - status, smbstate = msrpc.start_smb(host, msrpc.SAMR_PATH) + status, smbstate = start_smb(host, SAMR_PATH) if(status == false) then return false, smbstate end -- Bind to SAMR service - status, bind_result = msrpc.bind(smbstate, msrpc.SAMR_UUID, msrpc.SAMR_VERSION, nil) + status, bind_result = bind(smbstate, SAMR_UUID, SAMR_VERSION, nil) if(status == false) then - msrpc.stop_smb(smbstate) + stop_smb(smbstate) return false, bind_result end -- Call connect4() - status, connect4_result = msrpc.samr_connect4(smbstate, host.ip) + status, connect4_result = samr_connect4(smbstate, host.ip) if(status == false) then - msrpc.stop_smb(smbstate) + stop_smb(smbstate) return false, connect4_result end -- Call LookupDomain() - status, lookupdomain_result = msrpc.samr_lookupdomain(smbstate, connect4_result['connect_handle'], domain) + status, lookupdomain_result = samr_lookupdomain(smbstate, connect4_result['connect_handle'], domain) if(status == false) then - msrpc.samr_close(smbstate, connect4_result['connect_handle']) - msrpc.stop_smb(smbstate) + samr_close(smbstate, connect4_result['connect_handle']) + stop_smb(smbstate) return false, "Couldn't look up the domain: " .. lookupdomain_result end -- Call OpenDomain() - status, opendomain_result = msrpc.samr_opendomain(smbstate, connect4_result['connect_handle'], lookupdomain_result['sid']) + status, opendomain_result = samr_opendomain(smbstate, connect4_result['connect_handle'], lookupdomain_result['sid']) if(status == false) then - msrpc.samr_close(smbstate, connect4_result['connect_handle']) - msrpc.stop_smb(smbstate) + samr_close(smbstate, connect4_result['connect_handle']) + stop_smb(smbstate) return false, opendomain_result end -- Call QueryDomainInfo2() to get domain properties. We call these for three types -- 1, 8, and 12, since those return -- the most useful information. - local status_1, querydomaininfo2_result_1 = msrpc.samr_querydomaininfo2(smbstate, opendomain_result['domain_handle'], 1) - local status_8, querydomaininfo2_result_8 = msrpc.samr_querydomaininfo2(smbstate, opendomain_result['domain_handle'], 8) - local status_12, querydomaininfo2_result_12 = msrpc.samr_querydomaininfo2(smbstate, opendomain_result['domain_handle'], 12) + local status_1, querydomaininfo2_result_1 = samr_querydomaininfo2(smbstate, opendomain_result['domain_handle'], 1) + local status_8, querydomaininfo2_result_8 = samr_querydomaininfo2(smbstate, opendomain_result['domain_handle'], 8) + local status_12, querydomaininfo2_result_12 = samr_querydomaininfo2(smbstate, opendomain_result['domain_handle'], 12) if(status_1 == false) then - msrpc.samr_close(smbstate, connect4_result['connect_handle']) - msrpc.stop_smb(smbstate) + samr_close(smbstate, connect4_result['connect_handle']) + stop_smb(smbstate) return false, querydomaininfo2_result_1 end if(status_8 == false) then - msrpc.samr_close(smbstate, connect4_result['connect_handle']) - msrpc.stop_smb(smbstate) + samr_close(smbstate, connect4_result['connect_handle']) + stop_smb(smbstate) return false, querydomaininfo2_result_8 end if(status_12 == false) then - msrpc.samr_close(smbstate, connect4_result['connect_handle']) - msrpc.stop_smb(smbstate) + samr_close(smbstate, connect4_result['connect_handle']) + stop_smb(smbstate) return false, querydomaininfo2_result_12 end -- Call EnumDomainUsers() to get users - status, enumdomainusers_result = msrpc.samr_enumdomainusers(smbstate, opendomain_result['domain_handle']) + status, enumdomainusers_result = samr_enumdomainusers(smbstate, opendomain_result['domain_handle']) if(status == false) then - msrpc.samr_close(smbstate, connect4_result['connect_handle']) - msrpc.stop_smb(smbstate) + samr_close(smbstate, connect4_result['connect_handle']) + stop_smb(smbstate) return false, enumdomainusers_result end -- Call EnumDomainAliases() to get groups - local status, enumdomaingroups_result = msrpc.samr_enumdomainaliases(smbstate, opendomain_result['domain_handle']) + local status, enumdomaingroups_result = samr_enumdomainaliases(smbstate, opendomain_result['domain_handle']) if(status == false) then - msrpc.samr_close(smbstate, connect4_result['connect_handle']) - msrpc.stop_smb(smbstate) + samr_close(smbstate, connect4_result['connect_handle']) + stop_smb(smbstate) return false, enumdomaingroups_result end -- Close the domain handle - msrpc.samr_close(smbstate, opendomain_result['domain_handle']) + samr_close(smbstate, opendomain_result['domain_handle']) -- Close the smb session - msrpc.stop_smb(smbstate) + stop_smb(smbstate) -- Create a list of groups local groups = {} @@ -3881,7 +3885,7 @@ local function get_domain_info(host, domain) local password_properties_response = {} password_properties_response['name'] = "Password properties:" for j = 1, #password_properties, 1 do - table.insert(password_properties_response, msrpc.samr_PasswordProperties_tostr(password_properties[j])) + table.insert(password_properties_response, samr_PasswordProperties_tostr(password_properties[j])) end response['password_properties'] = password_properties_response @@ -3896,39 +3900,39 @@ function get_domains(host) local i, j -- Create the SMB session - status, smbstate = msrpc.start_smb(host, msrpc.SAMR_PATH) + status, smbstate = start_smb(host, SAMR_PATH) if(status == false) then return false, smbstate end -- Bind to SAMR service - status, bind_result = msrpc.bind(smbstate, msrpc.SAMR_UUID, msrpc.SAMR_VERSION, nil) + status, bind_result = bind(smbstate, SAMR_UUID, SAMR_VERSION, nil) if(status == false) then - msrpc.stop_smb(smbstate) + stop_smb(smbstate) return false, bind_result end -- Call connect4() - status, connect4_result = msrpc.samr_connect4(smbstate, host.ip) + status, connect4_result = samr_connect4(smbstate, host.ip) if(status == false) then - msrpc.stop_smb(smbstate) + stop_smb(smbstate) return false, connect4_result end -- Call EnumDomains() - status, enumdomains_result = msrpc.samr_enumdomains(smbstate, connect4_result['connect_handle']) + status, enumdomains_result = samr_enumdomains(smbstate, connect4_result['connect_handle']) if(status == false) then - msrpc.samr_close(smbstate, connect4_result['connect_handle']) - msrpc.stop_smb(smbstate) + samr_close(smbstate, connect4_result['connect_handle']) + stop_smb(smbstate) return false, enumdomains_result end -- Close the connect handle - msrpc.samr_close(smbstate, connect4_result['connect_handle']) + samr_close(smbstate, connect4_result['connect_handle']) -- Close the SMB session - msrpc.stop_smb(smbstate) + stop_smb(smbstate) -- If no domains were returned, return an error (not sure that this can ever happen, but who knows?) if(#enumdomains_result['sam']['entries'] == 0) then @@ -4721,3 +4725,5 @@ function random_crap(length, charset) return random_str end + +return _ENV; diff --git a/nselib/msrpcperformance.lua b/nselib/msrpcperformance.lua index 9f29fd8190..583cd57bdd 100644 --- a/nselib/msrpcperformance.lua +++ b/nselib/msrpcperformance.lua @@ -16,9 +16,13 @@ --@author Ron Bowes --@copyright Same as Nmap--See http://nmap.org/book/man-legal.html ----------------------------------------------------------------------- -module(... or "msrpcperformance", package.seeall) -require 'msrpctypes' +local bin = require "bin" +local bit = require "bit" +local msrpc = require "msrpc" +local msrpctypes = require "msrpctypes" +local stdnse = require "stdnse" +_ENV = stdnse.module("msrpcperformance", stdnse.seeall) ---Parses the title database, which is a series of null-terminated string pairs. -- @@ -609,3 +613,5 @@ function get_performance_data(host, objects) end + +return _ENV; diff --git a/nselib/msrpctypes.lua b/nselib/msrpctypes.lua index 568f916802..b9a692c9e8 100644 --- a/nselib/msrpctypes.lua +++ b/nselib/msrpctypes.lua @@ -103,11 +103,13 @@ -- * SIDs will be converted to user-readable strings in the standard format (S-x-y-...) -- * GUIDs are stored as tables of values; however, I might change this to a string representation at some point -module(... or "msrpctypes", package.seeall) - -require 'bit' -require 'bin' -require 'stdnse' +local bin = require "bin" +local bit = require "bit" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("msrpctypes", stdnse.seeall) local REFERENT_ID = 0x50414d4e local HEAD = 'HEAD' @@ -274,7 +276,7 @@ local function marshall_ptr(location, func, args, value) if(location == BODY or location == ALL) then if(func == nil or args == nil or value == nil) then else - result = result .. func(unpack(args)) + result = result .. func(table.unpack(args)) end end @@ -341,7 +343,7 @@ local function unmarshall_ptr(location, data, pos, func, args, result) if(location == BODY or location == ALL) then if(result == true) then - pos, result = func(data, pos, unpack(args)) + pos, result = func(data, pos, table.unpack(args)) else result = nil end @@ -373,7 +375,7 @@ local function marshall_basetype(location, func, args) stdnse.print_debug(4, string.format("MSRPC: Entering marshall_basetype()")) if(location == HEAD or location == ALL) then - result = bin.pack(" -- Revised 03/28/2010 - v0.2 - fixed incorrect token types. added 30 seconds timeout @@ -118,13 +131,6 @@ module(... or "mssql", package.seeall) -- -- (Patrik Karlsson, Chris Woodbury) -require("bit") -require("bin") -require("stdnse") -require("strbuf") -require("smb") -require("smbauth") - HAVE_SSL = (nmap.have_ssl() and pcall(require, "openssl")) do @@ -1819,7 +1825,7 @@ TDSStream = { pos, spid, self._packetId, window = bin.unpack(">SCC", readBuffer, pos ) -- TDS packet validity check: packet type is Response (0x4) - if ( packetType ~= mssql.PacketType.Response ) then + if ( packetType ~= PacketType.Response ) then stdnse.print_debug( 2, "%s: Receiving (%s): Expected type 0x4 (response), but received type 0x%x", "MSSQL", self._name, packetType ) return false, "Server returned invalid packet" @@ -2046,15 +2052,15 @@ Helper = DiscoverByTcp = function( host, port ) local version, instance, status -- Check to see if we've already discovered an instance on this port - instance = mssql.Helper.GetDiscoveredInstances( host, port ) + instance = Helper.GetDiscoveredInstances( host, port ) if ( not instance ) then - instance = mssql.SqlServerInstanceInfo:new() + instance = SqlServerInstanceInfo:new() instance.host = host instance.port = port - status, version = mssql.Helper.GetInstanceVersion( instance ) + status, version = Helper.GetInstanceVersion( instance ) if ( status ) then - mssql.Helper.AddOrMergeInstance( instance ) + Helper.AddOrMergeInstance( instance ) -- The point of this wasn't to get the version, just to use the -- pre-login packet to determine whether there was a SQL Server on -- the port. However, since we have the version now, we'll store it. @@ -2750,3 +2756,5 @@ Util = return new_tbl end, } + +return _ENV; diff --git a/nselib/mysql.lua b/nselib/mysql.lua index 0ec1877d05..f1a8915a79 100644 --- a/nselib/mysql.lua +++ b/nselib/mysql.lua @@ -7,7 +7,14 @@ -- -- @author "Patrik Karlsson " -module(... or "mysql", package.seeall) +local bin = require "bin" +local bit = require "bit" +local nmap = require "nmap" +local openssl = require "openssl" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("mysql", stdnse.seeall) -- Version 0.3 -- @@ -567,3 +574,5 @@ function formatResultset(rs, options) return tab.dump(restab) end + +return _ENV; diff --git a/nselib/natpmp.lua b/nselib/natpmp.lua index 3ad0213cf1..59230d4f35 100644 --- a/nselib/natpmp.lua +++ b/nselib/natpmp.lua @@ -6,10 +6,12 @@ -- -- @author "Patrik Karlsson " -- -module(... or "natpmp", package.seeall) - -require 'bin' -require 'ipOps' +local bin = require "bin" +local ipOps = require "ipOps" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +_ENV = stdnse.module("natpmp", stdnse.seeall) local ResultCode = { SUCCESS = 0, @@ -218,3 +220,5 @@ Helper = { end, } + +return _ENV; diff --git a/nselib/ncp.lua b/nselib/ncp.lua index f453974312..2844d49117 100644 --- a/nselib/ncp.lua +++ b/nselib/ncp.lua @@ -53,9 +53,15 @@ -- Version 0.1 -- Created 24/04/2011 - v0.1 - created by Patrik Karlsson -module(... or "ncp", package.seeall) +local bin = require "bin" +local bit = require "bit" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("ncp", stdnse.seeall) -require 'ipOps' NCPType = { CreateConnection = 0x1111, @@ -1197,3 +1203,5 @@ Util = end, } + +return _ENV; diff --git a/nselib/ndmp.lua b/nselib/ndmp.lua index 41ff7f3b49..2aa595cd16 100644 --- a/nselib/ndmp.lua +++ b/nselib/ndmp.lua @@ -4,9 +4,14 @@ -- @author Patrik Karlsson -- -module(... or "ndmp",package.seeall) - -require 'match' +local bin = require "bin" +local bit = require "bit" +local match = require "match" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("ndmp", stdnse.seeall) NDMP = { @@ -386,15 +391,15 @@ Helper = { end, getFsInfo = function(self) - return self.comm:exch(ndmp.NDMP.Message.ConfigGetFsInfo:new()) + return self.comm:exch(NDMP.Message.ConfigGetFsInfo:new()) end, getHostInfo = function(self) - return self.comm:exch(ndmp.NDMP.Message.ConfigGetHostInfo:new()) + return self.comm:exch(NDMP.Message.ConfigGetHostInfo:new()) end, getServerInfo = function(self) - return self.comm:exch(ndmp.NDMP.Message.ConfigGetServerInfo:new()) + return self.comm:exch(NDMP.Message.ConfigGetServerInfo:new()) end, close = function(self) @@ -403,3 +408,5 @@ Helper = { end } + +return _ENV; diff --git a/nselib/netbios.lua b/nselib/netbios.lua index b1aaf5f51e..d0b9e5ae38 100644 --- a/nselib/netbios.lua +++ b/nselib/netbios.lua @@ -5,12 +5,16 @@ -- @author Ron Bowes -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "netbios", package.seeall) +local bin = require "bin" +local bit = require "bit" +local dns = require "dns" +local math = require "math" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("netbios", stdnse.seeall) -require 'bit' -require 'bin' -require 'stdnse' -require 'dns' types = { NB = 32, @@ -441,3 +445,5 @@ function flags_to_string(flags) return result end + +return _ENV; diff --git a/nselib/nmap.luadoc b/nselib/nmap.luadoc index 67e876f31a..bbaccd8845 100644 --- a/nselib/nmap.luadoc +++ b/nselib/nmap.luadoc @@ -795,3 +795,14 @@ function ip_close() -- debugging level. -- @see stdnse.print_debug function log_write(file, string) + +--- Sleeps for a given amount of time. +-- +-- This causes the program to yield control and not regain it until the time +-- period has elapsed. The time may have a fractional part. Internally, the +-- timer provides millisecond resolution. +-- @name sleep +-- @class function +-- @param t Time to sleep, in seconds. +-- @usage stdnse.sleep(1.5) +function sleep (t) diff --git a/nselib/nrpc.lua b/nselib/nrpc.lua index dbdf829c2c..8eb963d10b 100644 --- a/nselib/nrpc.lua +++ b/nselib/nrpc.lua @@ -43,7 +43,10 @@ -- -module(... or "nrpc", package.seeall) +local bin = require "bin" +local nmap = require "nmap" +local stdnse = require "stdnse" +_ENV = stdnse.module("nrpc", stdnse.seeall) -- The Domino Packet DominoPacket = { @@ -223,4 +226,6 @@ Helper = { return true, id_data end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/nsedebug.lua b/nselib/nsedebug.lua index 0dc1b78e51..b131a8e574 100644 --- a/nselib/nsedebug.lua +++ b/nselib/nsedebug.lua @@ -6,12 +6,16 @@ -- -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -require "stdnse" +local coroutine = require "coroutine" +local debug = require "debug" +local io = require "io" +local math = require "math" +local stdnse = require "stdnse" +local string = require "string" +_ENV = stdnse.module("nsedebug", stdnse.seeall) local EMPTY = {}; -- Empty constant table -module(... or "nsedebug", package.seeall); - --- -- Converts an arbitrary data type into a string. Will recursively convert -- tables. This can be very useful for debugging. @@ -125,3 +129,5 @@ function print_stack() end + +return _ENV; diff --git a/nselib/omp2.lua b/nselib/omp2.lua index cb6151c2d5..9a09d84e6c 100644 --- a/nselib/omp2.lua +++ b/nselib/omp2.lua @@ -28,10 +28,10 @@ -- @args omp2.password The password to use for authentication. -- -module(... or "omp2", package.seeall) - -require("stdnse") -require("nmap") +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("omp2", stdnse.seeall) local HAVE_SSL = false @@ -177,3 +177,5 @@ function get_accounts(host) return nil end + +return _ENV; diff --git a/nselib/packet.lua b/nselib/packet.lua index fc04b454a2..0663a5d02c 100644 --- a/nselib/packet.lua +++ b/nselib/packet.lua @@ -4,10 +4,12 @@ -- @author Marek Majkowski -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "packet" ,package.seeall) - local bit = require "bit" +local nmap = require "nmap" local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("packet", stdnse.seeall) ---------------------------------------------------------------------------------------------------------------- @@ -1166,3 +1168,5 @@ function Packet:udp_count_checksum() self:udp_set_checksum(in_cksum(b)) end + +return _ENV; diff --git a/nselib/pgsql.lua b/nselib/pgsql.lua index 436003e740..65ed904aa1 100644 --- a/nselib/pgsql.lua +++ b/nselib/pgsql.lua @@ -12,7 +12,13 @@ -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -- @author "Patrik Karlsson " -module(... or "pgsql",package.seeall) +local bin = require "bin" +local nmap = require "nmap" +local openssl = require "openssl" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("pgsql", stdnse.seeall) -- Version 0.3 -- Created 02/05/2010 - v0.1 - created by Patrik Karlsson @@ -20,9 +26,6 @@ module(... or "pgsql",package.seeall) -- the correct version class -- Revised 03/04/2010 - v0.3 - added support for trust authentication method -require("openssl") -require("bit") - --- Supported pgsql message types MessageType = { Error = 0x45, @@ -478,7 +481,7 @@ v3 = local pos = 1 if ( params.authtype == AuthenticationType.MD5 ) then - local hash = pgsql.createMD5LoginHash(username, password, salt) + local hash = createMD5LoginHash(username, password, salt) data = bin.pack( "C>Iz", MessageType.PasswordMessage, 40, hash ) try( socket:send( data ) ) elseif ( params.authtype == AuthenticationType.Plain ) then @@ -621,3 +624,5 @@ function detectVersion(host, port) return v3 end + +return _ENV; diff --git a/nselib/pop3.lua b/nselib/pop3.lua index c6b30db556..62cf18b3f1 100644 --- a/nselib/pop3.lua +++ b/nselib/pop3.lua @@ -3,15 +3,17 @@ -- -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "pop3",package.seeall) +local base64 = require "base64" +local comm = require "comm" +local nmap = require "nmap" +local openssl = require "openssl" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("pop3", stdnse.seeall) local HAVE_SSL = false -require 'base64' -require 'bit' -require 'stdnse' -require 'comm' - if pcall(require,'openssl') then HAVE_SSL = true end @@ -229,3 +231,5 @@ if not HAVE_SSL then login_sasl_crammd5 = no_ssl end + +return _ENV; diff --git a/nselib/pppoe.lua b/nselib/pppoe.lua index acec7cd783..24f0d8b8fa 100644 --- a/nselib/pppoe.lua +++ b/nselib/pppoe.lua @@ -21,11 +21,15 @@ -- @author "Patrik Karlsson " -- -module(... or "pppoe", package.seeall) +local bin = require "bin" +local bit = require "bit" +local math = require "math" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("pppoe", stdnse.seeall) -require 'bin' -require 'bit' -require 'packet' EtherType = { PPPOE_DISCOVERY = 0x8863, @@ -1011,4 +1015,6 @@ Helper = { return true end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/proxy.lua b/nselib/proxy.lua index 73c37bfbc8..b63d62673b 100644 --- a/nselib/proxy.lua +++ b/nselib/proxy.lua @@ -4,10 +4,14 @@ -- @author Joao Correa -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "proxy",package.seeall) - -require 'dns' -require 'ipOps' +local bin = require "bin" +local dns = require "dns" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("proxy", stdnse.seeall) -- Start of local functions @@ -22,8 +26,8 @@ local function check_code(result) if result:match( "\r?\n\r?\n" ) then result = result:match( "^(.-)\r?\n\r?\n(.*)$" ) end - if result:lower():match("^http/%d\.%d%s*200") then return true end - if result:lower():match("^http/%d\.%d%s*30[12]") then return true end + if result:lower():match("^http/%d%.%d%s*200") then return true end + if result:lower():match("^http/%d%.%d%s*30[12]") then return true end end return false end @@ -133,7 +137,7 @@ function hex_resolve(hostname) end local t, err = ipOps.get_parts_as_number(ip) if t and not err - then a, b, c, d = unpack(t) + then a, b, c, d = table.unpack(t) else return false end local sip = string.format("%.2x ", a) .. string.format("%.2x ", b) .. string.format("%.2x ", c) .. string.format("%.2x ",d) @@ -280,3 +284,5 @@ function redirectCheck(resp1, resp2) end return false end + +return _ENV; diff --git a/nselib/redis.lua b/nselib/redis.lua index 4dab5bf097..2398439d96 100644 --- a/nselib/redis.lua +++ b/nselib/redis.lua @@ -2,10 +2,11 @@ -- -- @author "Patrik Karlsson " -module(... or "redis", package.seeall) - -local match = require 'match' - +local match = require "match" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("redis", stdnse.seeall) Request = { @@ -140,4 +141,6 @@ Helper = { return self.socket:close() end -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/rmi.lua b/nselib/rmi.lua index 49ab26d969..9205349aa3 100644 --- a/nselib/rmi.lua +++ b/nselib/rmi.lua @@ -42,13 +42,17 @@ -- Created 09/06/2010 - v0.1 - created by Martin Holst Swende -- Fixed more documentation - v0.2 Martin Holst Swende -module("rmi", package.seeall) -require("bin") -require("bit") +local bin = require "bin" +local bit = require "bit" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("rmi", stdnse.seeall) -- Some lazy shortcuts local function dbg(str,...) - stdnse.print_debug(3,"RMI:"..str, unpack(arg)) + stdnse.print_debug(3,"RMI:"..str, table.unpack(arg)) end -- Convenience function to both print an error message and return -- Example usage : @@ -56,7 +60,7 @@ end -- return doh("Foo should be gazonk but was %s", foo) -- end local function doh(str,...) - stdnse.print_debug("RMI-ERR:"..tostring(str), unpack(arg)) + stdnse.print_debug("RMI-ERR:"..tostring(str), table.unpack(arg)) return false, str end @@ -99,7 +103,7 @@ BufferedWriter = { end, -- Convenience function, wraps bin pack = function(self, fmt, ... ) - self.writeBuffer = self.writeBuffer .. bin.pack( fmt, unpack(arg)) + self.writeBuffer = self.writeBuffer .. bin.pack( fmt, table.unpack(arg)) end, -- This function flushes the buffer contents, thereby emptying @@ -192,7 +196,7 @@ BufferedReader = { unpack = function(self,format) local ret = {bin.unpack(format, self.readBuffer, self.pos)} self.pos = ret[1] - return unpack(ret,2) + return table.unpack(ret,2) end, --- -- This function works just like bin.unpack (in fact, it is @@ -204,7 +208,7 @@ BufferedReader = { --@return the unpacked value (NOT the index) peekUnpack = function(self,format) local ret = {bin.unpack(format, self.readBuffer, self.pos)} - return unpack(ret,2) + return table.unpack(ret,2) end, --- -- Tries to read a byte, without consuming it. @@ -290,7 +294,7 @@ JavaDOS = { return self:pack('>P', text) end, pack = function(self, ...) - return self.bWriter:pack(unpack(arg)) + return self.bWriter:pack(table.unpack(arg)) end, write = function(self, data) return self.bWriter:send(data) @@ -1539,3 +1543,5 @@ STREAM_MAGIC = 0xaced STREAM_VERSION = 5 baseWireHandle = 0x7E0000 + +return _ENV; diff --git a/nselib/rpc.lua b/nselib/rpc.lua index 194d90f658..c2dbf4c69a 100644 --- a/nselib/rpc.lua +++ b/nselib/rpc.lua @@ -75,8 +75,16 @@ -- @args rpc.protocol table If set overrides the preferred order in which -- protocols are tested. (ie. "tcp", "udp") -module(... or "rpc", package.seeall) -require("datafiles") +local bin = require "bin" +local bit = require "bit" +local datafiles = require "datafiles" +local math = require "math" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("rpc", stdnse.seeall) -- Version 0.3 -- @@ -2953,12 +2961,12 @@ Util = end return string.format("%s%s uid: %5d gid: %5d %6s %s", - rpc.Util.FtypeToChar(attr.mode), - rpc.Util.FpermToString(attr.mode), + Util.FtypeToChar(attr.mode), + Util.FpermToString(attr.mode), attr.uid, attr.gid, - rpc.Util.SizeToHuman(attr.size), - rpc.Util.TimeToString(attr[time].seconds)) + Util.SizeToHuman(attr.size), + Util.TimeToString(attr[time].seconds)) end, marshall_int32 = function(int32, count) @@ -3361,3 +3369,5 @@ Util = end end } + +return _ENV; diff --git a/nselib/rpcap.lua b/nselib/rpcap.lua index 98bd82d800..b5d5c5f369 100644 --- a/nselib/rpcap.lua +++ b/nselib/rpcap.lua @@ -25,11 +25,13 @@ -- @author "Patrik Karlsson " -module(... or "rpcap", package.seeall) - -require 'ipOps' -require 'match' - +local bin = require "bin" +local ipOps = require "ipOps" +local match = require "match" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("rpcap", stdnse.seeall) RPCAP = { @@ -435,3 +437,5 @@ Helper = { return self.comm:close() end, } + +return _ENV; diff --git a/nselib/rsync.lua b/nselib/rsync.lua index fa48d67c3d..d9f7e8374d 100644 --- a/nselib/rsync.lua +++ b/nselib/rsync.lua @@ -3,11 +3,15 @@ -- -- @author "Patrik Karlsson " -module(... or "rsync",package.seeall) +local base64 = require "base64" +local bin = require "bin" +local match = require "match" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +local openssl = stdnse.silent_require "openssl" +_ENV = stdnse.module("rsync", stdnse.seeall) -require 'base64' -require 'match' -stdnse.silent_require 'openssl' -- The Helper class serves as the main interface for script writers Helper = { @@ -166,4 +170,6 @@ Helper = { -- @return status true on success, false on failure disconnect = function(self) return self.socket:close() end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/rtsp.lua b/nselib/rtsp.lua index f8133793c4..d5da818633 100644 --- a/nselib/rtsp.lua +++ b/nselib/rtsp.lua @@ -34,7 +34,10 @@ -- Created 10/23/2011 - v0.1 - Created by Patrik Karlsson -- -module(... or "rtsp", package.seeall) +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("rtsp", stdnse.seeall) -- The RTSP Request object Request = { @@ -283,4 +286,6 @@ Helper = { return self.client:options(url) end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/sasl.lua b/nselib/sasl.lua index b8e4fd9641..10984c7582 100644 --- a/nselib/sasl.lua +++ b/nselib/sasl.lua @@ -41,14 +41,16 @@ -- Revised 07/18/2011 - v0.2 - Added NTLM, DIGEST-MD5 classes -module(... or "sasl", package.seeall) +local bin = require "bin" +local bit = require "bit" +local openssl = require "openssl" +local smbauth = require "smbauth" +local stdnse = require "stdnse" +local string = require "string" +_ENV = stdnse.module("sasl", stdnse.seeall) local HAVE_SSL = false -require 'stdnse' -require 'base64' -require 'smbauth' - local MECHANISMS = { } -- Calculates a DIGEST MD5 response @@ -430,3 +432,5 @@ Helper = { return self.callback(...) end, } + +return _ENV; diff --git a/nselib/shortport.lua b/nselib/shortport.lua index fb91a25479..02dea11a2c 100644 --- a/nselib/shortport.lua +++ b/nselib/shortport.lua @@ -6,9 +6,9 @@ -- -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "shortport", package.seeall) - local nmap = require "nmap" +local stdnse = require "stdnse" +_ENV = stdnse.module("shortport", stdnse.seeall) --- -- See if a table contains a value. @@ -175,7 +175,7 @@ LIKELY_HTTP_SERVICES = { -- @usage -- portrule = shortport.http -http = shortport.port_or_service(LIKELY_HTTP_PORTS, LIKELY_HTTP_SERVICES) +http = port_or_service(LIKELY_HTTP_PORTS, LIKELY_HTTP_SERVICES) local LIKELY_SSL_PORTS = { 443, 465, 587, 636, 989, 990, 992, 993, 994, 995, 5061, 6679, 6697, 8443, @@ -199,3 +199,5 @@ function ssl(host, port) return port.version.service_tunnel == "ssl" or port_or_service(LIKELY_SSL_PORTS, LIKELY_SSL_SERVICES, {"tcp", "sctp"})(host, port) end + +return _ENV; diff --git a/nselib/sip.lua b/nselib/sip.lua index 48890bde84..1bf71154ea 100644 --- a/nselib/sip.lua +++ b/nselib/sip.lua @@ -41,7 +41,15 @@ -- Version 0.1 -- Created 2011/03/30 - v0.1 - created by Patrik Karlsson -module(... or "sip", package.seeall) +local bin = require "bin" +local math = require "math" +local nmap = require "nmap" +local openssl = require "openssl" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("sip", stdnse.seeall) -- Method constants Method = { @@ -147,7 +155,7 @@ Session = { local timeout = ( ( options and options.timeout ) and options.timeout * 1000 ) or 5000 o.conn.socket:set_timeout( timeout ) - o.sessdata = sessdata or sip.SessionData:new() + o.sessdata = sessdata or SessionData:new() return o end, @@ -824,3 +832,5 @@ Helper = { end, } + +return _ENV; diff --git a/nselib/smb.lua b/nselib/smb.lua index 32a845ef93..1f219b795e 100644 --- a/nselib/smb.lua +++ b/nselib/smb.lua @@ -121,13 +121,18 @@ -- @author Ron Bowes -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html ----------------------------------------------------------------------- -module(... or "smb", package.seeall) - -require 'bit' -require 'bin' -require 'netbios' -require 'smbauth' -require 'stdnse' +local bin = require "bin" +local bit = require "bit" +local io = require "io" +local math = require "math" +local netbios = require "netbios" +local nmap = require "nmap" +local os = require "os" +local smbauth = require "smbauth" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("smb", stdnse.seeall) -- These arrays are filled in with constants at the bottom of this file command_codes = {} @@ -331,45 +336,45 @@ function start_ex(host, negotiate_protocol, start_session, tree_connect, create_ overrides = overrides or {} -- Begin the SMB session - status, smbstate = smb.start(host) + status, smbstate = start(host) if(status == false) then return false, smbstate end -- Disable extended security if it was requested if(disable_extended == true) then - smb.disable_extended(smbstate) + disable_extended(smbstate) end if(negotiate_protocol == true) then -- Negotiate the protocol - status, err = smb.negotiate_protocol(smbstate, overrides) + status, err = negotiate_protocol(smbstate, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end if(start_session == true) then -- Start up a session - status, err = smb.start_session(smbstate, overrides) + status, err = start_session(smbstate, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end if(tree_connect ~= nil) then -- Connect to share - status, err = smb.tree_connect(smbstate, tree_connect, overrides) + status, err = tree_connect(smbstate, tree_connect, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end if(create_file ~= nil) then -- Try to connect to requested pipe - status, err = smb.create_file(smbstate, create_file, overrides) + status, err = create_file(smbstate, create_file, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end end @@ -2240,7 +2245,7 @@ function file_upload(host, localfile, share, remotefile, overrides, encoded) end -- Create the SMB session - status, smbstate = smb.start_ex(host, true, true, share, remotefile, nil, overrides) + status, smbstate = start_ex(host, true, true, share, remotefile, nil, overrides) if(status == false) then return false, smbstate end @@ -2258,9 +2263,9 @@ function file_upload(host, localfile, share, remotefile, overrides, encoded) data = new_data end - status, err = smb.write_file(smbstate, data, i) + status, err = write_file(smbstate, data, i) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end @@ -2269,14 +2274,14 @@ function file_upload(host, localfile, share, remotefile, overrides, encoded) end handle:close() - status, err = smb.close_file(smbstate) + status, err = close_file(smbstate) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end -- Stop the session - smb.stop(smbstate) + stop(smbstate) return true end @@ -2300,7 +2305,7 @@ function file_write(host, data, share, remotefile, use_anonymous) end -- Create the SMB sessioan - status, smbstate = smb.start_ex(host, true, true, share, remotefile, nil, overrides) + status, smbstate = start_ex(host, true, true, share, remotefile, nil, overrides) if(status == false) then return false, smbstate @@ -2309,23 +2314,23 @@ function file_write(host, data, share, remotefile, use_anonymous) local i = 1 while(i <= #data) do local chunkdata = string.sub(data, i, i + chunk - 1) - status, err = smb.write_file(smbstate, chunkdata, i - 1) + status, err = write_file(smbstate, chunkdata, i - 1) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end i = i + chunk end - status, err = smb.close_file(smbstate) + status, err = close_file(smbstate) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end -- Stop the session - smb.stop(smbstate) + stop(smbstate) return true end @@ -2354,7 +2359,7 @@ function file_read(host, share, remotefile, use_anonymous, overrides) end -- Create the SMB sessioan - status, smbstate = smb.start_ex(host, true, true, share, remotefile, nil, overrides) + status, smbstate = start_ex(host, true, true, share, remotefile, nil, overrides) if(status == false) then return false, smbstate @@ -2362,9 +2367,9 @@ function file_read(host, share, remotefile, use_anonymous, overrides) local i = 1 while true do - status, result = smb.read_file(smbstate, i - 1, chunk) + status, result = read_file(smbstate, i - 1, chunk) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, result end @@ -2376,14 +2381,14 @@ function file_read(host, share, remotefile, use_anonymous, overrides) i = i + chunk end - status, err = smb.close_file(smbstate) + status, err = close_file(smbstate) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end -- Stop the session - smb.stop(smbstate) + stop(smbstate) return true, read end @@ -2406,7 +2411,7 @@ function files_exist(host, share, files, overrides) overrides['file_create_disposition'] = 1 -- Create the SMB sessioan - status, smbstate = smb.start_ex(host, true, true, share, nil, nil, overrides) + status, smbstate = start_ex(host, true, true, share, nil, nil, overrides) if(status == false) then return false, smbstate @@ -2428,16 +2433,16 @@ function files_exist(host, share, files, overrides) if(status) then exist = exist + 1 table.insert(list, file) - status, err = smb.close_file(smbstate) + status, err = close_file(smbstate) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end end end -- Stop the session - smb.stop(smbstate) + stop(smbstate) return true, exist, list end @@ -2451,7 +2456,7 @@ function file_delete(host, share, remotefile) local status, smbstate, err -- Create the SMB session - status, smbstate = smb.start_ex(host, true, true, share) + status, smbstate = start_ex(host, true, true, share) if(status == false) then return false, smbstate end @@ -2463,18 +2468,18 @@ function file_delete(host, share, remotefile) for _, file in ipairs(remotefile) do - status, err = smb.delete_file(smbstate, file) + status, err = delete_file(smbstate, file) if(status == false) then stdnse.print_debug(1, "SMB: Couldn't delete %s\\%s: %s", share, file, err) if(err ~= 'NT_STATUS_OBJECT_NAME_NOT_FOUND') then - smb.stop(smbstate) + stop(smbstate) return false, err end end end -- Stop the session - smb.stop(smbstate) + stop(smbstate) return true end @@ -2567,32 +2572,32 @@ function share_anonymous_can_read(host, share) local overrides = get_overrides_anonymous() -- Begin the SMB session - status, smbstate = smb.start(host) + status, smbstate = start(host) if(status == false) then return false, smbstate end -- Negotiate the protocol - status, err = smb.negotiate_protocol(smbstate, overrides) + status, err = negotiate_protocol(smbstate, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end -- Start up a null session - status, err = smb.start_session(smbstate, overrides) + status, err = start_session(smbstate, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end -- Attempt a connection to the share - status, err = smb.tree_connect(smbstate, share, overrides) + status, err = tree_connect(smbstate, share, overrides) if(status == false) then -- Stop the session - smb.stop(smbstate) + stop(smbstate) -- ACCESS_DENIED is the expected error: it tells us that the connection failed if(err == 0xc0000022 or err == 'NT_STATUS_ACCESS_DENIED') then @@ -2604,7 +2609,7 @@ function share_anonymous_can_read(host, share) - smb.stop(smbstate) + stop(smbstate) return true, true end @@ -2620,31 +2625,31 @@ function share_user_can_read(host, share) local overrides = {} -- Begin the SMB session - status, smbstate = smb.start(host) + status, smbstate = start(host) if(status == false) then return false, smbstate end -- Negotiate the protocol - status, err = smb.negotiate_protocol(smbstate, overrides) + status, err = negotiate_protocol(smbstate, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end -- Start up a null session - status, err = smb.start_session(smbstate, overrides) + status, err = start_session(smbstate, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end -- Attempt a connection to the share - status, err = smb.tree_connect(smbstate, share, overrides) + status, err = tree_connect(smbstate, share, overrides) if(status == false) then -- Stop the session - smb.stop(smbstate) + stop(smbstate) -- ACCESS_DENIED is the expected error: it tells us that the connection failed if(err == 0xc0000022 or err == 'NT_STATUS_ACCESS_DENIED') then @@ -2654,7 +2659,7 @@ function share_user_can_read(host, share) end end - smb.stop(smbstate) + stop(smbstate) return true, true end @@ -2670,45 +2675,45 @@ function share_host_returns_proper_error(host) local overrides = get_overrides_anonymous() -- Begin the SMB session - status, smbstate = smb.start(host) + status, smbstate = start(host) if(status == false) then return false, smbstate end -- Negotiate the protocol - status, err = smb.negotiate_protocol(smbstate, overrides) + status, err = negotiate_protocol(smbstate, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end -- Start up a null session - status, err = smb.start_session(smbstate, overrides) + status, err = start_session(smbstate, overrides) if(status == false) then - smb.stop(smbstate) + stop(smbstate) return false, err end -- Connect to the share stdnse.print_debug(1, "SMB: Trying a random share to see if server responds properly: %s", share) - status, err = smb.tree_connect(smbstate, share, overrides) + status, err = tree_connect(smbstate, share, overrides) if(status == false) then -- If the error is NT_STATUS_ACCESS_DENIED (0xc0000022), that's bad -- we don't want non-existent shares -- showing up as 'access denied'. Any other error is ok. if(err == 0xc0000022 or err == 'NT_STATUS_ACCESS_DENIED') then stdnse.print_debug(1, "SMB: Server doesn't return proper value for non-existent shares (returns ACCESS_DENIED)") - smb.stop(smbstate) + stop(smbstate) return true, false end else -- If we were actually able to connect to this share, then there's probably a serious issue stdnse.print_debug(1, "SMB: Server doesn't return proper value for non-existent shares (accepts the connection)") - smb.stop(smbstate) + stop(smbstate) return true, false end - smb.stop(smbstate) + stop(smbstate) return true, true end @@ -2719,6 +2724,7 @@ end --@return (status, result) If status is false, result is an error message. Otherwise, result is a boolean value: -- true if the file was successfully written, false if it was not. function share_get_details(host, share) + local msrpc = require "msrpc" -- avoid require cycle local smbstate, status, result local i local details = {} @@ -2796,7 +2802,7 @@ end --@return (status, result, extra) If status is false, result is an error message. Otherwise, result is an array of shares with as much -- detail as we could get. If extra isn't nil, it is set to extra information that should be displayed (such as a warning). function share_get_list(host) - + local msrpc = require "msrpc" -- avoid require cycle local status, result local enum_status local extra = "" @@ -2846,7 +2852,7 @@ function share_get_list(host) for i = 1, #shares, 1 do local status, result stdnse.print_debug(1, "SMB: Getting information for share: %s", shares[i]) - status, result = smb.share_get_details(host, shares[i]) + status, result = share_get_details(host, shares[i]) if(status == false and result == 'NT_STATUS_BAD_NETWORK_NAME') then stdnse.print_debug(1, "SMB: Share doesn't exist: %s", shares[i]) elseif(status == false) then @@ -2927,7 +2933,7 @@ function get_os(host) local response = {} -- Start up SMB - status, smbstate = smb.start_ex(host, true, true, nil, nil, true) + status, smbstate = start_ex(host, true, true, nil, nil, true) if(status == false) then return false, smbstate end @@ -2945,12 +2951,12 @@ function get_os(host) response['timezone_str'] = smbstate['timezone_str'] -- Kill SMB - smb.stop(smbstate) + stop(smbstate) -- Start another session with extended security. This will allow us to get -- additional information about the target. - status, smbstate = smb.start_ex(host, true, true, nil, nil, false) + status, smbstate = start_ex(host, true, true, nil, nil, false) if(status == true) then -- See if we actually got something if (smbstate['fqdn'] or smbstate['domain_dns'] or smbstate['forest_dns']) then @@ -2970,7 +2976,7 @@ function get_os(host) end -- Kill SMB again - smb.stop(smbstate) + stop(smbstate) end return true, response @@ -2991,7 +2997,7 @@ function get_socket_info(host) local smbstate, socket -- Start SMB (we need a socket to get the proper local ip - status, smbstate = smb.start_ex(host) + status, smbstate = start_ex(host) if(status == false) then return false, smbstate end @@ -3003,7 +3009,7 @@ function get_socket_info(host) end -- Stop SMB - smb.stop(smbstate) + stop(smbstate) -- Get the mac in hex format, if possible local lmac = nil @@ -3062,50 +3068,51 @@ end ---Determines, as accurately as possible, whether or not an account is an administrator. If there is an error, -- 'false' is simply returned. function is_admin(host, username, domain, password, password_hash, hash_type) + local msrpc = require "msrpc" local status, smbstate, err, result local overrides = get_overrides(username, domain, password, password_hash, hash_type) stdnse.print_debug("SMB: Checking if %s is an administrator", username) - status, smbstate = smb.start(host) + status, smbstate = start(host) if(status == false) then stdnse.print_debug("SMB; is_admin: Failed to start SMB: %s [%s]", smbstate, username) - smb.stop(smbstate) + stop(smbstate) return false end - status, err = smb.negotiate_protocol(smbstate, overrides) + status, err = negotiate_protocol(smbstate, overrides) if(status == false) then stdnse.print_debug("SMB; is_admin: Failed to negotiatie protocol: %s [%s]", err, username) - smb.stop(smbstate) + stop(smbstate) return false end - status, err = smb.start_session(smbstate, overrides) + status, err = start_session(smbstate, overrides) if(status == false) then stdnse.print_debug("SMB; is_admin: Failed to start session %s [%s]", err, username) - smb.stop(smbstate) + stop(smbstate) return false end - status, err = smb.tree_connect(smbstate, "IPC$", overrides) + status, err = tree_connect(smbstate, "IPC$", overrides) if(status == false) then stdnse.print_debug("SMB; is_admin: Failed to connect tree: %s [%s]", err, username) - smb.stop(smbstate) + stop(smbstate) return false end - status, err = smb.create_file(smbstate, msrpc.SRVSVC_PATH, overrides) + status, err = create_file(smbstate, msrpc.SRVSVC_PATH, overrides) if(status == false) then stdnse.print_debug("SMB; is_admin: Failed to create file: %s [%s]", err, username) - smb.stop(smbstate) + stop(smbstate) return false end status, err = msrpc.bind(smbstate, msrpc.SRVSVC_UUID, msrpc.SRVSVC_VERSION, nil) if(status == false) then stdnse.print_debug("SMB; is_admin: Failed to bind: %s [%s]", err, username) - smb.stop(smbstate) + stop(smbstate) return false end @@ -3113,11 +3120,11 @@ function is_admin(host, username, domain, password, password_hash, hash_type) status, err = msrpc.srvsvc_netservergetstatistics(smbstate, host.ip) if(status == false) then stdnse.print_debug("SMB; is_admin: Couldn't get server stats (may be normal): %s [%s]", err, username) - smb.stop(smbstate) + stop(smbstate) return false end - smb.stop(smbstate) + stop(smbstate) return true end @@ -3835,7 +3842,7 @@ namedpipes = stdnse.print_debug( 2, "%s: Connecting to named pipe: %s", NP_LIBRARY_NAME, self.name ) local status, result, errorMessage local negotiate_protocol, start_session, disable_extended = true, true, false - status, result = smb.start_ex( self._host, negotiate_protocol, start_session, + status, result = start_ex( self._host, negotiate_protocol, start_session, "IPC$", self._pipeSubPath, disable_extended, self._overrides ) if status then @@ -3853,7 +3860,7 @@ namedpipes = disconnect = function( self ) if ( self._smbstate ) then stdnse.print_debug( 2, "%s: Disconnecting named pipe: %s", NP_LIBRARY_NAME, self.name ) - return smb.stop( self._smbstate ) + return stop( self._smbstate ) else stdnse.print_debug( 2, "%s: disconnect() called, but SMB connection is already closed: %s", NP_LIBRARY_NAME, self.name ) end @@ -3869,7 +3876,7 @@ namedpipes = local offset = 0 -- offset is actually ignored for named pipes, but we'll define the argument for clarity local status, result, errorMessage - status, result = smb.write_file( self._smbstate, messageData, offset, self._overrides ) + status, result = write_file( self._smbstate, messageData, offset, self._overrides ) -- if status is true, result is data that we don't need to pay attention to if not status then @@ -3893,7 +3900,7 @@ namedpipes = local offset = 0 -- offset is actually ignored for named pipes, but we'll define the argument for clarity local MAX_BYTES_PER_READ = 4096 - status, result = smb.read_file( self._smbstate, offset, MAX_BYTES_PER_READ, self._overrides ) + status, result = read_file( self._smbstate, offset, MAX_BYTES_PER_READ, self._overrides ) if status and result.data then messageData = result.data @@ -3903,8 +3910,8 @@ namedpipes = return false, "Failed to read from named pipe", result end - while (result["status"] == smb.status_codes.NT_STATUS_BUFFER_OVERFLOW) do - status, result = smb.read_file( self._smbstate, offset, MAX_BYTES_PER_READ, self._overrides ) + while (result["status"] == status_codes.NT_STATUS_BUFFER_OVERFLOW) do + status, result = read_file( self._smbstate, offset, MAX_BYTES_PER_READ, self._overrides ) if status and result.data then messageData = messageData .. result.data @@ -3933,3 +3940,5 @@ filetype_codes = for i, v in pairs(filetype_codes) do filetype_names[v] = i end + +return _ENV; diff --git a/nselib/smbauth.lua b/nselib/smbauth.lua index 3d8fdf2c46..29873b3447 100644 --- a/nselib/smbauth.lua +++ b/nselib/smbauth.lua @@ -80,12 +80,13 @@ -- For information, see smbauth.lua. --@args smbnoguest Use to disable usage of the 'guest' account. -module(... or "smbauth", package.seeall) - -require 'bit' -require 'bin' -require 'netbios' -require 'stdnse' +local bin = require "bin" +local nmap = require "nmap" +local openssl = require "openssl" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("smbauth", stdnse.seeall) have_ssl = (nmap.have_ssl() and pcall(require, "openssl")) @@ -830,3 +831,5 @@ end + +return _ENV; diff --git a/nselib/smtp.lua b/nselib/smtp.lua index 4e00d5ad06..34c4740faa 100644 --- a/nselib/smtp.lua +++ b/nselib/smtp.lua @@ -3,13 +3,14 @@ -- -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "smtp", package.seeall) - -local comm = require 'comm' -local nmap = require 'nmap' -local stdnse = require 'stdnse' -local base64 = require 'base64' -local sasl = require 'sasl' +local base64 = require "base64" +local comm = require "comm" +local nmap = require "nmap" +local sasl = require "sasl" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("smtp", stdnse.seeall) local ERROR_MESSAGES = { ["EOF"] = "connection closed", @@ -194,7 +195,7 @@ get_auth_mech = function(response) local list = {} for _, line in pairs(stdnse.strsplit("\r?\n", response)) do - local authstr = line:match("%d+\-AUTH%s(.*)$") + local authstr = line:match("%d+%-AUTH%s(.*)$") if authstr then for mech in authstr:gmatch("[^%s]+") do table.insert(list, mech) @@ -639,7 +640,7 @@ login = function(socket, username, password, mech) -- All mechanisms expect username and pass -- add the otheronce for those who need them local mech_params = { username, password, chall, "smtp" } - local auth_data = sasl.Helper:new(mech):encode(unpack(mech_params)) + local auth_data = sasl.Helper:new(mech):encode(table.unpack(mech_params)) auth_data = base64.enc(auth_data) status, response = query(socket, auth_data) @@ -659,3 +660,5 @@ login = function(socket, username, password, mech) return false, response end + +return _ENV; diff --git a/nselib/snmp.lua b/nselib/snmp.lua index 40186d68cd..d96b9d7cbc 100644 --- a/nselib/snmp.lua +++ b/nselib/snmp.lua @@ -5,12 +5,16 @@ -- "public", or whatever is passed to buildPacket. -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "snmp",package.seeall) +local asn1 = require "asn1" +local bin = require "bin" +local math = require "math" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("snmp", stdnse.seeall) -require("bit") -require("asn1") - -- SNMP ASN.1 Encoders local tagEncoder = {} @@ -29,7 +33,7 @@ tagEncoder['table'] = function(self, val) return bin.pack("HAA", '06', self.encodeLength(#oidStr), oidStr) elseif (val._snmp == '40') then -- ipAddress - return bin.pack("HC4", '40 04', unpack(val)) + return bin.pack("HC4", '40 04', table.unpack(val)) -- counter or gauge or timeticks or opaque elseif (val._snmp == '41' or val._snmp == '42' or val._snmp == '43' or val._snmp == '44') then @@ -470,7 +474,7 @@ function snmpWalk( socket, base_oid ) local value, response, snmpdata, options, item = nil, nil, nil, {}, {} options.reqId = 28428 -- unnecessary? - payload = snmp.encode( snmp.buildPacket( snmp.buildGetNextRequest(options, oid) ) ) + payload = encode( buildPacket( buildGetNextRequest(options, oid) ) ) status, err = socket:send(payload) if ( not( status ) ) then @@ -488,7 +492,7 @@ function snmpWalk( socket, base_oid ) return false, nil end - snmpdata = snmp.fetchResponseValues( response ) + snmpdata = fetchResponseValues( response ) value = snmpdata[1][1] oid = snmpdata[1][2] @@ -509,3 +513,5 @@ function snmpWalk( socket, base_oid ) return true, snmp_table end + +return _ENV; diff --git a/nselib/socks.lua b/nselib/socks.lua index ba579fad1d..ba7610b6da 100644 --- a/nselib/socks.lua +++ b/nselib/socks.lua @@ -4,7 +4,11 @@ -- @author "Patrik Karlsson " -- -module(... or "socks", package.seeall) +local bin = require "bin" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +_ENV = stdnse.module("socks", stdnse.seeall) -- SOCKS Authentication methods AuthMethod = { @@ -350,4 +354,6 @@ Helper = { return self.socket:close() end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/srvloc.lua b/nselib/srvloc.lua index 246d23a0f4..037f3a6e68 100644 --- a/nselib/srvloc.lua +++ b/nselib/srvloc.lua @@ -31,9 +31,12 @@ -- Version 0.1 -- Created 24/04/2011 - v0.1 - created by Patrik Karlsson -module(... or "srvloc", package.seeall) - -require 'bit' +local bin = require "bin" +local bit = require "bit" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("srvloc", stdnse.seeall) PacketFunction = { SERVICE_REQUEST = 1, @@ -370,5 +373,6 @@ Helper = { close = function(self) return self.socket:close() end, - -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/ssh1.lua b/nselib/ssh1.lua index f1dcee7642..1fee0a530c 100644 --- a/nselib/ssh1.lua +++ b/nselib/ssh1.lua @@ -5,13 +5,14 @@ -- @author Sven Klemm -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "ssh1",package.seeall) -require "bin" -require "bit" -require "math" -require "stdnse" -require "openssl" +local bin = require "bin" +local bit = require "bit" +local math = require "math" +local nmap = require "nmap" +local openssl = require "openssl" +local stdnse = require "stdnse" +_ENV = stdnse.module("ssh1", stdnse.seeall) --- Retrieve the size of the packet that is being received -- and checks if it is fully received @@ -206,3 +207,5 @@ fingerprint_visual = function( fingerprint, algorithm, bits ) return s end + +return _ENV; diff --git a/nselib/ssh2.lua b/nselib/ssh2.lua index bc659027c5..346e93f02f 100644 --- a/nselib/ssh2.lua +++ b/nselib/ssh2.lua @@ -4,12 +4,13 @@ -- @author Sven Klemm -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "ssh2",package.seeall) - -require "bin" -require "base64" -require "openssl" -require "stdnse" +local base64 = require "base64" +local bin = require "bin" +local nmap = require "nmap" +local openssl = require "openssl" +local stdnse = require "stdnse" +local string = require "string" +_ENV = stdnse.module("ssh2", stdnse.seeall) -- table holding transport layer functions transport = {} @@ -238,3 +239,5 @@ SSH2 = { SSH_MSG_KEXDH_REPLY = 31, } + +return _ENV; diff --git a/nselib/sslcert.lua b/nselib/sslcert.lua index 2e3c0f4b5a..d37ab8dcbb 100644 --- a/nselib/sslcert.lua +++ b/nselib/sslcert.lua @@ -8,9 +8,11 @@ -- -- @author "Patrik Karlsson " -module(... or "sslcert", package.seeall) - -require("xmpp") +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local xmpp = require "xmpp" +_ENV = stdnse.module("sslcert", stdnse.seeall) StartTLS = { @@ -207,3 +209,5 @@ function getCertificate(host, port) end + +return _ENV; diff --git a/nselib/stdnse.lua b/nselib/stdnse.lua index 7a7ed7ee80..4ea6232dd4 100644 --- a/nselib/stdnse.lua +++ b/nselib/stdnse.lua @@ -4,53 +4,50 @@ -- -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html +local _G = require "_G" +local math = require "math" +local nmap = require "nmap" +local os = require "os" +local string = require "string" +local table = require "table" local assert = assert; local error = error; -local pairs = pairs +local getmetatable = getmetatable; local ipairs = ipairs +local pairs = pairs +local require = require; +local select = select +local setmetatable = setmetatable; local tonumber = tonumber; local type = type -local select = select -local unpack = unpack local ceil = math.ceil local max = math.max + local format = string.format; local rep = string.rep + local concat = table.concat; local insert = table.insert; -local os = os -local math = math -local string = string +local pack = table.pack; +local unpack = table.unpack; -local io = require 'io'; -- TODO: Remove - -local nmap = require "nmap"; - -local c_funcs = require "stdnse.c"; +local difftime = os.difftime; +local time = os.time; local EMPTY = {}; -- Empty constant table -module(... or "stdnse"); +_ENV = require "strict" {}; --- Load C functions from stdnse.c into this namespace. -for k, v in pairs(c_funcs) do - _M[k] = v -end --- Remove visibility of the stdnse.c table. -c = nil - ---- Sleeps for a given amount of time. +--- (Deprecated Alias) Sleeps for a given amount of time. +-- +-- Please use nmap.sleep instead. -- --- This causes the program to yield control and not regain it until the time --- period has elapsed. The time may have a fractional part. Internally, the --- timer provides millisecond resolution. -- @name sleep -- @class function -- @param t Time to sleep, in seconds. -- @usage stdnse.sleep(1.5) - --- sleep is a C function defined in nse_nmaplib.cc. +_ENV.sleep = nmap.sleep; --- -- Prints a formatted debug message if the current debugging level is greater @@ -349,7 +346,7 @@ end function format_difftime(t2, t1) local d, s, sign, yeardiff - d = os.difftime(os.time(t2), os.time(t1)) + d = difftime(time(t2), time(t1)) if d > 0 then sign = "+" elseif d < 0 then @@ -373,11 +370,11 @@ function format_difftime(t2, t1) local tmpyear = t1.year -- Put t1 in the same year as t2. t1.year = t2.year - d = os.difftime(os.time(t2), os.time(t1)) + d = difftime(time(t2), time(t1)) if d < 0 then -- Too far. Back off one year. t1.year = t2.year - 1 - d = os.difftime(os.time(t2), os.time(t1)) + d = difftime(time(t2), time(t1)) end yeardiff = t1.year - tmpyear t1.year = tmpyear @@ -853,7 +850,7 @@ end -- repeat -- local j = math.min(i+10, #requests); -- local co = stdnse.new_thread(thread_main, host, port, responses, --- unpack(requests, i, j)); +-- table.unpack(requests, i, j)); -- threads[co] = true; -- i = j+1; -- until i > #requests; @@ -968,4 +965,44 @@ function in_port_range(port,port_range) return false end +--- Module function that mimics some behavior of Lua 5.1 module function. +-- +-- This convenience function returns a module environment to set the _ENV +-- upvalue. The _NAME, _PACKAGE, and _M fields are set as in the Lua 5.1 +-- version of this function. Each option function (e.g. stdnse.seeall) +-- passed is run with the new environment, in order. +-- +-- @see stdnse.seeall +-- @see strict +-- @usage +-- _ENV = stdnse.module(name, stdnse.seeall, require "strict"); +-- @param name The module name. +-- @param ... Option functions which modify the environment of the module. +function module (name, ...) + local env = {}; + env._NAME = name; + env._PACKAGE = name:match("(.+)%.[^.]+$"); + env._M = env; + local mods = pack(...); + for i = 1, mods.n do + mods[i](env); + end + return env; +end + +--- Change environment to load global variables. +-- +-- Option function for use with stdnse.module. It is the same +-- as package.seeall from Lua 5.1. +-- +-- @see stdnse.module +-- @usage +-- _ENV = stdnse.module(name, stdnse.seeall); +-- @param env Environment to change. +function seeall (env) + local m = getmetatable(env) or {}; + m.__index = _G; + setmetatable(env, m); +end +return _ENV; diff --git a/nselib/strbuf.lua b/nselib/strbuf.lua index a0ad04c327..066dacc532 100644 --- a/nselib/strbuf.lua +++ b/nselib/strbuf.lua @@ -39,6 +39,8 @@ -- DEPENDENCIES -- +local stdnse = require "stdnse" +local table = require "table" local getmetatable = getmetatable; local setmetatable = setmetatable; local type = type; @@ -47,8 +49,7 @@ local ipairs = ipairs; local pairs = pairs; local concat = table.concat; - -module(... or "strbuf"); +_ENV = stdnse.module("strbuf", stdnse.seeall) -- String buffer functions. Concatenation is not efficient in -- lua as strings are immutable. If a large amount of '..' sequential @@ -136,3 +137,5 @@ local mt = { function new(...) return setmetatable({...}, mt); end + +return _ENV; diff --git a/nselib/strict.lua b/nselib/strict.lua index 29cfe0c34f..43f77abc33 100644 --- a/nselib/strict.lua +++ b/nselib/strict.lua @@ -14,16 +14,19 @@ -- @name strict -- @copyright Copyright© Same as Nmap--See http://nmap.org/book/man-legal.html +local debug = require "debug" + local error = error; -local getfenv = getfenv; -local lmodule = module; +local getmetatable = getmetatable; local rawset = rawset; local rawget = rawget; -local setfenv = setfenv; +local setmetatable = setmetatable; local type = type; local getinfo = debug.getinfo; +_ENV = {}; + local function what () local d = getinfo(3, "S"); return d and d.what or "C"; @@ -35,10 +38,18 @@ end -- undeclared globals. A global is 'undeclared' if not assigned in the file -- (script) scope previously. An error will be raised on use of an undeclared -- global. -function strict () - local _G = getfenv(2); - - local mt = getmetatable(_G) or setmetatable(_G, {}) and getmetatable(_G); +-- +-- This function should be passed last to stdnse.module in order to allow +-- other environment option functions (e.g. stdnse.seeall) to change the +-- environment first. This is important for allowing globals outside the +-- library (in _G) to be indexed. +-- +-- @see stdnse.module +-- @usage +-- _ENV = stdnse.module(name, require "strict"); +-- @param env The environment to modify. +local function strict (env) + local mt = getmetatable(env) or setmetatable(env, {}) and getmetatable(env); local _newindex, _index = mt.__newindex, mt.__index; mt.__declared = {}; @@ -70,16 +81,8 @@ function strict () end return rawget(t, n); end -end - -local strict = strict; -function module (...) - local myenv = getfenv(1); - lmodule(...); - strict(); - setfenv(2, getfenv(1)); - setfenv(1, myenv); + return env; end return strict; diff --git a/nselib/stun.lua b/nselib/stun.lua index 4bdc77f617..29932d853a 100644 --- a/nselib/stun.lua +++ b/nselib/stun.lua @@ -5,10 +5,16 @@ -- @author "Patrik Karlsson " -- -module(... or "stun", package.seeall) - -require 'ipOps' -require 'match' +local bin = require "bin" +local ipOps = require "ipOps" +local match = require "match" +local math = require "math" +local nmap = require "nmap" +local package = require "package" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("stun", stdnse.seeall) -- The supported request types MessageType = { @@ -366,3 +372,4 @@ Helper = { } +return _ENV; diff --git a/nselib/tab.lua b/nselib/tab.lua index 2846795038..08ff856f57 100644 --- a/nselib/tab.lua +++ b/nselib/tab.lua @@ -24,9 +24,11 @@ -- -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "tab", package.seeall) - -require('strbuf') +local stdnse = require "stdnse" +local strbuf = require "strbuf" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("tab", stdnse.seeall) --- Create and return a new table. -- @return A new table. @@ -122,3 +124,5 @@ function dump(t) return strbuf.dump(buf) end + +return _ENV; diff --git a/nselib/target.lua b/nselib/target.lua index 2f0f0effb8..de98358cf5 100644 --- a/nselib/target.lua +++ b/nselib/target.lua @@ -14,15 +14,14 @@ -- new targets. If set to 0 or less then there -- is no limit. The default value is 0. +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" local type = type local select = select -local unpack = unpack local tonumber = tonumber -local stdnse = require "stdnse" -local nmap = require "nmap" - -module ("target") +_ENV = stdnse.module("target", stdnse.seeall) -- This is a special variable and it is a global one, so @@ -69,7 +68,7 @@ end -- local status, err = target.add("192.168.1.1") -- local status, err = target.add("192.168.1.1","192.168.1.2",...) -- local status, err = target.add("scanme.nmap.org","192.168.1.1",...) --- local status, err = target.add(unpack(array_of_targets)) +-- local status, err = target.add(table.unpack(array_of_targets)) -- local status, pending_targets = target.add() -- @return True if it has been able to add a minimum one target, or -- False on failures and if no targets were added. If this @@ -103,7 +102,7 @@ add = function (...) return false, "Maximum new targets reached, no more new targets." end - local hosts, err = nmap.add_targets(unpack(new_targets,1,new_targets.count)) + local hosts, err = nmap.add_targets(table.unpack(new_targets,1,new_targets.count)) if hosts == 0 then stdnse.print_debug(3, "%s", err) @@ -112,3 +111,5 @@ add = function (...) return true, hosts end + +return _ENV; diff --git a/nselib/tftp.lua b/nselib/tftp.lua index 17bc9410e9..7a2f7b43fb 100644 --- a/nselib/tftp.lua +++ b/nselib/tftp.lua @@ -27,7 +27,13 @@ -- -- 2011-01-22 - re-wrote library to use coroutines instead of new_thread code. -module(... or "tftp", package.seeall) +local bin = require "bin" +local coroutine = require "coroutine" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("tftp", stdnse.seeall) threads, infiles, running = {}, {}, {} state = "STOPPED" @@ -336,3 +342,5 @@ function waitFile( filename, timeout ) return false end + +return _ENV; diff --git a/nselib/tns.lua b/nselib/tns.lua index 3170a489db..bba2cdb317 100644 --- a/nselib/tns.lua +++ b/nselib/tns.lua @@ -114,11 +114,15 @@ -- +--------+---------------+---------+-------+-------------------------------+ -- -require 'bin' -require 'bit' -stdnse.silent_require 'openssl' - -module(... or "tns", package.seeall) +local bin = require "bin" +local bit = require "bit" +local math = require "math" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local openssl = stdnse.silent_require "openssl" +_ENV = stdnse.module("tns", stdnse.seeall) -- Oracle version constants ORACLE_VERSION_10G = 313 @@ -1878,3 +1882,5 @@ TNSSocket = return self.Socket:send( data ) end, } + +return _ENV; diff --git a/nselib/unpwdb.lua b/nselib/unpwdb.lua index 60ad7dc1b0..9a54a6b1f7 100644 --- a/nselib/unpwdb.lua +++ b/nselib/unpwdb.lua @@ -65,7 +65,11 @@ -- @author Kris Katterjohn 06/2008 -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -module(... or "unpwdb", package.seeall) +local io = require "io" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +_ENV = stdnse.module("unpwdb", stdnse.seeall) local usertable = {} local passtable = {} @@ -281,3 +285,5 @@ passwords = function(time_limit, count_limit) return true, limited_iterator(iterator, time_limit, count_limit) end + +return _ENV; diff --git a/nselib/upnp.lua b/nselib/upnp.lua index 2c1c68c745..62949a8c27 100644 --- a/nselib/upnp.lua +++ b/nselib/upnp.lua @@ -33,11 +33,15 @@ -- Version 0.1 -- -module(... or "upnp", package.seeall) - -require("strbuf") -require("target") -require("http") +local http = require "http" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local strbuf = require "strbuf" +local string = require "string" +local table = require "table" +local target = require "target" +_ENV = stdnse.module("upnp", stdnse.seeall) Util = { @@ -339,3 +343,5 @@ Helper = { end, } + +return _ENV; diff --git a/nselib/url.lua b/nselib/url.lua index 513aebc26a..775dd1e530 100644 --- a/nselib/url.lua +++ b/nselib/url.lua @@ -30,10 +30,15 @@ parse_query and build_query added For nmap (Eddie Bell ) ----------------------------------------------------------------------------- -- Declare module ----------------------------------------------------------------------------- -local string = require("string") + +local _G = require "_G" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" local base = _G -local table = require("table") -module(... or "url",package.seeall) + + +_ENV = stdnse.module("url", stdnse.seeall) _VERSION = "URL 1.0" @@ -366,3 +371,5 @@ function build_query(query) end return string.sub(qstr, 0, #qstr-1) end + +return _ENV; diff --git a/nselib/versant.lua b/nselib/versant.lua index b3e004e72e..19c24c6a2b 100644 --- a/nselib/versant.lua +++ b/nselib/versant.lua @@ -6,9 +6,13 @@ -- @author "Patrik Karlsson " -- -module(... or "versant", package.seeall) - -require 'match' +local stdnse = require "stdnse" +local bin = require "bin" +local match = require "match" +local nmap = require "nmap" +local package = require "package" +local table = require "table" +_ENV = stdnse.module("versant", stdnse.seeall) Versant = { @@ -277,3 +281,5 @@ Versant.OBE = { return true, result end, } + +return _ENV; diff --git a/nselib/vnc.lua b/nselib/vnc.lua index 09564a27d0..4f8aedcd98 100644 --- a/nselib/vnc.lua +++ b/nselib/vnc.lua @@ -29,8 +29,13 @@ -- Created 07/07/2010 - v0.1 - created by Patrik Karlsson -module(... or "vnc", package.seeall) -require "bin" +local bin = require "bin" +local nmap = require "nmap" +local openssl = require "openssl" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("vnc", stdnse.seeall) local HAVE_SSL = false @@ -386,3 +391,5 @@ VNCSocket = return self.Socket:send( data ) end, } + +return _ENV; diff --git a/nselib/vulns.lua b/nselib/vulns.lua index 1dbbd2cb7b..cf014fdf7f 100644 --- a/nselib/vulns.lua +++ b/nselib/vulns.lua @@ -182,29 +182,29 @@ -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html +local bit = require "bit" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" local type = type local next = next local pairs = pairs local ipairs = ipairs local select = select local tostring = tostring -local table = require "table" local insert = table.insert local concat = table.concat local sort = table.sort local setmetatable = setmetatable -local string = require "string" local string_format = string.format local string_upper = string.upper -local bit = require "bit" -local ipOps = require "ipOps" -local nmap = require "nmap" -local stdnse = require "stdnse" local print_debug = stdnse.print_debug local compare_ip = ipOps.compare_ip -module("vulns") +_ENV = stdnse.module("vulns", stdnse.seeall) -- This is the vulnerability database -- (it will reference a table in the registry: nmap.registry.VULNS @@ -2261,3 +2261,5 @@ Report = { return stdnse.format_output(true, output) end, } + +return _ENV; diff --git a/nselib/vuzedht.lua b/nselib/vuzedht.lua index 3947667621..d15587e8f1 100644 --- a/nselib/vuzedht.lua +++ b/nselib/vuzedht.lua @@ -21,10 +21,17 @@ -- @author "Patrik Karlsson " -- -module(... or "vuzedht",package.seeall) +local bin = require "bin" +local ipOps = require "ipOps" +local math = require "math" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local openssl = stdnse.silent_require "openssl" +_ENV = stdnse.module("vuzedht", stdnse.seeall) -require 'ipOps' -stdnse.silent_require('openssl') Request = { @@ -546,3 +553,5 @@ Helper = { self.socket:close() end, } + +return _ENV; diff --git a/nselib/wsdd.lua b/nselib/wsdd.lua index 2f12d990f2..e269387fc0 100644 --- a/nselib/wsdd.lua +++ b/nselib/wsdd.lua @@ -32,9 +32,13 @@ -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -- -module(... or "wsdd", package.seeall) - -require 'target' +local bin = require "bin" +local nmap = require "nmap" +local openssl = require "openssl" +local stdnse = require "stdnse" +local table = require "table" +local target = require "target" +_ENV = stdnse.module("wsdd", stdnse.seeall) local HAVE_SSL = false @@ -136,15 +140,15 @@ Decoders = { local response = {} -- extracts the messagid, so we can check if we already got a response - response.msgid = data:match("\<.*:MessageID\>urn:uuid:(.*)\") + response.msgid = data:match("<.*:MessageID>urn:uuid:(.*)") -- if unable to parse msgid return nil if ( not(response.msgid) ) then return false, "No message id was found" end - response.xaddrs = data:match("\<.*:*XAddrs\>(.*)\") - response.types = data:match("\<.*:Types\>[wsdp:]*(.*)\") + response.xaddrs = data:match("<.*:*XAddrs>(.*)") + response.types = data:match("<.*:Types>[wsdp:]*(.*)") return true, response end, @@ -167,7 +171,7 @@ Decoders = { -- @return err string containing the error message ['error'] = function( data ) local response = "Failed to decode response from device: " - local err = data:match("\\(.-)\<") + local err = data:match("(.-)<") response = response .. (err or "Unknown error") return true, response @@ -380,3 +384,5 @@ Helper = { end, } + +return _ENV; diff --git a/nselib/xdmcp.lua b/nselib/xdmcp.lua index b12173b47e..ad64284f9f 100644 --- a/nselib/xdmcp.lua +++ b/nselib/xdmcp.lua @@ -4,7 +4,12 @@ -- -- @author "Patrik Karlsson " -module(... or "xdmcp", package.seeall) +local bin = require "bin" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +_ENV = stdnse.module("xdmcp", stdnse.seeall) -- Supported operations OpCode = { @@ -313,15 +318,15 @@ Helper = { return false, ("Failed to get information for interface %s"):format(self.host.interface) end - local req = xdmcp.Packet[xdmcp.OpCode.QUERY]:new(auth_names) + local req = Packet[OpCode.QUERY]:new(auth_names) local status, response = self:exch(req) if ( not(status) ) then return false, response - elseif ( response.header.opcode ~= xdmcp.OpCode.WILLING ) then + elseif ( response.header.opcode ~= OpCode.WILLING ) then return false, "Received unexpected response" end - local REQ = xdmcp.Packet[xdmcp.OpCode.REQUEST] + local REQ = Packet[OpCode.REQUEST] local iptype = REQ.Connection.IpType.IPv4 if ( nmap.address_family() == 'inet6' ) then iptype = REQ.Connection.IpType.IPv6 @@ -332,7 +337,7 @@ Helper = { local status, response = self:exch(req) if ( not(status) ) then return false, response - elseif ( response.header.opcode ~= xdmcp.OpCode.ACCEPT ) then + elseif ( response.header.opcode ~= OpCode.ACCEPT ) then return false, "Received unexpected response" end @@ -340,7 +345,7 @@ Helper = { -- set up a listening TCP server anyway. When we can, we could enable -- this and wait for the incoming request and retrieve X protocol info. - -- local manage = xdmcp.Packet[xdmcp.OpCode.MANAGE]:new(response.session_id, + -- local manage = Packet[OpCode.MANAGE]:new(response.session_id, -- disp_no, "MIT-unspecified") -- local status, response = self:exch(manage) -- if ( not(status) ) then @@ -391,4 +396,6 @@ Helper = { return self:recv() end, -} \ No newline at end of file +} + +return _ENV; diff --git a/nselib/xmpp.lua b/nselib/xmpp.lua index 47c06f0824..b2e63195a9 100644 --- a/nselib/xmpp.lua +++ b/nselib/xmpp.lua @@ -31,10 +31,14 @@ -- Revised 07/22/2011 - v0.2 - Added TagProcessors and two new auth mechs: -- CRAM-MD5 and LOGIN -module(... or "xmpp", package.seeall) +local base64 = require "base64" +local nmap = require "nmap" +local sasl = require "sasl" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +_ENV = stdnse.module("xmpp", stdnse.seeall) -require 'base64' -require 'sasl' XML = { @@ -43,7 +47,7 @@ XML = { -- stream handshake. If you see stanzas with uncommon symbols, feel -- free to enhance these regexps. parse_tag = function(s) - local _, _, contents, empty, name = string.find(s, "([^<]*)\<(/?)([?:%w-]+)") + local _, _, contents, empty, name = string.find(s, "([^<]*)<(/?)([?:%w-]+)") local attrs = {} if not name then return @@ -251,7 +255,7 @@ XMPP = { if ( mech == "PLAIN" ) then local mech_params = { username, password } - local auth_data = sasl.Helper:new(mech):encode(unpack(mech_params)) + local auth_data = sasl.Helper:new(mech):encode(table.unpack(mech_params)) auth = ("%s"):format(mech, base64.enc(auth_data)) @@ -303,7 +307,7 @@ XMPP = { end else local mech_params = { username, password, chall, "xmpp", "xmpp/" .. self.servername } - local auth_data = sasl.Helper:new(mech):encode(unpack(mech_params)) + local auth_data = sasl.Helper:new(mech):encode(table.unpack(mech_params)) auth_data = "" .. base64.enc(auth_data) .. "" @@ -414,4 +418,6 @@ Helper = { self.state = "DISCONNECTED" end, -} \ No newline at end of file +} + +return _ENV; diff --git a/scripts/acarsd-info.nse b/scripts/acarsd-info.nse index d591ec273f..c21f045fa0 100644 --- a/scripts/acarsd-info.nse +++ b/scripts/acarsd-info.nse @@ -1,3 +1,10 @@ +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Retrieves information from a listening acarsd daemon. Acarsd decodes ACARS (Aircraft Communication Addressing and Reporting System) data in @@ -37,9 +44,6 @@ author = "Brendan Coles" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe","discovery"} -require("stdnse") -require("comm") -require("shortport") portrule = shortport.port_or_service (2202, "acarsd", {"tcp"}) diff --git a/scripts/address-info.nse b/scripts/address-info.nse index c915088cdd..b7a26f55c0 100644 --- a/scripts/address-info.nse +++ b/scripts/address-info.nse @@ -1,3 +1,9 @@ +local bit = require "bit" +local datafiles = require "datafiles" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Shows extra information about IPv6 addresses, such as embedded MAC or IPv4 addresses when available. @@ -60,9 +66,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe"} -require("bit") -require("datafiles") -require("stdnse") hostrule = function(host) return true diff --git a/scripts/afp-brute.nse b/scripts/afp-brute.nse index 480577ddbe..94bea27ca6 100644 --- a/scripts/afp-brute.nse +++ b/scripts/afp-brute.nse @@ -1,3 +1,11 @@ +local afp = require "afp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local unpwdb = require "unpwdb" + description = [[ Performs password guessing against Apple Filing Protocol (AFP). ]] @@ -28,10 +36,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'stdnse' -require 'afp' -require 'unpwdb' -- Version 0.3 -- Created 01/15/2010 - v0.1 - created by Patrik Karlsson diff --git a/scripts/afp-ls.nse b/scripts/afp-ls.nse index 8ea43921c8..7d205648d4 100644 --- a/scripts/afp-ls.nse +++ b/scripts/afp-ls.nse @@ -1,3 +1,10 @@ +local afp = require "afp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Attempts to get useful information about files from AFP volumes. The output is intended to resemble the output of ls. @@ -53,10 +60,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'stdnse' -require 'afp' -require 'tab' dependencies = {"afp-brute"} diff --git a/scripts/afp-path-vuln.nse b/scripts/afp-path-vuln.nse index b9d5954082..f39a3ce3e2 100644 --- a/scripts/afp-path-vuln.nse +++ b/scripts/afp-path-vuln.nse @@ -1,3 +1,10 @@ +local afp = require "afp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local vulns = require "vulns" + description = [[ Detects the Mac OS X AFP directory traversal vulnerability, CVE-2010-0533. @@ -61,10 +68,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"exploit", "intrusive", "vuln"} -require 'shortport' -require 'stdnse' -require 'afp' -require 'vulns' dependencies = {"afp-brute"} diff --git a/scripts/afp-serverinfo.nse b/scripts/afp-serverinfo.nse index 2da5009f2d..ce4689fbbe 100644 --- a/scripts/afp-serverinfo.nse +++ b/scripts/afp-serverinfo.nse @@ -1,3 +1,10 @@ +local afp = require "afp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Shows AFP server information. This information includes the server's hostname, IPv4 and IPv6 addresses, and hardware type (for example @@ -41,10 +48,6 @@ author = "Andrew Orr" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require 'shortport' -require 'stdnse' -require 'afp' -require 'bit' portrule = shortport.portnumber(548, "tcp") diff --git a/scripts/afp-showmount.nse b/scripts/afp-showmount.nse index 162937e23a..b5247c2542 100644 --- a/scripts/afp-showmount.nse +++ b/scripts/afp-showmount.nse @@ -1,3 +1,9 @@ +local afp = require "afp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Shows AFP shares and ACLs. ]] @@ -32,9 +38,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'stdnse' -require 'afp' dependencies = {"afp-brute"} diff --git a/scripts/ajp-auth.nse b/scripts/ajp-auth.nse index 8e1dc305d1..463612f9cc 100644 --- a/scripts/ajp-auth.nse +++ b/scripts/ajp-auth.nse @@ -1,3 +1,9 @@ +local ajp = require "ajp" +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Retrieves the authentication scheme and realm of an AJP service that requires authentication. @@ -20,9 +26,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "auth", "safe"} -local ajp = require('ajp') -local http = require('http') -local shortport = require('shortport') portrule = shortport.port_or_service(8009, 'ajp13', 'tcp') diff --git a/scripts/ajp-brute.nse b/scripts/ajp-brute.nse index c186f6287f..b1925725f7 100644 --- a/scripts/ajp-brute.nse +++ b/scripts/ajp-brute.nse @@ -1,3 +1,11 @@ +local ajp = require "ajp" +local base64 = require "base64" +local brute = require "brute" +local creds = require "creds" +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Performs brute force passwords auditing against the Apache JServ protocol. The Apache JServ Protocol is commonly used by web servers to communicate with @@ -22,11 +30,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -local shortport = require('shortport') -local ajp = require('ajp') -local base64 = require('base64') -local brute = require('brute') -local http = require('http') portrule = shortport.port_or_service(8009, 'ajp13', 'tcp') @@ -106,4 +109,4 @@ action = function(host, port) if ( status ) then return result end -end \ No newline at end of file +end diff --git a/scripts/ajp-headers.nse b/scripts/ajp-headers.nse index 2cf53efe85..02612650be 100644 --- a/scripts/ajp-headers.nse +++ b/scripts/ajp-headers.nse @@ -1,3 +1,7 @@ +local ajp = require "ajp" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Performs a HEAD or GET request against either the root directory or any optional directory and returns the server response headers. @@ -18,8 +22,6 @@ optional directory and returns the server response headers. -- -- @args ajp-headers.path The path to request, such as /index.php. Default /. -local ajp = require('ajp') -local shortport = require('shortport') portrule = shortport.port_or_service(8009, 'ajp13', 'tcp') @@ -43,4 +45,4 @@ action = function(host, port) return fail("Failed to retrieve server headers") end return stdnse.format_output(true, response.rawheaders) -end \ No newline at end of file +end diff --git a/scripts/ajp-methods.nse b/scripts/ajp-methods.nse index c1a27edf0f..38270084dd 100644 --- a/scripts/ajp-methods.nse +++ b/scripts/ajp-methods.nse @@ -1,3 +1,8 @@ +local ajp = require "ajp" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Finds out what options are supported by the AJP server by sending an OPTIONS request and lists potentially risky methods. @@ -29,8 +34,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe"} -local ajp = require('ajp') -local shortport = require('shortport') portrule = shortport.port_or_service(8009, 'ajp13', 'tcp') @@ -77,4 +80,4 @@ action = function(host, port) table.insert(output, "See http://nmap.org/nsedoc/scripts/ajp-methods.html") end return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/ajp-request.nse b/scripts/ajp-request.nse index 1ab1cfd46c..4731f87702 100644 --- a/scripts/ajp-request.nse +++ b/scripts/ajp-request.nse @@ -1,3 +1,8 @@ +local ajp = require "ajp" +local io = require "io" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Request an URI over the Apache JServe Protocol and displays or alternatively stores the result in a file. Different AJP methods such as; GET, HEAD, TRACE, @@ -38,9 +43,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -local shortport = require('shortport') -local packet = require('packet') -local ajp = require('ajp') portrule = shortport.port_or_service(8009, 'ajp13', 'tcp') diff --git a/scripts/amqp-info.nse b/scripts/amqp-info.nse index 565e81b8c9..df671f1b50 100644 --- a/scripts/amqp-info.nse +++ b/scripts/amqp-info.nse @@ -1,3 +1,8 @@ +local amqp = require "amqp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Gathers information (a list of all server properties) from an AMQP (advanced message queuing protocol) server. @@ -33,9 +38,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe", "version"} -require("stdnse") -require("shortport") -require("amqp") portrule = shortport.port_or_service(5672, "amqp", "tcp", "open") diff --git a/scripts/asn-query.nse b/scripts/asn-query.nse index bb4c1ab3de..b24a7bb159 100644 --- a/scripts/asn-query.nse +++ b/scripts/asn-query.nse @@ -1,3 +1,10 @@ +local dns = require "dns" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Maps IP addresses to autonomous system (AS) numbers. @@ -36,10 +43,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "external", "safe"} -local dns = require "dns" -local comm = require "comm" -local ipOps = require "ipOps" -local stdnse = require "stdnse" local mutex = nmap.mutex( "ASN" ) @@ -333,9 +336,9 @@ function process_answers( records, output, ip ) elseif combined_records[record.cache_bgp].asn_type ~= record.asn_type then -- origin before peer. if record.asn_type == "Origin" then - combined_records[record.cache_bgp].asn = { unpack( record.asn ), unpack( combined_records[record.cache_bgp].asn ) } + combined_records[record.cache_bgp].asn = { table.unpack( record.asn ), table.unpack( combined_records[record.cache_bgp].asn ) } else - combined_records[record.cache_bgp].asn = { unpack( combined_records[record.cache_bgp].asn ), unpack( record.asn ) } + combined_records[record.cache_bgp].asn = { table.unpack( combined_records[record.cache_bgp].asn ), table.unpack( record.asn ) } end end end diff --git a/scripts/auth-owners.nse b/scripts/auth-owners.nse index 896d990015..c999c48082 100644 --- a/scripts/auth-owners.nse +++ b/scripts/auth-owners.nse @@ -1,3 +1,6 @@ +local nmap = require "nmap" +local string = require "string" + description = [[ Attempts to find the owner of an open TCP port by querying an auth daemon which must also be open on the target system. The auth service, diff --git a/scripts/auth-spoof.nse b/scripts/auth-spoof.nse index 334b781a5d..6213423d01 100644 --- a/scripts/auth-spoof.nse +++ b/scripts/auth-spoof.nse @@ -1,3 +1,6 @@ +local comm = require "comm" +local shortport = require "shortport" + description = [[ Checks for an identd (auth) server which is spoofing its replies. @@ -19,8 +22,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"malware", "safe"} -require "comm" -require "shortport" portrule = shortport.port_or_service(113, "auth") diff --git a/scripts/backorifice-brute.nse b/scripts/backorifice-brute.nse index 6dc0b5d487..8f4a69c395 100644 --- a/scripts/backorifice-brute.nse +++ b/scripts/backorifice-brute.nse @@ -1,3 +1,13 @@ +local bin = require "bin" +local bit = require "bit" +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Performs brute force password auditing against the BackOrifice service. The backorifice-brute.ports script argument is mandatory (it specifies ports to run @@ -36,13 +46,6 @@ author = "Gorjan Petrovski" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require("nmap") -require("bin") -require("bit") -require("shortport") -require("brute") -require("stdnse") -require("creds") -- This portrule succeeds only when the open|filtered port is in the port range -- which is specified by the ports script argument diff --git a/scripts/backorifice-info.nse b/scripts/backorifice-info.nse index aab407b93e..8b94b07952 100644 --- a/scripts/backorifice-info.nse +++ b/scripts/backorifice-info.nse @@ -1,3 +1,11 @@ +local bin = require "bin" +local bit = require "bit" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Connects to a BackOrifice service and gathers information about the host and the BackOrifice service itself. @@ -67,11 +75,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} dependencies = {"backorifice-brute"} -require("stdnse") -require("nmap") -require("bin") -require("bit") -require("shortport") portrule = shortport.port_or_service (31337, "BackOrifice", "udp") diff --git a/scripts/banner.nse b/scripts/banner.nse index 7b0be25db9..6aa85d155f 100644 --- a/scripts/banner.nse +++ b/scripts/banner.nse @@ -1,3 +1,8 @@ +local comm = require "comm" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" + description = [[ A simple banner grabber which connects to an open TCP port and prints out anything sent by the listening service within five seconds. @@ -17,9 +22,6 @@ categories = {"discovery", "safe"} -local nmap = require "nmap" -local comm = require "comm" -local stdnse = require "stdnse" --- diff --git a/scripts/bitcoin-getaddr.nse b/scripts/bitcoin-getaddr.nse index 1403f52bd2..69d78fecb6 100644 --- a/scripts/bitcoin-getaddr.nse +++ b/scripts/bitcoin-getaddr.nse @@ -1,3 +1,11 @@ +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" +local target = require "target" + +local bitcoin = stdnse.silent_require "bitcoin" + description = [[ Queries a Bitcoin server for a list of known Bitcoin nodes ]] @@ -21,11 +29,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'tab' -require 'target' -require 'stdnse' -stdnse.silent_require('bitcoin') -- -- Version 0.1 diff --git a/scripts/bitcoin-info.nse b/scripts/bitcoin-info.nse index e371ac7a3d..18e99f314b 100644 --- a/scripts/bitcoin-info.nse +++ b/scripts/bitcoin-info.nse @@ -1,3 +1,9 @@ +local bitcoin = require "bitcoin" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Extracts version and node information from a Bitcoin server ]] @@ -27,8 +33,6 @@ categories = {"discovery", "safe"} -- Created 11/09/2011 - v0.1 - created by Patrik Karlsson -- -require 'shortport' -require 'bitcoin' portrule = shortport.port_or_service(8333, "bitcoin", "tcp" ) diff --git a/scripts/bitcoinrpc-info.nse b/scripts/bitcoinrpc-info.nse index 4db18d4c38..f890a79498 100644 --- a/scripts/bitcoinrpc-info.nse +++ b/scripts/bitcoinrpc-info.nse @@ -1,3 +1,12 @@ +local creds = require "creds" +local http = require "http" +local json = require "json" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Obtains information from a Bitcoin server by calling getinfo on its JSON-RPC interface. ]] @@ -27,10 +36,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} dependencies = {"http-brute"} -require 'http' -require 'shortport' -require 'json' -require 'creds' portrule = shortport.portnumber(8332) diff --git a/scripts/bittorrent-discovery.nse b/scripts/bittorrent-discovery.nse index 32e67adc41..454a9d9ce9 100644 --- a/scripts/bittorrent-discovery.nse +++ b/scripts/bittorrent-discovery.nse @@ -1,3 +1,10 @@ +local stdnse = require "stdnse" +local table = require "table" +local target = require "target" + + +local bittorrent = stdnse.silent_require "bittorrent" + description = [[ Discovers bittorrent peers sharing a file based on a user-supplied torrent file or magnet link. Peers implement the Bittorrent protocol @@ -39,9 +46,6 @@ author = "Gorjan Petrovski" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","safe"} -require "target" -require 'stdnse' -stdnse.silent_require('bittorrent') prerule = function() if not stdnse.get_script_args(SCRIPT_NAME..".torrent") and diff --git a/scripts/broadcast-ataoe-discover.nse b/scripts/broadcast-ataoe-discover.nse index 43cfd333f4..9fc3a7242f 100644 --- a/scripts/broadcast-ataoe-discover.nse +++ b/scripts/broadcast-ataoe-discover.nse @@ -1,3 +1,12 @@ +local bin = require "bin" +local bit = require "bit" +local math = require "math" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Discovers servers supporting the ATA over Ethernet protocol. ATA over Ethernet is an ethernet protocol developed by the Brantley Coile Company and allows for @@ -22,8 +31,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'packet' -require 'bit' prerule = function() return true end @@ -170,4 +177,4 @@ action = function() if ( #result > 0 ) then return stdnse.format_output(true, result) end -end \ No newline at end of file +end diff --git a/scripts/broadcast-avahi-dos.nse b/scripts/broadcast-avahi-dos.nse index 94b874cbc8..7660bc426b 100644 --- a/scripts/broadcast-avahi-dos.nse +++ b/scripts/broadcast-avahi-dos.nse @@ -1,3 +1,8 @@ +local dnssd = require "dnssd" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" + description=[[ Attempts to discover hosts in the local network using the DNS Service Discovery protocol and sends a NULL UDP packet to each host to test @@ -36,8 +41,6 @@ author = "Djalal Harouni" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "dos", "intrusive", "vuln"} -require 'stdnse' -require 'dnssd' prerule = function() return true end diff --git a/scripts/broadcast-db2-discover.nse b/scripts/broadcast-db2-discover.nse index f8694e1a46..2ba67f3624 100644 --- a/scripts/broadcast-db2-discover.nse +++ b/scripts/broadcast-db2-discover.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + description = [[ Attempts to discover DB2 servers on the network by sending a broadcast request to port 523/udp. ]] @@ -19,9 +25,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require "stdnse" -require "shortport" -require "target" prerule = function() return true end @@ -80,4 +83,4 @@ action = function() socket:close() return stdnse.format_output( true, result ) -end \ No newline at end of file +end diff --git a/scripts/broadcast-dhcp-discover.nse b/scripts/broadcast-dhcp-discover.nse index a273525bcf..7b45f84614 100644 --- a/scripts/broadcast-dhcp-discover.nse +++ b/scripts/broadcast-dhcp-discover.nse @@ -1,3 +1,14 @@ +local bin = require "bin" +local coroutine = require "coroutine" +local dhcp = require "dhcp" +local ipOps = require "ipOps" +local math = require "math" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Sends a DHCP request to the broadcast address (255.255.255.255) and reports the results. The script uses a static MAC address (DE:AD:CO:DE:CA:FE) while @@ -38,10 +49,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'dhcp' -require 'ipOps' -require 'packet' -require 'nmap' prerule = function() if not nmap.is_privileged() then diff --git a/scripts/broadcast-dhcp6-discover.nse b/scripts/broadcast-dhcp6-discover.nse index 628fda16c8..09f0a2c116 100644 --- a/scripts/broadcast-dhcp6-discover.nse +++ b/scripts/broadcast-dhcp6-discover.nse @@ -1,3 +1,9 @@ +local coroutine = require "coroutine" +local dhcp6 = require "dhcp6" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Sends a DHCPv6 request (Solicit) to the DHCPv6 multicast address, parses the response, then extracts and prints the address along with @@ -29,7 +35,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'dhcp6' prerule = function() if not nmap.is_privileged() then @@ -108,4 +113,4 @@ action = function(host, port) until next(threads) == nil return stdnse.format_output(true, result) -end \ No newline at end of file +end diff --git a/scripts/broadcast-dns-service-discovery.nse b/scripts/broadcast-dns-service-discovery.nse index e515411020..a93fb9d314 100644 --- a/scripts/broadcast-dns-service-discovery.nse +++ b/scripts/broadcast-dns-service-discovery.nse @@ -1,3 +1,6 @@ +local dnssd = require "dnssd" +local stdnse = require "stdnse" + description=[[ Attempts to discover hosts' services using the DNS Service Discovery protocol. It sends a multicast DNS-SD query and collects all the responses. @@ -40,8 +43,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'shortport' -require 'dnssd' prerule = function() return true end diff --git a/scripts/broadcast-dropbox-listener.nse b/scripts/broadcast-dropbox-listener.nse index b99bad63cf..efc7d7fff0 100644 --- a/scripts/broadcast-dropbox-listener.nse +++ b/scripts/broadcast-dropbox-listener.nse @@ -1,3 +1,9 @@ +local json = require "json" +local nmap = require "nmap" +local stdnse = require "stdnse" +local tab = require "tab" +local target = require "target" + description = [[ Listens for the LAN sync information broadcasts that the Dropbox.com client broadcasts every 20 seconds, then prints all the discovered client IP addresses, port numbers, version numbers, display names, and more. @@ -29,11 +35,6 @@ author = "Ron Bowes, Mak Kolybabi, Andrew Orr, Russ Tait Milne" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require("json") -require("shortport") -require("stdnse") -require("tab") -require("target") local DROPBOX_BROADCAST_PERIOD = 20 local DROPBOX_PORT = 17500 diff --git a/scripts/broadcast-listener.nse b/scripts/broadcast-listener.nse index 53eafcab05..d080c16fbc 100644 --- a/scripts/broadcast-listener.nse +++ b/scripts/broadcast-listener.nse @@ -1,3 +1,11 @@ +local _G = require "_G" +local bin = require "bin" +local coroutine = require "coroutine" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Sniffs the network for incoming broadcast communication and attempts to decode the received packets. It supports protocols like CDP, HSRP, @@ -75,9 +83,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require('packet') -require('tab') -require('nmap') prerule = function() @@ -103,16 +108,16 @@ loadDecoders = function(fname) return false, ("ERROR: Failed to load decoder definition (%s)"):format(fname) end - local file = loadfile(abs_fname) + local env = setmetatable({Decoders = {}}, {__index = _G}); + local file = loadfile(abs_fname, "t", env) if(not(file)) then stdnse.print_debug("%s: Couldn't load decoder file: %s", SCRIPT_NAME, fname) return false, "ERROR: Couldn't load decoder file: " .. fname end - setfenv(file, setmetatable({Decoders = {}; }, {__index = _G})) file() - local d = getfenv(file)["Decoders"] + local d = env.Decoders if ( d ) then return true, d end return false, "ERROR: Failed to load decoders" diff --git a/scripts/broadcast-ms-sql-discover.nse b/scripts/broadcast-ms-sql-discover.nse index 21fefca57e..461b723af2 100644 --- a/scripts/broadcast-ms-sql-discover.nse +++ b/scripts/broadcast-ms-sql-discover.nse @@ -1,3 +1,9 @@ +local mssql = require "mssql" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -47,9 +53,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'mssql' -require 'target' -require 'stdnse' prerule = function() return true end diff --git a/scripts/broadcast-netbios-master-browser.nse b/scripts/broadcast-netbios-master-browser.nse index a2063b52a3..8ef52d5d29 100644 --- a/scripts/broadcast-netbios-master-browser.nse +++ b/scripts/broadcast-netbios-master-browser.nse @@ -1,3 +1,9 @@ +local bit = require "bit" +local netbios = require "netbios" +local nmap = require "nmap" +local stdnse = require "stdnse" +local tab = require "tab" + description = [[ Attempts to discover master browsers and the domains they manage. ]] @@ -19,9 +25,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'netbios' -require 'tab' -require 'bit' prerule = function() return true end @@ -62,4 +65,4 @@ action = function() end end return "\n" .. tab.dump(outtab) -end \ No newline at end of file +end diff --git a/scripts/broadcast-networker-discover.nse b/scripts/broadcast-networker-discover.nse index 9ce43698ba..ed2b7cba4b 100644 --- a/scripts/broadcast-networker-discover.nse +++ b/scripts/broadcast-networker-discover.nse @@ -1,3 +1,8 @@ +local nmap = require "nmap" +local rpc = require "rpc" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Discovers the EMC Networker backup software server on a LAN by using network broadcasts. @@ -17,7 +22,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'rpc' prerule = function() return true end @@ -88,4 +92,4 @@ action = function() if ( "table" == type(results) and 0 < #results ) then return stdnse.format_output(true, results) end -end \ No newline at end of file +end diff --git a/scripts/broadcast-novell-locate.nse b/scripts/broadcast-novell-locate.nse index 980ffc617d..a35beab815 100644 --- a/scripts/broadcast-novell-locate.nse +++ b/scripts/broadcast-novell-locate.nse @@ -1,3 +1,9 @@ +local bin = require "bin" +local ipOps = require "ipOps" +local srvloc = require "srvloc" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to use the Service Location Protocol to discover Novell NetWare Core Protocol (NCP) servers. ]] @@ -21,8 +27,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'srvloc' -require 'ipOps' prerule = function() return true end diff --git a/scripts/broadcast-pc-anywhere.nse b/scripts/broadcast-pc-anywhere.nse index dd9e4891bc..72028a1321 100644 --- a/scripts/broadcast-pc-anywhere.nse +++ b/scripts/broadcast-pc-anywhere.nse @@ -1,3 +1,8 @@ +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Sends a special broadcast probe to discover PC-Anywhere hosts running on a LAN. ]] diff --git a/scripts/broadcast-pc-duo.nse b/scripts/broadcast-pc-duo.nse index f14eade0cb..38266ec2f1 100644 --- a/scripts/broadcast-pc-duo.nse +++ b/scripts/broadcast-pc-duo.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local coroutine = require "coroutine" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Discovers PC-DUO remote control hosts and gateways running on a LAN by sending a special UDP probe. ]] @@ -119,4 +126,4 @@ action = function() if ( #responses > 0 ) then return stdnse.format_output(true, responses) end -end \ No newline at end of file +end diff --git a/scripts/broadcast-ping.nse b/scripts/broadcast-ping.nse index 23ae2eb6c8..4c7d48e149 100644 --- a/scripts/broadcast-ping.nse +++ b/scripts/broadcast-ping.nse @@ -1,3 +1,15 @@ +local bin = require "bin" +local coroutine = require "coroutine" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" +local target = require "target" + +local openssl = stdnse.silent_require "openssl" + description = [[ Sends broadcast pings on a selected interface using raw ethernet packets and outputs the responding hosts' IP and MAC addresses or (if requested) adds them as targets. Root privileges on UNIX are required to run this script since it uses raw sockets. Most operating systems don't respond to broadcast-ping probes, @@ -46,13 +58,6 @@ author = "Gorjan Petrovski" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","safe","broadcast"} -require "nmap" -require "stdnse" -require "packet" -require "bin" -require "tab" -require "target" -stdnse.silent_require("openssl") prerule = function() if not nmap.is_privileged() then diff --git a/scripts/broadcast-pppoe-discover.nse b/scripts/broadcast-pppoe-discover.nse index d0b3a42434..6bfe556826 100644 --- a/scripts/broadcast-pppoe-discover.nse +++ b/scripts/broadcast-pppoe-discover.nse @@ -1,3 +1,9 @@ +local bin = require "bin" +local nmap = require "nmap" +local pppoe = require "pppoe" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Discovers PPPoE servers using the PPPoE Discovery protocol (PPPoED). PPPoE is an ethernet based protocol so the script has to know what ethernet @@ -27,8 +33,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'pppoe' -require 'nmap' prerule = function() if not nmap.is_privileged() then @@ -125,4 +129,4 @@ action = function() return stdnse.format_output(true, output) end -end \ No newline at end of file +end diff --git a/scripts/broadcast-rip-discover.nse b/scripts/broadcast-rip-discover.nse index b4c0bdd973..755fdec7ca 100644 --- a/scripts/broadcast-rip-discover.nse +++ b/scripts/broadcast-rip-discover.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description=[[ Discovers hosts and routing information from devices running RIPv2 on the LAN. It does so by sending a RIPv2 Request command and collects the responses @@ -36,9 +43,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'bin' -require 'ipOps' -require 'tab' prerule = function() return not( nmap.address_family() == "inet6") end @@ -174,4 +178,4 @@ action = function() result.name = "Discovered RIPv2 devices" end return stdnse.format_output(true, result) -end \ No newline at end of file +end diff --git a/scripts/broadcast-ripng-discover.nse b/scripts/broadcast-ripng-discover.nse index 89e7ca9352..62cc8da194 100644 --- a/scripts/broadcast-ripng-discover.nse +++ b/scripts/broadcast-ripng-discover.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Discovers hosts and routing information from devices running RIPng on the LAN by sending a RIPng Request command and collecting the responses @@ -23,8 +30,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'ipOps' -require 'tab' prerule = function() return ( nmap.address_family() == "inet6" ) end @@ -208,4 +213,4 @@ action = function() table.insert(result, { name = ip, parse_response(resp) } ) end return stdnse.format_output(true, result) -end \ No newline at end of file +end diff --git a/scripts/broadcast-sybase-asa-discover.nse b/scripts/broadcast-sybase-asa-discover.nse index f8acd77d67..050fced7d2 100644 --- a/scripts/broadcast-sybase-asa-discover.nse +++ b/scripts/broadcast-sybase-asa-discover.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local bit = require "bit" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Discovers Sybase Anywhere servers on the LAN by sending broadcast discovery messages. ]] @@ -178,4 +185,4 @@ action = function() end table.sort(result) return stdnse.format_output(true, result) -end \ No newline at end of file +end diff --git a/scripts/broadcast-tellstick-discover.nse b/scripts/broadcast-tellstick-discover.nse index 54470fe303..c09a390f2f 100644 --- a/scripts/broadcast-tellstick-discover.nse +++ b/scripts/broadcast-tellstick-discover.nse @@ -1,3 +1,7 @@ +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" + description=[[ Discovers Telldus Technologies TellStickNet devices on the LAN. The Telldus TellStick is used to wirelessly control electric devices such as lights, diff --git a/scripts/broadcast-upnp-info.nse b/scripts/broadcast-upnp-info.nse index cf2cbae143..897fdde0b0 100644 --- a/scripts/broadcast-upnp-info.nse +++ b/scripts/broadcast-upnp-info.nse @@ -1,3 +1,6 @@ +local stdnse = require "stdnse" +local upnp = require "upnp" + description = [[ Attempts to extract system information from the UPnP service by sending a multicast query, then collecting, parsing, and displaying all responses. ]] @@ -30,8 +33,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require("shortport") -require("upnp") prerule = function() return true end diff --git a/scripts/broadcast-versant-locate.nse b/scripts/broadcast-versant-locate.nse index 36d983f5ad..5fa5abdf99 100644 --- a/scripts/broadcast-versant-locate.nse +++ b/scripts/broadcast-versant-locate.nse @@ -1,3 +1,7 @@ +local srvloc = require "srvloc" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Discovers Versant object databases using the srvloc protocol. ]] @@ -17,7 +21,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'srvloc' prerule = function() return true end @@ -32,4 +35,4 @@ action = function() table.insert(output, v:match("^service:odbms.versant:vod://(.*)$")) end return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/broadcast-wake-on-lan.nse b/scripts/broadcast-wake-on-lan.nse index 7ec4ecfecf..594a12418e 100644 --- a/scripts/broadcast-wake-on-lan.nse +++ b/scripts/broadcast-wake-on-lan.nse @@ -1,3 +1,7 @@ +local bin = require "bin" +local nmap = require "nmap" +local stdnse = require "stdnse" + description = [[ Wakes a remote system up from sleep by sending a Wake-On-Lan packet. ]] @@ -64,4 +68,4 @@ action = function() end return stdnse.format_output(true, ("Sent WOL packet to: %s"):format(MAC)) end - \ No newline at end of file + diff --git a/scripts/broadcast-wpad-discover.nse b/scripts/broadcast-wpad-discover.nse index 4d1bf8c40a..f82f37d524 100644 --- a/scripts/broadcast-wpad-discover.nse +++ b/scripts/broadcast-wpad-discover.nse @@ -1,3 +1,12 @@ +local dhcp = require "dhcp" +local dns = require "dns" +local http = require "http" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local url = require "url" + description = [[ Retrieves a list of proxy servers on the LAN using the Web Proxy Autodiscovery Protocol (WPAD). It implements both the DHCP and DNS @@ -26,10 +35,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'dns' -require 'dhcp' -require 'http' -require 'url' prerule = function() return true end @@ -224,4 +229,4 @@ action = function() local output = ( arg_getwpad and response or parseWPAD(response) ) return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/broadcast-wsdd-discover.nse b/scripts/broadcast-wsdd-discover.nse index 1fc60bb74e..112cc59446 100644 --- a/scripts/broadcast-wsdd-discover.nse +++ b/scripts/broadcast-wsdd-discover.nse @@ -1,3 +1,9 @@ +local coroutine = require "coroutine" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +local wsdd = require "wsdd" + description = [[ Uses a multicast query to discover devices supporting the Web Services Dynamic Discovery (WS-Discovery) protocol. It also attempts to locate @@ -39,8 +45,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'shortport' -require 'wsdd' prerule = function() return true end @@ -57,15 +61,8 @@ discoverThread = function( funcname, results ) helper:setMulticast(true) helper:setTimeout(timeout) - local func = loadstring( "return helper:" .. funcname .. "()" ) - setfenv(func, setmetatable({ helper=helper; }, {__index = _G})) - - if ( func ) then - local status, result = func() - if ( status ) then table.insert(results, result) end - else - stdnse.print_debug("ERROR: Failed to call function: %s", funcname) - end + local status, result = helper[funcname](helper) + if ( status ) then table.insert(results, result) end condvar("broadcast") end diff --git a/scripts/broadcast-xdmcp-discover.nse b/scripts/broadcast-xdmcp-discover.nse index 527982076c..1db237c7d7 100644 --- a/scripts/broadcast-xdmcp-discover.nse +++ b/scripts/broadcast-xdmcp-discover.nse @@ -1,3 +1,8 @@ +local os = require "os" +local stdnse = require "stdnse" +local table = require "table" +local xdmcp = require "xdmcp" + description = [[ Discovers servers running the X Display Manager Control Protocol (XDMCP) by sending a XDMCP broadcast request to the LAN. Display managers allowing access @@ -19,7 +24,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast", "safe"} -require 'xdmcp' prerule = function() return true end @@ -66,4 +70,4 @@ action = function() end end return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/cccam-version.nse b/scripts/cccam-version.nse index 33fa009f4b..00820cbd06 100644 --- a/scripts/cccam-version.nse +++ b/scripts/cccam-version.nse @@ -1,3 +1,8 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description = [[ Detects the CCcam service (software for sharing subscription TV among multiple receivers). @@ -14,8 +19,6 @@ categories = {"version"} author = "David Fifield" -require("bin") -require("shortport") -- A chi-square test for the null hypothesis that the members of data are drawn -- from a uniform distribution over num_cats categories. diff --git a/scripts/citrix-brute-xml.nse b/scripts/citrix-brute-xml.nse index 5e652b0a34..f0562a48e9 100644 --- a/scripts/citrix-brute-xml.nse +++ b/scripts/citrix-brute-xml.nse @@ -1,3 +1,10 @@ +local citrixxml = require "citrixxml" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local unpwdb = require "unpwdb" + description = [[ Attempts to guess valid credentials for the Citrix PN Web Agent XML Service. The XML service authenticates against the local Windows server @@ -30,9 +37,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "auth"} -require 'unpwdb' -require 'shortport' -require 'citrixxml' portrule = shortport.portnumber({8080,80,443}, "tcp") diff --git a/scripts/citrix-enum-apps-xml.nse b/scripts/citrix-enum-apps-xml.nse index 1c10deb132..fbbdad2d2c 100644 --- a/scripts/citrix-enum-apps-xml.nse +++ b/scripts/citrix-enum-apps-xml.nse @@ -1,3 +1,9 @@ +local citrixxml = require "citrixxml" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Extracts a list of applications, ACLs, and settings from the Citrix XML service. @@ -60,9 +66,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "comm" -require 'shortport' -require 'citrixxml' portrule = shortport.portnumber({8080,80,443}, "tcp") diff --git a/scripts/citrix-enum-apps.nse b/scripts/citrix-enum-apps.nse index c9e79a8b9c..1d24e6331d 100644 --- a/scripts/citrix-enum-apps.nse +++ b/scripts/citrix-enum-apps.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Extracts a list of published applications from the ICA Browser service. ]] @@ -26,10 +33,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","safe"} -require "comm" -require "shortport" -require "stdnse" -require "bin" portrule = shortport.portnumber(1604, "udp") diff --git a/scripts/citrix-enum-servers-xml.nse b/scripts/citrix-enum-servers-xml.nse index b0516cd60b..47df263d4c 100644 --- a/scripts/citrix-enum-servers-xml.nse +++ b/scripts/citrix-enum-servers-xml.nse @@ -1,3 +1,8 @@ +local citrixxml = require "citrixxml" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Extracts the name of the server farm and member servers from Citrix XML service. @@ -23,9 +28,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "comm" -require 'shortport' -require 'citrixxml' portrule = shortport.portnumber({8080,80,443}, "tcp") diff --git a/scripts/citrix-enum-servers.nse b/scripts/citrix-enum-servers.nse index 577035fd79..8f164282af 100644 --- a/scripts/citrix-enum-servers.nse +++ b/scripts/citrix-enum-servers.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Extracts a list of Citrix servers from the ICA Browser service. ]] @@ -23,8 +30,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "comm" -require "shortport" portrule = shortport.portnumber(1604, "udp") diff --git a/scripts/couchdb-databases.nse b/scripts/couchdb-databases.nse index 06e73fb62c..f7c521d8c9 100644 --- a/scripts/couchdb-databases.nse +++ b/scripts/couchdb-databases.nse @@ -1,3 +1,10 @@ +local http = require "http" +local json = require "json" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Gets database tables from a CouchDB database. @@ -28,14 +35,11 @@ http://wiki.apache.org/couchdb/HTTP_database_API. author = "Martin Holst Swende" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "shortport" -require "http" -require "json" portrule = shortport.port_or_service({5984}) -- Some lazy shortcuts local function dbg(str,...) - stdnse.print_debug("couchdb-get-tables:"..str, unpack(arg)) + stdnse.print_debug("couchdb-get-tables:"..str, table.unpack(arg)) end local DISCARD = {} diff --git a/scripts/couchdb-stats.nse b/scripts/couchdb-stats.nse index 294017b5f5..3d84f7c70e 100644 --- a/scripts/couchdb-stats.nse +++ b/scripts/couchdb-stats.nse @@ -1,3 +1,11 @@ +local http = require "http" +local json = require "json" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Gets database statistics from a CouchDB database. @@ -40,13 +48,10 @@ http://wiki.apache.org/couchdb/HTTP_database_API. author = "Martin Holst Swende" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "shortport" -require "http" -require "json" portrule = shortport.port_or_service({5984}) -- Some lazy shortcuts local function dbg(str,...) - stdnse.print_debug("couchdb-stats:"..str, unpack(arg)) + stdnse.print_debug("couchdb-stats:"..str, table.unpack(arg)) end diff --git a/scripts/creds-summary.nse b/scripts/creds-summary.nse index ce41fd9dfc..8c95e76d35 100644 --- a/scripts/creds-summary.nse +++ b/scripts/creds-summary.nse @@ -1,3 +1,5 @@ +local creds = require "creds" + description = [[ Lists all discovered credentials (e.g. from brute force and default password checking scripts) at end of scan. ]] @@ -26,7 +28,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "default", "safe"} -require 'creds' postrule = function() local all = creds.Credentials:new(creds.ALL_DATA) diff --git a/scripts/cups-info.nse b/scripts/cups-info.nse index dc53ee57b7..6b4259a77d 100644 --- a/scripts/cups-info.nse +++ b/scripts/cups-info.nse @@ -1,3 +1,9 @@ +local bin = require "bin" +local ipp = require "ipp" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Lists printers managed by the CUPS printing service. ]] @@ -34,9 +40,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -local http = require('http') -local shortport = require('shortport') -local ipp = require('ipp') portrule = shortport.port_or_service(631, "ipp", "tcp", "open") @@ -75,4 +78,4 @@ action = function(host, port) if ( 0 ~= #output ) then return stdnse.format_output(true, output) end -end \ No newline at end of file +end diff --git a/scripts/cups-queue-info.nse b/scripts/cups-queue-info.nse index 269ccc0592..f93bbf0bba 100644 --- a/scripts/cups-queue-info.nse +++ b/scripts/cups-queue-info.nse @@ -1,3 +1,7 @@ +local ipp = require "ipp" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Lists currently queued print jobs of the remote CUPS service grouped by printer. @@ -27,9 +31,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -local http = require('http') -local shortport = require('shortport') -local ipp = require('ipp') portrule = shortport.port_or_service(631, "ipp", "tcp", "open") @@ -45,4 +46,4 @@ action = function(host, port) if ( output ) then return stdnse.format_output(true, output) end -end \ No newline at end of file +end diff --git a/scripts/cvs-brute-repository.nse b/scripts/cvs-brute-repository.nse index e137df6a9c..2ad3b004b3 100644 --- a/scripts/cvs-brute-repository.nse +++ b/scripts/cvs-brute-repository.nse @@ -1,3 +1,12 @@ +local brute = require "brute" +local coroutine = require "coroutine" +local cvs = require "cvs" +local io = require "io" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to guess the name of the CVS repositories hosted on the remote server. With knowledge of the correct repository name, usernames and passwords can be guessed. @@ -29,10 +38,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'cvs' -require 'brute' -require 'creds' -require 'shortport' portrule = shortport.port_or_service(2401, "cvspserver") diff --git a/scripts/cvs-brute.nse b/scripts/cvs-brute.nse index e8eeb174cf..47816e5705 100644 --- a/scripts/cvs-brute.nse +++ b/scripts/cvs-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local cvs = require "cvs" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Performs brute force password auditing against CVS pserver authentication. ]] @@ -30,10 +37,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} dependencies = {"cvs-brute-repository"} -require 'cvs' -require 'brute' -require 'creds' -require 'shortport' portrule = shortport.port_or_service(2401, "cvspserver") diff --git a/scripts/daap-get-library.nse b/scripts/daap-get-library.nse index dfe39ea936..4a84fb468f 100644 --- a/scripts/daap-get-library.nse +++ b/scripts/daap-get-library.nse @@ -1,3 +1,11 @@ +local bin = require "bin" +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Retrieves a list of music from a DAAP server. The list includes artist names and album and song titles. @@ -36,9 +44,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'stdnse' -require 'http' -- Version 0.2 -- Created 01/14/2010 - v0.1 - created by Patrik Karlsson diff --git a/scripts/daytime.nse b/scripts/daytime.nse index 5b7c3a90ee..773f69c8a1 100644 --- a/scripts/daytime.nse +++ b/scripts/daytime.nse @@ -1,3 +1,6 @@ +local comm = require "comm" +local shortport = require "shortport" + description = [[ Retrieves the day and time from the Daytime service. ]] @@ -14,8 +17,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "comm" -require "shortport" portrule = shortport.port_or_service(13, "daytime", {"tcp", "udp"}) diff --git a/scripts/db2-das-info.nse b/scripts/db2-das-info.nse index 45688ad53f..b9e7584452 100644 --- a/scripts/db2-das-info.nse +++ b/scripts/db2-das-info.nse @@ -1,3 +1,9 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Connects to the IBM DB2 Administration Server (DAS) on TCP or UDP port 523 and exports the server profile. No authentication is required for this request. @@ -61,8 +67,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery", "version"} -require "stdnse" -require "shortport" --- Research Notes: -- diff --git a/scripts/db2-discover.nse b/scripts/db2-discover.nse index cc62940b44..524273a8d3 100644 --- a/scripts/db2-discover.nse +++ b/scripts/db2-discover.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to discover DB2 servers on the network by querying open ibm-db2 UDP ports (normally port 523). ]] @@ -23,8 +29,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe", "default"} -require "stdnse" -require "shortport" portrule = shortport.version_port_or_service(523, "ibm-db2", "udp", {"open", "open|filtered"}) diff --git a/scripts/dhcp-discover.nse b/scripts/dhcp-discover.nse index af265da5cd..bdca0907e8 100644 --- a/scripts/dhcp-discover.nse +++ b/scripts/dhcp-discover.nse @@ -1,3 +1,11 @@ +local dhcp = require "dhcp" +local math = require "math" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Sends a DHCPINFORM request to a host on UDP port 67 to obtain all the local configuration parameters without allocating a new address. @@ -59,11 +67,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'bin' -require 'bit' -require 'dhcp' -require 'shortport' -require 'stdnse' -- We want to run against a specific host if UDP/67 is open function portrule(host, port) diff --git a/scripts/dict-info.nse b/scripts/dict-info.nse index cb353e051f..78c8dc6710 100644 --- a/scripts/dict-info.nse +++ b/scripts/dict-info.nse @@ -1,3 +1,8 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Connects to a dictionary server using the DICT protocol and runs the SHOW SERVER command and displays the result. The DICT protocol is defined in RFC @@ -29,7 +34,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -local shortport = require('shortport') portrule = shortport.port_or_service(2628, "dict", "tcp") @@ -71,4 +75,4 @@ action = function(host, port) srvinfo[#srvinfo] = ( srvinfo[#srvinfo] ~= "" and srvinfo[#srvinfo] or nil ) return stdnse.format_output(true, srvinfo) -end \ No newline at end of file +end diff --git a/scripts/distcc-cve2004-2687.nse b/scripts/distcc-cve2004-2687.nse index 5954ff4504..b7261af702 100644 --- a/scripts/distcc-cve2004-2687.nse +++ b/scripts/distcc-cve2004-2687.nse @@ -1,3 +1,8 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local vulns = require "vulns" + description = [[ Detects and exploits a remote code execution vulnerability in the distributed compiler daemon distcc. The vulnerability was disclosed in 2002, but is still @@ -39,8 +44,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"exploit", "intrusive", "vuln"} -local shortport = require('shortport') -local vulns = require('vulns') portrule = shortport.port_or_service(3632, "distcc") @@ -102,4 +105,4 @@ earlier. The vulnerability is the consequence of weak service configuration. return report:make_output(distcc_vuln) end end -end \ No newline at end of file +end diff --git a/scripts/dns-blacklist.nse b/scripts/dns-blacklist.nse index ce8ab9195f..0d623adf69 100644 --- a/scripts/dns-blacklist.nse +++ b/scripts/dns-blacklist.nse @@ -1,3 +1,8 @@ +local dnsbl = require "dnsbl" +local ipOps = require "ipOps" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Checks target IP addresses against multiple DNS anti-spam and open proxy blacklists and returns a list of services for which an IP has been flagged. Checks may be limited by service category (eg: SPAM, @@ -68,10 +73,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"external", "safe"} -require 'dns' -require 'dnsbl' -require 'tab' -require 'ipOps' -- The script can be run either as a host- or pre-rule hostrule = function() return true end diff --git a/scripts/dns-brute.nse b/scripts/dns-brute.nse index 0afe1f99f2..54f74826f6 100644 --- a/scripts/dns-brute.nse +++ b/scripts/dns-brute.nse @@ -1,3 +1,13 @@ +local coroutine = require "coroutine" +local dns = require "dns" +local io = require "io" +local math = require "math" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + description = [[ Attempts to enumerate DNS hostnames by brute force guessing of common subdomains. ]] @@ -43,9 +53,6 @@ hostrule = function(host) end -require 'dns' -require 'stdnse' -require 'target' local HOST_LIST = { 'www', 'mail', 'blog', 'ns0', 'ns1', 'mail2', 'mail3', 'admin', 'ads', 'ssh', diff --git a/scripts/dns-cache-snoop.nse b/scripts/dns-cache-snoop.nse index 2b9980a44e..fb6bafc808 100644 --- a/scripts/dns-cache-snoop.nse +++ b/scripts/dns-cache-snoop.nse @@ -1,3 +1,10 @@ +local dns = require "dns" +local math = require "math" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Performs DNS cache snooping against a DNS server. @@ -47,11 +54,6 @@ different list. -- | www.google.co.uk -- |_www.linkedin.com -require("shortport") -require("dns") -require("stdnse") -require("nmap") -require("math") author = "Eugene V. Alexeev" diff --git a/scripts/dns-check-zone.nse b/scripts/dns-check-zone.nse index 179c86ab07..5d4f3a6a9c 100644 --- a/scripts/dns-check-zone.nse +++ b/scripts/dns-check-zone.nse @@ -1,3 +1,7 @@ +local dns = require "dns" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Checks DNS zone configuration against best practices, including RFC 1912. The configuration checks are divided into categories that each have a number @@ -48,9 +52,6 @@ categories = {"discovery", "safe", "external"} local arg_domain = stdnse.get_script_args(SCRIPT_NAME .. '.domain') -local shortport = require('shortport') -local dns = require('dns') -local ipops = require('ipOps') hostrule = function(host) return ( arg_domain ~= nil ) end @@ -445,4 +446,4 @@ action = function(host, port) table.insert(output, group_output) end return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/dns-client-subnet-scan.nse b/scripts/dns-client-subnet-scan.nse index a8f2f8f8df..4d92096f46 100644 --- a/scripts/dns-client-subnet-scan.nse +++ b/scripts/dns-client-subnet-scan.nse @@ -1,3 +1,10 @@ +local dns = require "dns" +local ipOps = require "ipOps" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Performs a domain lookup using the edns-client-subnet option that adds support for adding subnet information to the query describing where the @@ -44,9 +51,6 @@ author = "John Bond" license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licenses/BSD-simplified" categories = {"discovery", "safe"} -require "stdnse" -require "shortport" -require "dns" local argNS = stdnse.get_script_args(SCRIPT_NAME .. '.nameserver') local argDomain = stdnse.get_script_args(SCRIPT_NAME .. '.domain') diff --git a/scripts/dns-fuzz.nse b/scripts/dns-fuzz.nse index 9f2461856d..37f35136fb 100644 --- a/scripts/dns-fuzz.nse +++ b/scripts/dns-fuzz.nse @@ -1,3 +1,12 @@ +local bit = require "bit" +local comm = require "comm" +local dns = require "dns" +local math = require "math" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Launches a DNS fuzzing attack against DNS servers. @@ -30,11 +39,6 @@ author = "Michael Pattrick" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"fuzzer", "intrusive"} -require "bit" -require "dns" -require "stdnse" -require "comm" -require "shortport" portrule = shortport.portnumber(53, "udp") diff --git a/scripts/dns-ip6-arpa-scan.nse b/scripts/dns-ip6-arpa-scan.nse index 16d911496c..2935fab9e0 100644 --- a/scripts/dns-ip6-arpa-scan.nse +++ b/scripts/dns-ip6-arpa-scan.nse @@ -1,3 +1,11 @@ +local coroutine = require "coroutine" +local dns = require "dns" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Performs IPv6 a quick reverse lookup of an IPv6 network using a technique that allows reducing the amount of queries by analyzing DNS server response @@ -13,7 +21,7 @@ http://7bits.nl/blog/2012/03/26/finding-v6-hosts-by-efficiently-mapping-ip6-arpa --- -- @usage --- nmap --script dns-ipv6-arpa-scan --script-args='prefix=2001:0DB8,mask=48' +-- nmap --script dns-ip6-arpa-scan --script-args='prefix=2001:0DB8,mask=48' -- -- @output -- Pre-scan script results: @@ -29,23 +37,17 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "discovery"} -require 'dns' -require 'ipOps' -require 'tab' local arg_prefix = stdnse.get_script_args(SCRIPT_NAME .. ".prefix") local arg_mask = stdnse.get_script_args(SCRIPT_NAME .. ".mask") prerule = function() return (arg_prefix ~= nil and arg_mask ~= nil) end -local pending = {} -local result = {} - -local function query_prefix(query) +local function query_prefix(query, result) local condvar = nmap.condvar(result) local status, res = dns.query(query, { dtype='PTR' }) if ( not(status) and res == "No Answers") then - table.insert(pending, query) + table.insert(result, query) elseif ( status ) then local ip = query:sub(1, -10):gsub('%.',''):reverse():gsub('(....)', '%1:'):sub(1, -2) ip = ipOps.bin_to_ip(ipOps.ip_to_bin(ip)) @@ -67,11 +69,12 @@ action = function() local i = 20 + local result repeat - pending = {} + result = {} for _, f in ipairs(found) do for q in ("0123456789abcdef"):gmatch("(%w)") do - local co = stdnse.new_thread(query_prefix, q .. "." .. f) + local co = stdnse.new_thread(query_prefix, q .. "." .. f, result) threads[co] = true end end @@ -84,11 +87,11 @@ action = function() end until( next(threads) == nil ) - if ( 0 == #pending ) then - break + if ( 0 == #result ) then + return end - found = pending + found = result i = i + 1 until( 128 == i * 2 + arg_mask ) diff --git a/scripts/dns-nsec-enum.nse b/scripts/dns-nsec-enum.nse index fcf8f073d1..54cdd40a81 100644 --- a/scripts/dns-nsec-enum.nse +++ b/scripts/dns-nsec-enum.nse @@ -1,3 +1,9 @@ +local dns = require "dns" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Enumerates DNS names using the DNSSEC NSEC-walking technique. @@ -41,9 +47,6 @@ license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licen categories = {"discovery", "intrusive"} -require "stdnse" -require "shortport" -require "dns" portrule = shortport.port_or_service(53, "domain", {"tcp", "udp"}) @@ -163,7 +166,7 @@ local function increment_component(name) bytes[i] = DNS_CHARS[index] end - return string.char(unpack(bytes)) + return string.char(table.unpack(bytes)) end -- Return the lexicographically next domain name that does not add a new diff --git a/scripts/dns-nsid.nse b/scripts/dns-nsid.nse index e5096689d0..add9b27ba1 100644 --- a/scripts/dns-nsid.nse +++ b/scripts/dns-nsid.nse @@ -1,3 +1,9 @@ +local bin = require "bin" +local dns = require "dns" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Retrieves information from a DNS nameserver by requesting its nameserver ID (nsid) and asking for its id.server and @@ -28,9 +34,6 @@ license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licen categories = {"discovery", "default"} -require "stdnse" -require "shortport" -require "dns" portrule = shortport.port_or_service(53, "domain", {"tcp", "udp"}) diff --git a/scripts/dns-random-srcport.nse b/scripts/dns-random-srcport.nse index c312f2a05f..3864c1f45b 100644 --- a/scripts/dns-random-srcport.nse +++ b/scripts/dns-random-srcport.nse @@ -1,3 +1,9 @@ +local bit = require "bit" +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description = [[ Checks a DNS server for the predictable-port recursion vulnerability. Predictable source ports can make a DNS server vulnerable to cache poisoning @@ -32,9 +38,6 @@ porttest.dns-oarc.net: Duane Wessels categories = {"external", "intrusive"} -require "bit" -require "comm" -require "shortport" portrule = shortport.portnumber(53, "udp") diff --git a/scripts/dns-random-txid.nse b/scripts/dns-random-txid.nse index 151451a52b..e76bb3eeda 100644 --- a/scripts/dns-random-txid.nse +++ b/scripts/dns-random-txid.nse @@ -1,3 +1,9 @@ +local bit = require "bit" +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description = [[ Checks a DNS server for the predictable-TXID DNS recursion vulnerability. Predictable TXID values can make a DNS server vulnerable to @@ -32,9 +38,6 @@ txidtest.dns-oarc.net: Duane Wessels categories = {"external", "intrusive"} -require "bit" -require "comm" -require "shortport" portrule = shortport.portnumber(53, "udp") diff --git a/scripts/dns-recursion.nse b/scripts/dns-recursion.nse index 4ae4af94fc..b9b57204dc 100644 --- a/scripts/dns-recursion.nse +++ b/scripts/dns-recursion.nse @@ -1,3 +1,9 @@ +local bit = require "bit" +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description = [[ Checks if a DNS server allows queries for third-party names. It is expected that recursion will be enabled on your own internal @@ -16,9 +22,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe"} -require "bit" -require "comm" -require "shortport" portrule = shortport.portnumber(53, "udp") diff --git a/scripts/dns-service-discovery.nse b/scripts/dns-service-discovery.nse index 15301c651f..4f6fc6a3d3 100644 --- a/scripts/dns-service-discovery.nse +++ b/scripts/dns-service-discovery.nse @@ -1,3 +1,8 @@ +local dnssd = require "dnssd" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description=[[ Attempts to discover target hosts' services using the DNS Service Discovery protocol. @@ -46,8 +51,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require 'shortport' -require 'dnssd' portrule = shortport.portnumber(5353, "udp") diff --git a/scripts/dns-srv-enum.nse b/scripts/dns-srv-enum.nse index d213a81b0a..e4eaa8282c 100644 --- a/scripts/dns-srv-enum.nse +++ b/scripts/dns-srv-enum.nse @@ -1,3 +1,11 @@ +local coroutine = require "coroutine" +local dns = require "dns" +local nmap = require "nmap" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" +local target = require "target" + description = [[ Enumerates various common service (SRV) records for a given domain name. The service records contain the hostname, port and priority of servers for a given service. @@ -54,9 +62,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'dns' -require 'tab' -require 'target' local arg_domain = stdnse.get_script_args(SCRIPT_NAME .. ".domain") local arg_filter = stdnse.get_script_args(SCRIPT_NAME .. ".filter") @@ -171,4 +176,4 @@ action = function(host) table.sort(result, function(a,b) return a.name < b.name end) return stdnse.format_output(true, result) -end \ No newline at end of file +end diff --git a/scripts/dns-update.nse b/scripts/dns-update.nse index dc267b2bee..bc5a7571e9 100644 --- a/scripts/dns-update.nse +++ b/scripts/dns-update.nse @@ -1,3 +1,9 @@ +local dns = require "dns" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to perform a dynamic DNS update without authentication. ]] @@ -39,8 +45,6 @@ categories = {"discovery", "safe"} -- Created 01/09/2011 - v0.1 - created by Patrik Karlsson -- Revised 01/10/2011 - v0.2 - added test function -require 'shortport' -require 'dns' portrule = shortport.port_or_service( 53, "dns", "udp", {"open", "open|filtered"} ) @@ -97,4 +101,4 @@ action = function(host, port) return "\n ERROR: " .. err end -end \ No newline at end of file +end diff --git a/scripts/dns-zeustracker.nse b/scripts/dns-zeustracker.nse index 23020cbe9a..d73bfe30f5 100644 --- a/scripts/dns-zeustracker.nse +++ b/scripts/dns-zeustracker.nse @@ -1,3 +1,9 @@ +local dns = require "dns" +local ipOps = require "ipOps" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Checks if the target IP range is part of a Zeus botnet by querying ZTDNS @ abuse.ch. Please review the following information before you start to scan: @@ -18,10 +24,6 @@ author = "Mikael Keri" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery", "external", "malware"} -require "dns" -require "ipOps" -require "stdnse" -require "tab" hostrule = function(host) return not(ipOps.isPrivate(host.ip)) end @@ -50,7 +52,7 @@ action = function(host) "Files Online", "Date added") for _, record in ipairs(result) do local name, ip, sbl, asn, country, status, level, files_online, - dateadded = unpack(stdnse.strsplit("| ", record)) + dateadded = table.unpack(stdnse.strsplit("| ", record)) level = levels[tonumber(level)] or "Unknown" tab.addrow(output, name, ip, sbl, asn, country, status, level, files_online, dateadded) end diff --git a/scripts/dns-zone-transfer.nse b/scripts/dns-zone-transfer.nse index 289923a698..16dd27f505 100644 --- a/scripts/dns-zone-transfer.nse +++ b/scripts/dns-zone-transfer.nse @@ -1,3 +1,16 @@ +local bit = require "bit" +local dns = require "dns" +local ipOps = require "ipOps" +local listop = require "listop" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local strbuf = require "strbuf" +local string = require "string" +local tab = require "tab" +local table = require "table" +local target = require "target" + description = [[ Requests a zone transfer (AXFR) from a DNS server. @@ -68,15 +81,6 @@ Useful resources -- nmap --script dns-zone-transfer.nse \ -- --script-args dns-zone-transfer.domain= -require('shortport') -require('strbuf') -require('stdnse') -require('listop') -require('bit') -require('tab') -require('dns') -require('target') -require('ipOps') author = "Eddie Bell" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/domcon-brute.nse b/scripts/domcon-brute.nse index d3e354a3be..327dc60a1a 100644 --- a/scripts/domcon-brute.nse +++ b/scripts/domcon-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Performs brute force password auditing against the Lotus Domino Console. ]] @@ -27,9 +34,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'brute' -require 'creds' portrule = shortport.port_or_service(2050, "", "tcp", "open") diff --git a/scripts/domcon-cmd.nse b/scripts/domcon-cmd.nse index 23106fb776..186be88ca3 100644 --- a/scripts/domcon-cmd.nse +++ b/scripts/domcon-cmd.nse @@ -1,3 +1,8 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Runs a console command on the Lotus Domino Console using the given authentication credentials (see also: domcon-brute) ]] @@ -54,7 +59,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "auth"} -require 'shortport' portrule = shortport.port_or_service(2050, "dominoconsole", "tcp", "open") diff --git a/scripts/domino-enum-users.nse b/scripts/domino-enum-users.nse index 71800e5fc8..0006d5f688 100644 --- a/scripts/domino-enum-users.nse +++ b/scripts/domino-enum-users.nse @@ -1,3 +1,10 @@ +local io = require "io" +local nrpc = require "nrpc" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local unpwdb = require "unpwdb" + description = [[ Attempts to discover valid IBM Lotus Domino users and download their ID files by exploiting the CVE-2006-5835 vulnerability. ]] @@ -37,9 +44,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "auth"} -require 'shortport' -require 'nrpc' -require 'unpwdb' portrule = shortport.port_or_service(1352, "lotusnotes", "tcp", "open") diff --git a/scripts/dpap-brute.nse b/scripts/dpap-brute.nse index 71ded40bd1..1004fd00b4 100644 --- a/scripts/dpap-brute.nse +++ b/scripts/dpap-brute.nse @@ -1,3 +1,9 @@ +local base64 = require "base64" +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" + description = [[ Performs brute force password auditing against an iPhoto Library. ]] @@ -24,10 +30,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require("base64") -require("shortport") -require("brute") -require("creds") portrule = shortport.port_or_service(8770, "apple-iphoto") diff --git a/scripts/drda-brute.nse b/scripts/drda-brute.nse index c868b4a155..7672da2aed 100644 --- a/scripts/drda-brute.nse +++ b/scripts/drda-brute.nse @@ -1,3 +1,12 @@ +local coroutine = require "coroutine" +local drda = require "drda" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local unpwdb = require "unpwdb" + description = [[ Performs password guessing against databases supporting the IBM DB2 protocol such as Informix, DB2 and Derby ]] @@ -20,10 +29,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories={"intrusive", "brute"} -require "stdnse" -require "shortport" -require "drda" -require "unpwdb" -- Version 0.5 -- Created 05/08/2010 - v0.1 - created by Patrik Karlsson diff --git a/scripts/drda-info.nse b/scripts/drda-info.nse index 836f852d88..71d2cd98a6 100644 --- a/scripts/drda-info.nse +++ b/scripts/drda-info.nse @@ -1,3 +1,10 @@ +local drda = require "drda" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to extract information from database servers supporting the DRDA protocol. The script sends a DRDA EXCSAT (exchange server attributes) @@ -19,9 +26,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery", "version"} -require "stdnse" -require "shortport" -require "drda" -- Version 0.1 -- Created 05/08/2010 - v0.1 - created by Patrik Karlsson diff --git a/scripts/duplicates.nse b/scripts/duplicates.nse index e8859caef3..015f06976b 100644 --- a/scripts/duplicates.nse +++ b/scripts/duplicates.nse @@ -1,3 +1,10 @@ +local ipOps = require "ipOps" +local nmap = require "nmap" +local ssh1 = require "ssh1" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to discover multihomed systems by analysing and comparing information collected by other scripts. The information analyzed @@ -49,7 +56,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe"} dependencies = {"ssl-cert", "ssh-hostkey", "nbstat"} -require 'ipOps' hostrule = function() return true end postrule = function() return true end diff --git a/scripts/eap-info.nse b/scripts/eap-info.nse index 8acd74a547..df6819d847 100644 --- a/scripts/eap-info.nse +++ b/scripts/eap-info.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local eap = require "eap" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Enumerates the authentication methods offered by an EAP authenticator for a given identity or for the anonymous identity if no argument is passed. @@ -26,11 +33,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "broadcast", "safe" } -require 'nmap' -require 'packet' -require 'bin' -require 'stdnse' -require 'eap' prerule = function() return nmap.is_privileged() diff --git a/scripts/epmd-info.nse b/scripts/epmd-info.nse index 7df4cb5448..be03f17ad3 100644 --- a/scripts/epmd-info.nse +++ b/scripts/epmd-info.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Connects to Erlang Port Mapper Daemon (epmd) and retrieves a list of nodes with their respective port numbers. ]] @@ -17,8 +24,6 @@ Connects to Erlang Port Mapper Daemon (epmd) and retrieves a list of nodes with author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require "shortport" -require "bin" portrule = shortport.port_or_service (4369, "epmd") diff --git a/scripts/finger.nse b/scripts/finger.nse index cfbe1b78a7..bd5c2b5973 100644 --- a/scripts/finger.nse +++ b/scripts/finger.nse @@ -1,3 +1,7 @@ +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" + description = [[ Attempts to retrieve a list of usernames using the finger service. ]] @@ -22,8 +26,6 @@ categories = {"default", "discovery", "safe"} -- | Gutek Ange Gutek *pts/0 - Thu 00:41 -- |_Gutek Ange Gutek *pts/4 3 Thu 01:06 -require "comm" -require "shortport" portrule = shortport.port_or_service(79, "finger") diff --git a/scripts/firewalk.nse b/scripts/firewalk.nse index 0cb2fed36c..fb51254926 100644 --- a/scripts/firewalk.nse +++ b/scripts/firewalk.nse @@ -1,3 +1,11 @@ +local bin = require "bin" +local math = require "math" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Tries to discover firewall rules using an IP TTL expiration technique known as firewalking. @@ -73,10 +81,6 @@ categories = {"safe", "discovery"} -- o remove traceroute dependency -require('bin') -require('stdnse') -require('packet') -require('tab') -----= scan parameters defaults =----- diff --git a/scripts/ftp-anon.nse b/scripts/ftp-anon.nse index 87c2822507..eef41615e3 100644 --- a/scripts/ftp-anon.nse +++ b/scripts/ftp-anon.nse @@ -1,3 +1,10 @@ +local ftp = require "ftp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Checks if an FTP server allows anonymous logins. @@ -27,8 +34,6 @@ author = "Eddie Bell, Rob Nicholls, Ange Gutek, David Fifield" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "auth", "safe"} -require "ftp" -require "shortport" portrule = shortport.port_or_service(21, "ftp") diff --git a/scripts/ftp-bounce.nse b/scripts/ftp-bounce.nse index 328faaa2e7..40bf1829bf 100644 --- a/scripts/ftp-bounce.nse +++ b/scripts/ftp-bounce.nse @@ -1,3 +1,8 @@ +local coroutine = require "coroutine" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description=[[ Checks to see if an FTP server allows port scanning using the FTP bounce method. ]] @@ -25,7 +30,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe"} -require "shortport" portrule = shortport.service("ftp") diff --git a/scripts/ftp-brute.nse b/scripts/ftp-brute.nse index 7835f498e1..9fac3cb81c 100644 --- a/scripts/ftp-brute.nse +++ b/scripts/ftp-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Performs brute force password auditing against FTP servers. @@ -28,10 +35,6 @@ author = "Aleksandar Nikolic" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'brute' -require 'creds' - portrule = shortport.port_or_service(21, "ftp") local arg_timeout = stdnse.get_script_args(SCRIPT_NAME .. ".timeout") or 5 diff --git a/scripts/ftp-libopie.nse b/scripts/ftp-libopie.nse index a13714d807..6206d058ae 100644 --- a/scripts/ftp-libopie.nse +++ b/scripts/ftp-libopie.nse @@ -1,3 +1,8 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" +local vulns = require "vulns" + description = [[ Checks if an FTPd is prone to CVE-2010-1938 (OPIE off-by-one stack overflow), a vulnerability discovered by Maksymilian Arciemowicz and Adam "pi3" Zabrocki. @@ -32,8 +37,6 @@ author = "Ange Gutek" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"vuln","intrusive"} -require "shortport" -require "vulns" portrule = shortport.port_or_service(21, "ftp") diff --git a/scripts/ftp-proftpd-backdoor.nse b/scripts/ftp-proftpd-backdoor.nse index 5002f4014f..5298eba137 100644 --- a/scripts/ftp-proftpd-backdoor.nse +++ b/scripts/ftp-proftpd-backdoor.nse @@ -1,3 +1,8 @@ +local ftp = require "ftp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -25,9 +30,6 @@ author = "Mak Kolybabi" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"exploit", "intrusive", "malware", "vuln"} -require("ftp") -require("shortport") -require("stdnse") local CMD_FTP = "HELP ACIDBITCHEZ" local CMD_SHELL = "id" diff --git a/scripts/ftp-vsftpd-backdoor.nse b/scripts/ftp-vsftpd-backdoor.nse index 8449fbd7d3..9d7718f9ec 100644 --- a/scripts/ftp-vsftpd-backdoor.nse +++ b/scripts/ftp-vsftpd-backdoor.nse @@ -1,3 +1,11 @@ +local ftp = require "ftp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local vulns = require "vulns" + description = [[ Tests for the presence of the vsFTPd 2.3.4 backdoor reported on 2011-07-04 (CVE-2011-2523). This script attempts to exploit the backdoor using the @@ -44,11 +52,6 @@ author = "Daniel Miller" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"exploit", "intrusive", "malware", "vuln"} -require("ftp") -require("nmap") -require("shortport") -require("stdnse") -require("vulns") local CMD_FTP = "USER X:)\r\nPASS X\r\n" local CMD_SHELL_ID = "id" diff --git a/scripts/ftp-vuln-cve2010-4221.nse b/scripts/ftp-vuln-cve2010-4221.nse index 93289ad704..f5d39f75c0 100644 --- a/scripts/ftp-vuln-cve2010-4221.nse +++ b/scripts/ftp-vuln-cve2010-4221.nse @@ -1,3 +1,9 @@ +local ftp = require "ftp" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local vulns = require "vulns" + description = [[ Checks for a stack-based buffer overflow in the ProFTPD server, version between 1.3.2rc3 and 1.3.3b. By sending a large number of TELNET_IAC escape @@ -43,10 +49,6 @@ author = "Djalal Harouni" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "vuln"} -require "ftp" -require "shortport" -require "stdnse" -require "vulns" portrule = function (host, port) if port.version.product ~= nil and port.version.product ~= "ProFTPD" then diff --git a/scripts/ganglia-info.nse b/scripts/ganglia-info.nse index 87f890fcc8..bc4e9b13a9 100644 --- a/scripts/ganglia-info.nse +++ b/scripts/ganglia-info.nse @@ -1,3 +1,10 @@ +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Retrieves system information (OS version, available memory, etc.) from a listening Ganglia Monitoring Daemon or Ganglia Meta Daemon. @@ -78,8 +85,6 @@ author = "Brendan Coles" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require("comm") -require("shortport") portrule = shortport.port_or_service ({8649,8651}, "ganglia", {"tcp"}) diff --git a/scripts/giop-info.nse b/scripts/giop-info.nse index 6fa48815d1..10cf9cb139 100644 --- a/scripts/giop-info.nse +++ b/scripts/giop-info.nse @@ -1,3 +1,8 @@ +local giop = require "giop" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Queries a CORBA naming server for a list of objects. ]] @@ -20,8 +25,6 @@ categories = {"default", "discovery", "safe"} -- Created 07/08/2010 - v0.1 - created by Patrik Karlsson -require 'shortport' -require 'giop' portrule = shortport.port_or_service( {2809,1050,1049} , "giop", "tcp", "open") diff --git a/scripts/gkrellm-info.nse b/scripts/gkrellm-info.nse index f8926a8980..24142b74e5 100644 --- a/scripts/gkrellm-info.nse +++ b/scripts/gkrellm-info.nse @@ -1,3 +1,10 @@ +local math = require "math" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Queries a GKRellM service for monitoring information. A single round of collection is made, showing a snapshot of information at the time of the @@ -42,8 +49,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -local shortport = require('shortport') -local tab = require('tab') portrule = shortport.port_or_service(19150, "gkrellm", "tcp") @@ -213,4 +218,4 @@ action = function(host, port) table.sort(output, function(a,b) return getOrderPos(a) < getOrderPos(b) end) return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/gopher-ls.nse b/scripts/gopher-ls.nse index 36140969e5..0d5b1477e3 100644 --- a/scripts/gopher-ls.nse +++ b/scripts/gopher-ls.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Lists files and directories at the root of a gopher service. ]] @@ -22,9 +28,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require("nmap") -require("stdnse") -require("shortport") portrule = shortport.port_or_service (70, "gopher", {"tcp"}) diff --git a/scripts/gpsd-info.nse b/scripts/gpsd-info.nse index 9f410478f2..abe9959fea 100644 --- a/scripts/gpsd-info.nse +++ b/scripts/gpsd-info.nse @@ -1,3 +1,9 @@ +local gps = require "gps" +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Retrieves GPS time, coordinates and speed from the GPSD network daemon. ]] @@ -20,10 +26,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -local shortport = require 'shortport' -local gps = require 'gps' -local json = require 'json' -local match = require 'match' portrule = shortport.port_or_service(2947, "gpsd-ng", "tcp") @@ -96,4 +98,4 @@ action = function(host, port) ("Speed: %s knots"):format(gpsinfo.speed) } return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/hadoop-datanode-info.nse b/scripts/hadoop-datanode-info.nse index 74d470cdb1..d1a0219a50 100644 --- a/scripts/hadoop-datanode-info.nse +++ b/scripts/hadoop-datanode-info.nse @@ -1,3 +1,9 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Discovers information such as log directories from an Apache Hadoop DataNode HTTP status page. @@ -26,8 +32,6 @@ author = "John R. Bond" license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licenses/BSD-simplified" categories = {"default", "discovery", "safe"} -require ("shortport") -require ("http") portrule = function(host, port) -- Run for the special port number, or for any HTTP-like service that is diff --git a/scripts/hadoop-jobtracker-info.nse b/scripts/hadoop-jobtracker-info.nse index 6d7633b0bd..90ea6cd7c2 100644 --- a/scripts/hadoop-jobtracker-info.nse +++ b/scripts/hadoop-jobtracker-info.nse @@ -1,3 +1,11 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + description = [[ Retrieves information from an Apache Hadoop JobTracker HTTP status page. @@ -43,9 +51,6 @@ author = "John R. Bond" license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licenses/BSD-simplified" categories = {"default", "discovery", "safe"} -require ("shortport") -require ("target") -require ("http") portrule = function(host, port) -- Run for the special port number, or for any HTTP-like service that is diff --git a/scripts/hadoop-namenode-info.nse b/scripts/hadoop-namenode-info.nse index 0b56ba1f30..6c9c68fa4b 100644 --- a/scripts/hadoop-namenode-info.nse +++ b/scripts/hadoop-namenode-info.nse @@ -1,3 +1,11 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + description = [[ Retrieves information from an Apache Hadoop NameNode HTTP status page. @@ -43,9 +51,6 @@ author = "John R. Bond (john.r.bond@gmail.com)" license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licenses/BSD-simplified" categories = {"default", "discovery", "safe"} -require ("shortport") -require ("target") -require ("http") portrule = function(host, port) -- Run for the special port number, or for any HTTP-like service that is diff --git a/scripts/hadoop-secondary-namenode-info.nse b/scripts/hadoop-secondary-namenode-info.nse index 82a1c257d5..a48d67709d 100644 --- a/scripts/hadoop-secondary-namenode-info.nse +++ b/scripts/hadoop-secondary-namenode-info.nse @@ -1,3 +1,10 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + description = [[ Retrieves information from an Apache Hadoop secondary NameNode HTTP status page. @@ -39,9 +46,6 @@ author = "John R. Bond" license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licenses/BSD-simplified" categories = {"default", "discovery", "safe"} -require ("shortport") -require ("target") -require ("http") portrule = function(host, port) -- Run for the special port number, or for any HTTP-like service that is diff --git a/scripts/hadoop-tasktracker-info.nse b/scripts/hadoop-tasktracker-info.nse index d13c041c6a..71845684b3 100644 --- a/scripts/hadoop-tasktracker-info.nse +++ b/scripts/hadoop-tasktracker-info.nse @@ -1,3 +1,9 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Retrieves information from an Apache Hadoop TaskTracker HTTP status page. @@ -30,8 +36,6 @@ author = "John R. Bond" license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licenses/BSD-simplified" categories = {"default", "discovery", "safe"} -require ("shortport") -require ("http") portrule = function(host, port) -- Run for the special port number, or for any HTTP-like service that is diff --git a/scripts/hbase-master-info.nse b/scripts/hbase-master-info.nse index 539abdc28f..85951a091b 100644 --- a/scripts/hbase-master-info.nse +++ b/scripts/hbase-master-info.nse @@ -1,3 +1,11 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + description = [[ Retrieves information from an Apache HBase (Hadoop database) master HTTP status page. @@ -40,9 +48,6 @@ author = "John R. Bond" license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licenses/BSD-simplified" categories = {"default", "discovery", "safe"} -require ("shortport") -require ("http") -require ("target") portrule = function(host, port) -- Run for the special port number, or for any HTTP-like service that is diff --git a/scripts/hbase-region-info.nse b/scripts/hbase-region-info.nse index 3d28f8bc48..06f54f8c1c 100644 --- a/scripts/hbase-region-info.nse +++ b/scripts/hbase-region-info.nse @@ -1,3 +1,10 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local target = require "target" + description = [[ Retrieves information from an Apache HBase (Hadoop database) region server HTTP status page. @@ -34,9 +41,6 @@ author = "John R. Bond" license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licenses/BSD-simplified" categories = {"default", "discovery", "safe"} -require ("shortport") -require ("http") -require ("target") portrule = function(host, port) -- Run for the special port number, or for any HTTP-like service that is diff --git a/scripts/hddtemp-info.nse b/scripts/hddtemp-info.nse index a9eeb37042..9a1eeb48de 100644 --- a/scripts/hddtemp-info.nse +++ b/scripts/hddtemp-info.nse @@ -1,3 +1,10 @@ +local comm = require "comm" +local math = require "math" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Reads hard disk information (such as brand, model, and sometimes temperature) from a listening hddtemp service. ]] @@ -14,8 +21,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require("comm") -require("shortport") portrule = shortport.port_or_service (7634, "hddtemp", {"tcp"}) diff --git a/scripts/hostmap-bfk.nse b/scripts/hostmap-bfk.nse index 9e7a44b7c9..937e456147 100644 --- a/scripts/hostmap-bfk.nse +++ b/scripts/hostmap-bfk.nse @@ -1,3 +1,11 @@ +local dns = require "dns" +local http = require "http" +local io = require "io" +local ipOps = require "ipOps" +local stdnse = require "stdnse" +local string = require "string" +local target = require "target" + description = [[ Tries to find hostnames that resolve to the target's IP address by querying the online database at http://www.bfk.de/bfk_dnslogger.html. @@ -39,11 +47,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"external", "discovery", "intrusive"} -require "dns" -require "ipOps" -require "http" -require "stdnse" -require "target" local HOSTMAP_SERVER = "www.bfk.de" diff --git a/scripts/hostmap-robtex.nse b/scripts/hostmap-robtex.nse index f53d0e2901..36a40a3950 100644 --- a/scripts/hostmap-robtex.nse +++ b/scripts/hostmap-robtex.nse @@ -1,3 +1,9 @@ +local http = require "http" +local ipOps = require "ipOps" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Tries to find hostnames that resolve to the target's IP address by querying the Robtex service at http://www.robtex.com/dns/. ]]; @@ -24,9 +30,6 @@ categories = { "external" }; -require "http"; -require "ipOps" -require "shortport"; --- Scrape domains sharing target host ip from robtex website -- @param data string containing the retrieved web page diff --git a/scripts/http-affiliate-id.nse b/scripts/http-affiliate-id.nse index 2d6394350a..4208c898fd 100644 --- a/scripts/http-affiliate-id.nse +++ b/scripts/http-affiliate-id.nse @@ -1,3 +1,10 @@ +local http = require "http" +local nmap = require "nmap" +local pcre = require "pcre" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Grabs affiliate network IDs (e.g. Google AdSense or Analytics, Amazon Associates, etc.) from a web page. These can be used to identify pages @@ -41,10 +48,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -require 'shortport' -require 'http' -require 'pcre' -require 'stdnse' -- these are the regular expressions for affiliate IDs local AFFILIATE_PATTERNS = { diff --git a/scripts/http-apache-negotiation.nse b/scripts/http-apache-negotiation.nse index 51d62da9ba..5c814d0be2 100644 --- a/scripts/http-apache-negotiation.nse +++ b/scripts/http-apache-negotiation.nse @@ -1,3 +1,8 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Checks if the target http server has mod_negotiation enabled. This feature can be leveraged to find hidden resources and spider a web @@ -33,8 +38,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -require 'shortport' -require 'http' portrule = shortport.http diff --git a/scripts/http-auth-finder.nse b/scripts/http-auth-finder.nse index aae871777c..c2d19844af 100644 --- a/scripts/http-auth-finder.nse +++ b/scripts/http-auth-finder.nse @@ -1,3 +1,11 @@ +local http = require "http" +local httpspider = require "httpspider" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Spiders a web site to find web pages requiring form-based or HTTP-based authentication. The results are returned in a table with each url and the detected method. @@ -32,9 +40,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "httpspider" -require "shortport" -require "tab" portrule = shortport.http @@ -108,4 +113,4 @@ action = function(host, port) result.name = crawler:getLimitations() return stdnse.format_output(true, result) end -end \ No newline at end of file +end diff --git a/scripts/http-auth.nse b/scripts/http-auth.nse index 566bca2c46..532b80e1a9 100644 --- a/scripts/http-auth.nse +++ b/scripts/http-auth.nse @@ -1,3 +1,9 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Retrieves the authentication scheme and realm of a web service that requires authentication. @@ -35,8 +41,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "auth", "safe"} -require "shortport" -require "http" portrule = shortport.http diff --git a/scripts/http-awstatstotals-exec.nse b/scripts/http-awstatstotals-exec.nse index 321775885e..1d28dbd07d 100644 --- a/scripts/http-awstatstotals-exec.nse +++ b/scripts/http-awstatstotals-exec.nse @@ -1,3 +1,10 @@ +local http = require "http" +local io = require "io" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Exploits a remote code execution vulnerability in Awstats Totals 1.0 up to 1.14 and possibly other products based on it (CVE: 2008-3922). @@ -37,9 +44,6 @@ author = "Paulino Calderon" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"vuln", "intrusive", "exploit"} -require "shortport" -require "http" -require "url" portrule = shortport.http diff --git a/scripts/http-axis2-dir-traversal.nse b/scripts/http-axis2-dir-traversal.nse index a9958c1519..348d045d1b 100644 --- a/scripts/http-axis2-dir-traversal.nse +++ b/scripts/http-axis2-dir-traversal.nse @@ -1,3 +1,12 @@ +local creds = require "creds" +local http = require "http" +local io = require "io" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Exploits a directory traversal vulnerability in Apache Axis2 version 1.4.1 by sending a specially crafted request to the parameter xsd (OSVDB-59001). By default it will try to retrieve the configuration file of the Axis2 service '/conf/axis2.xml' using the path '/axis2/services/' to return the username and password of the admin account. @@ -33,9 +42,6 @@ author = "Paulino Calderon" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"vuln", "intrusive", "exploit"} -require "http" -require "shortport" -require "creds" portrule = shortport.http diff --git a/scripts/http-backup-finder.nse b/scripts/http-backup-finder.nse index 6046d1432c..ae0ccaa773 100644 --- a/scripts/http-backup-finder.nse +++ b/scripts/http-backup-finder.nse @@ -1,3 +1,11 @@ +local coroutine = require "coroutine" +local http = require "http" +local httpspider = require "httpspider" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local url = require "url" + description = [[ Spiders a website and attempts to identify backup copies of discovered files. It does so by requesting a number of different combinations of the filename (eg. index.bak, index.html~, copy of index.html). @@ -35,9 +43,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'httpspider' -require 'shortport' -require 'url' portrule = shortport.http diff --git a/scripts/http-barracuda-dir-traversal.nse b/scripts/http-barracuda-dir-traversal.nse index e753fe3e0d..64bb8bca36 100644 --- a/scripts/http-barracuda-dir-traversal.nse +++ b/scripts/http-barracuda-dir-traversal.nse @@ -1,3 +1,9 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to retrieve the configuration settings from a Barracuda Networks Spam & Virus Firewall device using the directory traversal @@ -74,12 +80,6 @@ author = "Brendan Coles" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "exploit", "auth"} -require("url") -require("dns") -require("http") -require("ipOps") -require("stdnse") -require("shortport") portrule = shortport.port_or_service (8000, "barracuda", {"tcp"}) diff --git a/scripts/http-brute.nse b/scripts/http-brute.nse index c800115276..d253dd7750 100644 --- a/scripts/http-brute.nse +++ b/scripts/http-brute.nse @@ -1,3 +1,11 @@ +local brute = require "brute" +local creds = require "creds" +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" +local table = require "table" + description = [[ Performs brute force password auditing against http basic authentication. ]] @@ -37,10 +45,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'http' -require 'brute' -require 'creds' portrule = shortport.port_or_service( {80, 443}, {"http", "https"}, "tcp", "open") diff --git a/scripts/http-cakephp-version.nse b/scripts/http-cakephp-version.nse index 426d6fce4f..eb0193a27f 100644 --- a/scripts/http-cakephp-version.nse +++ b/scripts/http-cakephp-version.nse @@ -1,3 +1,10 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local openssl = stdnse.silent_require "openssl" + description = [[ Obtains the CakePHP version of a web application built with the CakePHP framework by fingerprinting default files shipped with the CakePHP framework. @@ -25,10 +32,6 @@ author = "Paulino Calderon" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","safe"} -require "http" -require "shortport" -require "stdnse" -stdnse.silent_require "openssl" portrule = shortport.http diff --git a/scripts/http-chrono.nse b/scripts/http-chrono.nse index 2409a0376f..288d3dd9a2 100644 --- a/scripts/http-chrono.nse +++ b/scripts/http-chrono.nse @@ -1,3 +1,13 @@ +local http = require "http" +local httpspider = require "httpspider" +local math = require "math" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" +local url = require "url" + description = [[ This script measures the time a website takes to deliver a web page and returns the maximum, minimum and average time it took to fetch a page. @@ -51,10 +61,6 @@ author = "Ange Gutek" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require 'http' -require 'shortport' -require 'httpspider' -require 'tab' portrule = shortport.http diff --git a/scripts/http-config-backup.nse b/scripts/http-config-backup.nse index 6d2be32609..af06d63220 100644 --- a/scripts/http-config-backup.nse +++ b/scripts/http-config-backup.nse @@ -1,3 +1,12 @@ +local coroutine = require "coroutine" +local http = require "http" +local io = require "io" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local url = require "url" + description = [[ Checks for backups and swap files of common content management system and web server configuration files. @@ -53,9 +62,6 @@ author = "Riccardo Cecolin"; license = "Same as Nmap--See http://nmap.org/book/man-legal.html"; categories = { "auth", "intrusive" }; -require 'http'; -require 'shortport'; -require 'url'; portrule = shortport.http; diff --git a/scripts/http-cors.nse b/scripts/http-cors.nse index 20df00aa2e..a833ad55bf 100644 --- a/scripts/http-cors.nse +++ b/scripts/http-cors.nse @@ -1,3 +1,9 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Tests an http server for Cross-Origin Resource Sharing (CORS), a way for domains to explicitly opt in to having certain methods invoked by @@ -27,9 +33,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require("shortport") -require("stdnse") -require("http") portrule = shortport.http diff --git a/scripts/http-date.nse b/scripts/http-date.nse index e2f665a848..986bf02b1d 100644 --- a/scripts/http-date.nse +++ b/scripts/http-date.nse @@ -1,3 +1,9 @@ +local http = require "http" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Gets the date from HTTP-like services. Also prints how much the date differs from local time. Local time is the time the HTTP request was @@ -17,9 +23,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require("http") -require("shortport") -require("stdnse") portrule = shortport.http diff --git a/scripts/http-default-accounts.nse b/scripts/http-default-accounts.nse index 2058034635..acb8ad3a97 100644 --- a/scripts/http-default-accounts.nse +++ b/scripts/http-default-accounts.nse @@ -1,3 +1,12 @@ +local _G = require "_G" +local creds = require "creds" +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Tests for access with default credentials used by a variety of web applications and devices. @@ -45,9 +54,6 @@ author = "Paulino Calderon" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "auth", "safe"} -require "creds" -require "http" -require "shortport" portrule = shortport.http --- @@ -140,14 +146,14 @@ local function load_fingerprints(filename, cat) -- Load the file stdnse.print_debug(1, "%s: Loading fingerprints: %s", SCRIPT_NAME, filename_full) - file = loadfile(filename_full) + local env = setmetatable({fingerprints = {}}, {__index = _G}); + file = loadfile(filename_full, "t", env) if( not(file) ) then stdnse.print_debug(1, "%s: Couldn't load the file: %s", SCRIPT_NAME, filename_full) return false, "Couldn't load fingerprint file: " .. filename_full end - setfenv(file, setmetatable({fingerprints = {}; }, {__index = _G})) file() - fingerprints = getfenv(file)["fingerprints"] + fingerprints = env.fingerprints -- Validate fingerprints local valid_flag = validate_fingerprints(fingerprints) diff --git a/scripts/http-domino-enum-passwords.nse b/scripts/http-domino-enum-passwords.nse index 28fc49ff3c..495466e290 100644 --- a/scripts/http-domino-enum-passwords.nse +++ b/scripts/http-domino-enum-passwords.nse @@ -1,3 +1,10 @@ +local http = require "http" +local io = require "io" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to enumerate the hashed Domino Internet Passwords that are (by default) accessible by all authenticated users. This script can @@ -82,8 +89,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "auth"} dependencies = {"http-brute", "http-form-brute"} -require 'shortport' -require 'http' portrule = shortport.port_or_service({80, 443}, {"http","https"}, "tcp", "open") diff --git a/scripts/http-drupal-enum-users.nse b/scripts/http-drupal-enum-users.nse index 7c2b83391e..cce12676fd 100644 --- a/scripts/http-drupal-enum-users.nse +++ b/scripts/http-drupal-enum-users.nse @@ -1,3 +1,9 @@ +local http = require "http" +local json = require "json" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Enumerates Drupal users by exploiting a an information disclosure vulnerability in Views, Drupal's most popular module. @@ -29,10 +35,6 @@ author = "Hani Benhabiles" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require 'http' -require 'stdnse' -require 'shortport' -require 'json' portrule = shortport.http diff --git a/scripts/http-drupal-modules.nse b/scripts/http-drupal-modules.nse index 73c8ca6df6..58a5ab3e91 100644 --- a/scripts/http-drupal-modules.nse +++ b/scripts/http-drupal-modules.nse @@ -1,3 +1,12 @@ +local http = require "http" +local io = require "io" +local nmap = require "nmap" +local pcre = require "pcre" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Enumerates the installed Drupal modules by using a list of known modules. @@ -44,10 +53,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require 'http' -require 'stdnse' -require 'shortport' -require 'pcre' portrule = shortport.service("http") diff --git a/scripts/http-email-harvest.nse b/scripts/http-email-harvest.nse index 4278263fab..48a2295097 100644 --- a/scripts/http-email-harvest.nse +++ b/scripts/http-email-harvest.nse @@ -1,3 +1,8 @@ +local httpspider = require "httpspider" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Spiders a web site and collects e-mail addresses. ]] @@ -32,8 +37,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "httpspider" -require "shortport" portrule = shortport.http diff --git a/scripts/http-enum.nse b/scripts/http-enum.nse index 83cee07bd3..5cf396051d 100644 --- a/scripts/http-enum.nse +++ b/scripts/http-enum.nse @@ -1,3 +1,11 @@ +local _G = require "_G" +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Enumerates directories used by popular web applications and servers. @@ -56,10 +64,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive", "vuln"} -require 'http' -require 'shortport' -require 'stdnse' -require 'nsedebug' portrule = shortport.http @@ -174,16 +178,16 @@ local function get_fingerprints(fingerprint_file, category) end stdnse.print_debug("http-enum: Loading fingerprint database: %s", filename_full) - local file = loadfile(filename_full) + local env = setmetatable({fingerprints = {}}, {__index = _G}) + local file = loadfile(filename_full, "t", env) if(not(file)) then stdnse.print_debug("http-enum: Couldn't load configuration file: %s", filename_full) return false, "Couldn't load fingerprint file: " .. filename_full end - setfenv(file, setmetatable({fingerprints = {}; }, {__index = _G})) file() - local fingerprints = getfenv(file)["fingerprints"] + local fingerprints = env.fingerprints -- Sanity check our file to ensure that all the fields were good. If any are bad, we -- stop and don't load the file. diff --git a/scripts/http-favicon.nse b/scripts/http-favicon.nse index 11a66ded94..aa5722a345 100644 --- a/scripts/http-favicon.nse +++ b/scripts/http-favicon.nse @@ -1,3 +1,13 @@ +local datafiles = require "datafiles" +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local url = require "url" + +local openssl = stdnse.silent_require "openssl" + description = [[ Gets the favicon ("favorites icon") from a web page and matches it against a database of the icons of known web applications. If there is a match, the name @@ -32,13 +42,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require "shortport" -require "http" -require "stdnse" -require "datafiles" -require "nsedebug" -require "stdnse" -stdnse.silent_require "openssl" portrule = shortport.http diff --git a/scripts/http-form-brute.nse b/scripts/http-form-brute.nse index 0b0f5721f7..1a75bb2737 100644 --- a/scripts/http-form-brute.nse +++ b/scripts/http-form-brute.nse @@ -1,3 +1,12 @@ +local brute = require "brute" +local creds = require "creds" +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local url = require "url" + description = [[ Performs brute force password auditing against http form-based authentication. ]] @@ -69,11 +78,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'http' -require 'brute' -require 'url' -require 'creds' portrule = shortport.port_or_service( {80, 443}, {"http", "https"}, "tcp", "open") diff --git a/scripts/http-generator.nse b/scripts/http-generator.nse index d2fbb26795..b99856b13d 100644 --- a/scripts/http-generator.nse +++ b/scripts/http-generator.nse @@ -1,3 +1,8 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Displays the contents of the "generator" meta tag of a web page (default: /) if there is one. ]] @@ -41,9 +46,6 @@ categories = {"default", "discovery", "safe"} -- TODO: -- more generic generator pattern -require('http') -require('shortport') -require('stdnse') -- helper function local follow_redirects = function(host, port, path, n) diff --git a/scripts/http-gitweb-projects-enum.nse b/scripts/http-gitweb-projects-enum.nse index 5366290c73..15db4c1a15 100644 --- a/scripts/http-gitweb-projects-enum.nse +++ b/scripts/http-gitweb-projects-enum.nse @@ -1,3 +1,10 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" + description=[[ Gets a list of Git projects, owners and descriptions from a gitweb. ]] @@ -25,9 +32,6 @@ author = "riemann" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -local http = require 'http' -local shortport = require 'shortport' -local tab = require 'tab' portrule = shortport.http diff --git a/scripts/http-google-malware.nse b/scripts/http-google-malware.nse index 6de1d3917b..917e75a55a 100644 --- a/scripts/http-google-malware.nse +++ b/scripts/http-google-malware.nse @@ -1,3 +1,9 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Checks if hosts are on Google's blacklist of suspected malware and phishing servers. These lists are constantly updated and are part of Google's Safe Browsing service. @@ -27,8 +33,6 @@ author = "Paulino Calderon" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"malware", "discovery", "safe", "external"} -require "http" -require "shortport" portrule = shortport.http diff --git a/scripts/http-grep.nse b/scripts/http-grep.nse index 4d5fc98fc3..9386db39d1 100644 --- a/scripts/http-grep.nse +++ b/scripts/http-grep.nse @@ -1,3 +1,8 @@ +local httpspider = require "httpspider" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Spiders a website and attempts to match all pages and urls against a given string. Matches are counted and grouped per url under which they were @@ -42,9 +47,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'httpspider' -require 'shortport' -require 'url' portrule = shortport.http @@ -107,4 +109,4 @@ action = function(host, port) end table.sort(results, function(a,b) return a.name>b.name end) return stdnse.format_output(true, results) -end \ No newline at end of file +end diff --git a/scripts/http-headers.nse b/scripts/http-headers.nse index 49165b0c94..891e64798d 100644 --- a/scripts/http-headers.nse +++ b/scripts/http-headers.nse @@ -1,3 +1,9 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Performs a GET request for the root folder ("/") of a web server and displays the HTTP headers returned. ]] @@ -28,8 +34,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "shortport" -require "http" portrule = shortport.http diff --git a/scripts/http-icloud-findmyiphone.nse b/scripts/http-icloud-findmyiphone.nse index e48195fdd7..e2552e670d 100644 --- a/scripts/http-icloud-findmyiphone.nse +++ b/scripts/http-icloud-findmyiphone.nse @@ -1,3 +1,8 @@ +local mobileme = require "mobileme" +local os = require "os" +local stdnse = require "stdnse" +local tab = require "tab" + description = [[ Retrieves the locations of all "Find my iPhone" enabled iOS devices by querying the MobileMe web service. @@ -23,8 +28,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -local mobileme = require('mobileme') -local tab = require('tab') local arg_username = stdnse.get_script_args(SCRIPT_NAME .. ".username") local arg_password = stdnse.get_script_args(SCRIPT_NAME .. ".password") @@ -81,4 +84,4 @@ action = function() if ( 1 < #output ) then return stdnse.format_output(true, tab.dump(output)) end -end \ No newline at end of file +end diff --git a/scripts/http-icloud-sendmsg.nse b/scripts/http-icloud-sendmsg.nse index b575f0d4e6..c1600b0109 100644 --- a/scripts/http-icloud-sendmsg.nse +++ b/scripts/http-icloud-sendmsg.nse @@ -1,3 +1,7 @@ +local mobileme = require "mobileme" +local stdnse = require "stdnse" +local tab = require "tab" + description = [[ Sends a message to a iOS device throught the Apple MobileMe web service. The device has to be registered with an Apple ID using the Find My Iphone @@ -31,8 +35,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -local mobileme = require('mobileme') -local tab = require('tab') local arg_username = stdnse.get_script_args(SCRIPT_NAME .. ".username") local arg_password = stdnse.get_script_args(SCRIPT_NAME .. ".password") @@ -107,4 +109,4 @@ action = function() end end end -end \ No newline at end of file +end diff --git a/scripts/http-iis-webdav-vuln.nse b/scripts/http-iis-webdav-vuln.nse index 4e29009027..53994a40cb 100644 --- a/scripts/http-iis-webdav-vuln.nse +++ b/scripts/http-iis-webdav-vuln.nse @@ -1,3 +1,10 @@ +local http = require "http" +local io = require "io" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Checks for a vulnerability in IIS 5.1/6.0 that allows arbitrary users to access secured WebDAV folders by searching for a password-protected folder and attempting to access it. This vulnerability was patched in Microsoft Security Bulletin MS09-020, http://nmap.org/r/ms09-020. @@ -30,8 +37,6 @@ author = "Ron Bowes and Andrew Orr" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"vuln", "intrusive"} -require "http" -require "shortport" portrule = shortport.http diff --git a/scripts/http-joomla-brute.nse b/scripts/http-joomla-brute.nse index 1c4a4e38b2..bb9b183d93 100644 --- a/scripts/http-joomla-brute.nse +++ b/scripts/http-joomla-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Performs brute force password auditing against Joomla web CMS installations. @@ -50,10 +57,6 @@ author = "Paulino Calderon" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'http' -require 'brute' -require 'creds' portrule = shortport.http diff --git a/scripts/http-litespeed-sourcecode-download.nse b/scripts/http-litespeed-sourcecode-download.nse index cbf18d394b..2256a23d91 100644 --- a/scripts/http-litespeed-sourcecode-download.nse +++ b/scripts/http-litespeed-sourcecode-download.nse @@ -1,3 +1,9 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Exploits a null-byte poisoning vulnerability in Litespeed Web Servers 4.0.x before 4.0.15 to retrieve the target script's source code by sending a HTTP request with a null byte followed by a .txt file extension (CVE-2010-2333). @@ -31,8 +37,6 @@ author = "Paulino Calderon" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"vuln", "intrusive", "exploit"} -require "http" -require "shortport" portrule = shortport.http diff --git a/scripts/http-majordomo2-dir-traversal.nse b/scripts/http-majordomo2-dir-traversal.nse index 3aba03e2ba..f91cf1e259 100644 --- a/scripts/http-majordomo2-dir-traversal.nse +++ b/scripts/http-majordomo2-dir-traversal.nse @@ -1,3 +1,9 @@ +local http = require "http" +local io = require "io" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Exploits a directory traversal vulnerability existing in Majordomo2 to retrieve remote files. (CVE-2011-0049). @@ -34,8 +40,6 @@ author = "Paulino Calderon" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "vuln", "exploit"} -require "http" -require "shortport" portrule = shortport.http diff --git a/scripts/http-malware-host.nse b/scripts/http-malware-host.nse index 3fd35fdb97..dd0cf8c6ce 100644 --- a/scripts/http-malware-host.nse +++ b/scripts/http-malware-host.nse @@ -1,3 +1,10 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Looks for signature of known server compromises. @@ -27,9 +34,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"malware", "safe"} -require 'http' -require 'shortport' -require 'stdnse' portrule = shortport.http diff --git a/scripts/http-method-tamper.nse b/scripts/http-method-tamper.nse index d62342a3a8..b6debbf06d 100644 --- a/scripts/http-method-tamper.nse +++ b/scripts/http-method-tamper.nse @@ -1,3 +1,8 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Tests whether a JBoss target is vulnerable to jmx console authentication bypass (CVE-2010-0738). @@ -31,9 +36,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "auth", "vuln"} -require 'shortport' -require 'http' -require 'stdnse' portrule = shortport.http diff --git a/scripts/http-methods.nse b/scripts/http-methods.nse index 4b3fae4292..3a9737aa4a 100644 --- a/scripts/http-methods.nse +++ b/scripts/http-methods.nse @@ -1,3 +1,9 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Finds out what options are supported by an HTTP server by sending an OPTIONS request. Lists potentially risky methods. Optionally tests each @@ -46,10 +52,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe"} -require("http") -require("nmap") -require("shortport") -require("stdnse") -- We don't report these methods except with verbosity. local UNINTERESTING_METHODS = { diff --git a/scripts/http-open-proxy.nse b/scripts/http-open-proxy.nse index 38354c45cc..9d4a15e019 100644 --- a/scripts/http-open-proxy.nse +++ b/scripts/http-open-proxy.nse @@ -1,3 +1,9 @@ +local proxy = require "proxy" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local url = require "url" + description=[[ Checks if an HTTP proxy is open. @@ -37,11 +43,6 @@ the target to retrieve a web page from www.google.com. author = "Arturo 'Buanzo' Busleiman" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "external", "safe"} -require "comm" -require "shortport" -require "stdnse" -require "url" -require "proxy" --- Performs the custom test, with user's arguments -- @param host The host table diff --git a/scripts/http-open-redirect.nse b/scripts/http-open-redirect.nse index ae602aa8c1..b218c67ead 100644 --- a/scripts/http-open-redirect.nse +++ b/scripts/http-open-redirect.nse @@ -1,3 +1,11 @@ +local http = require "http" +local httpspider = require "httpspider" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local url = require "url" + description = [[ Spiders a website and attempts to identify open redirects. Open redirects are handlers which commonly take a URL as a parameter and @@ -32,14 +40,11 @@ author = "Martin Holst Swende" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require 'httpspider' -require 'shortport' -require 'url' portrule = shortport.http local function dbg(str,...) - stdnse.print_debug(2,"http-open-redirect:"..str, unpack(arg)) + stdnse.print_debug(2,"http-open-redirect:"..str, table.unpack(arg)) end local function dbgt(tbl) for k,v in pairs(tbl) do @@ -129,4 +134,4 @@ action = function(host, port) if ( #results> 0 ) then return stdnse.format_output(true, results) end -end \ No newline at end of file +end diff --git a/scripts/http-passwd.nse b/scripts/http-passwd.nse index 6884b2fe78..fa9c75fae1 100644 --- a/scripts/http-passwd.nse +++ b/scripts/http-passwd.nse @@ -1,3 +1,8 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Checks if a web server is vulnerable to directory traversal by attempting to retrieve /etc/passwd or \boot.ini. @@ -61,9 +66,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "vuln"} -require "http" -require "shortport" -require "stdnse" --- Validates the HTTP response code and checks for a valid passwd -- or Windows Boot Loader format in the body. diff --git a/scripts/http-php-version.nse b/scripts/http-php-version.nse index b4fc24ed93..71c7c0b6ec 100644 --- a/scripts/http-php-version.nse +++ b/scripts/http-php-version.nse @@ -1,3 +1,11 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + +local openssl = stdnse.silent_require "openssl" + description = [[ Attempts to retrieve the PHP version from a web server. PHP has a number of magic queries that return images or text that can vary with the PHP @@ -29,10 +37,6 @@ author = "Ange Gutek, Rob Nicholls" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "http" -require "shortport" -require "stdnse" -stdnse.silent_require "openssl" portrule = shortport.http diff --git a/scripts/http-proxy-brute.nse b/scripts/http-proxy-brute.nse index 8c97f7e6a8..cc55d0316e 100644 --- a/scripts/http-proxy-brute.nse +++ b/scripts/http-proxy-brute.nse @@ -1,3 +1,10 @@ +local base64 = require "base64" +local brute = require "brute" +local creds = require "creds" +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Performs brute force password guessing against a HTTP proxy server. ]] @@ -27,10 +34,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" -- as most request should not "leave" the proxy. categories = {"brute", "intrusive", "external"} -require 'base64' -require 'brute' -require 'http' -require 'shortport' portrule = shortport.port_or_service({8123,3128,8000,8080},{'polipo','squid-http','http-proxy'}) @@ -108,4 +111,4 @@ action = function(host, port) status, result = engine:start() return result -end \ No newline at end of file +end diff --git a/scripts/http-put.nse b/scripts/http-put.nse index 43895a3266..1a988c92aa 100644 --- a/scripts/http-put.nse +++ b/scripts/http-put.nse @@ -1,3 +1,8 @@ +local http = require "http" +local io = require "io" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Uploads a local file to a remote web server using the HTTP PUT method. You must specify the filename and URL path with NSE arguments. ]] @@ -27,9 +32,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require 'shortport' -require 'stdnse' -require 'http' portrule = shortport.port_or_service( {80, 443}, {"http", "https"}, "tcp", "open") diff --git a/scripts/http-qnap-nas-info.nse b/scripts/http-qnap-nas-info.nse index a024e7b633..bd630c8b2c 100644 --- a/scripts/http-qnap-nas-info.nse +++ b/scripts/http-qnap-nas-info.nse @@ -1,3 +1,9 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to retrieve the model, firmware version, and enabled services from a QNAP Network Attached Storage (NAS) device. @@ -36,10 +42,6 @@ author = "Brendan Coles" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe","discovery"} -require("url") -require("http") -require("stdnse") -require("shortport") portrule = shortport.port_or_service ({443,8080}, "https", "tcp") diff --git a/scripts/http-robots.txt.nse b/scripts/http-robots.txt.nse index 13d1d3faa3..16efe648f5 100644 --- a/scripts/http-robots.txt.nse +++ b/scripts/http-robots.txt.nse @@ -1,3 +1,9 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local strbuf = require "strbuf" +local table = require "table" + description = [[ Checks for disallowed entries in /robots.txt on a web server. @@ -17,9 +23,6 @@ The higher the verbosity or debug level, the more disallowed entries are shown. -- |_ /wml/? /wml/search? -require('shortport') -require('strbuf') -require('http') author = "Eddie Bell" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/http-robtex-reverse-ip.nse b/scripts/http-robtex-reverse-ip.nse index 40ec46c63d..7cea5599f5 100644 --- a/scripts/http-robtex-reverse-ip.nse +++ b/scripts/http-robtex-reverse-ip.nse @@ -1,3 +1,9 @@ +local http = require "http" +local ipOps = require "ipOps" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Obtains up to 100 forward DNS names for a target IP address by querying the Robtex service (http://www.robtex.com/ip/). ]] @@ -35,9 +41,6 @@ author = "riemann" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe", "external"} -require "http" -require "ipOps" -require "shortport" --- Scrape reverse ip informations from robtex website -- @param data string containing the retrieved web page diff --git a/scripts/http-robtex-shared-ns.nse b/scripts/http-robtex-shared-ns.nse index c09275f30f..a83adff95c 100644 --- a/scripts/http-robtex-shared-ns.nse +++ b/scripts/http-robtex-shared-ns.nse @@ -1,3 +1,8 @@ +local http = require "http" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Finds up to 100 domain names that use the same name server as the target by querying the Robtex service at http://www.robtex.com/dns/. @@ -29,8 +34,6 @@ categories = { "external" }; -require "http"; -require "shortport"; --- Scrape domains sharing name servers from robtex website -- @param data string containing the retrieved web page @@ -38,7 +41,7 @@ require "shortport"; function parse_robtex_response (data) local result = {}; - for linkhref, ns, domain in string.gmatch(data, "(.-)") do + for linkhref, ns, domain in string.gmatch(data, "(.-)") do if not table.contains(result, domain) then table.insert(result, domain); end diff --git a/scripts/http-title.nse b/scripts/http-title.nse index 33f0cef3cd..0a331089ff 100644 --- a/scripts/http-title.nse +++ b/scripts/http-title.nse @@ -1,3 +1,11 @@ +local dns = require "dns" +local http = require "http" +local ipOps = require "ipOps" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local url = require "url" + description = [[ Shows the title of the default page of a web server. @@ -20,11 +28,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -local url = require 'url' -local dns = require 'dns' -local http = require 'http' -local ipOps = require 'ipOps' -local stdnse = require 'stdnse' portrule = function(host, port) local svc = { std = { ["http"] = 1, ["http-alt"] = 1 }, diff --git a/scripts/http-trace.nse b/scripts/http-trace.nse index 2c6509fa46..de265b0de8 100644 --- a/scripts/http-trace.nse +++ b/scripts/http-trace.nse @@ -1,3 +1,8 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Sends an HTTP TRACE request and shows if the method TRACE is enabled. If debug is enabled, it returns the header fields that were modified in the response. ]] @@ -24,9 +29,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"vuln", "discovery", "safe"} -require "shortport" -require "stdnse" -require "http" portrule = shortport.http diff --git a/scripts/http-traceroute.nse b/scripts/http-traceroute.nse index ca38ca64fa..0d01be9ad9 100644 --- a/scripts/http-traceroute.nse +++ b/scripts/http-traceroute.nse @@ -1,3 +1,10 @@ +local http = require "http" +local nmap = require "nmap" +local pcre = require "pcre" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Exploits the Max-Forwards HTTP header to detect the presence of reverse proxies. @@ -56,9 +63,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'http' -require 'stdnse' -require 'shortport' portrule = shortport.service("http") diff --git a/scripts/http-unsafe-output-escaping.nse b/scripts/http-unsafe-output-escaping.nse index 4f3065d722..729ce422f3 100644 --- a/scripts/http-unsafe-output-escaping.nse +++ b/scripts/http-unsafe-output-escaping.nse @@ -1,3 +1,10 @@ +local http = require "http" +local httpspider = require "httpspider" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local url = require "url" + description = [[ Spiders a website and attempts to identify output escaping problems where content is reflected back to the user. This script locates all @@ -36,14 +43,11 @@ author = "Martin Holst Swende" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require 'httpspider' -require 'shortport' -require 'url' portrule = shortport.http local function dbg(str,...) - stdnse.print_debug(2,"%s:"..str, SCRIPT_NAME, unpack(arg)) + stdnse.print_debug(2,"%s:"..str, SCRIPT_NAME, table.unpack(arg)) end local function getHostPort(parsed) @@ -156,4 +160,4 @@ action = function(host, port) if ( #results> 0 ) then return stdnse.format_output(true, results) end -end \ No newline at end of file +end diff --git a/scripts/http-userdir-enum.nse b/scripts/http-userdir-enum.nse index fb6fd2bf61..dbd624e538 100644 --- a/scripts/http-userdir-enum.nse +++ b/scripts/http-userdir-enum.nse @@ -1,3 +1,15 @@ +local base64 = require "base64" +local bin = require "bin" +local datafiles = require "datafiles" +local http = require "http" +local nmap = require "nmap" +local openssl = require "openssl" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + author = "jah" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "intrusive"} @@ -28,10 +40,6 @@ CVE-2001-1013: http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2001-1013. -- 80/tcp open http syn-ack Apache httpd 2.2.9 -- |_ apache-userdir-enum: Potential Users: root (403), user (200), test (200) -local http = require 'http' -local shortport = require 'shortport' -local stdnse = require 'stdnse' -local datafiles = require 'datafiles' @@ -149,8 +157,6 @@ end -- @return String function randomstring() - local bin = require"bin" - local base64 = require"base64" local rnd, s, l, _ if pcall(require, "openssl") then rnd = openssl.rand_pseudo_bytes diff --git a/scripts/http-vhosts.nse b/scripts/http-vhosts.nse index 137efd77ef..610187b34d 100644 --- a/scripts/http-vhosts.nse +++ b/scripts/http-vhosts.nse @@ -1,3 +1,9 @@ +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Searches for web virtual hostnames by making a large number of HEAD requests against http servers using common hostnames. @@ -53,10 +59,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "discovery", "intrusive" } -require "http" -require "stdnse" -require "string" -require "shortport" -- List of domains to try. (Will become names like example.com, -- abbot.example.com, admin.example.com, etc.) The list is derived from diff --git a/scripts/http-virustotal.nse b/scripts/http-virustotal.nse index a7601f55ad..8fd7a48358 100644 --- a/scripts/http-virustotal.nse +++ b/scripts/http-virustotal.nse @@ -1,3 +1,11 @@ +local http = require "http" +local io = require "io" +local json = require "json" +local openssl = require "openssl" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Checks whether a file has been determined as malware by virustotal. Virustotal is a service that provides the capability to scan a file or check a checksum @@ -85,10 +93,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories={"safe", "malware", "external"} -local http = require 'http' -local json = require 'json' -local openssl = require 'openssl' -local tab = require 'tab' local arg_apiKey = stdnse.get_script_args(SCRIPT_NAME .. ".apikey") local arg_upload = stdnse.get_script_args(SCRIPT_NAME .. ".upload") or false @@ -248,4 +252,4 @@ action = function() end return stdnse.format_output(true, parseScanReport(response)) -end \ No newline at end of file +end diff --git a/scripts/http-vlcstreamer-ls.nse b/scripts/http-vlcstreamer-ls.nse index 7c383463b1..b0c0b0f091 100644 --- a/scripts/http-vlcstreamer-ls.nse +++ b/scripts/http-vlcstreamer-ls.nse @@ -1,3 +1,9 @@ +local http = require "http" +local json = require "json" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Connects to the VLC Streamer helper service and lists directory contents. The VLC Streamer helper service is used by the iOS VLC Streamer application to @@ -43,9 +49,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -local http = require('http') -local json = require('json') -local shortport = require('shortport') portrule = shortport.port_or_service(54340, "vlcstreamer", "tcp") @@ -80,4 +83,4 @@ action = function(host, port) end table.sort(output, function(a,b) return a -require 'creds' -require 'brute' -require 'shortport' -require 'imap' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/imap-capabilities.nse b/scripts/imap-capabilities.nse index c0277b6fe9..5b1e2a5b7e 100644 --- a/scripts/imap-capabilities.nse +++ b/scripts/imap-capabilities.nse @@ -1,3 +1,8 @@ +local imap = require "imap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Retrieves IMAP email server capabilities. @@ -17,9 +22,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe"} -require 'imap' -require 'shortport' -require 'stdnse' portrule = shortport.port_or_service({143}, "imap") diff --git a/scripts/informix-brute.nse b/scripts/informix-brute.nse index 937b136f19..9f61f09171 100644 --- a/scripts/informix-brute.nse +++ b/scripts/informix-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local informix = require "informix" +local nmap = require "nmap" +local shortport = require "shortport" +local table = require "table" + description = [[ Performs brute force password auditing against IBM Informix Dynamic Server. ]] @@ -30,10 +37,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'brute' -require 'informix' -require 'creds' portrule = shortport.port_or_service( { 1526, 9088, 9090, 9092 }, "informix", "tcp", "open") diff --git a/scripts/informix-query.nse b/scripts/informix-query.nse index a7d98c74ea..1f5fded426 100644 --- a/scripts/informix-query.nse +++ b/scripts/informix-query.nse @@ -1,3 +1,9 @@ +local informix = require "informix" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Runs a query against IBM Informix Dynamic Server using the given authentication credentials (see also: informix-brute). @@ -35,8 +41,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "auth"} dependencies = { "informix-brute" } -require 'shortport' -require 'informix' portrule = shortport.port_or_service( { 1526, 9088, 9090, 9092 }, "informix", "tcp", "open") diff --git a/scripts/informix-tables.nse b/scripts/informix-tables.nse index ae9daa51ed..13a653ad4f 100644 --- a/scripts/informix-tables.nse +++ b/scripts/informix-tables.nse @@ -1,3 +1,9 @@ +local informix = require "informix" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Retrieves a list of tables and column definitions for each database on an Informix server. ]] @@ -48,8 +54,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "auth"} dependencies = { "informix-brute" } -require 'shortport' -require 'informix' portrule = shortport.port_or_service( { 1526, 9088, 9090, 9092 }, "informix", "tcp", "open") diff --git a/scripts/ip-forwarding.nse b/scripts/ip-forwarding.nse index 0ae222a9bb..a4c8b7502f 100644 --- a/scripts/ip-forwarding.nse +++ b/scripts/ip-forwarding.nse @@ -1,3 +1,9 @@ +local dns = require "dns" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Detects whether the remote device has ip forwarding or "Internet connection sharing" enabled, by sending an ICMP echo request to a given target using @@ -38,10 +44,6 @@ hostrule = function(host) return (arg_target ~= nil and host.mac_addr ~= nil) end -local dns = require('dns') -local ipops = require('ipOps') -local tab = require('tab') -local packet = require('packet') local function format_mac(mac) local octets diff --git a/scripts/ip-geolocation-geobytes.nse b/scripts/ip-geolocation-geobytes.nse index 94470f658b..9952207403 100644 --- a/scripts/ip-geolocation-geobytes.nse +++ b/scripts/ip-geolocation-geobytes.nse @@ -1,3 +1,10 @@ +local http = require "http" +local ipOps = require "ipOps" +local json = require "json" +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Tries to identify the physical location of an IP address using the Geobytes geolocation web service @@ -22,11 +29,6 @@ author = "Gorjan Petrovski" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","external","safe"} -require "nmap" -require "stdnse" -require "ipOps" -require "json" -require "http" hostrule = function(host) local is_private, err = ipOps.isPrivate( host.ip ) diff --git a/scripts/ip-geolocation-geoplugin.nse b/scripts/ip-geolocation-geoplugin.nse index d492be8d3f..7475c14046 100644 --- a/scripts/ip-geolocation-geoplugin.nse +++ b/scripts/ip-geolocation-geoplugin.nse @@ -1,3 +1,9 @@ +local http = require "http" +local ipOps = require "ipOps" +local json = require "json" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Tries to identify the physical location of an IP address using the Geoplugin geolocation web service (http://www.geoplugin.com/). There @@ -19,10 +25,6 @@ author = "Gorjan Petrovski" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","external","safe"} -require "stdnse" -require "ipOps" -require "json" -require "http" hostrule = function(host) local is_private, err = ipOps.isPrivate( host.ip ) diff --git a/scripts/ip-geolocation-ipinfodb.nse b/scripts/ip-geolocation-ipinfodb.nse index 675f446706..2d34c8543b 100644 --- a/scripts/ip-geolocation-ipinfodb.nse +++ b/scripts/ip-geolocation-ipinfodb.nse @@ -1,3 +1,9 @@ +local http = require "http" +local ipOps = require "ipOps" +local json = require "json" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Tries to identify the physical location of an IP address using the IPInfoDB geolocation web service @@ -26,10 +32,6 @@ author = "Gorjan Petrovski" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","external","safe"} -require "stdnse" -require "ipOps" -require "json" -require "http" hostrule = function(host) local is_private, err = ipOps.isPrivate( host.ip ) diff --git a/scripts/ip-geolocation-maxmind.nse b/scripts/ip-geolocation-maxmind.nse index e9ccb674f5..51639fb7d1 100644 --- a/scripts/ip-geolocation-maxmind.nse +++ b/scripts/ip-geolocation-maxmind.nse @@ -1,3 +1,10 @@ +local bit = require "bit" +local io = require "io" +local ipOps = require "ipOps" +local math = require "math" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Tries to identify the physical location of an IP address using a Geolocation Maxmind database file (available from @@ -23,9 +30,6 @@ author = "Gorjan Petrovski" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","external","safe"} -require "stdnse" -require "ipOps" -require "bit" hostrule = function(host) local is_private, err = ipOps.isPrivate( host.ip ) diff --git a/scripts/ipidseq.nse b/scripts/ipidseq.nse index eef948130e..55d98036ee 100644 --- a/scripts/ipidseq.nse +++ b/scripts/ipidseq.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local math = require "math" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Classifies a host's IP ID sequence (test for susceptibility to idle scan). @@ -28,10 +35,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -require 'bin' -require 'packet' -require 'nmap' -require 'stdnse' local NUMPROBES = 6 diff --git a/scripts/ipv6-node-info.nse b/scripts/ipv6-node-info.nse index 5a800b2c0f..04710d8eb1 100644 --- a/scripts/ipv6-node-info.nse +++ b/scripts/ipv6-node-info.nse @@ -1,3 +1,13 @@ +local bin = require "bin" +local bit = require "bit" +local dns = require "dns" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" + +local openssl = stdnse.silent_require "openssl" + description = [[ Obtains hostnames, IPv4 and IPv6 addresses through IPv6 Node Information Queries. @@ -26,12 +36,6 @@ categories = {"default", "discovery", "safe"} author = "David Fifield" -require("bin") -require("bit") -require("dns") -require("stdnse") -require("packet") -stdnse.silent_require("openssl") local ICMPv6_NODEINFOQUERY = 139 local ICMPv6_NODEINFOQUERY_IPv6ADDR = 0 diff --git a/scripts/irc-botnet-channels.nse b/scripts/irc-botnet-channels.nse index fafc5bacb0..a69bbd8f5f 100644 --- a/scripts/irc-botnet-channels.nse +++ b/scripts/irc-botnet-channels.nse @@ -1,3 +1,10 @@ +local comm = require "comm" +local math = require "math" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Checks an IRC server for channels that are commonly used by malicious botnets. @@ -38,10 +45,6 @@ categories = {"discovery", "vuln", "safe"} -- | #loic -- |_ #RxBot -require("stdnse") -require "shortport" -require("nsedebug") -require("comm") -- See RFC 2812 for protocol documentation. diff --git a/scripts/irc-brute.nse b/scripts/irc-brute.nse index 4a55d81586..57ce5af202 100644 --- a/scripts/irc-brute.nse +++ b/scripts/irc-brute.nse @@ -1,3 +1,11 @@ +local brute = require "brute" +local comm = require "comm" +local creds = require "creds" +local math = require "math" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description=[[ Performs brute force password auditing against IRC (Internet Relay Chat) servers. ]] @@ -21,9 +29,6 @@ Performs brute force password auditing against IRC (Internet Relay Chat) servers -- Created 26/10/2011 - v0.1 - created by Patrik Karlsson -- -require 'brute' -require 'shortport' -require 'comm' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -135,4 +140,4 @@ action = function(host, port) return result -end \ No newline at end of file +end diff --git a/scripts/irc-info.nse b/scripts/irc-info.nse index 77dfb8d28e..9623ff4901 100644 --- a/scripts/irc-info.nse +++ b/scripts/irc-info.nse @@ -1,3 +1,11 @@ +local comm = require "comm" +local math = require "math" +local nmap = require "nmap" +local pcre = require "pcre" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Gathers information from an IRC server. @@ -20,10 +28,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require("stdnse") -require "shortport" -require("nsedebug") -require("comm") portrule = shortport.port_or_service({6666,6667,6697,6679},{"irc","ircs"}) diff --git a/scripts/irc-unrealircd-backdoor.nse b/scripts/irc-unrealircd-backdoor.nse index 0d96b24a33..c870d17244 100644 --- a/scripts/irc-unrealircd-backdoor.nse +++ b/scripts/irc-unrealircd-backdoor.nse @@ -1,3 +1,10 @@ +local comm = require "comm" +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Checks if an IRC server is backdoored by running a time-based command (ping) and checking how long it takes to respond. @@ -46,9 +53,6 @@ author = "Vlatko Kosturjak and Ron Bowes" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"exploit", "intrusive", "malware", "vuln"} -require "shortport" -require "comm" -require "stdnse" portrule = shortport.port_or_service({6666,6667,6697,6679,8067},{"irc","ircs"}) diff --git a/scripts/iscsi-brute.nse b/scripts/iscsi-brute.nse index fa27cc3777..077a1996d8 100644 --- a/scripts/iscsi-brute.nse +++ b/scripts/iscsi-brute.nse @@ -1,3 +1,9 @@ +local brute = require "brute" +local creds = require "creds" +local iscsi = require "iscsi" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Performs brute force password auditing against iSCSI targets. ]] @@ -16,10 +22,6 @@ Performs brute force password auditing against iSCSI targets. -- Created 2010/11/18 - v0.1 - created by Patrik Karlsson -- Revised 2010/11/27 - v0.2 - detect if no password is needed -require 'shortport' -require 'brute' -require 'iscsi' -require 'creds' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/iscsi-info.nse b/scripts/iscsi-info.nse index 0687ab7945..a9fff0123e 100644 --- a/scripts/iscsi-info.nse +++ b/scripts/iscsi-info.nse @@ -1,3 +1,8 @@ +local iscsi = require "iscsi" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Collects and displays information from remote iSCSI targets. ]] @@ -23,8 +28,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe", "discovery"} -require("shortport") -require("iscsi") portrule = shortport.portnumber(3260, "tcp", {"open", "open|filtered"}) diff --git a/scripts/jdwp-version.nse b/scripts/jdwp-version.nse index 282a399016..8944beb1fe 100644 --- a/scripts/jdwp-version.nse +++ b/scripts/jdwp-version.nse @@ -1,3 +1,8 @@ +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description = [[ Detects the Java Debug Wire Protocol. This protocol is used by Java programs to be debugged via the network. It should not be open to the public Internet, @@ -16,8 +21,6 @@ categories = {"version"} -- PORT STATE SERVICE VERSION -- 9999/tcp open jdwp Java Debug Wire Protocol (Reference Implementation) version 1.6 1.6.0_17 -require "comm" -require "shortport" portrule = function(host, port) -- JDWP will close the port if there is no valid handshake within 2 diff --git a/scripts/krb5-enum-users.nse b/scripts/krb5-enum-users.nse index 48676cfe58..252f1637ef 100644 --- a/scripts/krb5-enum-users.nse +++ b/scripts/krb5-enum-users.nse @@ -1,3 +1,13 @@ +local asn1 = require "asn1" +local bin = require "bin" +local coroutine = require "coroutine" +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local unpwdb = require "unpwdb" + description = [[ Discovers valid usernames by brute force querying likely usernames against a Kerberos service. When an invalid username is requested the server will responde using the @@ -37,10 +47,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "intrusive"} -require 'shortport' -require 'stdnse' -require 'asn1' -require 'unpwdb' portrule = shortport.port_or_service( 88, {"kerberos-sec"}, {"udp","tcp"}, {"open", "open|filtered"} ) @@ -393,4 +399,4 @@ action = function( host, port ) result = { name = "Discovered Kerberos principals", result } end return stdnse.format_output(true, result) -end \ No newline at end of file +end diff --git a/scripts/ldap-brute.nse b/scripts/ldap-brute.nse index 0b7f71ed2c..b393e12641 100644 --- a/scripts/ldap-brute.nse +++ b/scripts/ldap-brute.nse @@ -1,3 +1,13 @@ +local comm = require "comm" +local creds = require "creds" +local ldap = require "ldap" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local unpwdb = require "unpwdb" + description = [[ Attempts to brute-force LDAP authentication. By default it uses the built-in username and password lists. In order to use your @@ -71,12 +81,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'stdnse' -require 'ldap' -require 'unpwdb' -require 'comm' -require 'creds' -- Version 0.6 -- Created 01/20/2010 - v0.1 - created by Patrik Karlsson diff --git a/scripts/ldap-novell-getpass.nse b/scripts/ldap-novell-getpass.nse index f2f5c416ea..40a1fdbcb6 100644 --- a/scripts/ldap-novell-getpass.nse +++ b/scripts/ldap-novell-getpass.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local comm = require "comm" +local ldap = require "ldap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to retrieve the Novell Universal Password for a user. You must already have (and include in script arguments) the username and password for an eDirectory server @@ -42,9 +49,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "ldap" -require 'shortport' -require 'comm' portrule = shortport.port_or_service({389,636}, {"ldap","ldapssl"}) @@ -132,4 +136,4 @@ function action(host,port) else return "\n ERROR: No password was found" end -end \ No newline at end of file +end diff --git a/scripts/ldap-rootdse.nse b/scripts/ldap-rootdse.nse index e07ee2128d..9d7130a095 100644 --- a/scripts/ldap-rootdse.nse +++ b/scripts/ldap-rootdse.nse @@ -1,3 +1,10 @@ +local comm = require "comm" +local ldap = require "ldap" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Retrieves the LDAP root DSA-specific Entry (DSE) ]] @@ -88,9 +95,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} dependencies = {"ldap-brute"} -require "ldap" -require 'shortport' -require 'comm' portrule = shortport.port_or_service({389,636}, {"ldap","ldapssl"}) diff --git a/scripts/ldap-search.nse b/scripts/ldap-search.nse index b7e962c844..2dfd33eb99 100644 --- a/scripts/ldap-search.nse +++ b/scripts/ldap-search.nse @@ -1,3 +1,11 @@ +local comm = require "comm" +local ldap = require "ldap" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to perform an LDAP search and returns all matches. @@ -88,9 +96,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require "ldap" -require 'shortport' -require 'comm' dependencies = {"ldap-brute"} diff --git a/scripts/lexmark-config.nse b/scripts/lexmark-config.nse index 25fea6e27a..164a5fc03f 100644 --- a/scripts/lexmark-config.nse +++ b/scripts/lexmark-config.nse @@ -1,3 +1,9 @@ +local dns = require "dns" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Retrieves configuration information from a Lexmark S300-S400 printer. @@ -44,9 +50,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'stdnse' -require 'dns' portrule = shortport.portnumber({5353,9100}, "udp") diff --git a/scripts/lltd-discovery.nse b/scripts/lltd-discovery.nse index 43d3fe6549..2e463286f7 100644 --- a/scripts/lltd-discovery.nse +++ b/scripts/lltd-discovery.nse @@ -1,3 +1,14 @@ +local bin = require "bin" +local coroutine = require "coroutine" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + +local openssl = stdnse.silent_require "openssl" + description = [[ Uses the Microsoft LLTD protocol to discover hosts on a local network. @@ -22,11 +33,6 @@ author = "Gorjan Petrovski" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"broadcast","discovery","safe"} -require "bin" -require "target" -require "nmap" -require "stdnse" -stdnse.silent_require("openssl") prerule = function() if not nmap.is_privileged() then diff --git a/scripts/maxdb-info.nse b/scripts/maxdb-info.nse index f66707c18a..dc61ad3e55 100644 --- a/scripts/maxdb-info.nse +++ b/scripts/maxdb-info.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Retrieves version and database information from a SAP Max DB database. ]] @@ -27,8 +34,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "default", "version" } -require 'shortport' -require 'tab' portrule = shortport.port_or_service(7210, "maxdb", "tcp") @@ -168,4 +173,4 @@ action = function(host, port) nmap.set_port_version(host, port, "hardmatched") return stdnse.format_output(true, result) -end \ No newline at end of file +end diff --git a/scripts/membase-brute.nse b/scripts/membase-brute.nse index bdec355721..60062d4a60 100644 --- a/scripts/membase-brute.nse +++ b/scripts/membase-brute.nse @@ -1,3 +1,9 @@ +local brute = require "brute" +local creds = require "creds" +local membase = require "membase" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Performs brute force password auditing against Couchbase Membase servers. ]] @@ -23,9 +29,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'brute' -require 'shortport' -require 'membase' portrule = shortport.port_or_service({11210,11211}, "couchbase-tap", "tcp") @@ -107,4 +110,4 @@ action = function(host, port) status, result = engine:start() return result -end \ No newline at end of file +end diff --git a/scripts/membase-http-info.nse b/scripts/membase-http-info.nse index f12a5efc04..acc2f16c67 100644 --- a/scripts/membase-http-info.nse +++ b/scripts/membase-http-info.nse @@ -1,3 +1,10 @@ +local _G = require "_G" +local http = require "http" +local json = require "json" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" + description = [[ Retrieves information (hostname, OS, uptime, etc.) from the CouchBase Web Administration port. The information retrieved by this script @@ -32,10 +39,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'http' -require 'json' -require 'shortport' -require 'tab' portrule = shortport.port_or_service(8091, "http", "tcp") @@ -97,8 +100,8 @@ local function cmdReq(host, port, url, result) local var, val = "" for x in item:gmatch("(.-%])") do var = var .. x - local func = loadstring("return " .. var) - setfenv(func, setmetatable({ parsed=parsed }, {__index = _G})) + local env = setmetatable({parsed=parsed}, {__index = _G}) + local func = load("return " .. var, nil, "t", env) if ( not(func()) ) then val = nil @@ -137,4 +140,4 @@ action = function(host, port) end return stdnse.format_output(true, tab.dump(output)) -end \ No newline at end of file +end diff --git a/scripts/memcached-info.nse b/scripts/memcached-info.nse index c135d626c6..299e4dcdf2 100644 --- a/scripts/memcached-info.nse +++ b/scripts/memcached-info.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" + description = [[ Retrieves information (including system architecture, process ID, and server time) from distributed memory object caching system memcached. @@ -28,8 +34,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'tab' -- currently, we only support the TCP, text based protocol portrule = shortport.port_or_service(11211, "memcached", "tcp") @@ -123,4 +127,4 @@ action = function(host, port) end return stdnse.format_output(true, tab.dump(result)) -end \ No newline at end of file +end diff --git a/scripts/metasploit-xmlrpc-brute.nse b/scripts/metasploit-xmlrpc-brute.nse index a042d31631..3afda6b430 100644 --- a/scripts/metasploit-xmlrpc-brute.nse +++ b/scripts/metasploit-xmlrpc-brute.nse @@ -1,3 +1,13 @@ +local brute = require "brute" +local comm = require "comm" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + +local openssl = stdnse.silent_require "openssl" + description=[[ Performs brute force password auditing against a Metasploit RPC server using the XMLRPC protocol. ]] @@ -20,11 +30,6 @@ author = "Vlatko Kosturjak" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require "shortport" -require "brute" -require "comm" -require "stdnse" -stdnse.silent_require 'openssl' portrule = shortport.port_or_service(55553, "metasploit-xmlrpc", "tcp") diff --git a/scripts/mmouse-brute.nse b/scripts/mmouse-brute.nse index 9c43f41365..680c526fb0 100644 --- a/scripts/mmouse-brute.nse +++ b/scripts/mmouse-brute.nse @@ -1,3 +1,9 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Performs brute force password auditing against the RPA Tech Mobile Mouse Server. @@ -25,8 +31,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -local shortport = require('shortport') -local brute = require('brute') local arg_timeout = stdnse.get_script_args(SCRIPT_NAME .. ".timeout") or 5000 @@ -110,4 +114,4 @@ action = function(host, port) status, result = engine:start() return result -end \ No newline at end of file +end diff --git a/scripts/mmouse-exec.nse b/scripts/mmouse-exec.nse index d4e5ab8ac4..5e82bb37b3 100644 --- a/scripts/mmouse-exec.nse +++ b/scripts/mmouse-exec.nse @@ -1,3 +1,8 @@ +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Connects to the mobile mouse server, starts an application and sends a sequence of keys to it. Any application that the user has access to can be started and @@ -35,8 +40,6 @@ author = "Patrik Karlsson" categories = {"intrusive"} dependencies = {"mmouse-brute"} -local shortport = require('shortport') -local creds = require('creds') local arg_password = stdnse.get_script_args(SCRIPT_NAME .. '.password') local arg_app = stdnse.get_script_args(SCRIPT_NAME .. '.application') @@ -172,4 +175,4 @@ action = function(host, port) end return ("\n Attempted to start application \"%s\" and sent \"%s\""):format(arg_app, arg_keys) -end \ No newline at end of file +end diff --git a/scripts/modbus-discover.nse b/scripts/modbus-discover.nse index b580513826..c6449c3403 100644 --- a/scripts/modbus-discover.nse +++ b/scripts/modbus-discover.nse @@ -1,3 +1,11 @@ +local bin = require "bin" +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Enumerates SCADA Modbus slave ids (sids) and collects their device information. @@ -34,10 +42,6 @@ author = "Alexander Rudakov" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require "bin" -require "comm" -require "stdnse" -require "shortport" portrule = shortport.portnumber(502, "tcp") diff --git a/scripts/mongodb-brute.nse b/scripts/mongodb-brute.nse index 3fea0ef845..3e731e16ee 100644 --- a/scripts/mongodb-brute.nse +++ b/scripts/mongodb-brute.nse @@ -1,3 +1,11 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local mongodb = stdnse.silent_require "mongodb" + description = [[ Performs brute force password auditing against the MongoDB database. ]] @@ -16,10 +24,6 @@ Performs brute force password auditing against the MongoDB database. -- |_ Performed 3542 guesses in 9 seconds, average tps: 393 -- -require 'brute' -require 'shortport' -require 'stdnse' -stdnse.silent_require('mongodb') author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/mongodb-databases.nse b/scripts/mongodb-databases.nse index 8ef1f66bb2..5521c28ba6 100644 --- a/scripts/mongodb-databases.nse +++ b/scripts/mongodb-databases.nse @@ -1,3 +1,10 @@ +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local mongodb = stdnse.silent_require "mongodb" + description = [[ Attempts to get a list of tables from a MongoDB database. ]] @@ -39,10 +46,6 @@ categories = {"default", "discovery", "safe"} dependencies = {"mongodb-brute"} -require "creds" -require "shortport" -require 'stdnse' -stdnse.silent_require('mongodb') portrule = shortport.port_or_service({27017}, {"mongodb"}) diff --git a/scripts/mongodb-info.nse b/scripts/mongodb-info.nse index 9bafc95302..438391c601 100644 --- a/scripts/mongodb-info.nse +++ b/scripts/mongodb-info.nse @@ -1,3 +1,10 @@ +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local mongodb = stdnse.silent_require "mongodb" + description = [[ Attempts to get build info and server status from a MongoDB database. ]] @@ -52,10 +59,6 @@ categories = {"default", "discovery", "safe"} dependencies = {"mongodb-brute"} -require "creds" -require "shortport" -require 'stdnse' -stdnse.silent_require('mongodb') local arg_db = stdnse.get_script_args(SCRIPT_NAME .. ".db") or "admin" diff --git a/scripts/ms-sql-brute.nse b/scripts/ms-sql-brute.nse index ebb6634efc..a10aee7b68 100644 --- a/scripts/ms-sql-brute.nse +++ b/scripts/ms-sql-brute.nse @@ -1,3 +1,10 @@ +local mssql = require "mssql" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local unpwdb = require "unpwdb" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -70,10 +77,6 @@ categories = {"brute", "intrusive"} dependencies = {"ms-sql-empty-password"} -require 'shortport' -require 'stdnse' -require 'mssql' -require 'unpwdb' hostrule = mssql.Helper.GetHostrule_Standard() diff --git a/scripts/ms-sql-config.nse b/scripts/ms-sql-config.nse index 3af931a306..cce23d03db 100644 --- a/scripts/ms-sql-config.nse +++ b/scripts/ms-sql-config.nse @@ -1,3 +1,8 @@ +local mssql = require "mssql" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -64,9 +69,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'stdnse' -require 'mssql' dependencies = {"ms-sql-brute", "ms-sql-empty-password"} diff --git a/scripts/ms-sql-dump-hashes.nse b/scripts/ms-sql-dump-hashes.nse index 2a134627db..7b4f067806 100644 --- a/scripts/ms-sql-dump-hashes.nse +++ b/scripts/ms-sql-dump-hashes.nse @@ -1,3 +1,9 @@ +local io = require "io" +local mssql = require "mssql" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Dumps the password hashes from an MS-SQL server in a format suitable for cracking by tools such as John-the-ripper. In order to do so the user @@ -29,9 +35,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "discovery", "safe"} -require 'shortport' -require 'stdnse' -require 'mssql' dependencies = {"ms-sql-brute", "ms-sql-empty-password"} diff --git a/scripts/ms-sql-empty-password.nse b/scripts/ms-sql-empty-password.nse index 5bd1076923..36a2cb57d5 100644 --- a/scripts/ms-sql-empty-password.nse +++ b/scripts/ms-sql-empty-password.nse @@ -1,3 +1,9 @@ +local mssql = require "mssql" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -51,9 +57,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth","intrusive"} -require 'shortport' -require 'stdnse' -require 'mssql' hostrule = mssql.Helper.GetHostrule_Standard() portrule = mssql.Helper.GetPortrule_Standard() diff --git a/scripts/ms-sql-hasdbaccess.nse b/scripts/ms-sql-hasdbaccess.nse index 6ff74fa122..4e42834f45 100644 --- a/scripts/ms-sql-hasdbaccess.nse +++ b/scripts/ms-sql-hasdbaccess.nse @@ -1,3 +1,8 @@ +local mssql = require "mssql" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -67,9 +72,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "discovery","safe"} -require 'shortport' -require 'stdnse' -require 'mssql' dependencies = {"ms-sql-brute", "ms-sql-empty-password"} diff --git a/scripts/ms-sql-info.nse b/scripts/ms-sql-info.nse index f32fa1e026..47b6bf6e4b 100644 --- a/scripts/ms-sql-info.nse +++ b/scripts/ms-sql-info.nse @@ -1,3 +1,10 @@ +local mssql = require "mssql" +local nmap = require "nmap" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -106,8 +113,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require("shortport") -require("mssql") hostrule = function(host) if ( mssql.Helper.WasDiscoveryPerformed( host ) ) then diff --git a/scripts/ms-sql-query.nse b/scripts/ms-sql-query.nse index 3add286e18..4da1b3d08d 100644 --- a/scripts/ms-sql-query.nse +++ b/scripts/ms-sql-query.nse @@ -1,3 +1,8 @@ +local mssql = require "mssql" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -53,9 +58,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'stdnse' -require 'mssql' dependencies = {"ms-sql-brute", "ms-sql-empty-password"} diff --git a/scripts/ms-sql-tables.nse b/scripts/ms-sql-tables.nse index 02b54a1039..ab67872392 100644 --- a/scripts/ms-sql-tables.nse +++ b/scripts/ms-sql-tables.nse @@ -1,3 +1,8 @@ +local mssql = require "mssql" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -91,9 +96,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'stdnse' -require 'mssql' dependencies = {"ms-sql-brute", "ms-sql-empty-password"} diff --git a/scripts/ms-sql-xp-cmdshell.nse b/scripts/ms-sql-xp-cmdshell.nse index 758026f58c..bc338475ec 100644 --- a/scripts/ms-sql-xp-cmdshell.nse +++ b/scripts/ms-sql-xp-cmdshell.nse @@ -1,3 +1,9 @@ +local mssql = require "mssql" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -79,9 +85,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive"} -require 'shortport' -require 'stdnse' -require 'mssql' dependencies = {"ms-sql-brute", "ms-sql-empty-password"} diff --git a/scripts/mysql-audit.nse b/scripts/mysql-audit.nse index 8c17c5fd12..467c0d6d1a 100644 --- a/scripts/mysql-audit.nse +++ b/scripts/mysql-audit.nse @@ -1,3 +1,10 @@ +local _G = require "_G" +local mysql = require "mysql" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Audits MySQL database server security configuration against parts of the CIS MySQL v1.0.2 benchmark (the engine can be used for other MySQL @@ -82,27 +89,26 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'mysql' portrule = shortport.port_or_service(3306, "mysql") local TEMPLATE_NAME, ADMIN_ACCOUNTS = "", "" local function loadAuditRulebase( filename ) - local file, err = loadfile(filename) + local env = setmetatable({ + test = function(t) table.insert(rules, t) end; + }, {__index = _G}) + + local file, err = loadfile(filename, "t", env) local rules = {} if ( not(file) ) then return false, ("ERROR: Failed to load rulebase:\n%s"):format(err) end - setfenv(file, setmetatable({ - test = function(t) table.insert(rules, t) end; - }, {__index = _G})) file() - TEMPLATE_NAME = getfenv(file)["TEMPLATE_NAME"] + TEMPLATE_NAME = env.TEMPLATE_NAME ADMIN_ACCOUNTS = getfenv(file)["ADMIN_ACCOUNTS"] return true, rules end @@ -173,4 +179,4 @@ action = function( host, port ) }) return stdnse.format_output(true, { results }) -end \ No newline at end of file +end diff --git a/scripts/mysql-brute.nse b/scripts/mysql-brute.nse index 45cb92ecf9..4dc4875fb4 100644 --- a/scripts/mysql-brute.nse +++ b/scripts/mysql-brute.nse @@ -1,3 +1,12 @@ +local brute = require "brute" +local creds = require "creds" +local mysql = require "mysql" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local openssl = stdnse.silent_require "openssl" + description = [[ Performs password guessing against MySQL. ]] @@ -16,13 +25,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'stdnse' -require 'mysql' -require 'brute' -require 'creds' -stdnse.silent_require 'openssl' - -- Version 0.5 -- Created 01/15/2010 - v0.1 - created by Patrik Karlsson -- Revised 01/23/2010 - v0.2 - revised by Patrik Karlsson, changed username, password loop, added credential storage for other mysql scripts, added timelimit diff --git a/scripts/mysql-databases.nse b/scripts/mysql-databases.nse index b6ee7f7ac0..0b5fdd2584 100644 --- a/scripts/mysql-databases.nse +++ b/scripts/mysql-databases.nse @@ -1,3 +1,10 @@ +local mysql = require "mysql" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local openssl = stdnse.silent_require "openssl" + description = [[ Attempts to list all databases on a MySQL server. ]] @@ -24,10 +31,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require 'shortport' -require 'stdnse' -require 'mysql' -stdnse.silent_require 'openssl' dependencies = {"mysql-brute", "mysql-empty-password"} diff --git a/scripts/mysql-dump-hashes.nse b/scripts/mysql-dump-hashes.nse index 3f32f710ca..959ad85a7a 100644 --- a/scripts/mysql-dump-hashes.nse +++ b/scripts/mysql-dump-hashes.nse @@ -1,3 +1,8 @@ +local mysql = require "mysql" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Dumps the password hashes from an MySQL server in a format suitable for cracking by tools such as John-the-ripper. In order to do so the user @@ -28,8 +33,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "discovery", "safe"} -local shortport = require('shortport') -local mysql = require('mysql') dependencies = {"mysql-empty-password", "mysql-brute"} @@ -97,4 +100,4 @@ action = function(host, port) if ( result ) then return stdnse.format_output(true, result) end -end \ No newline at end of file +end diff --git a/scripts/mysql-empty-password.nse b/scripts/mysql-empty-password.nse index 016d36b6c2..6d1fac1032 100644 --- a/scripts/mysql-empty-password.nse +++ b/scripts/mysql-empty-password.nse @@ -1,3 +1,10 @@ +local mysql = require "mysql" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Checks for MySQL servers with an empty password for root or anonymous. @@ -14,9 +21,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "auth"} -require 'shortport' -require 'stdnse' -require 'mysql' -- Version 0.3 -- Created 01/15/2010 - v0.1 - created by Patrik Karlsson diff --git a/scripts/mysql-info.nse b/scripts/mysql-info.nse index 5bd5a88b41..202663f3ff 100644 --- a/scripts/mysql-info.nse +++ b/scripts/mysql-info.nse @@ -1,3 +1,6 @@ +local bit = require "bit" +local comm = require "comm" + description = [[ Connects to a MySQL server and prints information such as the protocol and version numbers, thread ID, status, capabilities, and the password salt. @@ -25,8 +28,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "default", "discovery", "safe" } -require 'bit' -require 'comm' --- Grabs NUL-terminated string --@param orig Start of the string diff --git a/scripts/mysql-query.nse b/scripts/mysql-query.nse index cbc7be9f35..670440a13b 100644 --- a/scripts/mysql-query.nse +++ b/scripts/mysql-query.nse @@ -1,3 +1,8 @@ +local mysql = require "mysql" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Runs a query against a MySQL database and returns the results as a table. ]] @@ -28,9 +33,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "discovery", "safe"} -local shortport = require('shortport') -local mysql = require('mysql') -local tab = require('tab') dependencies = {"mysql-empty-password", "mysql-brute"} @@ -112,4 +114,4 @@ action = function(host, port) end end return stdnse.format_output(true, (last_error and ("ERROR: %s"):format(last_error) or result)) -end \ No newline at end of file +end diff --git a/scripts/mysql-users.nse b/scripts/mysql-users.nse index 81a64d74e5..94f6a10623 100644 --- a/scripts/mysql-users.nse +++ b/scripts/mysql-users.nse @@ -1,3 +1,10 @@ +local mysql = require "mysql" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local openssl = stdnse.silent_require "openssl" + description = [[ Attempts to list all users on a MySQL server. ]] @@ -27,10 +34,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "intrusive"} -require 'shortport' -require 'stdnse' -require 'mysql' -stdnse.silent_require 'openssl' dependencies = {"mysql-brute", "mysql-empty-password"} diff --git a/scripts/mysql-variables.nse b/scripts/mysql-variables.nse index 0cd6e997bc..ee063421a6 100644 --- a/scripts/mysql-variables.nse +++ b/scripts/mysql-variables.nse @@ -1,3 +1,11 @@ +local mysql = require "mysql" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + +local openssl = stdnse.silent_require "openssl" + description = [[ Attempts to show all variables on a MySQL server. ]] @@ -35,10 +43,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require 'shortport' -require 'stdnse' -require 'mysql' -stdnse.silent_require 'openssl' dependencies = {"mysql-brute", "mysql-empty-password"} diff --git a/scripts/nat-pmp-info.nse b/scripts/nat-pmp-info.nse index 00b49adc49..cbd942f85b 100644 --- a/scripts/nat-pmp-info.nse +++ b/scripts/nat-pmp-info.nse @@ -1,3 +1,8 @@ +local natpmp = require "natpmp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Get's the routers WAN IP using the NAT Port Mapping Protocol (NAT-PMP). The NAT-PMP protocol is supported by a broad range of routers including: @@ -16,8 +21,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require 'shortport' -require 'natpmp' portrule = shortport.port_or_service(5351, "nat-pmp", {"udp"} ) diff --git a/scripts/nat-pmp-mapport.nse b/scripts/nat-pmp-mapport.nse index 00436b0a23..69c941a546 100644 --- a/scripts/nat-pmp-mapport.nse +++ b/scripts/nat-pmp-mapport.nse @@ -1,3 +1,9 @@ +local natpmp = require "natpmp" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Maps a WAN port on the router to a local port on the client using the NAT Port Mapping Protocol (NAT-PMP). It supports the following operations: o map - maps a new external port on the router to an internal port of the requesting IP @@ -40,9 +46,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'natpmp' -require 'tab' portrule = shortport.port_or_service(5351, "nat-pmp", {"udp"} ) @@ -110,4 +113,4 @@ action = function(host, port) return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/nbstat.nse b/scripts/nbstat.nse index 61ecf015fd..10fc82c87c 100644 --- a/scripts/nbstat.nse +++ b/scripts/nbstat.nse @@ -1,3 +1,10 @@ +local datafiles = require "datafiles" +local netbios = require "netbios" +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to retrieve the target's NetBIOS names and MAC address. @@ -33,8 +40,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" -- Christopher R. Hertel. categories = {"default", "discovery", "safe"} -require "netbios" -require "datafiles" hostrule = function(host) diff --git a/scripts/ncp-enum-users.nse b/scripts/ncp-enum-users.nse index 151d8c219e..6403b60dc7 100644 --- a/scripts/ncp-enum-users.nse +++ b/scripts/ncp-enum-users.nse @@ -1,3 +1,8 @@ +local ncp = require "ncp" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Retrieves a list of all eDirectory users from the Novell NetWare Core Protocol (NCP) service. ]] @@ -26,8 +31,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "safe"} -require 'shortport' -require 'ncp' portrule = shortport.port_or_service(524, "ncp", "tcp") diff --git a/scripts/ncp-serverinfo.nse b/scripts/ncp-serverinfo.nse index 88adb9e03d..7026263078 100644 --- a/scripts/ncp-serverinfo.nse +++ b/scripts/ncp-serverinfo.nse @@ -1,3 +1,7 @@ +local ncp = require "ncp" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Retrieves eDirectory server information (OS version, server name, mounts, etc.) from the Novell NetWare Core Protocol (NCP) service. @@ -29,8 +33,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require "shortport" -require "ncp" portrule = shortport.port_or_service(524, "ncp", "tcp") diff --git a/scripts/ndmp-fs-info.nse b/scripts/ndmp-fs-info.nse index b68ad209be..9caa63bd1c 100644 --- a/scripts/ndmp-fs-info.nse +++ b/scripts/ndmp-fs-info.nse @@ -1,3 +1,7 @@ +local ndmp = require "ndmp" +local shortport = require "shortport" +local tab = require "tab" + description = [[ Lists remote file systems by querying the remote device using the Network Data Management Protocol (ndmp). NDMP is a protocol intended to transport @@ -36,9 +40,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'ndmp' -require 'tab' portrule = shortport.port_or_service(10000, "ndmp", "tcp") @@ -66,4 +67,4 @@ action = function(host, port) end return "\n" .. tab.dump(result) -end \ No newline at end of file +end diff --git a/scripts/ndmp-version.nse b/scripts/ndmp-version.nse index 13b9c41e55..2d1ab13a82 100644 --- a/scripts/ndmp-version.nse +++ b/scripts/ndmp-version.nse @@ -1,3 +1,7 @@ +local ndmp = require "ndmp" +local nmap = require "nmap" +local shortport = require "shortport" + description = [[ Retrieves version information from the remote Network Data Management Protocol (ndmp) service. NDMP is a protocol intended to transport data between a NAS @@ -19,8 +23,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"version"} -require 'shortport' -require 'ndmp' portrule = shortport.port_or_service(10000, "ndmp", "tcp") @@ -58,4 +60,4 @@ action = function(host, port) port.version.extrainfo = port.version.extrainfo .. ("OS ver: %d.%d; OS Build: %d; OS Service Pack: %d"):format(major, minor, build, smajor) end nmap.set_port_version(host, port, "hardmatched") -end \ No newline at end of file +end diff --git a/scripts/nessus-brute.nse b/scripts/nessus-brute.nse index 4dda10fe3d..da9507888f 100644 --- a/scripts/nessus-brute.nse +++ b/scripts/nessus-brute.nse @@ -1,3 +1,8 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" + description=[[ Performs brute force password auditing against a Nessus vulnerability scanning daemon using the NTP 1.2 protocol. ]] @@ -28,9 +33,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'brute' -require 'comm' portrule = shortport.port_or_service(1241, "nessus", "tcp") @@ -148,4 +150,4 @@ action = function(host, port) status, result = engine:start() return result -end \ No newline at end of file +end diff --git a/scripts/nessus-xmlrpc-brute.nse b/scripts/nessus-xmlrpc-brute.nse index 0693821a19..fdcbc0e1f9 100644 --- a/scripts/nessus-xmlrpc-brute.nse +++ b/scripts/nessus-xmlrpc-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description=[[ Performs brute force password auditing against a Nessus vulnerability scanning daemon using the XMLRPC protocol. ]] @@ -20,9 +27,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require "shortport" -require "brute" -require "comm" portrule = shortport.port_or_service(8834, "ssl/http", "tcp") diff --git a/scripts/netbus-auth-bypass.nse b/scripts/netbus-auth-bypass.nse index 3c8863fb67..f5955dd0d8 100644 --- a/scripts/netbus-auth-bypass.nse +++ b/scripts/netbus-auth-bypass.nse @@ -1,3 +1,7 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Checks if a NetBus server is vulnerable to an authentication bypass vulnerability which allows full access without knowing the password. @@ -20,9 +24,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "safe", "vuln"} -require("nmap") -require("stdnse") -require("shortport") dependencies = {"netbus-version", "netbus-brute", "netbus-info"} diff --git a/scripts/netbus-brute.nse b/scripts/netbus-brute.nse index 31b20e1910..2ab1d0c77d 100644 --- a/scripts/netbus-brute.nse +++ b/scripts/netbus-brute.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local unpwdb = require "unpwdb" + description = [[ Performs brute force password auditing against the Netbus backdoor ("remote administration") service. ]] @@ -14,10 +20,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"brute", "intrusive"} -require("nmap") -require("stdnse") -require("shortport") -require("unpwdb") dependencies = {"netbus-version"} diff --git a/scripts/netbus-info.nse b/scripts/netbus-info.nse index a39205bf23..10dfbd2995 100644 --- a/scripts/netbus-info.nse +++ b/scripts/netbus-info.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Opens a connection to a NetBus server and extracts information about the host and the NetBus service itself. @@ -51,10 +57,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require("nmap") -require("comm") -require("stdnse") -require("shortport") dependencies = {"netbus-version", "netbus-brute"} diff --git a/scripts/netbus-version.nse b/scripts/netbus-version.nse index b7a9ffbbed..61bb0a1213 100644 --- a/scripts/netbus-version.nse +++ b/scripts/netbus-version.nse @@ -1,3 +1,7 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Extends version detection to detect NetBuster, a honeypot service that mimes NetBus. @@ -14,9 +18,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"version"} -require("nmap") -require("stdnse") -require("shortport") portrule = shortport.version_port_or_service ({}, "netbus", {"tcp"}) diff --git a/scripts/nexpose-brute.nse b/scripts/nexpose-brute.nse index 560521c095..b11b306be2 100644 --- a/scripts/nexpose-brute.nse +++ b/scripts/nexpose-brute.nse @@ -1,3 +1,11 @@ +local brute = require "brute" +local creds = require "creds" +local http = require "http" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local openssl = stdnse.silent_require "openssl" + description=[[ Performs brute force password auditing against a Nexpose vulnerability scanner using the API 1.1. By default it only tries three guesses per username to avoid target account lockout. ]] @@ -26,10 +34,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require "shortport" -require "brute" -require "http" -stdnse.silent_require "openssl" portrule = shortport.port_or_service(3780, "nexpose", "tcp") @@ -74,4 +78,4 @@ action = function(host, port) engine.options.max_guesses = tonumber(stdnse.get_script_args('brute.guesses')) or 3 status, result = engine:start() return result -end \ No newline at end of file +end diff --git a/scripts/nfs-ls.nse b/scripts/nfs-ls.nse index c11844a0ab..402dfd2435 100644 --- a/scripts/nfs-ls.nse +++ b/scripts/nfs-ls.nse @@ -1,3 +1,10 @@ +local rpc = require "rpc" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" + description = [[ Attempts to get useful information about files from NFS exports. The output is intended to resemble the output of ls. @@ -78,10 +85,6 @@ author = "Patrik Karlsson, Djalal Harouni" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'stdnse' -require 'shortport' -require 'rpc' -require 'tab' portrule = shortport.port_or_service(111, "rpcbind", {"tcp", "udp"} ) diff --git a/scripts/nfs-showmount.nse b/scripts/nfs-showmount.nse index 84ac84400c..8f6ae80426 100644 --- a/scripts/nfs-showmount.nse +++ b/scripts/nfs-showmount.nse @@ -1,3 +1,8 @@ +local rpc = require "rpc" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Shows NFS exports, like the showmount -e command. ]] @@ -26,9 +31,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require("stdnse") -require("shortport") -require("rpc") portrule = shortport.port_or_service(111, "rpcbind", {"tcp", "udp"} ) diff --git a/scripts/nfs-statfs.nse b/scripts/nfs-statfs.nse index 129c68ea9c..844db48f7a 100644 --- a/scripts/nfs-statfs.nse +++ b/scripts/nfs-statfs.nse @@ -1,3 +1,10 @@ +local rpc = require "rpc" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" + description = [[ Retrieves disk space statistics and information from a remote NFS share. The output is intended to resemble the output of df. @@ -30,10 +37,6 @@ author = "Patrik Karlsson, Djalal Harouni" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require("stdnse") -require("shortport") -require("rpc") -require("tab") portrule = shortport.port_or_service(111, "rpcbind", {"tcp", "udp"} ) diff --git a/scripts/nping-brute.nse b/scripts/nping-brute.nse index 38ad035425..b126f66a2a 100644 --- a/scripts/nping-brute.nse +++ b/scripts/nping-brute.nse @@ -1,3 +1,13 @@ +local bin = require "bin" +local brute = require "brute" +local creds = require "creds" +local math = require "math" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local openssl = stdnse.silent_require "openssl" + description = [[ Performs brute force password auditing against an Nping Echo service. @@ -21,13 +31,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"brute", "intrusive"} -require("bin") -require("nmap") -require("brute") -require("stdnse") -stdnse.silent_require "openssl" -require("shortport") -require("creds") portrule = shortport.port_or_service(9929, "nping-echo") diff --git a/scripts/nrpe-enum.nse b/scripts/nrpe-enum.nse index ba74a46c88..690087c1ea 100644 --- a/scripts/nrpe-enum.nse +++ b/scripts/nrpe-enum.nse @@ -1,3 +1,11 @@ +local bin = require "bin" +local bit = require "bit" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -29,10 +37,6 @@ author = "Mak Kolybabi" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require("bit") -require("shortport") -require("stdnse") -require("tab") local NRPE_PROTOCOLS = { "ssl", diff --git a/scripts/ntp-info.nse b/scripts/ntp-info.nse index 80b34fa505..673c39d30d 100644 --- a/scripts/ntp-info.nse +++ b/scripts/ntp-info.nse @@ -1,3 +1,12 @@ +local bin = require "bin" +local comm = require "comm" +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Gets the time and configuration variables from an NTP server. We send two requests: a time request and a "read variables" (opcode 2) control message. @@ -30,11 +39,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require "bin" -require "nmap" -require "stdnse" -require "comm" -require "shortport" portrule = shortport.port_or_service(123, "ntp", {"udp", "tcp"}) diff --git a/scripts/ntp-monlist.nse b/scripts/ntp-monlist.nse index 7438720fb9..b6c187db96 100644 --- a/scripts/ntp-monlist.nse +++ b/scripts/ntp-monlist.nse @@ -1,3 +1,14 @@ +local bin = require "bin" +local bit = require "bit" +local ipOps = require "ipOps" +local math = require "math" +local nmap = require "nmap" +local packet = require "packet" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + author = "jah" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} @@ -79,18 +90,11 @@ local MAX_RECORDS = 1200 local TIMEOUT = 5000 -- ms -local bin = require 'bin' -local bit = require 'bit' -local nmap = require 'nmap' -local ipOps = require 'ipOps' -local packet = require 'packet' -local stdnse = require 'stdnse' -local short = require 'shortport' --- -- ntp-monlist will run against the ntp service which only runs on UDP 123 -- -portrule = short.port_or_service(123, 'ntp', {'udp'}) +portrule = shortport.port_or_service(123, 'ntp', {'udp'}) --- -- Send an NTPv2 Mode 7 'monlist' command to the target, receive any responses diff --git a/scripts/omp2-brute.nse b/scripts/omp2-brute.nse index 16a0e04026..488d905845 100644 --- a/scripts/omp2-brute.nse +++ b/scripts/omp2-brute.nse @@ -1,3 +1,8 @@ +local brute = require "brute" +local creds = require "creds" +local omp2 = require "omp2" +local shortport = require "shortport" + description = [[ Performs brute force password auditing against the OpenVAS manager using OMPv2. ]] @@ -18,11 +23,6 @@ author = "Henri Doreau" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"brute", "intrusive"} -require("omp2") -require("nmap") -require("brute") -require("shortport") -require("creds") portrule = shortport.port_or_service(9390, "openvas") diff --git a/scripts/omp2-enum-targets.nse b/scripts/omp2-enum-targets.nse index 0a7e264c03..1887498086 100644 --- a/scripts/omp2-enum-targets.nse +++ b/scripts/omp2-enum-targets.nse @@ -1,3 +1,10 @@ +local omp2 = require "omp2" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" +local target = require "target" + description = [[ Attempts to retrieve the list of target systems and networks from an OpenVAS Manager server. @@ -33,11 +40,6 @@ categories = {"discovery", "safe"} dependencies = {"omp2-brute"} -require("tab") -require("omp2") -require("target") -require("stdnse") -require("shortport") portrule = shortport.port_or_service(9390, "openvas") @@ -114,7 +116,7 @@ action = function(host, port) if target.ALLOW_NEW_TARGETS and targets ~= nil then stdnse.print_debug("%s: adding new targets %s", SCRIPT_NAME, stdnse.strjoin(", ", targets)) - target.add(unpack(targets)) + target.add(table.unpack(targets)) end end diff --git a/scripts/openlookup-info.nse b/scripts/openlookup-info.nse index f638f73d7d..0d377a38b1 100644 --- a/scripts/openlookup-info.nse +++ b/scripts/openlookup-info.nse @@ -1,3 +1,11 @@ +local comm = require "comm" +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Parses and displays the banner information of an OpenLookup (network key-value store) server. ]] @@ -20,9 +28,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe", "version"} -require("comm") -require("stdnse") -require("shortport") portrule = shortport.port_or_service(5850, "openlookup") diff --git a/scripts/openvas-otp-brute.nse b/scripts/openvas-otp-brute.nse index c630e2db1b..45ae9d4824 100644 --- a/scripts/openvas-otp-brute.nse +++ b/scripts/openvas-otp-brute.nse @@ -1,3 +1,12 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" + +local openssl = stdnse.silent_require "openssl" + description=[[ Performs brute force password auditing against a OpenVAS vulnerability scanner daemon using the OTP 1.0 protocol. ]] @@ -20,11 +29,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require "shortport" -require "brute" -require "comm" -require "stdnse" -stdnse.silent_require('openssl') portrule = shortport.port_or_service({9390,9391}, "openvas", "tcp") diff --git a/scripts/oracle-brute.nse b/scripts/oracle-brute.nse index c308c8ec10..4f39464f0b 100644 --- a/scripts/oracle-brute.nse +++ b/scripts/oracle-brute.nse @@ -1,3 +1,14 @@ +local brute = require "brute" +local coroutine = require "coroutine" +local creds = require "creds" +local io = require "io" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tns = require "tns" + +local openssl = stdnse.silent_require "openssl" + description = [[ Performs brute force password auditing against Oracle servers. @@ -57,12 +68,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'brute' -require 'stdnse' -stdnse.silent_require 'openssl' -require 'tns' -require 'creds' portrule = shortport.port_or_service(1521, "oracle-tns", "tcp", "open") diff --git a/scripts/oracle-enum-users.nse b/scripts/oracle-enum-users.nse index 052258973d..266e918d90 100644 --- a/scripts/oracle-enum-users.nse +++ b/scripts/oracle-enum-users.nse @@ -1,3 +1,14 @@ +local math = require "math" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local tns = require "tns" +local unpwdb = require "unpwdb" + +local openssl = stdnse.silent_require "openssl" + description = [[ Attempts to enumerate valid Oracle user names against unpatched Oracle 11g servers (this bug was fixed in Oracle's October 2009 Critical Patch Update). @@ -32,11 +43,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "auth"} -require 'shortport' -require 'unpwdb' -require 'stdnse' -stdnse.silent_require 'openssl' -require 'tns' portrule = shortport.port_or_service(1521, 'oracle-tns' ) diff --git a/scripts/oracle-sid-brute.nse b/scripts/oracle-sid-brute.nse index f0eb25853b..831b9e22f5 100644 --- a/scripts/oracle-sid-brute.nse +++ b/scripts/oracle-sid-brute.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local io = require "io" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Guesses Oracle instance/SID names against the TNS-listener. @@ -32,9 +39,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'comm' -require 'datafiles' -require 'shortport' portrule = shortport.port_or_service(1521, 'oracle-tns') diff --git a/scripts/ovs-agent-version.nse b/scripts/ovs-agent-version.nse index 9cf6d9486c..43a292e35e 100644 --- a/scripts/ovs-agent-version.nse +++ b/scripts/ovs-agent-version.nse @@ -1,3 +1,8 @@ +local http = require "http" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description = [[ Detects the version of an Oracle OVSAgentServer by fingerprinting responses to an HTTP GET request and an XML-RPC method call. @@ -25,8 +30,6 @@ categories = {"version"} author = "David Fifield" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" -require("http") -require("shortport") portrule = shortport.port_or_service({8899}) diff --git a/scripts/p2p-conficker.nse b/scripts/p2p-conficker.nse index 3a1a0b038e..db38f51165 100644 --- a/scripts/p2p-conficker.nse +++ b/scripts/p2p-conficker.nse @@ -1,3 +1,14 @@ +local bin = require "bin" +local bit = require "bit" +local ipOps = require "ipOps" +local math = require "math" +local nmap = require "nmap" +local os = require "os" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Checks if a host is infected with Conficker.C or higher, based on Conficker's peer to peer communication. @@ -71,9 +82,6 @@ copyright = "Ron Bowes" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default","safe"} -require 'smb' -require 'stdnse' -require 'ipOps' -- Max packet size local MAX_PACKET = 0x2000 diff --git a/scripts/path-mtu.nse b/scripts/path-mtu.nse index 04c99a760a..cd7cfd98f3 100644 --- a/scripts/path-mtu.nse +++ b/scripts/path-mtu.nse @@ -1,3 +1,11 @@ +local bin = require "bin" +local math = require "math" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Performs simple Path MTU Discovery to target hosts. @@ -36,10 +44,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -require 'bin' -require 'packet' -require 'nmap' -require 'stdnse' local IPPROTO_ICMP = packet.IPPROTO_ICMP local IPPROTO_TCP = packet.IPPROTO_TCP diff --git a/scripts/pgsql-brute.nse b/scripts/pgsql-brute.nse index a577124dd9..0e5c4d1332 100644 --- a/scripts/pgsql-brute.nse +++ b/scripts/pgsql-brute.nse @@ -1,3 +1,13 @@ +local nmap = require "nmap" +local pgsql = require "pgsql" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local unpwdb = require "unpwdb" + +local openssl = stdnse.silent_require "openssl" + description = [[ Performs password guessing against PostgreSQL. ]] @@ -26,10 +36,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'stdnse' -require 'unpwdb' -stdnse.silent_require 'openssl' -- Version 0.4 -- Created 01/15/2010 - v0.1 - created by Patrik Karlsson diff --git a/scripts/pjl-ready-message.nse b/scripts/pjl-ready-message.nse index 0b2930fc31..1ec9c91af5 100644 --- a/scripts/pjl-ready-message.nse +++ b/scripts/pjl-ready-message.nse @@ -1,3 +1,6 @@ +local nmap = require "nmap" +local shortport = require "shortport" + description = [[ Retrieves or sets the ready message on printers that support the Printer Job Language. This includes most PostScript printers that listen on port @@ -21,8 +24,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive"} -require "nmap" -require "shortport" portrule = shortport.port_or_service(9100, "jetdirect") local function parse_response(response) diff --git a/scripts/pop3-brute.nse b/scripts/pop3-brute.nse index 1e127bb428..eadbb613f3 100644 --- a/scripts/pop3-brute.nse +++ b/scripts/pop3-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local comm = require "comm" +local nmap = require "nmap" +local pop3 = require "pop3" +local shortport = require "shortport" +local string = require "string" + description = [[ Tries to log into a POP3 account by guessing usernames and passwords. ]] @@ -21,11 +28,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'pop3' -require 'shortport' -require 'brute' - - Driver = { new = function(self, host, port, login_function, is_apop) local o = {} diff --git a/scripts/pop3-capabilities.nse b/scripts/pop3-capabilities.nse index 2d7943f804..f2bf97066e 100644 --- a/scripts/pop3-capabilities.nse +++ b/scripts/pop3-capabilities.nse @@ -1,3 +1,9 @@ +local pop3 = require "pop3" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Retrieves POP3 email server capabilities. @@ -17,9 +23,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default","discovery","safe"} -require 'pop3' -require 'shortport' -require 'stdnse' portrule = shortport.port_or_service({110,995},{"pop3","pop3s"}) diff --git a/scripts/pptp-version.nse b/scripts/pptp-version.nse index 025016a736..8cb5abec0e 100644 --- a/scripts/pptp-version.nse +++ b/scripts/pptp-version.nse @@ -1,3 +1,8 @@ +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description = [[ Attempts to extract system information from the point-to-point tunneling protocol (PPTP) service. ]] @@ -15,8 +20,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"version"} -require "comm" -require "shortport" portrule = shortport.version_port_or_service(1723) diff --git a/scripts/qscan.nse b/scripts/qscan.nse index 77b71f7b98..46d2e87d78 100644 --- a/scripts/qscan.nse +++ b/scripts/qscan.nse @@ -1,3 +1,12 @@ +local bin = require "bin" +local math = require "math" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" + description = [[ Repeatedly probe open and/or closed ports on a host to obtain a series of round-trip time values for each port. These values are used to @@ -49,11 +58,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -require 'stdnse' -require 'bin' -require 'packet' -require 'tab' -require 'nmap' -- defaults local DELAY = 0.200 diff --git a/scripts/quake3-info.nse b/scripts/quake3-info.nse index 9337c1e4da..60c109a65d 100644 --- a/scripts/quake3-info.nse +++ b/scripts/quake3-info.nse @@ -1,3 +1,11 @@ +local bin = require "bin" +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Extracts information from a Quake3 game server and other games which use the same protocol. ]] @@ -59,10 +67,6 @@ author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe", "version"} -require "shortport" -require "stdnse" -require "comm" -require "bin" local function range(first, last) local list = {} diff --git a/scripts/quake3-master-getservers.nse b/scripts/quake3-master-getservers.nse index 545957e330..848f4ccd93 100644 --- a/scripts/quake3-master-getservers.nse +++ b/scripts/quake3-master-getservers.nse @@ -1,3 +1,11 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" + description = [[ Queries Quake3-style master servers for game servers (many games other than Quake 3 use this same protocol). ]] @@ -19,10 +27,6 @@ Queries Quake3-style master servers for game servers (many games other than Quak author = "Toni Ruottu" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require "datafiles" -require "shortport" -require "bin" -require "tab" portrule = shortport.port_or_service ({20110, 20510, 27950, 30710}, "quake3-master", {"udp"}) postrule = function() diff --git a/scripts/rdp-vuln-ms12-020.nse b/scripts/rdp-vuln-ms12-020.nse index a076d25c95..f22e9d1f86 100644 --- a/scripts/rdp-vuln-ms12-020.nse +++ b/scripts/rdp-vuln-ms12-020.nse @@ -1,3 +1,9 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local vulns = require "vulns" + description = [[ Checks if a machine is vulnerable to MS12-020 RDP vulnerability. @@ -62,9 +68,6 @@ author = "Aleksandar Nikolic, based on python script by sleepya" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "vuln"} -require "shortport" -require "stdnse" -require "vulns" portrule = shortport.port_or_service({3389},{"ms-wbt-server"}) diff --git a/scripts/realvnc-auth-bypass.nse b/scripts/realvnc-auth-bypass.nse index b5dada97f9..6f053ce933 100644 --- a/scripts/realvnc-auth-bypass.nse +++ b/scripts/realvnc-auth-bypass.nse @@ -1,3 +1,6 @@ +local nmap = require "nmap" +local shortport = require "shortport" + description = [[ Checks if a VNC server is vulnerable to the RealVNC authentication bypass (CVE-2006-2369). @@ -13,7 +16,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth", "default", "safe"} -require "shortport" portrule = shortport.port_or_service(5900, "vnc") diff --git a/scripts/redis-brute.nse b/scripts/redis-brute.nse index 8d215b47de..547bf4391a 100644 --- a/scripts/redis-brute.nse +++ b/scripts/redis-brute.nse @@ -1,3 +1,8 @@ +local brute = require "brute" +local creds = require "creds" +local redis = require "redis" +local shortport = require "shortport" + description = [[ Performs brute force passwords auditing against a Redis key-value store. ]] @@ -21,9 +26,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'brute' -require 'redis' -require 'shortport' portrule = shortport.port_or_service(6379, "redis-server") @@ -105,4 +107,4 @@ action = function(host, port) status, result = engine:start() return result -end \ No newline at end of file +end diff --git a/scripts/redis-info.nse b/scripts/redis-info.nse index 4ec4f6c675..d3f56c4825 100644 --- a/scripts/redis-info.nse +++ b/scripts/redis-info.nse @@ -1,3 +1,9 @@ +local creds = require "creds" +local redis = require "redis" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" + description = [[ Retrieves information (such as version number and architecture) from a Redis key-value store. ]] @@ -26,10 +32,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} dependencies = {"redis-brute"} -require 'creds' -require 'redis' -require 'shortport' -require 'tab' portrule = shortport.port_or_service(6379, "redis-server") @@ -110,4 +112,4 @@ action = function(host, port) end end return stdnse.format_output(true, tab.dump(result)) -end \ No newline at end of file +end diff --git a/scripts/resolveall.nse b/scripts/resolveall.nse index 7d47f1139b..7f2ef209d6 100644 --- a/scripts/resolveall.nse +++ b/scripts/resolveall.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + description = [[ Resolves hostnames and adds every address (IPv4 or IPv6, depending on Nmap mode) to Nmap's target list. This differs from Nmap's normal @@ -27,8 +33,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -require 'target' -require 'stdnse' prerule = function() if not stdnse.get_script_args("resolveall.hosts") then diff --git a/scripts/reverse-index.nse b/scripts/reverse-index.nse index 2ffdc80e4e..51248fe1b0 100644 --- a/scripts/reverse-index.nse +++ b/scripts/reverse-index.nse @@ -1,3 +1,7 @@ +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Creates a reverse index at the end of scan output showing which hosts run a particular service. This is in addition to Nmap's normal output listing the services on each host. ]] diff --git a/scripts/rexec-brute.nse b/scripts/rexec-brute.nse index 61097ca178..1d88112672 100644 --- a/scripts/rexec-brute.nse +++ b/scripts/rexec-brute.nse @@ -1,3 +1,9 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description=[[ Performs brute force password auditing against the classic UNIX rexec (remote exec) service. ]] @@ -20,8 +26,6 @@ Performs brute force password auditing against the classic UNIX rexec (remote ex -- Version 0.1 -- Created 11/02/2011 - v0.1 - created by Patrik Karlsson -require 'brute' -require 'shortport' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/riak-http-info.nse b/scripts/riak-http-info.nse index 4d41696810..19acdb5c6d 100644 --- a/scripts/riak-http-info.nse +++ b/scripts/riak-http-info.nse @@ -1,3 +1,9 @@ +local http = require "http" +local json = require "json" +local shortport = require "shortport" +local stdnse = require "stdnse" +local tab = require "tab" + description = [[ Retrieves information (such as node name and architecture) from a Basho Riak distributed database using the HTTP protocol. ]] @@ -47,10 +53,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'http' -require 'json' -require 'shortport' -require 'tab' portrule = shortport.port_or_service(8098, "http") @@ -133,4 +135,4 @@ action = function(host, port) end return stdnse.format_output(true, tab.dump(result)) -end \ No newline at end of file +end diff --git a/scripts/rlogin-brute.nse b/scripts/rlogin-brute.nse index 7dea43a096..91ddd11fbb 100644 --- a/scripts/rlogin-brute.nse +++ b/scripts/rlogin-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local math = require "math" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description=[[ Performs brute force password auditing against the classic UNIX rlogin (remote login) service. This script must be run in privileged mode on UNIX because it must bind to a low source port number. ]] @@ -20,8 +27,6 @@ Performs brute force password auditing against the classic UNIX rlogin (remote l -- Version 0.1 -- Created 11/02/2011 - v0.1 - created by Patrik Karlsson -require 'brute' -require 'shortport' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/rmi-dumpregistry.nse b/scripts/rmi-dumpregistry.nse index 881346e608..3f415cdf6f 100644 --- a/scripts/rmi-dumpregistry.nse +++ b/scripts/rmi-dumpregistry.nse @@ -1,3 +1,10 @@ +local nmap = require "nmap" +local rmi = require "rmi" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Connects to a remote RMI registry and attempts to dump all of its objects. @@ -143,18 +150,16 @@ author = "Martin Holst Swende" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require "shortport" -require "rmi" portrule = shortport.port_or_service({1098, 1099, 1090, 8901, 8902, 8903}, {"java-rmi", "rmiregistry"}) -- Some lazy shortcuts local function dbg(str,...) - stdnse.print_debug(3,"RMI-DUMPREG:"..str, unpack(arg)) + stdnse.print_debug(3,"RMI-DUMPREG:"..str, table.unpack(arg)) end local function dbg_err(str, ... ) - stdnse.print_debug("RMI-DUMPREG-ERR:"..str, unpack(arg)) + stdnse.print_debug("RMI-DUMPREG-ERR:"..str, table.unpack(arg)) end -- Function to split a string diff --git a/scripts/rpcap-brute.nse b/scripts/rpcap-brute.nse index 2535b8904f..d7886a4bbe 100644 --- a/scripts/rpcap-brute.nse +++ b/scripts/rpcap-brute.nse @@ -1,3 +1,8 @@ +local brute = require "brute" +local creds = require "creds" +local rpcap = require "rpcap" +local shortport = require "shortport" + description = [[ Performs brute force password auditing against the WinPcap Remote Capture Daemon (rpcap). @@ -18,9 +23,6 @@ Daemon (rpcap). -- -- -require 'brute' -require 'rpcap' -require 'shortport' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/rpcap-info.nse b/scripts/rpcap-info.nse index 3f24eb902f..6e77027cdd 100644 --- a/scripts/rpcap-info.nse +++ b/scripts/rpcap-info.nse @@ -1,3 +1,9 @@ +local creds = require "creds" +local nmap = require "nmap" +local rpcap = require "rpcap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Connects to the rpcap service (provides remote sniffing capabilities through WinPcap) and retrieves interface information. The service can either be @@ -31,9 +37,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} dependencies = {"rpcap-brute"} -require 'creds' -require 'rpcap' -require 'shortport' portrule = shortport.port_or_service(2002, "rpcap", "tcp") diff --git a/scripts/rpcinfo.nse b/scripts/rpcinfo.nse index d33df8ae72..d35ba01151 100644 --- a/scripts/rpcinfo.nse +++ b/scripts/rpcinfo.nse @@ -1,3 +1,8 @@ +local rpc = require "rpc" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Connects to portmapper and fetches a list of all registered programs. It then prints out a table including (for each program) the RPC program number, supported version numbers, port number and protocol, and program name. ]] @@ -38,9 +43,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "default", "safe"} -require 'stdnse' -require 'shortport' -require 'rpc' portrule = shortport.port_or_service(111, "rpcbind", {"tcp", "udp"} ) diff --git a/scripts/rsync-brute.nse b/scripts/rsync-brute.nse index c1bb2e5eb4..9a2713a1e4 100644 --- a/scripts/rsync-brute.nse +++ b/scripts/rsync-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local rsync = stdnse.silent_require "rsync" + description = [[ Performs brute force password auditing against the rsync remote file syncing protocol. ]] @@ -19,10 +26,6 @@ Performs brute force password auditing against the rsync remote file syncing pro -- @args rsync-brute.module - the module against which brute forcing should be performed -require 'shortport' -require 'brute' -require 'stdnse' -stdnse.silent_require('rsync') author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/rsync-list-modules.nse b/scripts/rsync-list-modules.nse index 06e6f598b6..a721b7d839 100644 --- a/scripts/rsync-list-modules.nse +++ b/scripts/rsync-list-modules.nse @@ -1,3 +1,7 @@ +local rsync = require "rsync" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Lists modules available for rsync (remote file sync) synchronization. ]] @@ -15,8 +19,6 @@ Lists modules available for rsync (remote file sync) synchronization. -- |_ etc etc directory -- -require 'rsync' -require 'shortport' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -41,4 +43,4 @@ action = function(host, port) return "\n ERROR: Failed to retrieve a list of modules" end return stdnse.format_output(true, modules) -end \ No newline at end of file +end diff --git a/scripts/rtsp-methods.nse b/scripts/rtsp-methods.nse index f1aaa202fe..cba5890738 100644 --- a/scripts/rtsp-methods.nse +++ b/scripts/rtsp-methods.nse @@ -1,3 +1,7 @@ +local rtsp = require "rtsp" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Determines which methods are supported by the RTSP (real time streaming protocol) server. ]] @@ -24,8 +28,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe"} -require 'rtsp' -require 'shortport' portrule = shortport.port_or_service(554, "rtsp", "tcp", "open") diff --git a/scripts/rtsp-url-brute.nse b/scripts/rtsp-url-brute.nse index 6d47ad252f..baae329053 100644 --- a/scripts/rtsp-url-brute.nse +++ b/scripts/rtsp-url-brute.nse @@ -1,3 +1,11 @@ +local coroutine = require "coroutine" +local io = require "io" +local nmap = require "nmap" +local rtsp = require "rtsp" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to enumerate RTSP media URLS by testing for common paths on devices such as surveillance IP cameras. ]] @@ -29,8 +37,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"brute", "intrusive"} -require 'rtsp' -require 'shortport' portrule = shortport.port_or_service(554, "rtsp", "tcp", "open") @@ -152,4 +158,4 @@ action = function(host, port) -- end return stdnse.format_output(true, result ) -end \ No newline at end of file +end diff --git a/scripts/samba-vuln-cve-2012-1182.nse b/scripts/samba-vuln-cve-2012-1182.nse index 68c5aea3a6..f7e6c72d7a 100644 --- a/scripts/samba-vuln-cve-2012-1182.nse +++ b/scripts/samba-vuln-cve-2012-1182.nse @@ -1,3 +1,9 @@ +local bin = require "bin" +local msrpc = require "msrpc" +local smb = require "smb" +local string = require "string" +local vulns = require "vulns" + description = [[ Check if the machine is vulnerable to Samba heap overflow vulnerability marked with CVE-2012-1182. @@ -55,10 +61,6 @@ author = "Aleksandar Nikolic" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"vuln","intrusive"} -require 'msrpc' -require 'smb' -require 'stdnse' -require 'vulns' hostrule = function(host) return smb.get_port(host) ~= nil end diff --git a/scripts/servicetags.nse b/scripts/servicetags.nse index 8474572cb1..0066155bf1 100644 --- a/scripts/servicetags.nse +++ b/scripts/servicetags.nse @@ -1,3 +1,10 @@ +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to extract system information (OS, hardware, etc.) from the Sun Service Tags service agent (UDP port 6481). @@ -70,8 +77,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require("stdnse") -require("shortport") -- Mapping from XML element names to human-readable table labels. local XML_TO_TEXT = { diff --git a/scripts/sip-brute.nse b/scripts/sip-brute.nse index 661a2811b5..61144892a3 100644 --- a/scripts/sip-brute.nse +++ b/scripts/sip-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local math = require "math" +local shortport = require "shortport" +local sip = require "sip" +local stdnse = require "stdnse" + description = [[ Performs brute force password auditing against Session Initiation Protocol (SIP - http://en.wikipedia.org/wiki/Session_Initiation_Protocol) accounts. This protocol is most commonly associated with VoIP sessions. ]] @@ -21,10 +28,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require "shortport" -require "sip" -require "brute" -require "creds" portrule = shortport.port_or_service(5060, "sip", "udp") diff --git a/scripts/sip-enum-users.nse b/scripts/sip-enum-users.nse index 985b911799..386c23367a 100644 --- a/scripts/sip-enum-users.nse +++ b/scripts/sip-enum-users.nse @@ -1,3 +1,9 @@ +local shortport = require "shortport" +local sip = require "sip" +local stdnse = require "stdnse" +local table = require "table" +local unpwdb = require "unpwdb" + description = [[ Attempts to enumerate valid user account using SIP (Session Initiation Protocol - http://en.wikipedia.org/wiki/Session_Initiation_Protocol). @@ -28,9 +34,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "auth"} -require "shortport" -require "sip" -require "unpwdb" portrule = shortport.port_or_service(5060, "sip", "udp") @@ -142,4 +145,4 @@ action = function(host, port) accounts.name = "Valid SIP accounts" return stdnse.format_output(true, { accounts } ) -end \ No newline at end of file +end diff --git a/scripts/skypev2-version.nse b/scripts/skypev2-version.nse index 1b85dbd6e8..0070e69325 100644 --- a/scripts/skypev2-version.nse +++ b/scripts/skypev2-version.nse @@ -1,3 +1,8 @@ +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description = [[ Detects the Skype version 2 service. ]] @@ -11,8 +16,6 @@ author = "Brandon Enright" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"version"} -require "comm" -require "shortport" portrule = function(host, port) return (port.number == 80 or port.number == 443 or diff --git a/scripts/smb-brute.nse b/scripts/smb-brute.nse index 1cb08ed703..502a823fd6 100644 --- a/scripts/smb-brute.nse +++ b/scripts/smb-brute.nse @@ -1,3 +1,13 @@ +local bit = require "bit" +local math = require "math" +local msrpc = require "msrpc" +local nmap = require "nmap" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local unpwdb = require "unpwdb" + description = [[ Attempts to guess username/password combinations over SMB, storing discovered combinations for use in other scripts. Every attempt will be made to get a valid list of users and to @@ -98,10 +108,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'msrpc' -require 'smb' -require 'stdnse' -require 'unpwdb' ---The maximum number of usernames to check (can be modified with smblimit argument) -- The limit exists because domains may have hundreds of thousands of accounts, diff --git a/scripts/smb-check-vulns.nse b/scripts/smb-check-vulns.nse index 466a92f4a4..cbcb449cd0 100644 --- a/scripts/smb-check-vulns.nse +++ b/scripts/smb-check-vulns.nse @@ -1,3 +1,10 @@ +local msrpc = require "msrpc" +local nmap = require "nmap" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Checks for vulnerabilities: * MS08-067, a Windows RPC vulnerability @@ -110,9 +117,6 @@ dependencies = { "smb-psexec", }; -require 'msrpc' -require 'smb' -require 'stdnse' hostrule = function(host) return smb.get_port(host) ~= nil diff --git a/scripts/smb-enum-domains.nse b/scripts/smb-enum-domains.nse index 2b0af53aa3..f169660c5b 100644 --- a/scripts/smb-enum-domains.nse +++ b/scripts/smb-enum-domains.nse @@ -1,3 +1,10 @@ +local math = require "math" +local msrpc = require "msrpc" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to enumerate domains on a system, along with their policies. This generally requires credentials, except against Windows 2000. In addition to the actual domain, the "Builtin" @@ -54,11 +61,7 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","intrusive"} dependencies = {"smb-brute"} -require 'msrpc' -require 'smb' -require 'stdnse' -require 'nsedebug' -- TODO: This script needs some love... hostrule = function(host) diff --git a/scripts/smb-enum-groups.nse b/scripts/smb-enum-groups.nse index 47c6478986..9e25a5b5a6 100644 --- a/scripts/smb-enum-groups.nse +++ b/scripts/smb-enum-groups.nse @@ -1,3 +1,9 @@ +local msrpc = require "msrpc" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Obtains a list of groups from the remote Windows system, as well as a list of the group's users. This works similarly to enum.exe with the /G switch. @@ -59,9 +65,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","intrusive"} dependencies = {"smb-brute"} -require 'msrpc' -require 'smb' -require 'stdnse' hostrule = function(host) return smb.get_port(host) ~= nil diff --git a/scripts/smb-enum-processes.nse b/scripts/smb-enum-processes.nse index 0403e5186e..ea05dcc690 100644 --- a/scripts/smb-enum-processes.nse +++ b/scripts/smb-enum-processes.nse @@ -1,3 +1,10 @@ +local msrpcperformance = require "msrpcperformance" +local nmap = require "nmap" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Pulls a list of processes from the remote server over SMB. This will determine all running processes, their process IDs, and their parent processes. It is done @@ -78,11 +85,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} dependencies = {"smb-brute"} -require "bin" -require "msrpc" -require "msrpcperformance" -require "smb" -require "stdnse" function psl_mode (list, i) local mode diff --git a/scripts/smb-enum-sessions.nse b/scripts/smb-enum-sessions.nse index 749d9c1004..e3310864f3 100644 --- a/scripts/smb-enum-sessions.nse +++ b/scripts/smb-enum-sessions.nse @@ -1,3 +1,9 @@ +local msrpc = require "msrpc" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Enumerates the users logged into a system either locally or through an SMB share. The local users can be logged on either physically on the machine, or through a terminal services session. @@ -60,9 +66,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","intrusive"} dependencies = {"smb-brute"} -require 'msrpc' -require 'smb' -require 'stdnse' hostrule = function(host) return smb.get_port(host) ~= nil diff --git a/scripts/smb-enum-shares.nse b/scripts/smb-enum-shares.nse index 77879f892c..9f3e8734a1 100644 --- a/scripts/smb-enum-shares.nse +++ b/scripts/smb-enum-shares.nse @@ -1,3 +1,8 @@ +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to list shares using the srvsvc.NetShareEnumAll MSRPC function and retrieve more information about them using srvsvc.NetShareGetInfo. If access @@ -59,9 +64,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","intrusive"} dependencies = {"smb-brute"} -require 'msrpc' -require 'smb' -require 'stdnse' hostrule = function(host) return smb.get_port(host) ~= nil diff --git a/scripts/smb-enum-users.nse b/scripts/smb-enum-users.nse index 4e296170fd..43222e7b2d 100644 --- a/scripts/smb-enum-users.nse +++ b/scripts/smb-enum-users.nse @@ -1,3 +1,10 @@ +local msrpc = require "msrpc" +local nmap = require "nmap" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to enumerate the users on a remote Windows system, with as much information as possible, through two different techniques (both over MSRPC, @@ -138,9 +145,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth","intrusive"} dependencies = {"smb-brute"} -require 'msrpc' -require 'smb' -require 'stdnse' hostrule = function(host) return smb.get_port(host) ~= nil diff --git a/scripts/smb-flood.nse b/scripts/smb-flood.nse index ae9a56dd67..d9c5286034 100644 --- a/scripts/smb-flood.nse +++ b/scripts/smb-flood.nse @@ -1,3 +1,7 @@ +local smb = require "smb" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Exhausts a remote SMB server's connection limit by by opening as many connections as we can. Most implementations of SMB have a hard global @@ -32,8 +36,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive","dos"} dependencies = {"smb-brute"} -require 'smb' -require 'stdnse' hostrule = function(host) return smb.get_port(host) ~= nil diff --git a/scripts/smb-mbenum.nse b/scripts/smb-mbenum.nse index 51c3219f57..20201d09fa 100644 --- a/scripts/smb-mbenum.nse +++ b/scripts/smb-mbenum.nse @@ -1,3 +1,10 @@ +local bit = require "bit" +local msrpc = require "msrpc" +local smb = require "smb" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description=[[ Queries information managed by the Windows Master Browser. ]] @@ -54,10 +61,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'smb' -require 'msrpc' -require 'shortport' -require 'tab' hostrule = function(host) return smb.get_port(host) ~= nil end @@ -227,4 +230,4 @@ action = function(host, port) end return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/smb-os-discovery.nse b/scripts/smb-os-discovery.nse index 05320c1d57..09d16caeef 100644 --- a/scripts/smb-os-discovery.nse +++ b/scripts/smb-os-discovery.nse @@ -1,3 +1,8 @@ +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to determine the operating system, computer name, domain, workgroup, and current time over the SMB protocol (ports 445 or 139). @@ -58,8 +63,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} dependencies = {"smb-brute"} -require 'smb' -require 'stdnse' --- Check whether or not this script should be run. hostrule = function(host) diff --git a/scripts/smb-psexec.nse b/scripts/smb-psexec.nse index 50ae27a7c2..91baf48271 100644 --- a/scripts/smb-psexec.nse +++ b/scripts/smb-psexec.nse @@ -1,3 +1,14 @@ +local _G = require "_G" +local bit = require "bit" +local io = require "io" +local math = require "math" +local msrpc = require "msrpc" +local nmap = require "nmap" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Implements remote process execution similar to the Sysinternals' psexec tool, allowing a user to run a series of programs on a remote machine and read the output. This @@ -407,10 +418,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive"} dependencies = {"smb-brute"} -require 'bit' -require 'msrpc' -require 'smb' -require 'stdnse' -- Where we tell the user to get nmap_service.exe if it's not installed. @@ -661,7 +668,6 @@ end --@param config A table to fill with configuration values. --@return status true or false --@return config The configuration table or an error message. ---require 'nsedebug' local function get_config(host, config) local status local filename = nmap.registry.args.config @@ -675,17 +681,17 @@ local function get_config(host, config) end -- Load the config file + local env = setmetatable({modules = {}; overrides = {}; module = function() stdnse.print_debug(1, "WARNING: Selected config file contains an unnecessary call to module()") end}, {__index = _G}) stdnse.print_debug(1, "smb-psexec: Attempting to load config file: %s", filename) - local file = loadfile(filename) + local file = loadfile(filename, "t", env) if(not(file)) then return false, "Couldn't load module file:\n" .. filename end -- Run the config file - setfenv(file, setmetatable({modules = {}; overrides = {}; module = function() stdnse.print_debug(1, "WARNING: Selected config file contains an unnecessary call to module()") end}, {__index = _G})) file() - local modules = getfenv(file)["modules"] - local overrides = getfenv(file)["overrides"] + local modules = env.modules + local overrides = env.overrides -- Generate a cipher key if(stdnse.get_script_args( "nocipher" )) then diff --git a/scripts/smb-security-mode.nse b/scripts/smb-security-mode.nse index cc84ec8e8f..3077ff7d1b 100644 --- a/scripts/smb-security-mode.nse +++ b/scripts/smb-security-mode.nse @@ -1,3 +1,9 @@ +local bit = require "bit" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Returns information about the SMB security level determined by SMB. @@ -31,8 +37,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} dependencies = {"smb-brute"} -require 'smb' -require 'stdnse' -- Check whether or not this script should be run. hostrule = function(host) diff --git a/scripts/smb-server-stats.nse b/scripts/smb-server-stats.nse index f9f2dd20cb..87dd9f68ff 100644 --- a/scripts/smb-server-stats.nse +++ b/scripts/smb-server-stats.nse @@ -1,3 +1,9 @@ +local msrpc = require "msrpc" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to grab the server's statistics over SMB and MSRPC, which uses TCP ports 445 or 139. @@ -32,9 +38,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","intrusive"} dependencies = {"smb-brute"} -require 'msrpc' -require 'smb' -require 'stdnse' hostrule = function(host) return smb.get_port(host) ~= nil diff --git a/scripts/smb-system-info.nse b/scripts/smb-system-info.nse index 76c745d0ac..5a49c8f92c 100644 --- a/scripts/smb-system-info.nse +++ b/scripts/smb-system-info.nse @@ -1,3 +1,10 @@ +local msrpc = require "msrpc" +local os = require "os" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Pulls back information about the remote system from the registry. Getting all of the information requires an administrative account, although a user account @@ -50,9 +57,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","intrusive"} dependencies = {"smb-brute"} -require 'msrpc' -require 'smb' -require 'stdnse' -- TODO: This script needs some love diff --git a/scripts/smbv2-enabled.nse b/scripts/smbv2-enabled.nse index 26fb7cb960..d2841daec3 100644 --- a/scripts/smbv2-enabled.nse +++ b/scripts/smbv2-enabled.nse @@ -1,3 +1,7 @@ +local nmap = require "nmap" +local smb = require "smb" +local string = require "string" + description = [[ Checks whether or not a server is running the SMBv2 protocol. ]] @@ -18,9 +22,6 @@ copyright = "Ron Bowes" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe"} -require 'msrpc' -require 'smb' -require 'stdnse' hostrule = function(host) return smb.get_port(host) ~= nil diff --git a/scripts/smtp-brute.nse b/scripts/smtp-brute.nse index a35677c294..716d8d7138 100644 --- a/scripts/smtp-brute.nse +++ b/scripts/smtp-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local coroutine = require "coroutine" +local creds = require "creds" +local shortport = require "shortport" +local smtp = require "smtp" +local stdnse = require "stdnse" + description = [[ Performs brute force password auditing against SMTP servers using either LOGIN, PLAIN, CRAM-MD5, DIGEST-MD5 or NTLM authentication. ]] @@ -23,10 +30,6 @@ Performs brute force password auditing against SMTP servers using either LOGIN, -- Version 0.1 -- Created 07/15/2011 - v0.1 - created by Patrik Karlsson -require 'creds' -require 'brute' -require 'shortport' -require 'smtp' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/smtp-commands.nse b/scripts/smtp-commands.nse index a97f9928cc..9669e4222d 100644 --- a/scripts/smtp-commands.nse +++ b/scripts/smtp-commands.nse @@ -1,3 +1,9 @@ +local shortport = require "shortport" +local smtp = require "smtp" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to use EHLO and HELP to gather the Extended commands supported by an SMTP server. @@ -60,9 +66,6 @@ author = "Jason DePriest" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require "shortport" -require "stdnse" -require "smtp" portrule = shortport.port_or_service({ 25, 465, 587 }, { "smtp", "smtps", "submission" }) diff --git a/scripts/smtp-enum-users.nse b/scripts/smtp-enum-users.nse index 4b2c687769..2be6447b69 100644 --- a/scripts/smtp-enum-users.nse +++ b/scripts/smtp-enum-users.nse @@ -1,3 +1,11 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local smtp = require "smtp" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local unpwdb = require "unpwdb" + description = [[ Attempts to enumerate the users on a SMTP server by issuing the VRFY, EXPN or RCPT TO commands. The goal of this script is to discover all the user accounts in the remote @@ -44,10 +52,6 @@ author = "Duarte Silva " license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"auth","external","intrusive"} -require "shortport" -require "stdnse" -require "smtp" -require "unpwdb" portrule = shortport.port_or_service({ 25, 465, 587 }, { "smtp", "smtps", "submission" }) diff --git a/scripts/smtp-open-relay.nse b/scripts/smtp-open-relay.nse index 369f16105a..d16ee0ffce 100644 --- a/scripts/smtp-open-relay.nse +++ b/scripts/smtp-open-relay.nse @@ -1,3 +1,10 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local smtp = require "smtp" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to relay mail by issuing a predefined combination of SMTP commands. The goal of this script is to tell if a SMTP server is vulnerable to mail relaying. @@ -70,9 +77,6 @@ author = "Arturo 'Buanzo' Busleiman" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","intrusive","external"} -require "shortport" -require "stdnse" -require "smtp" portrule = shortport.port_or_service({ 25, 465, 587 }, { "smtp", "smtps", "submission" }) diff --git a/scripts/smtp-vuln-cve2010-4344.nse b/scripts/smtp-vuln-cve2010-4344.nse index 22c8474177..b9dccbfd82 100644 --- a/scripts/smtp-vuln-cve2010-4344.nse +++ b/scripts/smtp-vuln-cve2010-4344.nse @@ -1,3 +1,10 @@ +local math = require "math" +local shortport = require "shortport" +local smtp = require "smtp" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Checks for and/or exploits a heap overflow within versions of Exim prior to version 4.69 (CVE-2010-4344) and a privilege escalation @@ -66,9 +73,6 @@ author = "Djalal Harouni" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"exploit", "intrusive", "vuln"} -require "shortport" -require "smtp" -require "stdnse" portrule = shortport.port_or_service({25, 465, 587}, {"smtp", "smtps", "submission"}) diff --git a/scripts/smtp-vuln-cve2011-1720.nse b/scripts/smtp-vuln-cve2011-1720.nse index 8dd517df27..41ab3805ce 100644 --- a/scripts/smtp-vuln-cve2011-1720.nse +++ b/scripts/smtp-vuln-cve2011-1720.nse @@ -1,3 +1,10 @@ +local shortport = require "shortport" +local smtp = require "smtp" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local vulns = require "vulns" + description = [[ Checks for a memory corruption in the Postfix SMTP server when it uses Cyrus SASL library authentication mechanisms (CVE-2011-1720). This @@ -40,10 +47,6 @@ author = "Djalal Harouni" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "vuln"} -require "shortport" -require "smtp" -require "stdnse" -require "vulns" portrule = shortport.port_or_service({25, 465, 587}, {"smtp", "smtps", "submission"}) diff --git a/scripts/smtp-vuln-cve2011-1764.nse b/scripts/smtp-vuln-cve2011-1764.nse index 71f0b13fd8..5da2745b31 100644 --- a/scripts/smtp-vuln-cve2011-1764.nse +++ b/scripts/smtp-vuln-cve2011-1764.nse @@ -1,3 +1,10 @@ +local shortport = require "shortport" +local smtp = require "smtp" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local vulns = require "vulns" + description = [[ Checks for a format string vulnerability in the Exim SMTP server (version 4.70 through 4.75) with DomainKeys Identified Mail (DKIM) support @@ -47,10 +54,6 @@ author = "Djalal Harouni" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "vuln"} -require "shortport" -require "smtp" -require "stdnse" -require "vulns" portrule = function (host, port) if port.version.product ~= nil and port.version.product ~= "Exim smtpd" then diff --git a/scripts/sniffer-detect.nse b/scripts/sniffer-detect.nse index f3b14af3fb..6ee9e39b9e 100644 --- a/scripts/sniffer-detect.nse +++ b/scripts/sniffer-detect.nse @@ -1,3 +1,7 @@ +local nmap = require "nmap" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Checks if a target on a local Ethernet has its network card in promiscuous mode. @@ -10,7 +14,6 @@ http://www.securityfriday.com/promiscuous_detection_01.pdf. -- Host script results: -- |_ sniffer-detect: Likely in promiscuous mode (tests: "11111111") -require 'nmap' author = "Marek Majkowski" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/snmp-brute.nse b/scripts/snmp-brute.nse index 6a899ab343..fdcfb3b58a 100644 --- a/scripts/snmp-brute.nse +++ b/scripts/snmp-brute.nse @@ -1,3 +1,14 @@ +local coroutine = require "coroutine" +local creds = require "creds" +local io = require "io" +local nmap = require "nmap" +local packet = require "packet" +local shortport = require "shortport" +local snmp = require "snmp" +local stdnse = require "stdnse" +local string = require "string" +local unpwdb = require "unpwdb" + description = [[ Attempts to find an SNMP community string by brute force guessing. @@ -43,12 +54,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require "shortport" -require "snmp" -require "creds" -require "unpwdb" -require "nmap" -require "packet" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) diff --git a/scripts/snmp-interfaces.nse b/scripts/snmp-interfaces.nse index 61cb2aa2bf..09cbfa0322 100644 --- a/scripts/snmp-interfaces.nse +++ b/scripts/snmp-interfaces.nse @@ -1,3 +1,12 @@ +local datafiles = require "datafiles" +local nmap = require "nmap" +local shortport = require "shortport" +local snmp = require "snmp" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + description = [[ Attempts to enumerate network interfaces through SNMP. @@ -38,11 +47,6 @@ dependencies = {"snmp-brute"} -- Revised 05/27/2011 - v0.4 - action; add MAC addresses to nmap.registry[host.ip]["mac-geolocation"] (Gorjan Petrovski) -require "stdnse" -require "shortport" -require "snmp" -require "datafiles" -require "target" prerule = function() diff --git a/scripts/snmp-ios-config.nse b/scripts/snmp-ios-config.nse index 202efe891f..d1f130086a 100644 --- a/scripts/snmp-ios-config.nse +++ b/scripts/snmp-ios-config.nse @@ -1,3 +1,11 @@ +local io = require "io" +local nmap = require "nmap" +local shortport = require "shortport" +local snmp = require "snmp" +local stdnse = require "stdnse" +local table = require "table" +local tftp = require "tftp" + description = [[ Attempts to downloads Cisco router IOS configuration files using SNMP RW (v1) and display or save them. ]] @@ -35,9 +43,6 @@ categories = {"intrusive"} dependencies = {"snmp-brute"} -require "shortport" -require "snmp" -require "tftp" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) diff --git a/scripts/snmp-netstat.nse b/scripts/snmp-netstat.nse index 1585176350..258c6ecc6a 100644 --- a/scripts/snmp-netstat.nse +++ b/scripts/snmp-netstat.nse @@ -1,3 +1,10 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local snmp = require "snmp" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Attempts to query SNMP for a netstat like output. ]] @@ -26,8 +33,6 @@ dependencies = {"snmp-brute"} -- Created 01/19/2010 - v0.1 - created by Patrik Karlsson -- Revised 04/11/2010 - v0.2 - moved snmp_walk to snmp library -require "shortport" -require "snmp" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) diff --git a/scripts/snmp-processes.nse b/scripts/snmp-processes.nse index b02fbf2f48..471bbfcb18 100644 --- a/scripts/snmp-processes.nse +++ b/scripts/snmp-processes.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local snmp = require "snmp" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to enumerate running processes through SNMP. ]] @@ -36,8 +42,6 @@ dependencies = {"snmp-brute"} -- Revised 01/19/2010 - v0.3 - removed debugging output and renamed file -- Revised 04/11/2010 - v0.4 - moved snmp_walk to snmp library -require "shortport" -require "snmp" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) diff --git a/scripts/snmp-sysdescr.nse b/scripts/snmp-sysdescr.nse index 713fc95b7b..2593d0861e 100644 --- a/scripts/snmp-sysdescr.nse +++ b/scripts/snmp-sysdescr.nse @@ -1,3 +1,9 @@ +local math = require "math" +local nmap = require "nmap" +local shortport = require "shortport" +local snmp = require "snmp" +local string = require "string" + description = [[ Attempts to extract system information from an SNMP version 1 service. ]] @@ -18,8 +24,6 @@ categories = {"default", "discovery", "safe"} dependencies = {"snmp-brute"} -require "shortport" -require "snmp" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) diff --git a/scripts/snmp-win32-services.nse b/scripts/snmp-win32-services.nse index 45a7cbe921..c0d21fc3dc 100644 --- a/scripts/snmp-win32-services.nse +++ b/scripts/snmp-win32-services.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local snmp = require "snmp" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to enumerate Windows services through SNMP. ]] @@ -29,8 +35,6 @@ dependencies = {"snmp-brute"} -- Revised 01/19/2010 - v0.2 - fixed loop that would occure if a mib did not exist -- Revised 04/11/2010 - v0.3 - moved snmp_walk to snmp library -require "shortport" -require "snmp" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) diff --git a/scripts/snmp-win32-shares.nse b/scripts/snmp-win32-shares.nse index a55ed5ba26..92c52c008e 100644 --- a/scripts/snmp-win32-shares.nse +++ b/scripts/snmp-win32-shares.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local snmp = require "snmp" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to enumerate Windows Shares through SNMP. ]] @@ -22,8 +28,6 @@ dependencies = {"snmp-brute"} -- Revised 01/19/2010 - v0.2 - fixed loop that would occure if a mib did not exist -- Revised 04/11/2010 - v0.3 - moved snmp_walk to snmp library -require "shortport" -require "snmp" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) diff --git a/scripts/snmp-win32-software.nse b/scripts/snmp-win32-software.nse index 6f8d0ec04e..2361179871 100644 --- a/scripts/snmp-win32-software.nse +++ b/scripts/snmp-win32-software.nse @@ -1,3 +1,10 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local snmp = require "snmp" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to enumerate installed software through SNMP. ]] @@ -23,8 +30,6 @@ dependencies = {"snmp-brute"} -- Revised 01/19/2010 - v0.2 - fixed loop that would occure if a mib did not exist -- Revised 04/11/2010 - v0.3 - moved snmp_walk to snmp library -require "shortport" -require "snmp" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) diff --git a/scripts/snmp-win32-users.nse b/scripts/snmp-win32-users.nse index 4b938690b1..2561ed8fa8 100644 --- a/scripts/snmp-win32-users.nse +++ b/scripts/snmp-win32-users.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local snmp = require "snmp" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Attempts to enumerate Windows user accounts through SNMP ]] @@ -26,8 +32,6 @@ dependencies = {"snmp-brute"} -- Revised 01/19/2010 - v0.2 - fixed loop that would occure if a mib did not exist -- Revised 04/11/2010 - v0.3 - moved snmp_walk to snmp library -require "shortport" -require "snmp" portrule = shortport.portnumber(161, "udp", {"open", "open|filtered"}) diff --git a/scripts/socks-auth-info.nse b/scripts/socks-auth-info.nse index a46814214b..488d1c0677 100644 --- a/scripts/socks-auth-info.nse +++ b/scripts/socks-auth-info.nse @@ -1,3 +1,8 @@ +local shortport = require "shortport" +local socks = require "socks" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Determines the supported authentication mechanisms of a remote SOCKS proxy server. Starting with SOCKS version 5 socks servers may support @@ -20,8 +25,6 @@ types: -- |_ Username and password -- -require 'shortport' -require 'socks' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -46,4 +49,4 @@ action = function(host, port) helper:close() if ( 0 == #auth_methods ) then return end return stdnse.format_output(true, auth_methods) -end \ No newline at end of file +end diff --git a/scripts/socks-brute.nse b/scripts/socks-brute.nse index 9432d57557..cdc8aa0d3e 100644 --- a/scripts/socks-brute.nse +++ b/scripts/socks-brute.nse @@ -1,3 +1,8 @@ +local brute = require "brute" +local creds = require "creds" +local shortport = require "shortport" +local socks = require "socks" + description = [[ Performs brute force password auditing against SOCKS 5 proxy servers. ]] @@ -20,9 +25,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"brute", "intrusive"} -require 'brute' -require 'shortport' -require 'socks' portrule = shortport.port_or_service({1080, 9050}, {"socks", "socks5", "tor-socks"}) @@ -95,4 +97,4 @@ action = function(host, port) engine.options.script_name = SCRIPT_NAME status, result = engine:start() return result -end \ No newline at end of file +end diff --git a/scripts/socks-open-proxy.nse b/scripts/socks-open-proxy.nse index 0f91fcbc84..c9b390d57c 100644 --- a/scripts/socks-open-proxy.nse +++ b/scripts/socks-open-proxy.nse @@ -1,3 +1,9 @@ +local proxy = require "proxy" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local url = require "url" + description=[[ Checks if an open socks proxy is running on the target. @@ -26,10 +32,6 @@ author = "Joao Correa" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "external", "safe"} -require "shortport" -require "stdnse" -require "url" -require "proxy" --- Performs the custom test, with user's arguments -- @param host The host table diff --git a/scripts/sql-injection.nse b/scripts/sql-injection.nse index 5924877e3f..1f2f88d2b9 100644 --- a/scripts/sql-injection.nse +++ b/scripts/sql-injection.nse @@ -1,3 +1,11 @@ +local http = require "http" +local httpspider = require "httpspider" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local url = require "url" + description = [[ Spiders an HTTP server looking for URLs containing queries vulnerable to an SQL injection attack. @@ -12,14 +20,6 @@ We may not have access to the target web server's true hostname, which can preve virtually hosted sites. ]] -require('url') -require('shortport') -require('stdnse') -require('strbuf') -require('comm') -require('http') -require('nsedebug') -require('httpspider') author = "Eddie Bell" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/ssh-hostkey.nse b/scripts/ssh-hostkey.nse index 9907d057f5..e7ead065b9 100644 --- a/scripts/ssh-hostkey.nse +++ b/scripts/ssh-hostkey.nse @@ -1,3 +1,13 @@ +local ipOps = require "ipOps" +local nmap = require "nmap" +local shortport = require "shortport" +local ssh1 = require "ssh1" +local ssh2 = require "ssh2" +local stdnse = require "stdnse" +local table = require "table" + +local openssl = stdnse.silent_require "openssl" + description = [[ Shows SSH hostkeys. @@ -54,12 +64,6 @@ author = "Sven Klemm" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe","default","discovery"} -require("ipOps") -require("shortport") -require("stdnse") -stdnse.silent_require("openssl") -require("ssh1") -require("ssh2") portrule = shortport.port_or_service(22, "ssh") diff --git a/scripts/ssh2-enum-algos.nse b/scripts/ssh2-enum-algos.nse index 7a3d446e03..36051d6b79 100644 --- a/scripts/ssh2-enum-algos.nse +++ b/scripts/ssh2-enum-algos.nse @@ -1,3 +1,11 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + +local openssl = stdnse.silent_require "openssl" +local ssh2 = stdnse.silent_require "ssh2" + description = [[ Reports the number of algorithms (for encryption, compression, etc.) that the target SSH2 server offers. If verbosity is set, the offered algorithms @@ -55,10 +63,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -require "shortport" -require "stdnse" -stdnse.silent_require "openssl" -stdnse.silent_require "ssh2" portrule = shortport.port_or_service(22, "ssh") diff --git a/scripts/sshv1.nse b/scripts/sshv1.nse index a5327b87b0..8dab47ee63 100644 --- a/scripts/sshv1.nse +++ b/scripts/sshv1.nse @@ -1,3 +1,7 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" + description = [[ Checks if an SSH server supports the obsolete and less secure SSH Protocol Version 1. ]] @@ -11,7 +15,6 @@ categories = {"default", "safe"} -- 22/tcp open ssh -- |_sshv1: Server supports SSHv1 -require "shortport" portrule = shortport.port_or_service(22, "ssh") diff --git a/scripts/ssl-cert.nse b/scripts/ssl-cert.nse index 103c44f0b0..e3763894aa 100644 --- a/scripts/ssl-cert.nse +++ b/scripts/ssl-cert.nse @@ -1,3 +1,10 @@ +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local sslcert = require "sslcert" +local stdnse = require "stdnse" +local string = require "string" + description = [[ Retrieves a server's SSL certificate. The amount of information printed about the certificate depends on the verbosity level. With no extra @@ -64,8 +71,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "default", "safe", "discovery" } -require("sslcert") -require("shortport") portrule = function(host, port) return shortport.ssl(host, port) or sslcert.isPortSupported(port) diff --git a/scripts/ssl-enum-ciphers.nse b/scripts/ssl-enum-ciphers.nse index 44abadfc91..a478a84938 100644 --- a/scripts/ssl-enum-ciphers.nse +++ b/scripts/ssl-enum-ciphers.nse @@ -1,3 +1,13 @@ +local bin = require "bin" +local coroutine = require "coroutine" +local io = require "io" +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ This script repeatedly initiates SSL/TLS connections, each time trying a new cipher or compressor while recording whether a host accepts or rejects it. The @@ -60,10 +70,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require("bin") -require("nmap") -require("shortport") -require("stdnse") -- Most of the values in the tables below are from: -- http://www.iana.org/assignments/tls-parameters/ diff --git a/scripts/ssl-google-cert-catalog.nse b/scripts/ssl-google-cert-catalog.nse index 74df181083..e2503c740f 100644 --- a/scripts/ssl-google-cert-catalog.nse +++ b/scripts/ssl-google-cert-catalog.nse @@ -1,3 +1,11 @@ +local dns = require "dns" +local os = require "os" +local shortport = require "shortport" +local sslcert = require "sslcert" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Queries Google's Certificate Catalog for the SSL certificates retrieved from target hosts. @@ -24,11 +32,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "safe", "discovery", "external" } --dependencies = { "ssl-cert" } -require("nmap") -require("shortport") -require("stdnse") -require("dns") -require("sslcert") local format_date = function(day_num) return os.date("%d %b %Y", 60 * 60 * 24 * tonumber(day_num)) diff --git a/scripts/ssl-known-key.nse b/scripts/ssl-known-key.nse index 4f2b43dd0e..bc65df8dda 100644 --- a/scripts/ssl-known-key.nse +++ b/scripts/ssl-known-key.nse @@ -1,3 +1,8 @@ +local io = require "io" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -28,10 +33,6 @@ author = "Mak Kolybabi" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery", "vuln"} -require("bin") -require("nmap") -require("shortport") -require("stdnse") local FINGERPRINT_FILE = "ssl-fingerprints" diff --git a/scripts/sslv2.nse b/scripts/sslv2.nse index 7af6019615..9975c11c73 100644 --- a/scripts/sslv2.nse +++ b/scripts/sslv2.nse @@ -1,3 +1,8 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local string = require "string" +local table = require "table" + description = [[ Determines whether the server supports obsolete and less secure SSLv2, and discovers which ciphers it supports. @@ -19,7 +24,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe"} -require "shortport" portrule = shortport.ssl diff --git a/scripts/stun-info.nse b/scripts/stun-info.nse index adcdd8b87d..a3a643c7f0 100644 --- a/scripts/stun-info.nse +++ b/scripts/stun-info.nse @@ -1,3 +1,7 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stun = require "stun" + description = [[ Retrieves the external IP address of a NAT:ed host using the STUN protocol. ]] @@ -17,8 +21,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'stun' portrule = shortport.port_or_service(3478, "stun", "udp") @@ -43,4 +45,4 @@ action = function(host, port) if ( result ) then return "\n External IP: " .. result end -end \ No newline at end of file +end diff --git a/scripts/stun-version.nse b/scripts/stun-version.nse index 89c81f55b5..635e411143 100644 --- a/scripts/stun-version.nse +++ b/scripts/stun-version.nse @@ -1,3 +1,7 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stun = require "stun" + description = [[ Sends a binding request to the server and attempts to extract version information from the response, if the server attribute is present. @@ -13,8 +17,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"version"} -require 'shortport' -require 'stun' portrule = shortport.port_or_service(3478, "stun", "udp") @@ -36,4 +38,4 @@ action = function(host, port) port.version.product = result nmap.set_port_state(host, port, "open") nmap.set_port_version(host, port, "hardmatched") -end \ No newline at end of file +end diff --git a/scripts/stuxnet-detect.nse b/scripts/stuxnet-detect.nse index 0546b93907..3795cefc58 100644 --- a/scripts/stuxnet-detect.nse +++ b/scripts/stuxnet-detect.nse @@ -1,3 +1,9 @@ +local io = require "io" +local msrpc = require "msrpc" +local smb = require "smb" +local stdnse = require "stdnse" +local string = require "string" + -- -*- mode: lua -*- -- vim: set filetype=lua : @@ -27,9 +33,6 @@ author = "Mak Kolybabi" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "intrusive"} -require("msrpc") -require("smb") -require("stdnse") local STUXNET_PATHS = {"\\\\browser", "\\\\ntsvcs", "\\\\pipe\\browser", "\\\\pipe\\ntsvcs"} local STUXNET_UUID = string.char(0xe1, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46) diff --git a/scripts/svn-brute.nse b/scripts/svn-brute.nse index 586db1e3f8..1af0e5c302 100644 --- a/scripts/svn-brute.nse +++ b/scripts/svn-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local openssl = require "openssl" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Performs brute force password auditing against Subversion source code control servers. ]] @@ -30,9 +37,6 @@ Performs brute force password auditing against Subversion source code control se -- Created 07/12/2010 - v0.1 - created by Patrik Karlsson -- -require 'shortport' -require 'brute' -require 'creds' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/targets-asn.nse b/scripts/targets-asn.nse index 7970ab71e1..9fb43acc47 100644 --- a/scripts/targets-asn.nse +++ b/scripts/targets-asn.nse @@ -1,3 +1,8 @@ +local nmap = require "nmap" +local stdnse = require "stdnse" +local table = require "table" +local target = require "target" + description = [[ Produces a list of IP prefixes for a given AS number (ASN). @@ -33,9 +38,6 @@ license = "Simplified (2-clause) BSD license--See http://nmap.org/svn/docs/licen categories = {"discovery", "external", "safe"} -require "stdnse" -require "shortport" -require "target" prerule = function() return true diff --git a/scripts/targets-ipv6-multicast-echo.nse b/scripts/targets-ipv6-multicast-echo.nse index 20d8649399..93c2880a27 100644 --- a/scripts/targets-ipv6-multicast-echo.nse +++ b/scripts/targets-ipv6-multicast-echo.nse @@ -1,3 +1,12 @@ +local coroutine = require "coroutine" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" +local target = require "target" + description = [[ Sends an ICMPv6 echo request packet to the all-nodes link-local multicast address (ff02::1) to discover responsive hosts @@ -21,11 +30,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","broadcast"} -require 'nmap' -require 'tab' -require 'target' -require 'packet' -local bit = require 'bit' prerule = function() return nmap.is_privileged() diff --git a/scripts/targets-ipv6-multicast-invalid-dst.nse b/scripts/targets-ipv6-multicast-invalid-dst.nse index 3ef584119d..e240db06d9 100644 --- a/scripts/targets-ipv6-multicast-invalid-dst.nse +++ b/scripts/targets-ipv6-multicast-invalid-dst.nse @@ -1,3 +1,12 @@ +local coroutine = require "coroutine" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" +local target = require "target" + description = [[ Sends an ICMPv6 packet with an invalid extension header to the all-nodes link-local multicast address (ff02::1) to @@ -23,11 +32,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","broadcast"} -require 'nmap' -require 'tab' -require 'target' -require 'packet' -local bit = require 'bit' prerule = function() return nmap.is_privileged() diff --git a/scripts/targets-ipv6-multicast-mld.nse b/scripts/targets-ipv6-multicast-mld.nse index e25b03e95c..2fde34a236 100644 --- a/scripts/targets-ipv6-multicast-mld.nse +++ b/scripts/targets-ipv6-multicast-mld.nse @@ -1,3 +1,12 @@ +local bin = require "bin" +local coroutine = require "coroutine" +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" +local target = require "target" + description = [[ Attempts to discover available IPv6 hosts on the LAN by sending an MLD (multicast listener discovery) query to the link-local multicast address (ff02::1) and listening for any responses. The query's maximum response delay set to 0 to provoke hosts to respond immediately rather than waiting for other responses from their multicast group. ]] @@ -21,12 +30,6 @@ author = "niteesh" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","broadcast"} -local nmap = require 'nmap' -local tab = require 'tab' -local target = require 'target' -local packet = require 'packet' -local bit = require 'bit' -local bin = require 'bin' local arg_timeout = tonumber(stdnse.get_script_args(SCRIPT_NAME .. '.timeout')) diff --git a/scripts/targets-ipv6-multicast-slaac.nse b/scripts/targets-ipv6-multicast-slaac.nse index 108987c451..b71260b570 100644 --- a/scripts/targets-ipv6-multicast-slaac.nse +++ b/scripts/targets-ipv6-multicast-slaac.nse @@ -1,3 +1,15 @@ +local coroutine = require "coroutine" +local ipOps = require "ipOps" +local math = require "math" +local nmap = require "nmap" +local os = require "os" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" +local tab = require "tab" +local table = require "table" +local target = require "target" + description = [[ Performs IPv6 host discovery by triggering stateless address auto-configuration (SLAAC). @@ -34,13 +46,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery","broadcast"} -require 'ipOps' -require 'nmap' -require 'tab' -require 'target' -require 'packet' -require "os" -require "math" prerule = function() return nmap.is_privileged() diff --git a/scripts/targets-sniffer.nse b/scripts/targets-sniffer.nse index 7c4306af65..7f8aaebf47 100644 --- a/scripts/targets-sniffer.nse +++ b/scripts/targets-sniffer.nse @@ -1,3 +1,10 @@ +local nmap = require "nmap" +local packet = require "packet" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local target = require "target" + -- -*- mode: lua -*-: -- vim: set filetype=lua : @@ -32,11 +39,6 @@ author = "Nick Nikolaou" categories = {"broadcast", "discovery", "safe"} license = "Same as Nmap--See http://nmap.org/book/man-legal.html" -require("stdnse") -require("target") -require("nmap") -require("packet") -require("bin") local interface_info local all_addresses= {} diff --git a/scripts/targets-traceroute.nse b/scripts/targets-traceroute.nse index 6d088f0730..e73641fab4 100644 --- a/scripts/targets-traceroute.nse +++ b/scripts/targets-traceroute.nse @@ -1,3 +1,7 @@ +local stdnse = require "stdnse" +local string = require "string" +local target = require "target" + description = [[ Inserts traceroute hops into the Nmap scanning queue. It only functions if Nmap's --traceroute option is used and the newtargets script argument is given. ]] @@ -21,8 +25,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -require("stdnse") -require("target") hostrule = function(host) -- print debug messages because the script relies on diff --git a/scripts/telnet-brute.nse b/scripts/telnet-brute.nse index 331b9404f5..0c269c8e66 100644 --- a/scripts/telnet-brute.nse +++ b/scripts/telnet-brute.nse @@ -1,3 +1,11 @@ +local comm = require "comm" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local strbuf = require "strbuf" +local string = require "string" +local unpwdb = require "unpwdb" + description = [[ Tries to get Telnet login credentials by guessing usernames and passwords. ]] @@ -14,11 +22,6 @@ categories = {'brute', 'intrusive'} -- Update (Ron Bowes, November, 2009): Now uses unpwdb database. -require('shortport') -require('stdnse') -require('strbuf') -require('comm') -require('unpwdb') local soc local catch = function() soc:close() end diff --git a/scripts/telnet-encryption.nse b/scripts/telnet-encryption.nse index 17a75fa0bb..5a9960d719 100644 --- a/scripts/telnet-encryption.nse +++ b/scripts/telnet-encryption.nse @@ -1,3 +1,8 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local table = require "table" + description = [[ Determines whether the encryption option is supported on a remote telnet server. Some systems (including FreeBSD and the krb5 telnetd available in many Linux distributions) implement this option incorrectly, leading to a remote root vulnerability. This script currently only tests whether encryption is supported, not for that particular vulnerability. @@ -21,7 +26,6 @@ References: categories = {"safe", "discovery"} -require 'shortport' portrule = shortport.port_or_service(23, 'telnet') diff --git a/scripts/tftp-enum.nse b/scripts/tftp-enum.nse index 6fd1354e94..ddb91a4e84 100644 --- a/scripts/tftp-enum.nse +++ b/scripts/tftp-enum.nse @@ -1,3 +1,13 @@ +local bin = require "bin" +local datafiles = require "datafiles" +local math = require "math" +local nmap = require "nmap" +local os = require "os" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Enumerates TFTP (trivial file transfer protocol) filenames by testing for a list of common ones. @@ -31,10 +41,6 @@ author = "Alexander Rudakov" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "discovery", "intrusive" } -require'bin' -require'stdnse' -require'shortport' -require'datafiles' local REQUEST_ERROR = -1 local FILE_FOUND = 1 diff --git a/scripts/traceroute-geolocation.nse b/scripts/traceroute-geolocation.nse index e3c4daa22a..355e9d6484 100644 --- a/scripts/traceroute-geolocation.nse +++ b/scripts/traceroute-geolocation.nse @@ -1,3 +1,10 @@ +local http = require "http" +local io = require "io" +local json = require "json" +local stdnse = require "stdnse" +local tab = require "tab" +local table = require "table" + description = [[ Lists the geographic locations of each hop in a traceroute and optionally saves the results to a KML file, plottable on Google earth and maps. @@ -26,10 +33,6 @@ saves the results to a KML file, plottable on Google earth and maps. -- traceroute data. -- -local ipops = require("ipOps") -local http = require("http") -local json = require("json") -local tab = require("tab") author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -116,4 +119,4 @@ action = function(host) return stdnse.format_output(true, output) end -end \ No newline at end of file +end diff --git a/scripts/unusual-port.nse b/scripts/unusual-port.nse index 0029887a8f..44e20e269d 100644 --- a/scripts/unusual-port.nse +++ b/scripts/unusual-port.nse @@ -1,3 +1,8 @@ +local datafiles = require "datafiles" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + description = [[ Compares the detected service on a port against the expected service for that port number (e.g. ssh on 22, http on 80) and reports deviations. The script requires that a version scan has been run in order to be able to discover what service is actually running on each port. ]] @@ -16,7 +21,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = { "safe" } -require 'datafiles' portrule = function() return true end hostrule = function() return true end diff --git a/scripts/upnp-info.nse b/scripts/upnp-info.nse index 9e0e46fbb9..4c97357769 100644 --- a/scripts/upnp-info.nse +++ b/scripts/upnp-info.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local upnp = require "upnp" + description = [[ Attempts to extract system information from the UPnP service. ]] @@ -22,9 +28,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "discovery", "safe"} -require("stdnse") -require("shortport") -require("upnp") --- -- Runs on UDP port 1900 diff --git a/scripts/url-snarf.nse b/scripts/url-snarf.nse index 09b1cddacb..4e4fc661c8 100644 --- a/scripts/url-snarf.nse +++ b/scripts/url-snarf.nse @@ -1,3 +1,11 @@ +local io = require "io" +local nmap = require "nmap" +local os = require "os" +local packet = require "packet" +local stdnse = require "stdnse" +local table = require "table" +local url = require "url" + description=[[ Sniffs an interface for HTTP traffic and dumps any URLs, and their originating IP address. Script output differs from other script as @@ -26,8 +34,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe"} -require 'packet' -require 'url' local arg_iface = nmap.get_interface() or stdnse.get_script_args(SCRIPT_NAME .. ".interface") @@ -48,7 +54,7 @@ end -- are all declared local. local function get_url(data) - local headers, body = unpack(stdnse.strsplit("\r\n\r\n", data)) + local headers, body = table.unpack(stdnse.strsplit("\r\n\r\n", data)) if ( not(headers) ) then return end diff --git a/scripts/versant-info.nse b/scripts/versant-info.nse index bc2a1cd1b5..f6d15f3e47 100644 --- a/scripts/versant-info.nse +++ b/scripts/versant-info.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local versant = require "versant" + description = [[ Extracts information, including file paths, version and database names from a Versant object database. @@ -31,8 +37,6 @@ a Versant object database. -- |_ Version: 8.0.2 -- -require 'shortport' -require 'versant' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" @@ -107,4 +111,4 @@ action = function(host, port) table.insert(output, databases) return stdnse.format_output(true, output) -end \ No newline at end of file +end diff --git a/scripts/vmauthd-brute.nse b/scripts/vmauthd-brute.nse index f3e97b4392..a736e84410 100644 --- a/scripts/vmauthd-brute.nse +++ b/scripts/vmauthd-brute.nse @@ -1,3 +1,8 @@ +local brute = require "brute" +local creds = require "creds" +local nmap = require "nmap" +local shortport = require "shortport" + description = [[ Performs brute force password auditing against the VMWare Authentication Daemon (vmware-authd). ]] @@ -20,8 +25,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"brute", "intrusive"} -require 'brute' -require 'shortport' portrule = shortport.port_or_service(902, {"ssl/vmware-auth", "vmware-auth"}, "tcp") diff --git a/scripts/vnc-brute.nse b/scripts/vnc-brute.nse index b4d5bfcd1d..1644c83bd9 100644 --- a/scripts/vnc-brute.nse +++ b/scripts/vnc-brute.nse @@ -1,3 +1,9 @@ +local brute = require "brute" +local creds = require "creds" +local shortport = require "shortport" +local stdnse = require "stdnse" +local vnc = require "vnc" + description = [[ Performs brute force password auditing against VNC servers. ]] @@ -29,10 +35,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"intrusive", "brute"} -require 'shortport' -require 'brute' -require 'vnc' -require 'creds' portrule = shortport.port_or_service(5901, "vnc", "tcp", "open") diff --git a/scripts/vnc-info.nse b/scripts/vnc-info.nse index c294b6ee8b..583da63ab1 100644 --- a/scripts/vnc-info.nse +++ b/scripts/vnc-info.nse @@ -1,3 +1,8 @@ +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local vnc = require "vnc" + description = [[ Queries a VNC server for its protocol version and supported security types. ]] @@ -22,8 +27,6 @@ categories = {"default", "discovery", "safe"} -- Created 07/07/2010 - v0.1 - created by Patrik Karlsson -- Revised 08/14/2010 - v0.2 - changed so that errors are reported even without debugging -require 'shortport' -require 'vnc' portrule = shortport.port_or_service( {5900, 5901, 5902} , "vnc", "tcp", "open") diff --git a/scripts/voldemort-info.nse b/scripts/voldemort-info.nse index edfeddaa2e..af6afce6ca 100644 --- a/scripts/voldemort-info.nse +++ b/scripts/voldemort-info.nse @@ -1,3 +1,9 @@ +local bin = require "bin" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Retrieves cluster and store information from the Voldemort distributed key-value store using the Voldemort Native Protocol. ]] @@ -35,7 +41,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' portrule = shortport.port_or_service(6666, "vp3", "tcp") diff --git a/scripts/vuze-dht-info.nse b/scripts/vuze-dht-info.nse index 98f464558d..29d4d9baed 100644 --- a/scripts/vuze-dht-info.nse +++ b/scripts/vuze-dht-info.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" + +local vuzedht = stdnse.silent_require "vuzedht" + description = [[ Retrieves some basic information, including protocol version from a Vuze filesharing node. ]] @@ -32,10 +38,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "safe"} -require 'shortport' -require 'ipOps' -require 'stdnse' -stdnse.silent_require('vuzedht') portrule = function(host, port) local allports = stdnse.get_script_args('vuze-dht-info.allports') diff --git a/scripts/wdb-version.nse b/scripts/wdb-version.nse index 6e20cdb819..6aa6b5d7ca 100644 --- a/scripts/wdb-version.nse +++ b/scripts/wdb-version.nse @@ -1,3 +1,11 @@ +local bin = require "bin" +local bit = require "bit" +local nmap = require "nmap" +local rpc = require "rpc" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" + description = [[ Detects vulnerabilities and gathers information (such as version numbers and hardware support) from VxWorks Wind DeBug agents. @@ -28,9 +36,6 @@ license = "Same as Nmap--See http://nmap.org/book/man-legal.html" -- may also be "safe", but need testing to determine categories = {"default", "version", "discovery", "vuln"} -require 'shortport' -require 'rpc' -require 'stdnse' -- WDB protocol information -- http://www-kryo.desy.de/documents/vxWorks/V5.5/tornado-api/wdbpcl/wdb.html diff --git a/scripts/whois.nse b/scripts/whois.nse index 387933c99c..69585fe315 100644 --- a/scripts/whois.nse +++ b/scripts/whois.nse @@ -1,3 +1,13 @@ +local http = require "http" +local io = require "io" +local ipOps = require "ipOps" +local math = require "math" +local nmap = require "nmap" +local os = require "os" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" + description = [[ Queries the WHOIS services of Regional Internet Registries (RIR) and attempts to retrieve information about the IP Address Assignment which contains the Target IP Address. @@ -77,10 +87,6 @@ author = "jah" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"discovery", "external", "safe"} -local url = require "url" -local http = require "http" -local ipOps = require "ipOps" -local stdnse = require "stdnse" @@ -921,7 +927,7 @@ function redirection_rules( db, ip, data, meta ) -- iterate over each table of redirect info for a specific field for _, redirect_elems in ipairs( meta.redirects ) do - local obj, fld, pattern = unpack( redirect_elems ) -- three redirect elements + local obj, fld, pattern = table.unpack( redirect_elems ) -- three redirect elements -- if a field has been captured for the given redirect info if data[db][obj] and data[db][obj][fld] then diff --git a/scripts/wsdd-discover.nse b/scripts/wsdd-discover.nse index 6fdcf0e2cd..e402342e1a 100644 --- a/scripts/wsdd-discover.nse +++ b/scripts/wsdd-discover.nse @@ -1,3 +1,10 @@ +local coroutine = require "coroutine" +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local wsdd = require "wsdd" + description = [[ Retrieves and displays information from devices supporting the Web Services Dynamic Discovery (WS-Discovery) protocol. It also attempts @@ -28,8 +35,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery", "default"} -require 'shortport' -require 'wsdd' portrule = shortport.portnumber(3702, "udp", {"open", "open|filtered"}) @@ -45,11 +50,8 @@ discoverThread = function( funcname, host, port, results ) local helper = wsdd.Helper:new(host, port) helper:setTimeout(timeout) - local func = loadstring( "return helper:" .. funcname .. "()" ) - setfenv(func, setmetatable({ helper=helper; }, {__index = _G})) - if ( func ) then - local status, result = func() + local status, result = helper[funcname](helper) if ( status ) then table.insert(results, result) end else stdnse.print_debug("ERROR: Failed to call function: %s", funcname) @@ -88,4 +90,4 @@ action = function(host, port) table.sort( results, sortfunc ) return stdnse.format_output(true, results) end -end \ No newline at end of file +end diff --git a/scripts/x11-access.nse b/scripts/x11-access.nse index cbaa1b6f3b..98a04f59a0 100644 --- a/scripts/x11-access.nse +++ b/scripts/x11-access.nse @@ -1,3 +1,6 @@ +local nmap = require "nmap" +local string = require "string" + -- NSE x11-access v1.3 description = [[ diff --git a/scripts/xdmcp-discover.nse b/scripts/xdmcp-discover.nse index bf04042ff0..e92a807a8c 100644 --- a/scripts/xdmcp-discover.nse +++ b/scripts/xdmcp-discover.nse @@ -1,3 +1,9 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local table = require "table" +local xdmcp = require "xdmcp" + description = [[ Requests an XDMCP (X display manager control protocol) session and lists supported authentication and authorization mechanisms. ]] @@ -19,9 +25,6 @@ author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"safe", "discovery"} -require 'ipOps' -require 'shortport' -require 'xdmcp' portrule = shortport.port_or_service(177, "xdmcp", "udp") @@ -61,4 +64,4 @@ action = function(host, port) table.insert(result, ("Authorization data: %s"):format(stdnse.tohex(response.authr_data))) end return stdnse.format_output(true, result) -end \ No newline at end of file +end diff --git a/scripts/xmpp-brute.nse b/scripts/xmpp-brute.nse index ccf39e8907..f728f730a1 100644 --- a/scripts/xmpp-brute.nse +++ b/scripts/xmpp-brute.nse @@ -1,3 +1,10 @@ +local brute = require "brute" +local coroutine = require "coroutine" +local creds = require "creds" +local shortport = require "shortport" +local stdnse = require "stdnse" +local xmpp = require "xmpp" + description = [[ Performs brute force password auditing against XMPP (Jabber) instant messaging servers. ]] @@ -26,9 +33,6 @@ Performs brute force password auditing against XMPP (Jabber) instant messaging s -- Version 0.1 -- Created 07/21/2011 - v0.1 - created by Patrik Karlsson -require 'brute' -require 'shortport' -require 'xmpp' author = "Patrik Karlsson" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" diff --git a/scripts/xmpp-info.nse b/scripts/xmpp-info.nse index 27cc398f77..223aab0e7e 100644 --- a/scripts/xmpp-info.nse +++ b/scripts/xmpp-info.nse @@ -1,3 +1,10 @@ +local nmap = require "nmap" +local shortport = require "shortport" +local stdnse = require "stdnse" +local string = require "string" +local table = require "table" +local xmpp = require "xmpp" + description = [[ Connects to XMPP server (port 5222) and collects server information such as: supported auth mechanisms, compression methods, whether TLS is supported @@ -41,10 +48,6 @@ author = "Vasiliy Kulikov" license = "Same as Nmap--See http://nmap.org/book/man-legal.html" categories = {"default", "safe", "discovery", "version"} -require 'shortport' -require 'stdnse' -require 'dns' -require 'xmpp' local known_features = { ['starttls'] = true,