From 2db49088141b6238e92aecc4c073076a02c73065 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 14 Feb 2016 08:16:35 +0100 Subject: [PATCH] Added lua-zlib, lfs and luv support for LUA, exposed all using luaengine (nw) --- 3rdparty/lua-zlib/.gitattributes | 1 + 3rdparty/lua-zlib/CMakeLists.txt | 62 + 3rdparty/lua-zlib/Makefile | 62 + 3rdparty/lua-zlib/README | 151 ++ 3rdparty/lua-zlib/amnon_david.gz | Bin 0 -> 65 bytes .../lua-zlib/cmake/Modules/FindLuaJIT.cmake | 63 + 3rdparty/lua-zlib/lua_zlib.c | 401 +++++ 3rdparty/lua-zlib/rockspec | 35 + 3rdparty/lua-zlib/tap.lua | 24 + 3rdparty/lua-zlib/test.lua | 198 +++ 3rdparty/lua-zlib/tom_macwright.gz | 4 + 3rdparty/lua-zlib/tom_macwright.out | Bin 0 -> 245 bytes 3rdparty/lua-zlib/zlib.def | 2 + 3rdparty/luafilesystem/.travis.yml | 33 + 3rdparty/luafilesystem/.travis/platform.sh | 15 + 3rdparty/luafilesystem/.travis/setup_lua.sh | 101 ++ 3rdparty/luafilesystem/LICENSE | 21 + 3rdparty/luafilesystem/Makefile | 25 + 3rdparty/luafilesystem/Makefile.win | 25 + 3rdparty/luafilesystem/README | 23 + 3rdparty/luafilesystem/config | 24 + 3rdparty/luafilesystem/config.win | 19 + 3rdparty/luafilesystem/doc/us/doc.css | 212 +++ 3rdparty/luafilesystem/doc/us/examples.html | 103 ++ 3rdparty/luafilesystem/doc/us/index.html | 218 +++ 3rdparty/luafilesystem/doc/us/license.html | 122 ++ .../luafilesystem/doc/us/luafilesystem.png | Bin 0 -> 8535 bytes 3rdparty/luafilesystem/doc/us/manual.html | 280 ++++ .../rockspecs/luafilesystem-1.3.0-1.rockspec | 27 + .../rockspecs/luafilesystem-1.4.0-1.rockspec | 27 + .../rockspecs/luafilesystem-1.4.0-2.rockspec | 43 + .../rockspecs/luafilesystem-1.4.1-1.rockspec | 43 + .../luafilesystem-1.4.1rc1-1.rockspec | 43 + .../rockspecs/luafilesystem-1.4.2-1.rockspec | 26 + .../rockspecs/luafilesystem-1.5.0-1.rockspec | 27 + .../rockspecs/luafilesystem-1.6.0-1.rockspec | 27 + .../rockspecs/luafilesystem-1.6.1-1.rockspec | 27 + .../rockspecs/luafilesystem-1.6.2-1.rockspec | 27 + .../rockspecs/luafilesystem-1.6.3-1.rockspec | 28 + .../rockspecs/luafilesystem-cvs-1.rockspec | 44 + .../rockspecs/luafilesystem-cvs-2.rockspec | 26 + .../rockspecs/luafilesystem-cvs-3.rockspec | 27 + 3rdparty/luafilesystem/src/.gitignore | 2 + 3rdparty/luafilesystem/src/lfs.c | 906 ++++++++++++ 3rdparty/luafilesystem/src/lfs.def | 4 + 3rdparty/luafilesystem/src/lfs.h | 34 + 3rdparty/luafilesystem/tests/test.lua | 175 +++ 3rdparty/luafilesystem/vc6/lfs.def | 5 + 3rdparty/luafilesystem/vc6/luafilesystem.dsw | 33 + .../luafilesystem/vc6/luafilesystem_dll.dsp | 127 ++ 3rdparty/luv/.ci/install.bat | 270 ++++ 3rdparty/luv/.ci/platform.sh | 15 + 3rdparty/luv/.ci/set_compiler_env.bat | 40 + 3rdparty/luv/.ci/setenv_lua.sh | 3 + 3rdparty/luv/.ci/setup_lua.sh | 122 ++ 3rdparty/luv/.ci/winmake.bat | 457 ++++++ 3rdparty/luv/.gitignore | 10 + 3rdparty/luv/.travis.yml | 36 + 3rdparty/luv/CMakeLists.txt | 191 +++ 3rdparty/luv/LICENSE.txt | 202 +++ 3rdparty/luv/Makefile | 61 + 3rdparty/luv/README.md | 213 +++ 3rdparty/luv/appveyor.yml | 42 + 3rdparty/luv/cmake/Modules/FindLibuv.cmake | 11 + 3rdparty/luv/cmake/Modules/FindLuaJIT.cmake | 55 + 3rdparty/luv/deps/lua.cmake | 128 ++ 3rdparty/luv/deps/lua_one.c | 97 ++ 3rdparty/luv/deps/luajit.cmake | 407 +++++ 3rdparty/luv/deps/uv.cmake | 224 +++ 3rdparty/luv/docs.md | 1309 +++++++++++++++++ 3rdparty/luv/examples/cqueues-main.lua | 31 + 3rdparty/luv/examples/cqueues-slave.lua | 55 + 3rdparty/luv/examples/echo-server-client.lua | 68 + 3rdparty/luv/examples/killing-children.lua | 24 + 3rdparty/luv/examples/lots-o-dns.lua | 49 + 3rdparty/luv/examples/repl.lua | 89 ++ 3rdparty/luv/examples/talking-to-children.lua | 47 + 3rdparty/luv/examples/tcp-cluster.lua | 84 ++ 3rdparty/luv/examples/timers.lua | 68 + 3rdparty/luv/examples/uvbook/helloworld.lua | 5 + 3rdparty/luv/examples/uvbook/idle-basic.lua | 14 + 3rdparty/luv/examples/uvbook/onchange.lua | 30 + 3rdparty/luv/examples/uvbook/queue-work.lua | 19 + .../luv/examples/uvbook/tcp-echo-client.lua | 21 + .../luv/examples/uvbook/tcp-echo-server.lua | 22 + .../luv/examples/uvbook/thread-create.lua | 38 + 3rdparty/luv/examples/uvbook/uvcat.lua | 37 + 3rdparty/luv/examples/uvbook/uvtee.lua | 35 + 3rdparty/luv/lib/tap.lua | 165 +++ 3rdparty/luv/lib/utils.lua | 165 +++ 3rdparty/luv/luv-1.8.0-4.rockspec | 34 + 3rdparty/luv/msvcbuild.bat | 13 + 3rdparty/luv/src/async.c | 63 + 3rdparty/luv/src/check.c | 59 + 3rdparty/luv/src/constants.c | 649 ++++++++ 3rdparty/luv/src/dns.c | 296 ++++ 3rdparty/luv/src/fs.c | 614 ++++++++ 3rdparty/luv/src/fs_event.c | 97 ++ 3rdparty/luv/src/fs_poll.c | 90 ++ 3rdparty/luv/src/handle.c | 173 +++ 3rdparty/luv/src/idle.c | 59 + 3rdparty/luv/src/lhandle.c | 116 ++ 3rdparty/luv/src/lhandle.h | 67 + 3rdparty/luv/src/loop.c | 92 ++ 3rdparty/luv/src/lreq.c | 71 + 3rdparty/luv/src/lreq.h | 43 + 3rdparty/luv/src/lthreadpool.h | 48 + 3rdparty/luv/src/luv.c | 519 +++++++ 3rdparty/luv/src/luv.h | 109 ++ 3rdparty/luv/src/misc.c | 316 ++++ 3rdparty/luv/src/pipe.c | 114 ++ 3rdparty/luv/src/poll.c | 100 ++ 3rdparty/luv/src/prepare.c | 59 + 3rdparty/luv/src/process.c | 266 ++++ 3rdparty/luv/src/req.c | 52 + 3rdparty/luv/src/schema.c | 16 + 3rdparty/luv/src/signal.c | 72 + 3rdparty/luv/src/stream.c | 263 ++++ 3rdparty/luv/src/tcp.c | 182 +++ 3rdparty/luv/src/thread.c | 353 +++++ 3rdparty/luv/src/timer.c | 84 ++ 3rdparty/luv/src/tty.c | 65 + 3rdparty/luv/src/udp.c | 260 ++++ 3rdparty/luv/src/util.c | 56 + 3rdparty/luv/src/util.h | 26 + 3rdparty/luv/src/work.c | 224 +++ 3rdparty/luv/tests/manual-test-cluster.lua | 213 +++ 3rdparty/luv/tests/run.lua | 33 + 3rdparty/luv/tests/test-async.lua | 32 + 3rdparty/luv/tests/test-conversions.lua | 6 + 3rdparty/luv/tests/test-dns.lua | 125 ++ 3rdparty/luv/tests/test-fs.lua | 90 ++ 3rdparty/luv/tests/test-leaks.lua | 186 +++ 3rdparty/luv/tests/test-misc.lua | 85 ++ .../tests/test-prepare-check-idle-async.lua | 49 + 3rdparty/luv/tests/test-process.lua | 101 ++ .../luv/tests/test-sigchld-after-lua_close.sh | 45 + 3rdparty/luv/tests/test-signal.lua | 40 + 3rdparty/luv/tests/test-tcp.lua | 114 ++ 3rdparty/luv/tests/test-thread.lua | 47 + 3rdparty/luv/tests/test-timer.lua | 87 ++ 3rdparty/luv/tests/test-work.lua | 48 + scripts/genie.lua | 5 +- scripts/src/3rdparty.lua | 73 +- scripts/src/main.lua | 3 +- src/emu/luaengine.cpp | 75 +- 146 files changed, 16054 insertions(+), 34 deletions(-) create mode 100644 3rdparty/lua-zlib/.gitattributes create mode 100644 3rdparty/lua-zlib/CMakeLists.txt create mode 100644 3rdparty/lua-zlib/Makefile create mode 100644 3rdparty/lua-zlib/README create mode 100644 3rdparty/lua-zlib/amnon_david.gz create mode 100644 3rdparty/lua-zlib/cmake/Modules/FindLuaJIT.cmake create mode 100644 3rdparty/lua-zlib/lua_zlib.c create mode 100644 3rdparty/lua-zlib/rockspec create mode 100644 3rdparty/lua-zlib/tap.lua create mode 100644 3rdparty/lua-zlib/test.lua create mode 100644 3rdparty/lua-zlib/tom_macwright.gz create mode 100644 3rdparty/lua-zlib/tom_macwright.out create mode 100644 3rdparty/lua-zlib/zlib.def create mode 100644 3rdparty/luafilesystem/.travis.yml create mode 100644 3rdparty/luafilesystem/.travis/platform.sh create mode 100644 3rdparty/luafilesystem/.travis/setup_lua.sh create mode 100644 3rdparty/luafilesystem/LICENSE create mode 100644 3rdparty/luafilesystem/Makefile create mode 100644 3rdparty/luafilesystem/Makefile.win create mode 100644 3rdparty/luafilesystem/README create mode 100644 3rdparty/luafilesystem/config create mode 100644 3rdparty/luafilesystem/config.win create mode 100644 3rdparty/luafilesystem/doc/us/doc.css create mode 100644 3rdparty/luafilesystem/doc/us/examples.html create mode 100644 3rdparty/luafilesystem/doc/us/index.html create mode 100644 3rdparty/luafilesystem/doc/us/license.html create mode 100644 3rdparty/luafilesystem/doc/us/luafilesystem.png create mode 100644 3rdparty/luafilesystem/doc/us/manual.html create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.3.0-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-2.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1rc1-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.2-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.5.0-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.0-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.1-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.2-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.3-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-1.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-2.rockspec create mode 100644 3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-3.rockspec create mode 100644 3rdparty/luafilesystem/src/.gitignore create mode 100644 3rdparty/luafilesystem/src/lfs.c create mode 100644 3rdparty/luafilesystem/src/lfs.def create mode 100644 3rdparty/luafilesystem/src/lfs.h create mode 100644 3rdparty/luafilesystem/tests/test.lua create mode 100644 3rdparty/luafilesystem/vc6/lfs.def create mode 100644 3rdparty/luafilesystem/vc6/luafilesystem.dsw create mode 100644 3rdparty/luafilesystem/vc6/luafilesystem_dll.dsp create mode 100644 3rdparty/luv/.ci/install.bat create mode 100644 3rdparty/luv/.ci/platform.sh create mode 100644 3rdparty/luv/.ci/set_compiler_env.bat create mode 100644 3rdparty/luv/.ci/setenv_lua.sh create mode 100644 3rdparty/luv/.ci/setup_lua.sh create mode 100644 3rdparty/luv/.ci/winmake.bat create mode 100644 3rdparty/luv/.gitignore create mode 100644 3rdparty/luv/.travis.yml create mode 100644 3rdparty/luv/CMakeLists.txt create mode 100644 3rdparty/luv/LICENSE.txt create mode 100644 3rdparty/luv/Makefile create mode 100644 3rdparty/luv/README.md create mode 100644 3rdparty/luv/appveyor.yml create mode 100644 3rdparty/luv/cmake/Modules/FindLibuv.cmake create mode 100644 3rdparty/luv/cmake/Modules/FindLuaJIT.cmake create mode 100644 3rdparty/luv/deps/lua.cmake create mode 100644 3rdparty/luv/deps/lua_one.c create mode 100644 3rdparty/luv/deps/luajit.cmake create mode 100644 3rdparty/luv/deps/uv.cmake create mode 100644 3rdparty/luv/docs.md create mode 100644 3rdparty/luv/examples/cqueues-main.lua create mode 100644 3rdparty/luv/examples/cqueues-slave.lua create mode 100644 3rdparty/luv/examples/echo-server-client.lua create mode 100644 3rdparty/luv/examples/killing-children.lua create mode 100644 3rdparty/luv/examples/lots-o-dns.lua create mode 100644 3rdparty/luv/examples/repl.lua create mode 100644 3rdparty/luv/examples/talking-to-children.lua create mode 100644 3rdparty/luv/examples/tcp-cluster.lua create mode 100644 3rdparty/luv/examples/timers.lua create mode 100644 3rdparty/luv/examples/uvbook/helloworld.lua create mode 100644 3rdparty/luv/examples/uvbook/idle-basic.lua create mode 100644 3rdparty/luv/examples/uvbook/onchange.lua create mode 100644 3rdparty/luv/examples/uvbook/queue-work.lua create mode 100644 3rdparty/luv/examples/uvbook/tcp-echo-client.lua create mode 100644 3rdparty/luv/examples/uvbook/tcp-echo-server.lua create mode 100644 3rdparty/luv/examples/uvbook/thread-create.lua create mode 100644 3rdparty/luv/examples/uvbook/uvcat.lua create mode 100644 3rdparty/luv/examples/uvbook/uvtee.lua create mode 100644 3rdparty/luv/lib/tap.lua create mode 100644 3rdparty/luv/lib/utils.lua create mode 100644 3rdparty/luv/luv-1.8.0-4.rockspec create mode 100644 3rdparty/luv/msvcbuild.bat create mode 100644 3rdparty/luv/src/async.c create mode 100644 3rdparty/luv/src/check.c create mode 100644 3rdparty/luv/src/constants.c create mode 100644 3rdparty/luv/src/dns.c create mode 100644 3rdparty/luv/src/fs.c create mode 100644 3rdparty/luv/src/fs_event.c create mode 100644 3rdparty/luv/src/fs_poll.c create mode 100644 3rdparty/luv/src/handle.c create mode 100644 3rdparty/luv/src/idle.c create mode 100644 3rdparty/luv/src/lhandle.c create mode 100644 3rdparty/luv/src/lhandle.h create mode 100644 3rdparty/luv/src/loop.c create mode 100644 3rdparty/luv/src/lreq.c create mode 100644 3rdparty/luv/src/lreq.h create mode 100644 3rdparty/luv/src/lthreadpool.h create mode 100644 3rdparty/luv/src/luv.c create mode 100644 3rdparty/luv/src/luv.h create mode 100644 3rdparty/luv/src/misc.c create mode 100644 3rdparty/luv/src/pipe.c create mode 100644 3rdparty/luv/src/poll.c create mode 100644 3rdparty/luv/src/prepare.c create mode 100644 3rdparty/luv/src/process.c create mode 100644 3rdparty/luv/src/req.c create mode 100644 3rdparty/luv/src/schema.c create mode 100644 3rdparty/luv/src/signal.c create mode 100644 3rdparty/luv/src/stream.c create mode 100644 3rdparty/luv/src/tcp.c create mode 100644 3rdparty/luv/src/thread.c create mode 100644 3rdparty/luv/src/timer.c create mode 100644 3rdparty/luv/src/tty.c create mode 100644 3rdparty/luv/src/udp.c create mode 100644 3rdparty/luv/src/util.c create mode 100644 3rdparty/luv/src/util.h create mode 100644 3rdparty/luv/src/work.c create mode 100644 3rdparty/luv/tests/manual-test-cluster.lua create mode 100644 3rdparty/luv/tests/run.lua create mode 100644 3rdparty/luv/tests/test-async.lua create mode 100644 3rdparty/luv/tests/test-conversions.lua create mode 100644 3rdparty/luv/tests/test-dns.lua create mode 100644 3rdparty/luv/tests/test-fs.lua create mode 100644 3rdparty/luv/tests/test-leaks.lua create mode 100644 3rdparty/luv/tests/test-misc.lua create mode 100644 3rdparty/luv/tests/test-prepare-check-idle-async.lua create mode 100644 3rdparty/luv/tests/test-process.lua create mode 100644 3rdparty/luv/tests/test-sigchld-after-lua_close.sh create mode 100644 3rdparty/luv/tests/test-signal.lua create mode 100644 3rdparty/luv/tests/test-tcp.lua create mode 100644 3rdparty/luv/tests/test-thread.lua create mode 100644 3rdparty/luv/tests/test-timer.lua create mode 100644 3rdparty/luv/tests/test-work.lua diff --git a/3rdparty/lua-zlib/.gitattributes b/3rdparty/lua-zlib/.gitattributes new file mode 100644 index 00000000000..54be6288857 --- /dev/null +++ b/3rdparty/lua-zlib/.gitattributes @@ -0,0 +1 @@ +lua_zlib.c export-subst ident diff --git a/3rdparty/lua-zlib/CMakeLists.txt b/3rdparty/lua-zlib/CMakeLists.txt new file mode 100644 index 00000000000..1cda6b7532b --- /dev/null +++ b/3rdparty/lua-zlib/CMakeLists.txt @@ -0,0 +1,62 @@ +# Copyright (C) 2007-2009 LuaDist. +# Submitted by David Manura +# Redistribution and use of this file is allowed according to the +# terms of the MIT license. +# For details see the COPYRIGHT file distributed with LuaDist. +# Please note that the package source code is licensed under its own +# license. + +PROJECT(lua-zlib C) +CMAKE_MINIMUM_REQUIRED (VERSION 2.6) + +option(USE_LUA "Use Lua (also called 'C' Lua) includes (default)" ON) +option(USE_LUAJIT "Use LuaJIT includes instead of 'C' Lua ones (recommended, if you're using LuaJIT, but disabled by default)") +set(USE_LUA_VERSION 5.1 CACHE STRING "Set the Lua version to use (default: 5.1)") + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") + +if(USE_LUAJIT) +# Find luajit + find_package(LuaJIT REQUIRED) + set(USE_LUA OFF) +# / Find lua +endif() + +if(USE_LUA) +# Find lua + find_package(Lua ${USE_LUA_VERSION} EXACT REQUIRED) +# / Find lua +endif() + + +# Basic configurations + SET(INSTALL_CMOD share/lua/cmod CACHE PATH "Directory to install Lua binary modules (configure lua via LUA_CPATH)") +# / configs + +# Find zlib + FIND_PACKAGE(ZLIB REQUIRED) +# / Find zlib + +# Define how to build zlib.so: + INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIRS} ${LUA_INCLUDE_DIR}) + ADD_LIBRARY(cmod_zlib MODULE + lua_zlib.c zlib.def) + SET_TARGET_PROPERTIES(cmod_zlib PROPERTIES PREFIX "") + SET_TARGET_PROPERTIES(cmod_zlib PROPERTIES OUTPUT_NAME zlib) + TARGET_LINK_LIBRARIES(cmod_zlib ${ZLIB_LIBRARIES}) +# / build zlib.so + +# Define how to test zlib.so: + INCLUDE(CTest) + SET(LUA_BIN "lua${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}") + FIND_PROGRAM(LUA NAMES ${LUA_BIN} lua luajit lua.bat) + ADD_TEST(basic ${LUA} ${CMAKE_CURRENT_SOURCE_DIR}/test.lua ${CMAKE_CURRENT_SOURCE_DIR}/ ${CMAKE_CURRENT_BINARY_DIR}/) + SET_TESTS_PROPERTIES(basic + PROPERTIES + FAIL_REGULAR_EXPRESSION + "not ok") +# / test zlib.so + +# Where to install stuff + INSTALL (TARGETS cmod_zlib DESTINATION ${INSTALL_CMOD}) +# / Where to install. diff --git a/3rdparty/lua-zlib/Makefile b/3rdparty/lua-zlib/Makefile new file mode 100644 index 00000000000..801ea0436f2 --- /dev/null +++ b/3rdparty/lua-zlib/Makefile @@ -0,0 +1,62 @@ +# This Makefile is based on LuaSec's Makefile. Thanks to the LuaSec developers. +# Inform the location to intall the modules +LUAPATH ?= /usr/share/lua/5.1 +LUACPATH ?= /usr/lib/lua/5.1 +INCDIR ?= -I/usr/include/lua5.1 +LIBDIR ?= -L/usr/lib + +# For Mac OS X: set the system version +MACOSX_VERSION = 10.4 + +CMOD = zlib.so +OBJS = lua_zlib.o + +LIBS = -lz -llua -lm +WARN = -Wall -pedantic + +BSD_CFLAGS = -O2 -fPIC $(WARN) $(INCDIR) $(DEFS) +BSD_LDFLAGS = -O -shared -fPIC $(LIBDIR) + +LNX_CFLAGS = -O2 -fPIC $(WARN) $(INCDIR) $(DEFS) +LNX_LDFLAGS = -O -shared -fPIC $(LIBDIR) + +MAC_ENV = env MACOSX_DEPLOYMENT_TARGET='$(MACVER)' +MAC_CFLAGS = -O2 -fPIC -fno-common $(WARN) $(INCDIR) $(DEFS) +MAC_LDFLAGS = -bundle -undefined dynamic_lookup -fPIC $(LIBDIR) + +CC = gcc +LD = $(MYENV) gcc +CFLAGS = $(MYCFLAGS) +LDFLAGS = $(MYLDFLAGS) + +.PHONY: all clean install none linux bsd macosx + +all: + @echo "Usage: $(MAKE) " + @echo " * linux" + @echo " * bsd" + @echo " * macosx" + +install: $(CMOD) + cp $(CMOD) $(LUACPATH) + +uninstall: + rm $(LUACPATH)/zlib.so + +linux: + @$(MAKE) $(CMOD) MYCFLAGS="$(LNX_CFLAGS)" MYLDFLAGS="$(LNX_LDFLAGS)" INCDIR="$(INCDIR)" LIBDIR="$(LIBDIR)" DEFS="$(DEFS)" + +bsd: + @$(MAKE) $(CMOD) MYCFLAGS="$(BSD_CFLAGS)" MYLDFLAGS="$(BSD_LDFLAGS)" INCDIR="$(INCDIR)" LIBDIR="$(LIBDIR)" DEFS="$(DEFS)" + +macosx: + @$(MAKE) $(CMOD) MYCFLAGS="$(MAC_CFLAGS)" MYLDFLAGS="$(MAC_LDFLAGS)" MYENV="$(MAC_ENV)" INCDIR="$(INCDIR)" LIBDIR="$(LIBDIR)" DEFS="$(DEFS)" + +clean: + rm -f $(OBJS) $(CMOD) + +.c.o: + $(CC) -c $(CFLAGS) $(DEFS) $(INCDIR) -o $@ $< + +$(CMOD): $(OBJS) + $(LD) $(LDFLAGS) $(LIBDIR) $(OBJS) $(LIBS) -o $@ diff --git a/3rdparty/lua-zlib/README b/3rdparty/lua-zlib/README new file mode 100644 index 00000000000..8c1ef8d5f8d --- /dev/null +++ b/3rdparty/lua-zlib/README @@ -0,0 +1,151 @@ +********************************************************************** +* Author : Brian Maher +* Library : lua_zlib - Lua 5.1 interface to zlib +* +* The MIT License +* +* Copyright (c) 2009 Brian Maher +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +********************************************************************** + +To use this library, you need zlib, get it here: + http://www.gzip.org/zlib/ + +To build this library, you can use CMake and get it here: + http://www.cmake.org/cmake/resources/software.html + +...or you can use GNU Make. + make + +Loading the library: + + If you built the library as a loadable package + [local] zlib = require 'zlib' + + If you compiled the package statically into your application, call + the function "luaopen_zlib(L)". It will create a table with the zlib + functions and leave it on the stack. + +-- zlib functions -- + +int major, int minor, int patch = zlib.version() + + returns numeric zlib version for the major, minor, and patch + levels of the version dynamically linked in. + +function stream = zlib.deflate([ int compression_level ], [ int window_size ]) + + If no compression_level is provided uses Z_DEFAULT_COMPRESSION (6), + compression level is a number from 1-9 where zlib.BEST_SPEED is 1 + and zlib.BEST_COMPRESSION is 9. + + Returns a "stream" function that compresses (or deflates) all + strings passed in. Specifically, use it as such: + + string deflated, bool eof, int bytes_in, int bytes_out = + stream(string input [, 'sync' | 'full' | 'finish']) + + Takes input and deflates and returns a portion of it, + optionally forcing a flush. + + A 'sync' flush will force all pending output to be flushed to + the return value and the output is aligned on a byte boundary, + so that the decompressor can get all input data available so + far. Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + A 'full' flush will flush all output as with 'sync', and the + compression state is reset so that decompression can restart + from this point if previous compressed data has been damaged + or if random access is desired. Using Z_FULL_FLUSH too often + can seriously degrade the compression. + + A 'finish' flush will force all pending output to be processed + and results in the stream become unusable. Any future + attempts to print anything other than the empty string will + result in an error that begins with IllegalState. + + The eof result is true if 'finish' was specified, otherwise + it is false. + + The bytes_in is how many bytes of input have been passed to + stream, and bytes_out is the number of bytes returned in + deflated string chunks. + +function stream = zlib.inflate([int windowBits]) + + Returns a "stream" function that decompresses (or inflates) all + strings passed in. Optionally specify a windowBits argument + that is passed to inflateInit2(), see zlib.h for details about + this argument. By default, gzip header detection is done, and + the max window size is used. + + The "stream" function should be used as such: + + string inflated, bool eof, int bytes_in, int bytes_out = + stream(string input) + + Takes input and inflates and returns a portion of it. If it + detects the end of a deflation stream, then total will be the + total number of bytes read from input and all future calls to + stream() with a non empty string will result in an error that + begins with IllegalState. + + No flush options are provided since the maximal amount of + input is always processed. + + eof will be true when the input string is determined to be at + the "end of the file". + + The bytes_in is how many bytes of input have been passed to + stream, and bytes_out is the number of bytes returned in + inflated string chunks. + + +function compute_checksum = zlib.adler32() +function compute_checksum = zlib.crc32() + + Create a new checksum computation function using either the + adler32 or crc32 algorithms. This resulting function should be + used as such: + + int checksum = compute_checksum(string input | + function compute_checksum) + + The compute_checksum function takes as input either a string + that is logically getting appended to or another + compute_checksum function that is logically getting appended. + The result is the updated checksum. + + For example, these uses will all result in the same checksum: + + -- All in one call: + local csum = zlib.crc32()("one two") + + -- Multiple calls: + local compute = zlib.crc32() + compute("one") + assert(csum == compute(" two")) + + -- Multiple compute_checksums joined: + local compute1, compute2 = zlib.crc32(), zlib.crc32() + compute1("one") + compute2(" two") + assert(csum == compute1(compute2)) diff --git a/3rdparty/lua-zlib/amnon_david.gz b/3rdparty/lua-zlib/amnon_david.gz new file mode 100644 index 0000000000000000000000000000000000000000..c56de231d1a73e79950442e4eab732788ca0b506 GIT binary patch literal 65 zcmb2|=3oE==FKNHPM+QPc$4QT|CL)FpYk|+@?`jhP>qu(bix=GxwKBY@<_;5Pr9~a TPp_Ser8vWk8&~$219bubjUOAL literal 0 HcmV?d00001 diff --git a/3rdparty/lua-zlib/cmake/Modules/FindLuaJIT.cmake b/3rdparty/lua-zlib/cmake/Modules/FindLuaJIT.cmake new file mode 100644 index 00000000000..e626a5a1d94 --- /dev/null +++ b/3rdparty/lua-zlib/cmake/Modules/FindLuaJIT.cmake @@ -0,0 +1,63 @@ +# Locate LuaJIT library +# This module defines +# LUAJIT_FOUND, if false, do not try to link to Lua +# LUA_LIBRARIES +# LUA_INCLUDE_DIR, where to find lua.h +# LUAJIT_VERSION_STRING, the version of Lua found (since CMake 2.8.8) + +## Copied from default CMake FindLua51.cmake + +find_path(LUA_INCLUDE_DIR luajit.h + HINTS + ENV LUA_DIR + PATH_SUFFIXES include/luajit-2.0 include + PATHS + ~/Library/Frameworks + /Library/Frameworks + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) + +find_library(LUA_LIBRARY + NAMES luajit-5.1 + HINTS + ENV LUA_DIR + PATH_SUFFIXES lib + PATHS + ~/Library/Frameworks + /Library/Frameworks + /sw + /opt/local + /opt/csw + /opt +) + +if(LUA_LIBRARY) + # include the math library for Unix + if(UNIX AND NOT APPLE) + find_library(LUA_MATH_LIBRARY m) + set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries") + # For Windows and Mac, don't need to explicitly include the math library + else() + set( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries") + endif() +endif() + +if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/luajit.h") + file(STRINGS "${LUA_INCLUDE_DIR}/luajit.h" luajit_version_str REGEX "^#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT .+\"") + + string(REGEX REPLACE "^#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT ([^\"]+)\".*" "\\1" LUAJIT_VERSION_STRING "${luajit_version_str}") + unset(luajit_version_str) +endif() + +include(FindPackageHandleStandardArgs) +# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if +# all listed variables are TRUE +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT + REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR + VERSION_VAR LUAJIT_VERSION_STRING) + +mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY) + diff --git a/3rdparty/lua-zlib/lua_zlib.c b/3rdparty/lua-zlib/lua_zlib.c new file mode 100644 index 00000000000..b619258c75f --- /dev/null +++ b/3rdparty/lua-zlib/lua_zlib.c @@ -0,0 +1,401 @@ +#include +#include +#include +#include +#include +#include + +/* + * ** compatibility with Lua 5.2 + * */ +#if (LUA_VERSION_NUM >= 502) +#undef luaL_register +#define luaL_register(L,n,f) \ + { if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); } + +#endif + +#if (LUA_VERSION_NUM >= 503) +#undef luaL_optint +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L,(n),(d))) +#endif + +#define DEF_MEM_LEVEL 8 + +typedef uLong (*checksum_t) (uLong crc, const Bytef *buf, uInt len); +typedef uLong (*checksum_combine_t)(uLong crc1, uLong crc2, z_off_t len2); + + +static int lz_deflate(lua_State *L); +static int lz_deflate_delete(lua_State *L); +static int lz_inflate_delete(lua_State *L); +static int lz_inflate(lua_State *L); +static int lz_checksum(lua_State *L); +static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine); +static int lz_adler32(lua_State *L); +static int lz_crc32(lua_State *L); + +static int lz_version(lua_State *L) { + const char* version = zlibVersion(); + int count = strlen(version) + 1; + char* cur = (char*)memcpy(lua_newuserdata(L, count), + version, count); + + count = 0; + while ( *cur ) { + char* begin = cur; + /* Find all digits: */ + while ( isdigit(*cur) ) cur++; + if ( begin != cur ) { + int is_end = *cur == '\0'; + *cur = '\0'; + lua_pushnumber(L, atoi(begin)); + count++; + if ( is_end ) break; + cur++; + } + while ( *cur && ! isdigit(*cur) ) cur++; + } + + return count; +} + +static int lz_assert(lua_State *L, int result, const z_stream* stream, const char* file, int line) { + /* Both of these are "normal" return codes: */ + if ( result == Z_OK || result == Z_STREAM_END ) return result; + switch ( result ) { + case Z_NEED_DICT: + lua_pushfstring(L, "RequiresDictionary: input stream requires a dictionary to be deflated (%s) at %s line %d", + stream->msg, file, line); + break; + case Z_STREAM_ERROR: + lua_pushfstring(L, "InternalError: inconsistent internal zlib stream (%s) at %s line %d", + stream->msg, file, line); + break; + case Z_DATA_ERROR: + lua_pushfstring(L, "InvalidInput: input string does not conform to zlib format or checksum failed at %s line %d", + file, line); + break; + case Z_MEM_ERROR: + lua_pushfstring(L, "OutOfMemory: not enough memory (%s) at %s line %d", + stream->msg, file, line); + break; + case Z_BUF_ERROR: + lua_pushfstring(L, "InternalError: no progress possible (%s) at %s line %d", + stream->msg, file, line); + break; + case Z_VERSION_ERROR: + lua_pushfstring(L, "IncompatibleLibrary: built with version %s, but dynamically linked with version %s (%s) at %s line %d", + ZLIB_VERSION, zlibVersion(), stream->msg, file, line); + break; + default: + lua_pushfstring(L, "ZLibError: unknown code %d (%s) at %s line %d", + result, stream->msg, file, line); + } + lua_error(L); + return result; +} + +/** + * @upvalue z_stream - Memory for the z_stream. + * @upvalue remainder - Any remainder from the last deflate call. + * + * @param string - "print" to deflate stream. + * @param int - flush output buffer? Z_SYNC_FLUSH, Z_FULL_FLUSH, or Z_FINISH. + * + * if no params, terminates the stream (as if we got empty string and Z_FINISH). + */ +static int lz_filter_impl(lua_State *L, int (*filter)(z_streamp, int), int (*end)(z_streamp), const char* name) { + int flush = Z_NO_FLUSH, result; + z_stream* stream; + luaL_Buffer buff; + size_t avail_in; + + if ( filter == deflate ) { + const char *const opts[] = { "none", "sync", "full", "finish", NULL }; + flush = luaL_checkoption(L, 2, opts[0], opts); + if ( flush ) flush++; + /* Z_NO_FLUSH(0) Z_SYNC_FLUSH(2), Z_FULL_FLUSH(3), Z_FINISH (4) */ + + /* No arguments or nil, we are terminating the stream: */ + if ( lua_gettop(L) == 0 || lua_isnil(L, 1) ) { + flush = Z_FINISH; + } + } + + stream = (z_stream*)lua_touserdata(L, lua_upvalueindex(1)); + if ( stream == NULL ) { + if ( lua_gettop(L) >= 1 && lua_isstring(L, 1) ) { + lua_pushfstring(L, "IllegalState: calling %s function when stream was previously closed", name); + lua_error(L); + } + lua_pushstring(L, ""); + lua_pushboolean(L, 1); + return 2; /* Ignore duplicate calls to "close". */ + } + + luaL_buffinit(L, &buff); + + if ( lua_gettop(L) > 1 ) lua_pushvalue(L, 1); + + if ( lua_isstring(L, lua_upvalueindex(2)) ) { + lua_pushvalue(L, lua_upvalueindex(2)); + if ( lua_gettop(L) > 1 && lua_isstring(L, -2) ) { + lua_concat(L, 2); + } + } + + /* Do the actual deflate'ing: */ + if (lua_gettop(L) > 0) { + stream->next_in = (unsigned char*)lua_tolstring(L, -1, &avail_in); + } else { + stream->next_in = NULL; + avail_in = 0; + } + stream->avail_in = avail_in; + + if ( ! stream->avail_in && ! flush ) { + /* Passed empty string, make it a noop instead of erroring out. */ + lua_pushstring(L, ""); + lua_pushboolean(L, 0); + lua_pushinteger(L, stream->total_in); + lua_pushinteger(L, stream->total_out); + return 4; + } + + do { + stream->next_out = (unsigned char*)luaL_prepbuffer(&buff); + stream->avail_out = LUAL_BUFFERSIZE; + result = filter(stream, flush); + if ( Z_BUF_ERROR != result ) { + /* Ignore Z_BUF_ERROR since that just indicates that we + * need a larger buffer in order to proceed. Thanks to + * Tobias Markmann for finding this bug! + */ + lz_assert(L, result, stream, __FILE__, __LINE__); + } + luaL_addsize(&buff, LUAL_BUFFERSIZE - stream->avail_out); + } while ( stream->avail_out == 0 ); + + /* Need to do this before we alter the stack: */ + luaL_pushresult(&buff); + + /* Save remainder in lua_upvalueindex(2): */ + if ( NULL != stream->next_in ) { + lua_pushlstring(L, (char*)stream->next_in, stream->avail_in); + lua_replace(L, lua_upvalueindex(2)); + } + + /* "close" the stream/remove finalizer: */ + if ( result == Z_STREAM_END ) { + /* Clear-out the metatable so end is not called twice: */ + lua_pushnil(L); + lua_setmetatable(L, lua_upvalueindex(1)); + + /* nil the upvalue: */ + lua_pushnil(L); + lua_replace(L, lua_upvalueindex(1)); + + /* Close the stream: */ + lz_assert(L, end(stream), stream, __FILE__, __LINE__); + + lua_pushboolean(L, 1); + } else { + lua_pushboolean(L, 0); + } + lua_pushinteger(L, stream->total_in); + lua_pushinteger(L, stream->total_out); + return 4; +} + +static void lz_create_deflate_mt(lua_State *L) { + luaL_newmetatable(L, "lz.deflate.meta"); /* {} */ + + lua_pushcfunction(L, lz_deflate_delete); + lua_setfield(L, -2, "__gc"); + + lua_pop(L, 1); /* */ +} + +static int lz_deflate_new(lua_State *L) { + int level = luaL_optint(L, 1, Z_DEFAULT_COMPRESSION); + int window_size = luaL_optint(L, 2, MAX_WBITS); + + /* Allocate the stream: */ + z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream)); + + stream->zalloc = Z_NULL; + stream->zfree = Z_NULL; + + int result = deflateInit2(stream, level, Z_DEFLATED, window_size, + DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + + lz_assert(L, result, stream, __FILE__, __LINE__); + + /* Don't allow destructor to execute unless deflateInit2 was successful: */ + luaL_getmetatable(L, "lz.deflate.meta"); + lua_setmetatable(L, -2); + + lua_pushnil(L); + lua_pushcclosure(L, lz_deflate, 2); + return 1; +} + +static int lz_deflate(lua_State *L) { + return lz_filter_impl(L, deflate, deflateEnd, "deflate"); +} + +static int lz_deflate_delete(lua_State *L) { + z_stream* stream = (z_stream*)lua_touserdata(L, 1); + + /* Ignore errors. */ + deflateEnd(stream); + + return 0; +} + + +static void lz_create_inflate_mt(lua_State *L) { + luaL_newmetatable(L, "lz.inflate.meta"); /* {} */ + + lua_pushcfunction(L, lz_inflate_delete); + lua_setfield(L, -2, "__gc"); + + lua_pop(L, 1); /* */ +} + +static int lz_inflate_new(lua_State *L) { + /* Allocate the stream */ + z_stream* stream = (z_stream*)lua_newuserdata(L, sizeof(z_stream)); + + /* By default, we will do gzip header detection w/ max window size */ + int window_size = lua_isnumber(L, 1) ? lua_tointeger(L, 1) : MAX_WBITS + 32; + + stream->zalloc = Z_NULL; + stream->zfree = Z_NULL; + stream->next_in = Z_NULL; + stream->avail_in = 0; + + lz_assert(L, inflateInit2(stream, window_size), stream, __FILE__, __LINE__); + + /* Don't allow destructor to execute unless deflateInit was successful: */ + luaL_getmetatable(L, "lz.inflate.meta"); + lua_setmetatable(L, -2); + + lua_pushnil(L); + lua_pushcclosure(L, lz_inflate, 2); + return 1; +} + +static int lz_inflate(lua_State *L) { + return lz_filter_impl(L, inflate, inflateEnd, "inflate"); +} + +static int lz_inflate_delete(lua_State *L) { + z_stream* stream = (z_stream*)lua_touserdata(L, 1); + + /* Ignore errors: */ + inflateEnd(stream); + + return 0; +} + +static int lz_checksum(lua_State *L) { + if ( lua_gettop(L) <= 0 ) { + lua_pushvalue(L, lua_upvalueindex(3)); + lua_pushvalue(L, lua_upvalueindex(4)); + } else if ( lua_isfunction(L, 1) ) { + checksum_combine_t combine = (checksum_combine_t) + lua_touserdata(L, lua_upvalueindex(2)); + + lua_pushvalue(L, 1); + lua_call(L, 0, 2); + if ( ! lua_isnumber(L, -2) || ! lua_isnumber(L, -1) ) { + luaL_argerror(L, 1, "expected function to return two numbers"); + } + + /* Calculate and replace the checksum */ + lua_pushnumber(L, + combine(lua_tonumber(L, lua_upvalueindex(3)), + lua_tonumber(L, -2), + lua_tonumber(L, -1))); + lua_pushvalue(L, -1); + lua_replace(L, lua_upvalueindex(3)); + + /* Calculate and replace the length */ + lua_pushnumber(L, + lua_tonumber(L, lua_upvalueindex(4)) + lua_tonumber(L, -2)); + lua_pushvalue(L, -1); + lua_replace(L, lua_upvalueindex(4)); + } else { + const Bytef* str; + size_t len; + + checksum_t checksum = (checksum_t) + lua_touserdata(L, lua_upvalueindex(1)); + str = (const Bytef*)luaL_checklstring(L, 1, &len); + + /* Calculate and replace the checksum */ + lua_pushnumber(L, + checksum(lua_tonumber(L, lua_upvalueindex(3)), + str, + len)); + lua_pushvalue(L, -1); + lua_replace(L, lua_upvalueindex(3)); + + /* Calculate and replace the length */ + lua_pushnumber(L, + lua_tonumber(L, lua_upvalueindex(4)) + len); + lua_pushvalue(L, -1); + lua_replace(L, lua_upvalueindex(4)); + } + return 2; +} + +static int lz_checksum_new(lua_State *L, checksum_t checksum, checksum_combine_t combine) { + lua_pushlightuserdata(L, checksum); + lua_pushlightuserdata(L, combine); + lua_pushnumber(L, checksum(0L, Z_NULL, 0)); + lua_pushnumber(L, 0); + lua_pushcclosure(L, lz_checksum, 4); + return 1; +} + +static int lz_adler32(lua_State *L) { + return lz_checksum_new(L, adler32, adler32_combine); +} + +static int lz_crc32(lua_State *L) { + return lz_checksum_new(L, crc32, crc32_combine); +} + +static const luaL_Reg zlib_functions[] = { + { "deflate", lz_deflate_new }, + { "inflate", lz_inflate_new }, + { "adler32", lz_adler32 }, + { "crc32", lz_crc32 }, + { "version", lz_version }, + { NULL, NULL } +}; + +#define SETLITERAL(n,v) (lua_pushliteral(L, n), lua_pushliteral(L, v), lua_settable(L, -3)) +#define SETINT(n,v) (lua_pushliteral(L, n), lua_pushinteger(L, v), lua_settable(L, -3)) + +LUALIB_API int luaopen_zlib(lua_State * const L) { + lz_create_deflate_mt(L); + lz_create_inflate_mt(L); + + luaL_register(L, "zlib", zlib_functions); + + SETINT("BEST_SPEED", Z_BEST_SPEED); + SETINT("BEST_COMPRESSION", Z_BEST_COMPRESSION); + + SETLITERAL("_COPYRIGHT", "Copyright (c) 2009-2010 Brian Maher"); + SETLITERAL("_DESCRIPTION", "Yet another binding to the zlib library"); + SETLITERAL("_VERSION", "lua-zlib $Id$ $Format:%d$"); + + /* Expose this to lua so we can do a test: */ + SETINT("_TEST_BUFSIZ", LUAL_BUFFERSIZE); + + return 1; +} diff --git a/3rdparty/lua-zlib/rockspec b/3rdparty/lua-zlib/rockspec new file mode 100644 index 00000000000..d248bc099ed --- /dev/null +++ b/3rdparty/lua-zlib/rockspec @@ -0,0 +1,35 @@ +package = "lua-zlib" +version = "0.3-1" +source = { + url = "git://github.com/brimworks/lua-zlib.git", + tag = "v0.4", +} +description = { + summary = "Simple streaming interface to zlib for Lua.", + detailed = [[ + Simple streaming interface to zlib for Lua. + Consists of two functions: inflate and deflate. + Both functions return "stream functions" (takes a buffer of input and returns a buffer of output). + This project is hosted on github. + ]], + homepage = "https://github.com/brimworks/lua-zlib", + license = "MIT" +} +dependencies = { + "lua >= 5.1, < 5.3" +} +external_dependencies = { + ZLIB = { + header = "zlib.h" + } +} + +build = { + type = "builtin", + modules = { + zlib = { + sources = { "lua_zlib.c" }; + libraries = { "z" }, + }; + } +} diff --git a/3rdparty/lua-zlib/tap.lua b/3rdparty/lua-zlib/tap.lua new file mode 100644 index 00000000000..05266a9c997 --- /dev/null +++ b/3rdparty/lua-zlib/tap.lua @@ -0,0 +1,24 @@ +local tap_module = {} + +local os = require("os") + +local counter = 1 +local failed = false + +function tap_module.ok(assert_true, desc) + local msg = ( assert_true and "ok " or "not ok " ) .. counter + if ( not assert_true ) then + failed = true + end + if ( desc ) then + msg = msg .. " - " .. desc + end + print(msg) + counter = counter + 1 +end + +function tap_module.exit() + os.exit(failed and 1 or 0) +end + +return tap_module diff --git a/3rdparty/lua-zlib/test.lua b/3rdparty/lua-zlib/test.lua new file mode 100644 index 00000000000..d64e1835506 --- /dev/null +++ b/3rdparty/lua-zlib/test.lua @@ -0,0 +1,198 @@ +print "1..9" + +local src_dir, build_dir = ... +package.path = (src_dir or "./") .. "?.lua;" .. package.path +package.cpath = (build_dir or "./") .. "?.so;" .. package.cpath + +local tap = require("tap") +local lz = require("zlib") +local ok = tap.ok +local table = require("table") +local io = require("io") + +function main() + test_stats() + test_buff_err() + test_small_inputs() + test_basic() + test_large() + test_no_input() + test_invalid_input() + test_streaming() + test_illegal_state() + test_checksum() + test_version() + test_tom_macwright() + test_amnon_david() +end + +function test_tom_macwright() + local deflated = + assert(io.open(src_dir.. "/tom_macwright.gz")):read("*a") + + local inflated = lz.inflate()(deflated) + + local expected_inflated = + assert(io.open(src_dir.. "/tom_macwright.out")):read("*a") + + ok(expected_inflated == inflated, "Tom MacWright Test") +end + +function test_amnon_david() + local body = assert(io.open(src_dir.."/amnon_david.gz")):read("*a") + + local inflate = lz.inflate() + local inflated, eof, bytes_in, bytes_out = inflate(body) + + local deflate = lz.deflate() + local deflated, eof, bytes_in, bytes_out = deflate(inflated, "full") +end + +function test_stats() + local string = ("one"):rep(20) + local deflated, eof, bin, bout = lz.deflate()(string, 'finish') + ok(eof == true, "eof is true (" .. tostring(eof) .. ")"); + ok(bin > bout, "bytes in is greater than bytes out?") + ok(#deflated == bout, "bytes out is the same size as deflated string length") + ok(#string == bin, "bytes in is the same size as the input string length") +end + +-- Thanks to Tobias Markmann for the bug report! We are trying to +-- force inflate() to return a Z_BUF_ERROR (which should be recovered +-- from). For some reason this only happens when the input is exactly +-- LUAL_BUFFERSIZE (at least on my machine). +function test_buff_err() + local text = ("X"):rep(lz._TEST_BUFSIZ); + + local deflated = lz.deflate()(text, 'finish') + + for i=1,#deflated do + lz.inflate()(deflated:sub(1,i)) + end +end + +function test_small_inputs() + local text = ("X"):rep(lz._TEST_BUFSIZ); + + local deflated = lz.deflate()(text, 'finish') + + local inflated = {} + local inflator = lz.inflate() + for i=1,#deflated do + local part = inflator(deflated:sub(i,i)) + table.insert(inflated, part) + end + inflated = table.concat(inflated) + ok(inflated == text, "Expected " .. #text .. " Xs got " .. #inflated) +end + +function test_basic() + local test_string = "abcdefghijklmnopqrstuv" + + ok(lz.inflate()(lz.deflate()(), "finish") == "") + + -- Input to deflate is same as output to inflate: + local deflated = lz.deflate()(test_string, "finish") + local inflated = lz.inflate()(deflated, "finish") + + ok(test_string == inflated, "'" .. tostring(test_string) .. "' == '" .. tostring(inflated) .. "'") +end + +function test_large() + -- Try a larger string: + local numbers = "" + for i=1, 100 do numbers = numbers .. string.format("%3d", i) end + local numbers_table = {} + for i=1, 10000 do numbers_table[i] = numbers end + local test_string = table.concat(numbers_table, "\n") + + local deflated = lz.deflate()(test_string, "finish") + local inflated = lz.inflate()(deflated, "finish") + ok(test_string == inflated, "large string") +end + +function test_no_input() + local stream = lz.deflate() + local deflated = stream("") + deflated = deflated .. stream("") + deflated = deflated .. stream(nil, "finish") + ok("" == lz.inflate()(deflated, "finish"), "empty string") +end + +function test_invalid_input() + local stream = lz.inflate() + local isok, err = pcall( + function() + stream("bad input") + end) + ok(not isok) + ok(string.find(err, "^InvalidInput"), + string.format("InvalidInput error (%s)", err)) +end + +function test_streaming() + local shrink = lz.deflate(lz.BEST_COMPRESSION) + local enlarge = lz.inflate() + local expected = {} + local got = {} + local chant = "Isn't He great, isn't He wonderful?\n" + for i=1,100 do + if ( i == 100 ) then + chant = nil + print "EOF round" + end + local shrink_part, shrink_eof = shrink(chant) + local enlarge_part, enlarge_eof = enlarge(shrink_part) + if ( i == 100 ) then + if not shrink_eof then error("expected eof after shrinking flush") end + if not enlarge_eof then error("expected eof after enlarging") end + else + if shrink_eof then error("unexpected eof after shrinking") end + if enlarge_eof then error("unexpected eof after enlarging") end + end + if enlarge_part then table.insert(got, enlarge_part) end + if chant then table.insert(expected, chant) end + end + ok(table.concat(got) == table.concat(expected), "streaming works") +end + +function test_illegal_state() + local stream = lz.deflate() + stream("abc") + stream() -- eof/close + + local _, emsg = pcall( + function() + stream("printing on 'closed' handle") + end) + ok(string.find(emsg, "^IllegalState"), + string.format("IllegalState error (%s)", emsg)) + + local enlarge = lz.inflate() +end + +function test_checksum() + for _, factory in pairs{lz.crc32, lz.adler32} do + local csum = factory()("one two") + + -- Multiple calls: + local compute = factory() + compute("one") + assert(csum == compute(" two")) + + -- Multiple compute_checksums joined: + local compute1, compute2 = factory(), factory() + compute1("one") + compute2(" two") + assert(csum == compute1(compute2)) + end +end + +function test_version() + local major, minor, patch = lz.version() + ok(1 == major, "major version 1 == " .. major); + ok(type(minor) == "number", "minor version is number (" .. minor .. ")") + ok(type(patch) == "number", "patch version is number (" .. patch .. ")") +end + +main() diff --git a/3rdparty/lua-zlib/tom_macwright.gz b/3rdparty/lua-zlib/tom_macwright.gz new file mode 100644 index 00000000000..bb9060b2535 --- /dev/null +++ b/3rdparty/lua-zlib/tom_macwright.gz @@ -0,0 +1,4 @@ +x[ +0E*fIg(NL#m[\scy*=&N:'I1Yi[pzU +R?0JzQꁭ%Iw +cǩ)˘lbgФ!ሌv򧮮K EF}H \ No newline at end of file diff --git a/3rdparty/lua-zlib/tom_macwright.out b/3rdparty/lua-zlib/tom_macwright.out new file mode 100644 index 0000000000000000000000000000000000000000..ca88bcb6c2d1eaeff50828c541df0cd97247cd0a GIT binary patch literal 245 zcmbV`TMEK35JmmYDrN(gNoVpXi0A_R6Z}q-=>tq7ZN%+cT!Md>1BY{C$$75O5+CX+ z0zD@3PK@t^A37(Ng-Mt(S!r7v*l>&%qk4r^mI{uI^W?nkQa>u1kWw Lz6q2?wnlvcn#xGo literal 0 HcmV?d00001 diff --git a/3rdparty/lua-zlib/zlib.def b/3rdparty/lua-zlib/zlib.def new file mode 100644 index 00000000000..d6c5a916b64 --- /dev/null +++ b/3rdparty/lua-zlib/zlib.def @@ -0,0 +1,2 @@ +EXPORTS +luaopen_zlib diff --git a/3rdparty/luafilesystem/.travis.yml b/3rdparty/luafilesystem/.travis.yml new file mode 100644 index 00000000000..67b5812e09e --- /dev/null +++ b/3rdparty/luafilesystem/.travis.yml @@ -0,0 +1,33 @@ +language: c + +env: + global: + - LUAROCKS=2.2.0-rc1 + matrix: + - LUA=lua5.1 + - LUA=lua5.2 + - LUA=lua5.3 + - LUA=luajit + +branches: + only: + - master + +before_install: + - bash .travis/setup_lua.sh + - sudo pip install cpp-coveralls + +install: + - sudo luarocks make rockspecs/luafilesystem-cvs-3.rockspec CFLAGS="-O2 -fPIC -ftest-coverage -fprofile-arcs" LIBFLAG="-shared --coverage" + +script: + - cd tests + - sudo lua test.lua + +after_success: + - coveralls -b .. -r .. -E usr + +notifications: + email: + on_success: change + on_failure: always diff --git a/3rdparty/luafilesystem/.travis/platform.sh b/3rdparty/luafilesystem/.travis/platform.sh new file mode 100644 index 00000000000..4a3af0d487e --- /dev/null +++ b/3rdparty/luafilesystem/.travis/platform.sh @@ -0,0 +1,15 @@ +if [ -z "$PLATFORM" ]; then + PLATFORM=$TRAVIS_OS_NAME; +fi + +if [ "$PLATFORM" == "osx" ]; then + PLATFORM="macosx"; +fi + +if [ -z "$PLATFORM" ]; then + if [ "$(uname)" == "Linux" ]; then + PLATFORM="linux"; + else + PLATFORM="macosx"; + fi; +fi diff --git a/3rdparty/luafilesystem/.travis/setup_lua.sh b/3rdparty/luafilesystem/.travis/setup_lua.sh new file mode 100644 index 00000000000..373e24d979b --- /dev/null +++ b/3rdparty/luafilesystem/.travis/setup_lua.sh @@ -0,0 +1,101 @@ +#! /bin/bash + +# A script for setting up environment for travis-ci testing. +# Sets up Lua and Luarocks. +# LUA must be "lua5.1", "lua5.2" or "luajit". +# luajit2.0 - master v2.0 +# luajit2.1 - master v2.1 + +LUAJIT_BASE="LuaJIT-2.0.3" + +source .travis/platform.sh + +LUAJIT="no" + +if [ "$PLATFORM" == "macosx" ]; then + if [ "$LUA" == "luajit" ]; then + LUAJIT="yes"; + fi + if [ "$LUA" == "luajit2.0" ]; then + LUAJIT="yes"; + fi + if [ "$LUA" == "luajit2.1" ]; then + LUAJIT="yes"; + fi; +elif [ "$(expr substr $LUA 1 6)" == "luajit" ]; then + LUAJIT="yes"; +fi + +if [ "$LUAJIT" == "yes" ]; then + + if [ "$LUA" == "luajit" ]; then + curl http://luajit.org/download/$LUAJIT_BASE.tar.gz | tar xz; + else + git clone http://luajit.org/git/luajit-2.0.git $LUAJIT_BASE; + fi + + cd $LUAJIT_BASE + + if [ "$LUA" == "luajit2.1" ]; then + git checkout v2.1; + fi + + make && sudo make install + + if [ "$LUA" == "luajit2.1" ]; then + sudo ln -s /usr/local/bin/luajit-2.1.0-alpha /usr/local/bin/luajit + sudo ln -s /usr/local/bin/luajit /usr/local/bin/lua; + else + sudo ln -s /usr/local/bin/luajit /usr/local/bin/lua; + fi; + +else + if [ "$LUA" == "lua5.1" ]; then + curl http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz + cd lua-5.1.5; + elif [ "$LUA" == "lua5.2" ]; then + curl http://www.lua.org/ftp/lua-5.2.3.tar.gz | tar xz + cd lua-5.2.3; + elif [ "$LUA" == "lua5.3" ]; then + curl http://www.lua.org/work/lua-5.3.0-beta.tar.gz | tar xz + cd lua-5.3.0-beta; + fi + sudo make $PLATFORM install; +fi + +cd $TRAVIS_BUILD_DIR; + +LUAROCKS_BASE=luarocks-$LUAROCKS + +# curl http://luarocks.org/releases/$LUAROCKS_BASE.tar.gz | tar xz + +git clone https://github.com/keplerproject/luarocks.git $LUAROCKS_BASE +cd $LUAROCKS_BASE + +git checkout v$LUAROCKS + +if [ "$LUA" == "luajit" ]; then + ./configure --lua-suffix=jit --with-lua-include=/usr/local/include/luajit-2.0; +elif [ "$LUA" == "luajit2.0" ]; then + ./configure --lua-suffix=jit --with-lua-include=/usr/local/include/luajit-2.0; +elif [ "$LUA" == "luajit2.1" ]; then + ./configure --lua-suffix=jit --with-lua-include=/usr/local/include/luajit-2.1; +else + ./configure; +fi + +make build && sudo make install + +cd $TRAVIS_BUILD_DIR + +rm -rf $LUAROCKS_BASE + +if [ "$LUAJIT" == "yes" ]; then + rm -rf $LUAJIT_BASE; +elif [ "$LUA" == "lua5.1" ]; then + rm -rf lua-5.1.5; +elif [ "$LUA" == "lua5.2" ]; then + rm -rf lua-5.2.3; +elif [ "$LUA" == "lua5.3" ]; then + rm -rf lua-5.3.0-beta; +fi diff --git a/3rdparty/luafilesystem/LICENSE b/3rdparty/luafilesystem/LICENSE new file mode 100644 index 00000000000..8475345a64e --- /dev/null +++ b/3rdparty/luafilesystem/LICENSE @@ -0,0 +1,21 @@ +Copyright © 2003-2014 Kepler Project. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/3rdparty/luafilesystem/Makefile b/3rdparty/luafilesystem/Makefile new file mode 100644 index 00000000000..b834a4d51ab --- /dev/null +++ b/3rdparty/luafilesystem/Makefile @@ -0,0 +1,25 @@ +# $Id: Makefile,v 1.36 2009/09/21 17:02:44 mascarenhas Exp $ + +T= lfs + +CONFIG= ./config + +include $(CONFIG) + +SRCS= src/$T.c +OBJS= src/$T.o + +lib: src/lfs.so + +src/lfs.so: $(OBJS) + MACOSX_DEPLOYMENT_TARGET="10.3"; export MACOSX_DEPLOYMENT_TARGET; $(CC) $(CFLAGS) $(LIB_OPTION) -o src/lfs.so $(OBJS) + +test: lib + LUA_CPATH=./src/?.so lua tests/test.lua + +install: + mkdir -p $(LUA_LIBDIR) + cp src/lfs.so $(LUA_LIBDIR) + +clean: + rm -f src/lfs.so $(OBJS) diff --git a/3rdparty/luafilesystem/Makefile.win b/3rdparty/luafilesystem/Makefile.win new file mode 100644 index 00000000000..65cab812408 --- /dev/null +++ b/3rdparty/luafilesystem/Makefile.win @@ -0,0 +1,25 @@ +# $Id: Makefile.win,v 1.11 2008/05/07 19:06:37 carregal Exp $ + +T= lfs + +include config.win + +SRCS= src\$T.c +OBJS= src\$T.obj + +lib: src\lfs.dll + +.c.obj: + $(CC) /c /Fo$@ $(CFLAGS) $< + +src\lfs.dll: $(OBJS) + link /dll /def:src\$T.def /out:src\lfs.dll $(OBJS) "$(LUA_LIB)" + IF EXIST src\lfs.dll.manifest mt -manifest src\lfs.dll.manifest -outputresource:src\lfs.dll;2 + +install: src\lfs.dll + IF NOT EXIST "$(LUA_LIBDIR)" mkdir "$(LUA_LIBDIR)" + copy src\lfs.dll "$(LUA_LIBDIR)" + +clean: + del src\lfs.dll $(OBJS) src\$T.lib src\$T.exp + IF EXIST src\lfs.dll.manifest del src\lfs.dll.manifest \ No newline at end of file diff --git a/3rdparty/luafilesystem/README b/3rdparty/luafilesystem/README new file mode 100644 index 00000000000..9d37a4e2513 --- /dev/null +++ b/3rdparty/luafilesystem/README @@ -0,0 +1,23 @@ +LuaFileSystem - File System Library for Lua +Copyright 2003-2015 Kepler Project + +http://keplerproject.github.io/luafilesystem + +Description +----------- +LuaFileSystem is a Lua library developed to complement the set of functions +related to file systems offered by the standard Lua distribution. + +LuaFileSystem offers a portable way to access the underlying directory structure and file attributes. +LuaFileSystem is free software and uses the same license as Lua 5.1 + +LuaRocks Installation +--------------------- + +``` +luarocks install luafilesystem +``` + +Documentation +------------- +Please check the documentation at doc/us/ for more information. diff --git a/3rdparty/luafilesystem/config b/3rdparty/luafilesystem/config new file mode 100644 index 00000000000..cfd4c6a6d3e --- /dev/null +++ b/3rdparty/luafilesystem/config @@ -0,0 +1,24 @@ +# Installation directories + +# Default installation prefix +PREFIX=/usr/local + +# System's libraries directory (where binary libraries are installed) +LUA_LIBDIR= $(PREFIX)/lib/lua/5.1 + +# Lua includes directory +LUA_INC= $(PREFIX)/include + +# OS dependent +LIB_OPTION= -shared #for Linux +#LIB_OPTION= -bundle -undefined dynamic_lookup #for MacOS X + +LIBNAME= $T.so.$V + +# Compilation directives +WARN= -O2 -Wall -fPIC -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings -pedantic +INCS= -I$(LUA_INC) +CFLAGS= $(WARN) $(INCS) +CC= gcc + +# $Id: config,v 1.21 2007/10/27 22:42:32 carregal Exp $ diff --git a/3rdparty/luafilesystem/config.win b/3rdparty/luafilesystem/config.win new file mode 100644 index 00000000000..50e81f64206 --- /dev/null +++ b/3rdparty/luafilesystem/config.win @@ -0,0 +1,19 @@ +# Installation directories +# System's libraries directory (where binary libraries are installed) +LUA_LIBDIR= "c:\lua5.1" + +# Lua includes directory +LUA_INC= "c:\lua5.1\include" + +# Lua library +LUA_LIB= "c:\lua5.1\lua5.1.lib" + +LIBNAME= $T.dll + +# Compilation directives +WARN= /O2 +INCS= /I$(LUA_INC) +CFLAGS= /MD $(WARN) $(INCS) +CC= cl + +# $Id: config.win,v 1.7 2008/03/25 17:39:29 mascarenhas Exp $ diff --git a/3rdparty/luafilesystem/doc/us/doc.css b/3rdparty/luafilesystem/doc/us/doc.css new file mode 100644 index 00000000000..e816a7e2c63 --- /dev/null +++ b/3rdparty/luafilesystem/doc/us/doc.css @@ -0,0 +1,212 @@ +body { + margin-left: 1em; + margin-right: 1em; + font-family: arial, helvetica, geneva, sans-serif; + background-color:#ffffff; margin:0px; +} + +code { + font-family: "Andale Mono", monospace; +} + +tt { + font-family: "Andale Mono", monospace; +} + +body, td, th { font-size: 11pt; } + +h1, h2, h3, h4 { margin-left: 0em; } + +textarea, pre, tt { font-size:10pt; } +body, td, th { color:#000000; } +small { font-size:0.85em; } +h1 { font-size:1.5em; } +h2 { font-size:1.25em; } +h3 { font-size:1.15em; } +h4 { font-size:1.06em; } + +a:link { font-weight:bold; color: #004080; text-decoration: none; } +a:visited { font-weight:bold; color: #006699; text-decoration: none; } +a:link:hover { text-decoration:underline; } +hr { color:#cccccc } +img { border-width: 0px; } + +h3 { padding-top: 1em; } + +p { margin-left: 1em; } + +p.name { + font-family: "Andale Mono", monospace; + padding-top: 1em; + margin-left: 0em; +} + +blockquote { margin-left: 3em; } + +.example { + background-color: rgb(245, 245, 245); + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-color: silver; + border-right-color: silver; + border-bottom-color: silver; + border-left-color: silver; + padding: 1em; + margin-left: 1em; + margin-right: 1em; + font-family: "Andale Mono", monospace; + font-size: smaller; +} + +hr { + margin-left: 0em; + background: #00007f; + border: 0px; + height: 1px; +} + +ul { list-style-type: disc; } + +table.index { border: 1px #00007f; } +table.index td { text-align: left; vertical-align: top; } +table.index ul { padding-top: 0em; margin-top: 0em; } + +table { + border: 1px solid black; + border-collapse: collapse; + margin-left: auto; + margin-right: auto; +} + +th { + border: 1px solid black; + padding: 0.5em; +} + +td { + border: 1px solid black; + padding: 0.5em; +} +div.header, div.footer { margin-left: 0em; } + +#container { + margin-left: 1em; + margin-right: 1em; + background-color: #f0f0f0; +} + +#product { + text-align: center; + border-bottom: 1px solid #cccccc; + background-color: #ffffff; +} + +#product big { + font-size: 2em; +} + +#product_logo { +} + +#product_name { +} + +#product_description { +} + +#main { + background-color: #f0f0f0; + border-left: 2px solid #cccccc; +} + +#navigation { + float: left; + width: 12em; + margin: 0; + vertical-align: top; + background-color: #f0f0f0; + overflow:visible; +} + +#navigation h1 { + background-color:#e7e7e7; + font-size:1.1em; + color:#000000; + text-align:left; + margin:0px; + padding:0.2em; + border-top:1px solid #dddddd; + border-bottom:1px solid #dddddd; +} + +#navigation ul { + font-size:1em; + list-style-type: none; + padding: 0; + margin: 1px; +} + +#navigation li { + text-indent: -1em; + margin: 0em 0em 0em 0.5em; + display: block; + padding: 3px 0px 0px 12px; +} + +#navigation li li a { + padding: 0px 3px 0px -1em; +} + +#content { + margin-left: 12em; + padding: 1em; + border-left: 2px solid #cccccc; + border-right: 2px solid #cccccc; + background-color: #ffffff; +} + +#about { + clear: both; + margin: 0; + padding: 5px; + border-top: 2px solid #cccccc; + background-color: #ffffff; +} + +@media print { + body { + font: 10pt "Times New Roman", "TimeNR", Times, serif; + } + a { + font-weight:bold; color: #004080; text-decoration: underline; + } + #main { + background-color: #ffffff; border-left: 0px; + } + #container { + margin-left: 2%; margin-right: 2%; background-color: #ffffff; + } + #content { + margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; + } + #navigation { + display: none; + } + #product_logo { + display: none; + } + #about img { + display: none; + } + .example { + font-family: "Andale Mono", monospace; + font-size: 8pt; + page-break-inside: avoid; + } +} diff --git a/3rdparty/luafilesystem/doc/us/examples.html b/3rdparty/luafilesystem/doc/us/examples.html new file mode 100644 index 00000000000..2c1644cb8a0 --- /dev/null +++ b/3rdparty/luafilesystem/doc/us/examples.html @@ -0,0 +1,103 @@ + + + + LuaFileSystem + + + + + + +
+ +
+ +
LuaFileSystem
+
File System Library for the Lua Programming Language
+
+ +
+ + + +
+ +

Examples

+ +

Directory iterator

+ +

The following example iterates over a directory and recursively lists the +attributes for each file inside it.

+ +
+local lfs = require"lfs"
+
+function attrdir (path)
+    for file in lfs.dir(path) do
+        if file ~= "." and file ~= ".." then
+            local f = path..'/'..file
+            print ("\t "..f)
+            local attr = lfs.attributes (f)
+            assert (type(attr) == "table")
+            if attr.mode == "directory" then
+                attrdir (f)
+            else
+                for name, value in pairs(attr) do
+                    print (name, value)
+                end
+            end
+        end
+    end
+end
+
+attrdir (".")
+
+ +
+ +
+ +
+

Valid XHTML 1.0!

+

$Id: examples.html,v 1.8 2007/12/14 15:28:04 carregal Exp $

+
+ +
+ + + diff --git a/3rdparty/luafilesystem/doc/us/index.html b/3rdparty/luafilesystem/doc/us/index.html new file mode 100644 index 00000000000..2bb7f5d2cbb --- /dev/null +++ b/3rdparty/luafilesystem/doc/us/index.html @@ -0,0 +1,218 @@ + + + + LuaFileSystem + + + + + + +
+ +
+ +
LuaFileSystem
+
File System Library for the Lua Programming Language
+
+ +
+ + + +
+ +

Overview

+ +

LuaFileSystem is a Lua library +developed to complement the set of functions related to file +systems offered by the standard Lua distribution.

+ +

LuaFileSystem offers a portable way to access +the underlying directory structure and file attributes.

+ +

LuaFileSystem is free software and uses the same +license as Lua 5.1.

+ +

Status

+ +

Current version is 1.6.3. It works with Lua 5.1, 5.2 and 5.3.

+ +

Download

+ +

LuaFileSystem source can be downloaded from its +Github +page.

+ +

History

+ +
+
Version 1.6.3 [15/Jan/2015]
+
    +
  • Lua 5.3 support.
  • +
  • Assorted bugfixes.
  • +
+ +
Version 1.6.2 [??/Oct/2012]
+
    +
  • Full Lua 5.2 compatibility (with Lua 5.1 fallbacks)
  • +
+ +
Version 1.6.1 [01/Oct/2012]
+
    +
  • fix build for Lua 5.2
  • +
+ +
Version 1.6.0 [26/Sep/2012]
+
    +
  • getcwd fix for Android
  • +
  • support for Lua 5.2
  • +
  • add lfs.link
  • +
  • other bug fixes
  • +
+ +
Version 1.5.0 [20/Oct/2009]
+
    +
  • Added explicit next and close methods to second return value of lfs.dir +(the directory object), for explicit iteration or explicit closing.
  • +
  • Added directory locking via lfs.lock_dir function (see the manual).
  • +
+
Version 1.4.2 [03/Feb/2009]
+
+
    +
  • fixed bug [#13198] + lfs.attributes(filename, 'size') overflow on files > 2 Gb again (bug report and patch by KUBO Takehiro).
  • +
  • fixed bug [#39794] + Compile error on Solaris 10 (bug report and patch by Aaron B).
  • +
  • fixed compilation problems with Borland C.
  • +
+
+ +
Version 1.4.1 [07/May/2008]
+
+
    +
  • documentation review
  • +
  • fixed Windows compilation issues
  • +
  • fixed bug in the Windows tests (patch by Shmuel Zeigerman)
  • +
  • fixed bug [#2185] + lfs.attributes(filename, 'size') overflow on files > 2 Gb +
  • +
+
+ +
Version 1.4.0 [13/Feb/2008]
+
+
    +
  • added function + lfs.setmode + (works only in Windows systems).
  • +
  • lfs.attributes + raises an error if attribute does not exist
  • +
+
+ +
Version 1.3.0 [26/Oct/2007]
+
+ +
+ +
Version 1.2.1 [08/May/2007]
+
+
    +
  • compatible only with Lua 5.1 (Lua 5.0 support was dropped)
  • +
+
+ +
Version 1.2 [15/Mar/2006]
+
+ +
+ +
Version 1.1 [30/May/2005]
+
+ +
+ +
Version 1.0 [21/Jan/2005]
+
+ +
Version 1.0 Beta [10/Nov/2004]
+
+
+ +

Credits

+ +

LuaFileSystem was designed by Roberto Ierusalimschy, +André Carregal and Tomás Guisasola as part of the +Kepler Project, +which holds its copyright. LuaFileSystem is currently maintained by Fábio Mascarenhas.

+ +

Contact us

+ +

For more information please +contact us. +Comments are welcome!

+ +

You can also reach other Kepler developers and users on the Kepler Project +mailing list.

+ +
+ +
+ +
+

Valid XHTML 1.0!

+

$Id: index.html,v 1.44 2009/02/04 21:21:33 carregal Exp $

+
+ +
+ + + diff --git a/3rdparty/luafilesystem/doc/us/license.html b/3rdparty/luafilesystem/doc/us/license.html new file mode 100644 index 00000000000..30033817229 --- /dev/null +++ b/3rdparty/luafilesystem/doc/us/license.html @@ -0,0 +1,122 @@ + + + + LuaFileSystem + + + + + + +
+ +
+ +
LuaFileSystem
+
File System Library for the Lua Programming Language
+
+ +
+ + + +
+ +

License

+ +

+LuaFileSystem is free software: it can be used for both academic +and commercial purposes at absolutely no cost. There are no +royalties or GNU-like "copyleft" restrictions. LuaFileSystem +qualifies as +Open Source +software. +Its licenses are compatible with +GPL. +LuaFileSystem is not in the public domain and the +Kepler Project +keep its copyright. +The legal details are below. +

+ +

The spirit of the license is that you are free to use +LuaFileSystem for any purpose at no cost without having to ask us. +The only requirement is that if you do use LuaFileSystem, then you +should give us credit by including the appropriate copyright notice +somewhere in your product or its documentation.

+ +

The LuaFileSystem library is designed and implemented by Roberto +Ierusalimschy, André Carregal and Tomás Guisasola. +The implementation is not derived from licensed software.

+ +
+

Copyright © 2003 Kepler Project.

+ +

Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions:

+ +

The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software.

+ +

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.

+ +
+ +
+ +
+

Valid XHTML 1.0!

+

$Id: license.html,v 1.13 2008/02/11 22:42:21 carregal Exp $

+
+ +
+ + + diff --git a/3rdparty/luafilesystem/doc/us/luafilesystem.png b/3rdparty/luafilesystem/doc/us/luafilesystem.png new file mode 100644 index 0000000000000000000000000000000000000000..e1dd8c65b5211ba5dd37f2e86da987fdd517d6c6 GIT binary patch literal 8535 zcmX|HWjvj4AHSLIW~Ld_c9`y-9%i~tP3P1xaWFl@Oig!B593TtcMUV$lhdB-|K_vubSnPD0R77LtEJjNJ~5XFio48jap#gTF&V>n*LS$ctAksetdeg{te{@40W^;3G{ zPW2ANlX?Zeu?QGYIT#p{1{rjMi9Qe^2CuKJ{B>}ipAUZ@Jv{w~sX6PvU;oeWkb3#7 z(np35FH|Z`)K%ve<$n8yJ(zt%6GiPQ9LN0qr4FPsNUsLXRGJL*_owYt@v()K+(Dtl zSZI0oFFBGkGc(FMd5BvEz(^9@c5b^?Yz zKK}|-Q!y|xpR;_><-i9UA)(Uo?Z!~L8f%h9k&lm$n6U6*h6rhVucjByS3Y$|2oE_l zG!z~lZen7>LSnx?UU0H8gj{jO!;oVk>F(}+QKDO*{dRl&F(qYcz2gi?)Q_J(f1aLt zQba%V*ieI{9UUFj)nki_*wWO7`}&G2D)6zf**Q5w8Tw{sQion^CS5&^y@IF^j~+b= zmt};$-Dz%hJk)o=vN;gc(%L%Z;02CaCQpJzhV%I8)3Nb!62yv2$8AG%^TU!Sthw4H z*Vjs6vg`zyZ=ATdJaGtY^}9c_px_Y_rY0xXH#GclZTj+s0SP((J?|_7#bRCYs(f*Fk;nKS64SQ^sF9DPftU^@7|$^W>)Hz^;_2#6%`p)DEh&` ztl{F~LQs5fT|+}dZLO^3>X9!U9bKOh1Ub}G6Bmue#5}1q4Rl*q@sg48H(RdWXo<$< z7SCvVds4n-=Yoo&vkQBOT3l8((AW1xyM%^7=?R%>d%)YXohe*O9^De%%gal0a&n_a z=kC>`JoIYoev%xmPf1D4$to692#Z-TTfK3#x*W;MEbqH5U%h%|WMtHAOh-f{%|en` z+kPx`dX~J!*Baj@{*;oOci$LY+Jy)d0%3(n_GLa#84RSmx_x0$+$L(unufoNrx zrDhK{QBmsn-o~$Ajho$VkO+L`I7~D&hWG*N+Pk|TTU*;TGrD+8WVIXW?~{mzH_d+k zocSI4T0}eN>rP%*Yde6i4U0oKnM#9i>Bli6&1xm zN4M`Pp4ws4%n}w6VMLO1a&lsY5M7RKpB^6{gC*P7*9ZP=7IeAZ9ZgAwqX5>re)ad| zWiy^sTr^bmI55fa!)|o(z2_rQd)G@tEYfzkjPr!SU(o*V@|Sqa%YF%kH6cq5b{+L@o?Sng~>YuD*WXx_h#U zjg3t~X69nKK^+7Qr1J7|a4->JK@dTN$M5g&rlu$cfw8UaW}$leAWV7^9S`YHZ@61dg;<%NpU=q1Xm6L~Np1BzbI8yAnCj!vyj(KX zV@sB)QCYQo_}g6MZaPdzMwi2Db2t;6!Wx#=Zyi^84a(@7&mmpzS4NVkbRieXpqmSM zI3b!$izf*Y+U522_0^T0p5FQSxr5}{-<1FzcY26{V&FqkwA7t&z)b~q8uq~YF#>_O zy7Eg?!+^f8xN2xW+GJcJ@_9P*V0}lyG9Ms5^t_KvX&!q>d zId~h1jHqB{e*J`$n>)8f^j&uL;-}r$6cB6#2T%tALCV0o&%v)|&uwi>OQuYXk&zKz zUS6{%SAgTCrKJ@WPM62)pBYQEo~UVPG&DBa*3Bg)R()dUTutLF9oNoELkFe%IXxX* zi9kV9Zf@7o65YcyLPElm%K#S_7feh{)OQIVKYD_(+}nGD`VQQ-_u{z^V>ypGlF&xS$3LW`G+1`Of2^9q@G1d?9!&-;&QxAA0vw$8 zk&#VayA;vghSlbsfD&~%$YHCrq~vHa056MO!YrD~RL94e9Gu9HF69CPk<830CA!$q z7p=c!IAg=Z-~zjlp`EY!O^oddcQb5Yb!X4rn^TI_NT3L0RBUXU+bTl41P>QCl)C?lvzIC^+vu-e1~FSx-<|H(!i!E%E94xb*;oF*=Mbd zimD$?F@%NfhKuV_G!eUP!o~euQM`a07neJEK^aB&)hiES8l3R1b$4tuSw%&JF^^e| zWq5WreNzA6&!2$g(*e^$(goT_mjOaTLULwfixR&3hC@?jyf`@Xv789m90A@#8*pl7 zC7eF%0N3i>tFt?7Z2rtl`&s6rzvfh_3iG*^aUFIskTq;>vDN1hHT86b5hjF%hsQz^ z^{UDgD2^8|UOWozx6fEOm=l0p4X#~B{yH|2yBu}59uJR4UCbli+yGXZy2u0&-9EbS6qk|=91a!_zf zOA7$Q$9#NztgM9{9rxfOxVgFi10+&PN~NNS7postk~c?E>BY{Q+D(J0XFY{!HabH) z7aB*Vsw!w6z7Q6pCy&Z!ZRg<|tto%gm@+)VfD$R6>;LbdyQhaK?+joV83jcpAhq+o zIViZWuuwIX2b5x!Nh?JJlCh2tmKHNlTB^HqvY8FP+D1<6jiK2z@)(;`+@Dny{C66i zN9PA^UdPsnQM^|h=~Mpycxd2@5XyJHj1M1}QU@Acmg9=KEvSZpegaez87Ym(;x%hm zQ&l}VJylay{$4D``NVFaQNJP~q8YC{tHE7~!VDCtJeGL~AFXs~tdi82| zem>Ap%;Kh(9v<^FWqf?xb|lMbu2!LLG9rf7>CKzk+S;q@>$bKw@O$=+w}nMcLN{P~i+uQx(+SOy))p2EivzNsv+i<5I+5}>ZT?%kd@UE-MHj(P z%CwQbW3V!dsMii4hEK2imgnZ8dRIaHbl!9O&&|&}FMXREAJ@*&`Z8RUCAsgr8taIU zf18xt|H-^Ajh+2SH6@0&u0(eyEG#=#2dC}+?hkK!ooTQ4%2~L8D7ccWeDgv$Og`qV%ZADzt5tVsugR6pzxq zH`KO2Zt$^cYiB7bnNjgyu_XTOjZ={D`ziq@b)-(1hK&Bu%(Q*;cc=LzF+-swgjfOO zUtZ3I6{1&Rn4Fz`xVH8+=+-Y(fLnG&Sxs$cwU<^Wtt#&rD?Y-Us#w=S;vpZr{bYZ^ zXn&8Z$2h_QVCLq|)Musmc?ZYqur6Y(5E>dT+u^T-g#Tun+$hqAzJC(Iz>~woz^F9q zSQ;ILWJa?j{1ta$FNmWH%Jd4v1LsBhA4*V*(-}6z(9$1v_||Zy59N<3bCCa<5i&NI z^SBQ>Ss$1(v}HWm5Ls+%9qQ>Z=fsJj5+r_PLY|wOOJwqBM@PE^CVD07?7WLsfP$MY zG;+0;gk@$XW`goji(kl_Q+EI+w9rFqLZQ0QK3}~hpY~HKwzMim6ejwdc0CW z$g=P1e0Ov*>Cu_KIgEXCxWcHehfwu*r_ANuZR1E5_al$MTfh5k_)>9)*c1a9&cMLH zGsN*#rzr92$t5fe@96YsX)>+Mlpl4kx`~KXX7BwKfA+S68KFWiRA%alho}vj7pWF_;#4^bdjm=-01bFc>V3PGWv`wpg``5ASf! zBeeHXMr1~}ta7B0rDeicJZaQL5}Q@eVDrVzN~Rcp4H>(U(L!)AfJN5Hge{zbg9B&z z2aFWaU@6_)-U9sLriccpK*^>5Ww)g4m1EHD6yAn_;)&UP{p1gH3!WJf!D%-BI_J}F zKnLUF9F5MIp;x|YYIqcZe17=murvh)1^4D}B_;hsL-^Y+pi+S*^V$}BOfvWGfzROQ zY{be+r+)h{ybW#uwY2b~wtuzN~+ekkloui{p ziD?PuHZjgi{gUP;mV;#fJL@feDo5RWQ8#m!- zoAC3;lR$o+pL?4iM6S@P{mynqM@Kg{HhOw`e*H4GK5R}+edX%<_tPydb^GSE(=yb&s%&wC8>xHJoO?H5%P=t`T3SR+P)BFbWQeStoPebMYJo)jTk?0AC{))j zA)8aKATQ7kygHqvghSH)t#7IApx~^AyI%SMt<+=&EZ`za%E~6Da4cv!e!DiM@!KjY zDvsL;m~>0A6%`aHSXX{b@2a!isHsWl|M>D{Tg!pBH-WWno@PBL_-@OmwJFc&GEs|* zi$~vVjDNR=iHUjbobsBM!&Gb4fzDH`E0%V5H}rZYgJo~OWoQag1wzRS>6wh@{`3r~ z1BZ*P5pR^0TFeB~)mf8NRa895;o-72DVZ# zhu=xkMsB-h#oR@xC zz8B1GNTDZk#hH?P#za7Quyf(Q>8Pbcx`=xaPrzV`YgwU2`W169=f z7W1tHGQ`SZ2k+(Kea}wX!R1L-r;Lb0HSjqA3yx-LaHK2rm`(k@E>%=fezI&8brTQ( zBOOrqf8*_|$T8avaGjGy0{q zwV0|bo}wb`>{yp3+T$;^MxC{ssg;y^rF}1&8<$Q0u0&WE{wrk$x+iJk>h9XW#%2-G zo(p#KqK}A;jhz-4M;~) zwyZ2kla`=1DND+=-{w(Bkcx4V?aa@&U;j&=80Sz`X^DyMs3DfP1a8T&NUH-I_zVty z{v_EP22O5I(ZEwP>!*+bA(f_Mna1spQwv{xw-wp$a9nZ-a&)XsCdYOYF4X$eLX0zT zlZ{-7sacc1P=^i<4&2<_`daezxtyJx6dEcWQD^7o>|;E7`NADLdYVKOa|P_0GcA+FG8OM1nIT@3!z3lZl8bJ0LKV?+^D#R~PD3XR5qq z!}zJvkB>jC>0H=ha{|xKvuV_xw@achw8vIc#cSl8B}YjUeHl|$V+~hiepn&Y^&ucp zIn399&V#l9yQ_GRiG&ULfHwm9tJa19GWXR#T2Bpc2|-7z{>GvOLXRMW9Al& zSXeQ-e_Wtp)Y=Ka2rx^g{{H?_UR(QbV+cVH=UP9(x0|kEfm>VWH#7)}iuw(Doivp( zCbA;$i&Ing*|Oy!=;DS^0u>9-nz7Tt;ldET+IHlISxIl)uH%vRsw+{b3_iXWA->oB z^>XUoeDd2f4!wUp)-bgrxA>S>2QUirRz{Pxf6d2-S6X)2>a#5D_9yw}+=s``RJT%A&)ZW|L73XwGh+S1 z6oAV0)o5F?gVzrjewxH}a@xXb@4i)oxt;R!66qj)gT!K8wZKQ|L(=$itV#7PVG3_i zlKLlGV)!uN@KYz;iFXl%X7A-;khEKk#sun6KFPKFhOegUtPC*}+By2)|Kxmf)W}~| zP8v6B=Sks3ScP)eE`Q?hy;#c=kO3@)L?RuYy>EBz!E2)IHOyA&lNG$hod$|RjEadStEwzn1z+x8>2%YVWe&ZpD$|GcuGfuiFrjSm*Szke*&X zp`?DTztF2xlL{^2E^BJO(w^v9q`PsIt_r_Zv1a?zT1hhG&lV+x*(6BDd>{qF>-=)IJ9B+; zVF#z(IRUnJYO215c=0#^X`v|Z`{^<1nOp&hS3N(#K$y0_fmMy^T)x0F?6cW3tLzCb z)4lfvw_}8bGI1b`GBKeowS{AaEWNd5Ou>qkD+x$;)YD@zDg8+(g;&=w?c9=6W0w9D zY53}?k88EKr*d{g&Dh>z>!|1QfE%&k{PL>0O^k+m$sg+KLhrgP%ZUp{Y)PKAh zf<9bQf^BNr;ngLdtHH){aBv!i#!pipGG(If+S+4LKsTJlz0fWpx64h?TUg`P zk(1rzWaOvv(__s?rZcWP+9Yv#XsFAj{jH(yBztPv&COne6RvSh7b)}?Nm$_0){PEL zPX4tW5-o{}Q0tkQIaCrzE?3-dWSI;Jr3eV&whJN%GNA>es*o)Yi;$3`w~13DDsF zm&Yfz!{xNgFA4DaB(I)qUL3J;rH~(|9JN=~)>2zpYIodA#tqSxwGl_<18;iKmxu~- z@~Kzx9XBv-&Fi48QFpF^gyiI8A~eR{>}^ZgxS9|PVU8Wt6#O?m?~pR8sVxx^{=U9^ z$}Hm9Qa5`Kd71Ml@}iwkQ79kwV`IB{c-8l;xQb`3ZBGmXMWJYvR%NjIh;&swFVVAdlR4XgLebX25heO? ztNuU;0NHG-4{zxV42ecWO+CN3Xkrv?FSOPkSd~`$)`6OY?%=2sGrA^1D8BXc7^r2C zpRcX0nU|pXiXYru`chIp7{*N-uGZIMXWt$AgKjH;p+rec%t(gwG^_t$%kJ!CB)vy0 z>>eq@w8Cq)#OL>>G@`RpW>2E56BSs6R`30;prwsJ-IY>zP19=+ugOjpecV)2{mil1 zlU0a|5L8xzg|apJT%n!}@JrS2sb-3ngi?zadv)tkQSYc8EO)@^q2RV)4a5s>=r=Im zx+6RjNuVHad!=OgD4KxV`|#ld5cPX(mY-Rm0_~`b$xs|L88AAtD@e{eeWx)%kO5cQ zu$bm5y|OB^j)UD@$I-WatV3bErr(sA605IkA}lTj(`p-++byozo1zfX-)W`jZW}v> zgoW|esJbk+glFi-B?33o-RS2sKcA-GrF9#W&ZWj@D|0$Wa2YJ+{A_m7D2r4jS?rtm)>gkSHYYiKC$;HSI4h=c2_QWb?6YwUn^YiZlsB49Hbbs3fRofJa<*lu)74WTNn?u%Q zgA&8yjy1A(wIDwqNW1pCt6c=a``*zRp@3DzMUZ6@(tZ8(C$4Kcg_^iCF7Et&?Ag>R z%ueM~f}}J9QGP)IXpvPIH;;1>b0qIvUA6bdi-B0TwA3#>Jv=k>K}+F;JkxM@_vfM4 zgIW80wsEU~k^z+RIXB9wgG}I+G}I!(1b(vUv~$MutB3z zRykUHb2p}&7oP=gK4+1VLLrFW+*kiJ|oGHQzWT2II*d5nRj#R7>wHg;N*w|z*k zg|Dlt*8RJ8iu}*j6AUYO*x8%m_wDudXP=)r8k?A~trRFeKvt`6qwbWo0F>5FjfDlR)aFlGi^t$i>OYOcDip&ULScfZctn z;pWIwmo{mvWGdgG?y8n<=rlqa(Z1 z+_l+wXfY*)qTX=-;6PHnka^+{^VdJ1`L@5$ozxEkZeQ^wDzQU;+hHs;R3?yr6aDqQ zX%D;>KsR6@Vqs%@0D-<~XeX6b0rGYFN`fXoEYLAHXntYgF-epfEAX!>1@2?H3ZF~A z=yIT=zN@c)7A~81oJh_A*G0L3Bl8KG@2tiD{{+GPgO6mJs0j~RZoq>M;+_ino^mcu zPBzY-5W{mP3tJloTN`H^cMDG&YX-}=3`!a=8I + + + LuaFileSystem + + + + + + +
+ +
+ +
LuaFileSystem
+
File System Library for the Lua Programming Language
+
+ +
+ + + +
+ +

Introduction

+ +

LuaFileSystem is a Lua library +developed to complement the set of functions related to file +systems offered by the standard Lua distribution.

+ +

LuaFileSystem offers a portable way to access +the underlying directory structure and file attributes.

+ +

Building

+ +

+LuaFileSystem should be built with Lua 5.1 so the language library +and header files for the target version must be installed properly. +

+ +

+LuaFileSystem offers a Makefile and a separate configuration file, +config, +which should be edited to suit your installation before running +make. +The file has some definitions like paths to the external libraries, +compiler options and the like. +

+ +

On Windows, the C runtime used to compile LuaFileSystem must be the same +runtime that Lua uses, or some LuaFileSystem functions will not work.

+ +

Installation

+ +

The easiest way to install LuaFileSystem is to use LuaRocks:

+ +
+luarocks install luafilesystem
+
+ +

If you prefer to install LuaFileSystem manually, the compiled binary should be copied to a directory in your +C path.

+ +

Reference

+ +

+LuaFileSystem offers the following functions: +

+ +
+
lfs.attributes (filepath [, aname])
+
Returns a table with the file attributes corresponding to + filepath (or nil followed by an error message + in case of error). + If the second optional argument is given, then only the value of the + named attribute is returned (this use is equivalent to + lfs.attributes(filepath).aname, but the table is not created + and only one attribute is retrieved from the O.S.). + The attributes are described as follows; + attribute mode is a string, all the others are numbers, + and the time related attributes use the same time reference of + os.time: +
+
dev
+
on Unix systems, this represents the device that the inode resides on. On Windows systems, + represents the drive number of the disk containing the file
+ +
ino
+
on Unix systems, this represents the inode number. On Windows systems this has no meaning
+ +
mode
+
string representing the associated protection mode (the values could be + file, directory, link, socket, + named pipe, char device, block device or + other)
+ +
nlink
+
number of hard links to the file
+ +
uid
+
user-id of owner (Unix only, always 0 on Windows)
+ +
gid
+
group-id of owner (Unix only, always 0 on Windows)
+ +
rdev
+
on Unix systems, represents the device type, for special file inodes. + On Windows systems represents the same as dev
+ +
access
+
time of last access
+ +
modification
+
time of last data modification
+ +
change
+
time of last file status change
+ +
size
+
file size, in bytes
+ +
blocks
+
block allocated for file; (Unix only)
+ +
blksize
+
optimal file system I/O blocksize; (Unix only)
+
+ This function uses stat internally thus if the given + filepath is a symbolic link, it is followed (if it points to + another link the chain is followed recursively) and the information + is about the file it refers to. + To obtain information about the link itself, see function + lfs.symlinkattributes. +
+ +
lfs.chdir (path)
+
Changes the current working directory to the given + path.
+ Returns true in case of success or nil plus an + error string.
+ +
lfs.lock_dir(path, [seconds_stale])
+
Creates a lockfile (called lockfile.lfs) in path if it does not + exist and returns the lock. If the lock already exists checks if + it's stale, using the second parameter (default for the second + parameter is INT_MAX, which in practice means the lock will never + be stale. To free the the lock call lock:free().
+ In case of any errors it returns nil and the error message. In + particular, if the lock exists and is not stale it returns the + "File exists" message.
+ +
lfs.currentdir ()
+
Returns a string with the current working directory or nil + plus an error string.
+ +
iter, dir_obj = lfs.dir (path)
+
+ Lua iterator over the entries of a given directory. + Each time the iterator is called with dir_obj it returns a directory entry's name as a string, or + nil if there are no more entries. You can also iterate by calling dir_obj:next(), and + explicitly close the directory before the iteration finished with dir_obj:close(). + Raises an error if path is not a directory. +
+ +
lfs.lock (filehandle, mode[, start[, length]])
+
Locks a file or a part of it. This function works on open files; the + file handle should be specified as the first argument. + The string mode could be either + r (for a read/shared lock) or w (for a + write/exclusive lock). The optional arguments start + and length can be used to specify a starting point and + its length; both should be numbers.
+ Returns true if the operation was successful; in + case of error, it returns nil plus an error string. +
+ +
lfs.link (old, new[, symlink])
+
Creates a link. The first argument is the object to link to + and the second is the name of the link. If the optional third + argument is true, the link will by a symbolic link (by default, a + hard link is created). +
+ +
lfs.mkdir (dirname)
+
Creates a new directory. The argument is the name of the new + directory.
+ Returns true if the operation was successful; + in case of error, it returns nil plus an error string. +
+ +
lfs.rmdir (dirname)
+
Removes an existing directory. The argument is the name of the directory.
+ Returns true if the operation was successful; + in case of error, it returns nil plus an error string.
+ +
lfs.setmode (file, mode)
+
Sets the writing mode for a file. The mode string can be either "binary" or "text". + Returns true followed the previous mode string for the file, or + nil followed by an error string in case of errors. + On non-Windows platforms, where the two modes are identical, + setting the mode has no effect, and the mode is always returned as binary. +
+ +
lfs.symlinkattributes (filepath [, aname])
+
Identical to lfs.attributes except that + it obtains information about the link itself (not the file it refers to). + On Windows this function does not yet support links, and is identical to + lfs.attributes. +
+ +
lfs.touch (filepath [, atime [, mtime]])
+
Set access and modification times of a file. This function is + a bind to utime function. The first argument is the + filename, the second argument (atime) is the access time, + and the third argument (mtime) is the modification time. + Both times are provided in seconds (which should be generated with + Lua standard function os.time). + If the modification time is omitted, the access time provided is used; + if both times are omitted, the current time is used.
+ Returns true if the operation was successful; + in case of error, it returns nil plus an error string. +
+ +
lfs.unlock (filehandle[, start[, length]])
+
Unlocks a file or a part of it. This function works on + open files; the file handle should be specified as the first + argument. The optional arguments start and + length can be used to specify a starting point and its + length; both should be numbers.
+ Returns true if the operation was successful; + in case of error, it returns nil plus an error string. +
+
+ +
+ +
+ +
+

Valid XHTML 1.0!

+

$Id: manual.html,v 1.45 2009/06/03 20:53:55 mascarenhas Exp $

+
+ +
+ + + diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.3.0-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.3.0-1.rockspec new file mode 100644 index 00000000000..d4d484f68a7 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.3.0-1.rockspec @@ -0,0 +1,27 @@ +package = "LuaFileSystem" +version = "1.3.0-1" +source = { + url = "http://luaforge.net/frs/download.php/2679/luafilesystem-1.3.0.tar.gz" +} +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "make", + build_variables = { + LUA_INC = "$(LUA_INCDIR)", + LIB_OPTION = "$(LIBFLAG)" + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)" + } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-1.rockspec new file mode 100644 index 00000000000..b6936182394 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-1.rockspec @@ -0,0 +1,27 @@ +package = "LuaFileSystem" +version = "1.4.0-1" +source = { + url = "http://luaforge.net/frs/download.php/3158/luafilesystem-1.4.0.tar.gz" +} +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "make", + build_variables = { + LUA_INC = "$(LUA_INCDIR)", + LIB_OPTION = "$(LIBFLAG)" + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)" + } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-2.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-2.rockspec new file mode 100644 index 00000000000..f7ed871527f --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-2.rockspec @@ -0,0 +1,43 @@ +package = "LuaFileSystem" +version = "1.4.0-2" +source = { + url = "http://luaforge.net/frs/download.php/3158/luafilesystem-1.4.0.tar.gz" +} +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} +dependencies = { + "lua >= 5.1" +} +build = { + platforms = { + unix = { + type = "make", + build_variables = { + LIB_OPTION = "$(LIBFLAG)", + CFLAGS = "$(CFLAGS) -I$(LUA_INCDIR)", + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)" + } + }, + win32 = { + type = "make", + build_variables = { + LUA_LIB = "$(LUA_LIBDIR)\\lua5.1.lib", + CFLAGS = "/MD $(CFLAGS) /I$(LUA_INCDIR)", + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)", + LUA_DIR = "$(LUADIR)", + BIN_DIR = "$(BINDIR)" + } + } + } +} \ No newline at end of file diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1-1.rockspec new file mode 100644 index 00000000000..db3a3ebb6df --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1-1.rockspec @@ -0,0 +1,43 @@ +package = "LuaFileSystem" +version = "1.4.1-1" +source = { + url = "http://luaforge.net/frs/download.php/3345/luafilesystem-1.4.1.tar.gz", +} +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} +dependencies = { + "lua >= 5.1" +} +build = { + platforms = { + unix = { + type = "make", + build_variables = { + LIB_OPTION = "$(LIBFLAG)", + CFLAGS = "$(CFLAGS) -I$(LUA_INCDIR) $(STAT64)", + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)" + } + }, + win32 = { + type = "make", + build_variables = { + LUA_LIB = "$(LUA_LIBDIR)\\lua5.1.lib", + CFLAGS = "/MD $(CFLAGS) /I$(LUA_INCDIR)", + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)", + LUA_DIR = "$(LUADIR)", + BIN_DIR = "$(BINDIR)" + } + } + } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1rc1-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1rc1-1.rockspec new file mode 100644 index 00000000000..1194711715b --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1rc1-1.rockspec @@ -0,0 +1,43 @@ +package = "LuaFileSystem" +version = "1.4.1rc1-1" +source = { + url = "http://luafilesystem.luaforge.net/luafilesystem-1.4.1rc1.tar.gz", +} +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} +dependencies = { + "lua >= 5.1" +} +build = { + platforms = { + unix = { + type = "make", + build_variables = { + LIB_OPTION = "$(LIBFLAG)", + CFLAGS = "$(CFLAGS) -I$(LUA_INCDIR) $(STAT64)", + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)" + } + }, + win32 = { + type = "make", + build_variables = { + LUA_LIB = "$(LUA_LIBDIR)\\lua5.1.lib", + CFLAGS = "/MD $(CFLAGS) /I$(LUA_INCDIR)", + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)", + LUA_DIR = "$(LUADIR)", + BIN_DIR = "$(BINDIR)" + } + } + } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.2-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.2-1.rockspec new file mode 100644 index 00000000000..7cfe92b78ef --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.2-1.rockspec @@ -0,0 +1,26 @@ +package = "LuaFileSystem" + +version = "1.4.2-1" + +source = { + url = "http://luaforge.net/frs/download.php/3931/luafilesystem-1.4.2.tar.gz", +} + +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} + +dependencies = { + "lua >= 5.1" +} + +build = { + type = "module", + modules = { lfs = "src/lfs.c" } +} \ No newline at end of file diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.5.0-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.5.0-1.rockspec new file mode 100644 index 00000000000..1170ad25c90 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.5.0-1.rockspec @@ -0,0 +1,27 @@ +package = "LuaFileSystem" + +version = "1.5.0-1" + +source = { + url = "http://cloud.github.com/downloads/keplerproject/luafilesystem/luafilesystem-1.5.0.tar.gz", +} + +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} + +dependencies = { + "lua >= 5.1" +} + +build = { + type = "module", + modules = { lfs = "src/lfs.c" }, + copy_directories = { "doc", "tests" } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.0-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.0-1.rockspec new file mode 100644 index 00000000000..82d349cf016 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.0-1.rockspec @@ -0,0 +1,27 @@ +package = "LuaFileSystem" + +version = "1.6.0-1" + +source = { + url = "https://github.com/downloads/keplerproject/luafilesystem/luafilesystem-1.6.0.tar.gz", +} + +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} + +dependencies = { + "lua >= 5.1" +} + +build = { + type = "builtin", + modules = { lfs = "src/lfs.c" }, + copy_directories = { "doc", "tests" } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.1-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.1-1.rockspec new file mode 100644 index 00000000000..7f45e332c44 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.1-1.rockspec @@ -0,0 +1,27 @@ +package = "LuaFileSystem" + +version = "1.6.1-1" + +source = { + url = "https://github.com/downloads/keplerproject/luafilesystem/luafilesystem-1.6.1.tar.gz", +} + +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} + +dependencies = { + "lua >= 5.1" +} + +build = { + type = "builtin", + modules = { lfs = "src/lfs.c" }, + copy_directories = { "doc", "tests" } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.2-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.2-1.rockspec new file mode 100644 index 00000000000..1c11efc89e1 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.2-1.rockspec @@ -0,0 +1,27 @@ +package = "LuaFileSystem" + +version = "1.6.2-1" + +source = { + url = "https://github.com/downloads/keplerproject/luafilesystem/luafilesystem-1.6.2.tar.gz", +} + +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} + +dependencies = { + "lua >= 5.1" +} + +build = { + type = "builtin", + modules = { lfs = "src/lfs.c" }, + copy_directories = { "doc", "tests" } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.3-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.3-1.rockspec new file mode 100644 index 00000000000..89b25d42fe3 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.3-1.rockspec @@ -0,0 +1,28 @@ +package = "LuaFileSystem" +version = "1.6.3-1" +source = { + url = "git://github.com/keplerproject/luafilesystem", + tag = "v_1_6_3", +} +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]], + license = "MIT/X11", +} +dependencies = { + "lua >= 5.1" +} +build = { + type = "builtin", + modules = { + lfs = "src/lfs.c" + }, + copy_directories = { + "doc", "tests" + } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-1.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-1.rockspec new file mode 100644 index 00000000000..a02d4f14e71 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-1.rockspec @@ -0,0 +1,44 @@ +package = "LuaFileSystem" +version = "cvs-1" +source = { + url = "cvs://:pserver:anonymous:@cvs.luaforge.net:/cvsroot/luafilesystem", + cvs_tag = "HEAD" +} +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} +dependencies = { + "lua >= 5.1" +} +build = { + platforms = { + unix = { + type = "make", + build_variables = { + LIB_OPTION = "$(LIBFLAG)", + CFLAGS = "$(CFLAGS) -I$(LUA_INCDIR)", + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)" + } + }, + win32 = { + type = "make", + build_variables = { + LUA_LIB = "$(LUA_LIBDIR)\\lua5.1.lib", + CFLAGS = "$(CFLAGS) /I$(LUA_INCDIR)", + }, + install_variables = { + LUA_LIBDIR = "$(LIBDIR)", + LUA_DIR = "$(LUADIR)", + BIN_DIR = "$(BINDIR)" + } + } + } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-2.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-2.rockspec new file mode 100644 index 00000000000..651c7cf1317 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-2.rockspec @@ -0,0 +1,26 @@ +package = "LuaFileSystem" + +version = "cvs-2" + +source = { + url = "git://github.com/keplerproject/luafilesystem.git", +} + +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} + +dependencies = { + "lua >= 5.1" +} + +build = { + type = "module", + modules = { lfs = "src/lfs.c" } +} diff --git a/3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-3.rockspec b/3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-3.rockspec new file mode 100644 index 00000000000..a4388cd7619 --- /dev/null +++ b/3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-3.rockspec @@ -0,0 +1,27 @@ +package = "LuaFileSystem" + +version = "cvs-3" + +source = { + url = "git://github.com/keplerproject/luafilesystem.git", +} + +description = { + summary = "File System Library for the Lua Programming Language", + detailed = [[ + LuaFileSystem is a Lua library developed to complement the set of + functions related to file systems offered by the standard Lua + distribution. LuaFileSystem offers a portable way to access the + underlying directory structure and file attributes. + ]] +} + +dependencies = { + "lua >= 5.1, < 5.4" +} + +build = { + type = "builtin", + modules = { lfs = "src/lfs.c" }, + copy_directories = { "doc", "tests" } +} diff --git a/3rdparty/luafilesystem/src/.gitignore b/3rdparty/luafilesystem/src/.gitignore new file mode 100644 index 00000000000..9d22eb46a9c --- /dev/null +++ b/3rdparty/luafilesystem/src/.gitignore @@ -0,0 +1,2 @@ +*.o +*.so diff --git a/3rdparty/luafilesystem/src/lfs.c b/3rdparty/luafilesystem/src/lfs.c new file mode 100644 index 00000000000..ac483fa067b --- /dev/null +++ b/3rdparty/luafilesystem/src/lfs.c @@ -0,0 +1,906 @@ +/* +** LuaFileSystem +** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem) +** +** File system manipulation library. +** This library offers these functions: +** lfs.attributes (filepath [, attributename]) +** lfs.chdir (path) +** lfs.currentdir () +** lfs.dir (path) +** lfs.lock (fh, mode) +** lfs.lock_dir (path) +** lfs.mkdir (path) +** lfs.rmdir (path) +** lfs.setmode (filepath, mode) +** lfs.symlinkattributes (filepath [, attributename]) -- thanks to Sam Roberts +** lfs.touch (filepath [, atime [, mtime]]) +** lfs.unlock (fh) +** +** $Id: lfs.c,v 1.61 2009/07/04 02:10:16 mascarenhas Exp $ +*/ + +#ifndef LFS_DO_NOT_USE_LARGE_FILE +#ifndef _WIN32 +#ifndef _AIX +#define _FILE_OFFSET_BITS 64 /* Linux, Solaris and HP-UX */ +#else +#define _LARGE_FILES 1 /* AIX */ +#endif +#endif +#endif + +#ifndef LFS_DO_NOT_USE_LARGE_FILE +#define _LARGEFILE64_SOURCE +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#include +#include +#ifdef __BORLANDC__ + #include +#else + #include +#endif +#include +#else +#include +#include +#include +#include +#include +#endif + +#include +#include +#include + +#include "lfs.h" + +#define LFS_VERSION "1.6.3" +#define LFS_LIBNAME "lfs" + +#if LUA_VERSION_NUM >= 503 /* Lua 5.3 */ + +#ifndef luaL_optlong +#define luaL_optlong luaL_optinteger +#endif + +#endif + +#if LUA_VERSION_NUM < 502 +# define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l)) +#endif + +/* Define 'strerror' for systems that do not implement it */ +#ifdef NO_STRERROR +#define strerror(_) "System unable to describe the error" +#endif + +/* Define 'getcwd' for systems that do not implement it */ +#ifdef NO_GETCWD +#define getcwd(p,s) NULL +#define getcwd_error "Function 'getcwd' not provided by system" +#else +#define getcwd_error strerror(errno) + #ifdef _WIN32 + /* MAX_PATH seems to be 260. Seems kind of small. Is there a better one? */ + #define LFS_MAXPATHLEN MAX_PATH + #else + /* For MAXPATHLEN: */ + #include + #define LFS_MAXPATHLEN MAXPATHLEN + #endif +#endif + +#define DIR_METATABLE "directory metatable" +typedef struct dir_data { + int closed; +#ifdef _WIN32 + intptr_t hFile; + char pattern[MAX_PATH+1]; +#else + DIR *dir; +#endif +} dir_data; + +#define LOCK_METATABLE "lock metatable" + +#ifdef _WIN32 + #ifdef __BORLANDC__ + #define lfs_setmode(L,file,m) ((void)L, setmode(_fileno(file), m)) + #define STAT_STRUCT struct stati64 + #else + #define lfs_setmode(L,file,m) ((void)L, _setmode(_fileno(file), m)) + #define STAT_STRUCT struct _stati64 + #endif +#define STAT_FUNC _stati64 +#define LSTAT_FUNC STAT_FUNC +#else +#define _O_TEXT 0 +#define _O_BINARY 0 +#define lfs_setmode(L,file,m) ((void)L, (void)file, (void)m, 0) +#define STAT_STRUCT struct stat +#define STAT_FUNC stat +#define LSTAT_FUNC lstat +#endif + +/* +** Utility functions +*/ +static int pusherror(lua_State *L, const char *info) +{ + lua_pushnil(L); + if (info==NULL) + lua_pushstring(L, strerror(errno)); + else + lua_pushfstring(L, "%s: %s", info, strerror(errno)); + lua_pushinteger(L, errno); + return 3; +} + +#ifndef _WIN32 +static int pushresult(lua_State *L, int i, const char *info) +{ + if (i==-1) + return pusherror(L, info); + lua_pushinteger(L, i); + return 1; +} +#endif +/* +** This function changes the working (current) directory +*/ +static int change_dir (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + if (chdir(path)) { + lua_pushnil (L); + lua_pushfstring (L,"Unable to change working directory to '%s'\n%s\n", + path, chdir_error); + return 2; + } else { + lua_pushboolean (L, 1); + return 1; + } +} + +/* +** This function returns the current directory +** If unable to get the current directory, it returns nil +** and a string describing the error +*/ +static int get_dir (lua_State *L) { + char *path; + /* Passing (NULL, 0) is not guaranteed to work. Use a temp buffer and size instead. */ + char buf[LFS_MAXPATHLEN]; + if ((path = getcwd(buf, LFS_MAXPATHLEN)) == NULL) { + lua_pushnil(L); + lua_pushstring(L, getcwd_error); + return 2; + } + else { + lua_pushstring(L, path); + return 1; + } +} + +/* +** Check if the given element on the stack is a file and returns it. +*/ +static FILE *check_file (lua_State *L, int idx, const char *funcname) { +#if LUA_VERSION_NUM == 501 + FILE **fh = (FILE **)luaL_checkudata (L, idx, "FILE*"); + if (*fh == NULL) { + luaL_error (L, "%s: closed file", funcname); + return 0; + } else + return *fh; +#elif LUA_VERSION_NUM >= 502 && LUA_VERSION_NUM <= 503 + luaL_Stream *fh = (luaL_Stream *)luaL_checkudata (L, idx, "FILE*"); + if (fh->closef == 0 || fh->f == NULL) { + luaL_error (L, "%s: closed file", funcname); + return 0; + } else + return fh->f; +#else +#error unsupported Lua version +#endif +} + + +/* +** +*/ +static int _file_lock (lua_State *L, FILE *fh, const char *mode, const long start, long len, const char *funcname) { + int code; +#ifdef _WIN32 + /* lkmode valid values are: + LK_LOCK Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error. + LK_NBLCK Locks the specified bytes. If the bytes cannot be locked, the constant returns an error. + LK_NBRLCK Same as _LK_NBLCK. + LK_RLCK Same as _LK_LOCK. + LK_UNLCK Unlocks the specified bytes, which must have been previously locked. + + Regions should be locked only briefly and should be unlocked before closing a file or exiting the program. + + http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__locking.asp + */ + int lkmode; + switch (*mode) { + case 'r': lkmode = LK_NBLCK; break; + case 'w': lkmode = LK_NBLCK; break; + case 'u': lkmode = LK_UNLCK; break; + default : return luaL_error (L, "%s: invalid mode", funcname); + } + if (!len) { + fseek (fh, 0L, SEEK_END); + len = ftell (fh); + } + fseek (fh, start, SEEK_SET); +#ifdef __BORLANDC__ + code = locking (fileno(fh), lkmode, len); +#else + code = _locking (fileno(fh), lkmode, len); +#endif +#else + struct flock f; + switch (*mode) { + case 'w': f.l_type = F_WRLCK; break; + case 'r': f.l_type = F_RDLCK; break; + case 'u': f.l_type = F_UNLCK; break; + default : return luaL_error (L, "%s: invalid mode", funcname); + } + f.l_whence = SEEK_SET; + f.l_start = (off_t)start; + f.l_len = (off_t)len; + code = fcntl (fileno(fh), F_SETLK, &f); +#endif + return (code != -1); +} + +#ifdef _WIN32 +typedef struct lfs_Lock { + HANDLE fd; +} lfs_Lock; +static int lfs_lock_dir(lua_State *L) { + size_t pathl; HANDLE fd; + lfs_Lock *lock; + char *ln; + const char *lockfile = "/lockfile.lfs"; + const char *path = luaL_checklstring(L, 1, &pathl); + ln = (char*)malloc(pathl + strlen(lockfile) + 1); + if(!ln) { + lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; + } + strcpy(ln, path); strcat(ln, lockfile); + if((fd = CreateFile(ln, GENERIC_WRITE, 0, NULL, CREATE_NEW, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, NULL)) == INVALID_HANDLE_VALUE) { + int en = GetLastError(); + free(ln); lua_pushnil(L); + if(en == ERROR_FILE_EXISTS || en == ERROR_SHARING_VIOLATION) + lua_pushstring(L, "File exists"); + else + lua_pushstring(L, strerror(en)); + return 2; + } + free(ln); + lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock)); + lock->fd = fd; + luaL_getmetatable (L, LOCK_METATABLE); + lua_setmetatable (L, -2); + return 1; +} +static int lfs_unlock_dir(lua_State *L) { + lfs_Lock *lock = (lfs_Lock *)luaL_checkudata(L, 1, LOCK_METATABLE); + if(lock->fd != INVALID_HANDLE_VALUE) { + CloseHandle(lock->fd); + lock->fd=INVALID_HANDLE_VALUE; + } + return 0; +} +#else +typedef struct lfs_Lock { + char *ln; +} lfs_Lock; +static int lfs_lock_dir(lua_State *L) { + lfs_Lock *lock; + size_t pathl; + char *ln; + const char *lockfile = "/lockfile.lfs"; + const char *path = luaL_checklstring(L, 1, &pathl); + lock = (lfs_Lock*)lua_newuserdata(L, sizeof(lfs_Lock)); + ln = (char*)malloc(pathl + strlen(lockfile) + 1); + if(!ln) { + lua_pushnil(L); lua_pushstring(L, strerror(errno)); return 2; + } + strcpy(ln, path); strcat(ln, lockfile); + if(symlink("lock", ln) == -1) { + free(ln); lua_pushnil(L); + lua_pushstring(L, strerror(errno)); return 2; + } + lock->ln = ln; + luaL_getmetatable (L, LOCK_METATABLE); + lua_setmetatable (L, -2); + return 1; +} +static int lfs_unlock_dir(lua_State *L) { + lfs_Lock *lock = (lfs_Lock *)luaL_checkudata(L, 1, LOCK_METATABLE); + if(lock->ln) { + unlink(lock->ln); + free(lock->ln); + lock->ln = NULL; + } + return 0; +} +#endif + +static int lfs_g_setmode (lua_State *L, FILE *f, int arg) { + static const int mode[] = {_O_BINARY, _O_TEXT}; + static const char *const modenames[] = {"binary", "text", NULL}; + int op = luaL_checkoption(L, arg, NULL, modenames); + int res = lfs_setmode(L, f, mode[op]); + if (res != -1) { + int i; + lua_pushboolean(L, 1); + for (i = 0; modenames[i] != NULL; i++) { + if (mode[i] == res) { + lua_pushstring(L, modenames[i]); + goto exit; + } + } + lua_pushnil(L); + exit: + return 2; + } else { + int en = errno; + lua_pushnil(L); + lua_pushfstring(L, "%s", strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + +static int lfs_f_setmode(lua_State *L) { + return lfs_g_setmode(L, check_file(L, 1, "setmode"), 2); +} + +/* +** Locks a file. +** @param #1 File handle. +** @param #2 String with lock mode ('w'rite, 'r'ead). +** @param #3 Number with start position (optional). +** @param #4 Number with length (optional). +*/ +static int file_lock (lua_State *L) { + FILE *fh = check_file (L, 1, "lock"); + const char *mode = luaL_checkstring (L, 2); + const long start = (long) luaL_optinteger (L, 3, 0); + long len = (long) luaL_optinteger (L, 4, 0); + if (_file_lock (L, fh, mode, start, len, "lock")) { + lua_pushboolean (L, 1); + return 1; + } else { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror(errno)); + return 2; + } +} + + +/* +** Unlocks a file. +** @param #1 File handle. +** @param #2 Number with start position (optional). +** @param #3 Number with length (optional). +*/ +static int file_unlock (lua_State *L) { + FILE *fh = check_file (L, 1, "unlock"); + const long start = (long) luaL_optinteger (L, 2, 0); + long len = (long) luaL_optinteger (L, 3, 0); + if (_file_lock (L, fh, "u", start, len, "unlock")) { + lua_pushboolean (L, 1); + return 1; + } else { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror(errno)); + return 2; + } +} + + +/* +** Creates a link. +** @param #1 Object to link to. +** @param #2 Name of link. +** @param #3 True if link is symbolic (optional). +*/ +static int make_link(lua_State *L) +{ +#ifndef _WIN32 + const char *oldpath = luaL_checkstring(L, 1); + const char *newpath = luaL_checkstring(L, 2); + return pushresult(L, + (lua_toboolean(L,3) ? symlink : link)(oldpath, newpath), NULL); +#else + return pusherror(L, "make_link is not supported on Windows"); +#endif +} + + +/* +** Creates a directory. +** @param #1 Directory path. +*/ +static int make_dir (lua_State *L) { + const char *path = luaL_checkstring (L, 1); + int fail; +#ifdef _WIN32 + fail = _mkdir (path); +#else + fail = mkdir (path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | + S_IWGRP | S_IXGRP | S_IROTH | S_IXOTH ); +#endif + if (fail) { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror(errno)); + return 2; + } + lua_pushboolean (L, 1); + return 1; +} + + +/* +** Removes a directory. +** @param #1 Directory path. +*/ +static int remove_dir (lua_State *L) { + const char *path = luaL_checkstring (L, 1); + int fail; + + fail = rmdir (path); + + if (fail) { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror(errno)); + return 2; + } + lua_pushboolean (L, 1); + return 1; +} + + +/* +** Directory iterator +*/ +static int dir_iter (lua_State *L) { +#ifdef _WIN32 + struct _finddata_t c_file; +#else + struct dirent *entry; +#endif + dir_data *d = (dir_data *)luaL_checkudata (L, 1, DIR_METATABLE); + luaL_argcheck (L, d->closed == 0, 1, "closed directory"); +#ifdef _WIN32 + if (d->hFile == 0L) { /* first entry */ + if ((d->hFile = _findfirst (d->pattern, &c_file)) == -1L) { + lua_pushnil (L); + lua_pushstring (L, strerror (errno)); + d->closed = 1; + return 2; + } else { + lua_pushstring (L, c_file.name); + return 1; + } + } else { /* next entry */ + if (_findnext (d->hFile, &c_file) == -1L) { + /* no more entries => close directory */ + _findclose (d->hFile); + d->closed = 1; + return 0; + } else { + lua_pushstring (L, c_file.name); + return 1; + } + } +#else + if ((entry = readdir (d->dir)) != NULL) { + lua_pushstring (L, entry->d_name); + return 1; + } else { + /* no more entries => close directory */ + closedir (d->dir); + d->closed = 1; + return 0; + } +#endif +} + + +/* +** Closes directory iterators +*/ +static int dir_close (lua_State *L) { + dir_data *d = (dir_data *)lua_touserdata (L, 1); +#ifdef _WIN32 + if (!d->closed && d->hFile) { + _findclose (d->hFile); + } +#else + if (!d->closed && d->dir) { + closedir (d->dir); + } +#endif + d->closed = 1; + return 0; +} + + +/* +** Factory of directory iterators +*/ +static int dir_iter_factory (lua_State *L) { + const char *path = luaL_checkstring (L, 1); + dir_data *d; + lua_pushcfunction (L, dir_iter); + d = (dir_data *) lua_newuserdata (L, sizeof(dir_data)); + luaL_getmetatable (L, DIR_METATABLE); + lua_setmetatable (L, -2); + d->closed = 0; +#ifdef _WIN32 + d->hFile = 0L; + if (strlen(path) > MAX_PATH-2) + luaL_error (L, "path too long: %s", path); + else + sprintf (d->pattern, "%s/*", path); +#else + d->dir = opendir (path); + if (d->dir == NULL) + luaL_error (L, "cannot open %s: %s", path, strerror (errno)); +#endif + return 2; +} + + +/* +** Creates directory metatable. +*/ +static int dir_create_meta (lua_State *L) { + luaL_newmetatable (L, DIR_METATABLE); + + /* Method table */ + lua_newtable(L); + lua_pushcfunction (L, dir_iter); + lua_setfield(L, -2, "next"); + lua_pushcfunction (L, dir_close); + lua_setfield(L, -2, "close"); + + /* Metamethods */ + lua_setfield(L, -2, "__index"); + lua_pushcfunction (L, dir_close); + lua_setfield (L, -2, "__gc"); + return 1; +} + + +/* +** Creates lock metatable. +*/ +static int lock_create_meta (lua_State *L) { + luaL_newmetatable (L, LOCK_METATABLE); + + /* Method table */ + lua_newtable(L); + lua_pushcfunction(L, lfs_unlock_dir); + lua_setfield(L, -2, "free"); + + /* Metamethods */ + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, lfs_unlock_dir); + lua_setfield(L, -2, "__gc"); + return 1; +} + + +#ifdef _WIN32 + #ifndef S_ISDIR + #define S_ISDIR(mode) (mode&_S_IFDIR) + #endif + #ifndef S_ISREG + #define S_ISREG(mode) (mode&_S_IFREG) + #endif + #ifndef S_ISLNK + #define S_ISLNK(mode) (0) + #endif + #ifndef S_ISSOCK + #define S_ISSOCK(mode) (0) + #endif + #ifndef S_ISFIFO + #define S_ISFIFO(mode) (0) + #endif + #ifndef S_ISCHR + #define S_ISCHR(mode) (mode&_S_IFCHR) + #endif + #ifndef S_ISBLK + #define S_ISBLK(mode) (0) + #endif +#endif +/* +** Convert the inode protection mode to a string. +*/ +#ifdef _WIN32 +static const char *mode2string (unsigned short mode) { +#else +static const char *mode2string (mode_t mode) { +#endif + if ( S_ISREG(mode) ) + return "file"; + else if ( S_ISDIR(mode) ) + return "directory"; + else if ( S_ISLNK(mode) ) + return "link"; + else if ( S_ISSOCK(mode) ) + return "socket"; + else if ( S_ISFIFO(mode) ) + return "named pipe"; + else if ( S_ISCHR(mode) ) + return "char device"; + else if ( S_ISBLK(mode) ) + return "block device"; + else + return "other"; +} + + +/* +** Set access time and modification values for file +*/ +static int file_utime (lua_State *L) { + const char *file = luaL_checkstring (L, 1); + struct utimbuf utb, *buf; + + if (lua_gettop (L) == 1) /* set to current date/time */ + buf = NULL; + else { + utb.actime = luaL_optnumber (L, 2, 0); + utb.modtime = (time_t) luaL_optinteger (L, 3, utb.actime); + buf = &utb; + } + if (utime (file, buf)) { + lua_pushnil (L); + lua_pushfstring (L, "%s", strerror (errno)); + return 2; + } + lua_pushboolean (L, 1); + return 1; +} + + +/* inode protection mode */ +static void push_st_mode (lua_State *L, STAT_STRUCT *info) { + lua_pushstring (L, mode2string (info->st_mode)); +} +/* device inode resides on */ +static void push_st_dev (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_dev); +} +/* inode's number */ +static void push_st_ino (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_ino); +} +/* number of hard links to the file */ +static void push_st_nlink (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_nlink); +} +/* user-id of owner */ +static void push_st_uid (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_uid); +} +/* group-id of owner */ +static void push_st_gid (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_gid); +} +/* device type, for special file inode */ +static void push_st_rdev (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_rdev); +} +/* time of last access */ +static void push_st_atime (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_atime); +} +/* time of last data modification */ +static void push_st_mtime (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_mtime); +} +/* time of last file status change */ +static void push_st_ctime (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer) info->st_ctime); +} +/* file size, in bytes */ +static void push_st_size (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_size); +} +#ifndef _WIN32 +/* blocks allocated for file */ +static void push_st_blocks (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_blocks); +} +/* optimal file system I/O blocksize */ +static void push_st_blksize (lua_State *L, STAT_STRUCT *info) { + lua_pushinteger (L, (lua_Integer)info->st_blksize); +} +#endif + + /* +** Convert the inode protection mode to a permission list. +*/ + +#ifdef _WIN32 +static const char *perm2string (unsigned short mode) { + static char perms[10] = "---------"; + int i; + for (i=0;i<9;i++) perms[i]='-'; + if (mode & _S_IREAD) + { perms[0] = 'r'; perms[3] = 'r'; perms[6] = 'r'; } + if (mode & _S_IWRITE) + { perms[1] = 'w'; perms[4] = 'w'; perms[7] = 'w'; } + if (mode & _S_IEXEC) + { perms[2] = 'x'; perms[5] = 'x'; perms[8] = 'x'; } + return perms; +} +#else +static const char *perm2string (mode_t mode) { + static char perms[10] = "---------"; + int i; + for (i=0;i<9;i++) perms[i]='-'; + if (mode & S_IRUSR) perms[0] = 'r'; + if (mode & S_IWUSR) perms[1] = 'w'; + if (mode & S_IXUSR) perms[2] = 'x'; + if (mode & S_IRGRP) perms[3] = 'r'; + if (mode & S_IWGRP) perms[4] = 'w'; + if (mode & S_IXGRP) perms[5] = 'x'; + if (mode & S_IROTH) perms[6] = 'r'; + if (mode & S_IWOTH) perms[7] = 'w'; + if (mode & S_IXOTH) perms[8] = 'x'; + return perms; +} +#endif + +/* permssions string */ +static void push_st_perm (lua_State *L, STAT_STRUCT *info) { + lua_pushstring (L, perm2string (info->st_mode)); +} + +typedef void (*_push_function) (lua_State *L, STAT_STRUCT *info); + +struct _stat_members { + const char *name; + _push_function push; +}; + +struct _stat_members members[] = { + { "mode", push_st_mode }, + { "dev", push_st_dev }, + { "ino", push_st_ino }, + { "nlink", push_st_nlink }, + { "uid", push_st_uid }, + { "gid", push_st_gid }, + { "rdev", push_st_rdev }, + { "access", push_st_atime }, + { "modification", push_st_mtime }, + { "change", push_st_ctime }, + { "size", push_st_size }, + { "permissions", push_st_perm }, +#ifndef _WIN32 + { "blocks", push_st_blocks }, + { "blksize", push_st_blksize }, +#endif + { NULL, NULL } +}; + +/* +** Get file or symbolic link information +*/ +static int _file_info_ (lua_State *L, int (*st)(const char*, STAT_STRUCT*)) { + STAT_STRUCT info; + const char *file = luaL_checkstring (L, 1); + int i; + + if (st(file, &info)) { + lua_pushnil (L); + lua_pushfstring (L, "cannot obtain information from file `%s'", file); + return 2; + } + if (lua_isstring (L, 2)) { + const char *member = lua_tostring (L, 2); + for (i = 0; members[i].name; i++) { + if (strcmp(members[i].name, member) == 0) { + /* push member value and return */ + members[i].push (L, &info); + return 1; + } + } + /* member not found */ + return luaL_error(L, "invalid attribute name"); + } + /* creates a table if none is given */ + if (!lua_istable (L, 2)) { + lua_newtable (L); + } + /* stores all members in table on top of the stack */ + for (i = 0; members[i].name; i++) { + lua_pushstring (L, members[i].name); + members[i].push (L, &info); + lua_rawset (L, -3); + } + return 1; +} + + +/* +** Get file information using stat. +*/ +static int file_info (lua_State *L) { + return _file_info_ (L, STAT_FUNC); +} + + +/* +** Get symbolic link information using lstat. +*/ +static int link_info (lua_State *L) { + return _file_info_ (L, LSTAT_FUNC); +} + + +/* +** Assumes the table is on top of the stack. +*/ +static void set_info (lua_State *L) { + lua_pushliteral (L, "_COPYRIGHT"); + lua_pushliteral (L, "Copyright (C) 2003-2012 Kepler Project"); + lua_settable (L, -3); + lua_pushliteral (L, "_DESCRIPTION"); + lua_pushliteral (L, "LuaFileSystem is a Lua library developed to complement the set of functions related to file systems offered by the standard Lua distribution"); + lua_settable (L, -3); + lua_pushliteral (L, "_VERSION"); + lua_pushliteral (L, "LuaFileSystem "LFS_VERSION); + lua_settable (L, -3); +} + + +static const struct luaL_Reg fslib[] = { + {"attributes", file_info}, + {"chdir", change_dir}, + {"currentdir", get_dir}, + {"dir", dir_iter_factory}, + {"link", make_link}, + {"lock", file_lock}, + {"mkdir", make_dir}, + {"rmdir", remove_dir}, + {"symlinkattributes", link_info}, + {"setmode", lfs_f_setmode}, + {"touch", file_utime}, + {"unlock", file_unlock}, + {"lock_dir", lfs_lock_dir}, + {NULL, NULL}, +}; + +int luaopen_lfs (lua_State *L) { + dir_create_meta (L); + lock_create_meta (L); + luaL_newlib (L, fslib); + lua_pushvalue(L, -1); + lua_setglobal(L, LFS_LIBNAME); + set_info (L); + return 1; +} diff --git a/3rdparty/luafilesystem/src/lfs.def b/3rdparty/luafilesystem/src/lfs.def new file mode 100644 index 00000000000..6c782eb6968 --- /dev/null +++ b/3rdparty/luafilesystem/src/lfs.def @@ -0,0 +1,4 @@ +LIBRARY lfs.dll +VERSION 1.6 +EXPORTS +luaopen_lfs diff --git a/3rdparty/luafilesystem/src/lfs.h b/3rdparty/luafilesystem/src/lfs.h new file mode 100644 index 00000000000..ea1720dba75 --- /dev/null +++ b/3rdparty/luafilesystem/src/lfs.h @@ -0,0 +1,34 @@ +/* +** LuaFileSystem +** Copyright Kepler Project 2003 (http://www.keplerproject.org/luafilesystem) +** +** $Id: lfs.h,v 1.5 2008/02/19 20:08:23 mascarenhas Exp $ +*/ + +/* Define 'chdir' for systems that do not implement it */ +#ifdef NO_CHDIR +#define chdir(p) (-1) +#define chdir_error "Function 'chdir' not provided by system" +#else +#define chdir_error strerror(errno) + +#endif + +#ifdef _WIN32 +#define chdir(p) (_chdir(p)) +#define getcwd(d, s) (_getcwd(d, s)) +#define rmdir(p) (_rmdir(p)) +#ifndef fileno +#define fileno(f) (_fileno(f)) +#endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +int luaopen_lfs (lua_State *L); + +#ifdef __cplusplus +} +#endif diff --git a/3rdparty/luafilesystem/tests/test.lua b/3rdparty/luafilesystem/tests/test.lua new file mode 100644 index 00000000000..abfbd4d9690 --- /dev/null +++ b/3rdparty/luafilesystem/tests/test.lua @@ -0,0 +1,175 @@ +#!/usr/bin/env lua5.1 + +local tmp = "/tmp" +local sep = string.match (package.config, "[^\n]+") +local upper = ".." + +local lfs = require"lfs" +print (lfs._VERSION) + +io.write(".") +io.flush() + +function attrdir (path) + for file in lfs.dir(path) do + if file ~= "." and file ~= ".." then + local f = path..sep..file + print ("\t=> "..f.." <=") + local attr = lfs.attributes (f) + assert (type(attr) == "table") + if attr.mode == "directory" then + attrdir (f) + else + for name, value in pairs(attr) do + print (name, value) + end + end + end + end +end + +-- Checking changing directories +local current = assert (lfs.currentdir()) +local reldir = string.gsub (current, "^.*%"..sep.."([^"..sep.."])$", "%1") +assert (lfs.chdir (upper), "could not change to upper directory") +assert (lfs.chdir (reldir), "could not change back to current directory") +assert (lfs.currentdir() == current, "error trying to change directories") +assert (lfs.chdir ("this couldn't be an actual directory") == nil, "could change to a non-existent directory") + +io.write(".") +io.flush() + +-- Changing creating and removing directories +local tmpdir = current..sep.."lfs_tmp_dir" +local tmpfile = tmpdir..sep.."tmp_file" +-- Test for existence of a previous lfs_tmp_dir +-- that may have resulted from an interrupted test execution and remove it +if lfs.chdir (tmpdir) then + assert (lfs.chdir (upper), "could not change to upper directory") + assert (os.remove (tmpfile), "could not remove file from previous test") + assert (lfs.rmdir (tmpdir), "could not remove directory from previous test") +end + +io.write(".") +io.flush() + +-- tries to create a directory +assert (lfs.mkdir (tmpdir), "could not make a new directory") +local attrib, errmsg = lfs.attributes (tmpdir) +if not attrib then + error ("could not get attributes of file `"..tmpdir.."':\n"..errmsg) +end +local f = io.open(tmpfile, "w") +f:close() + +io.write(".") +io.flush() + +-- Change access time +local testdate = os.time({ year = 2007, day = 10, month = 2, hour=0}) +assert (lfs.touch (tmpfile, testdate)) +local new_att = assert (lfs.attributes (tmpfile)) +assert (new_att.access == testdate, "could not set access time") +assert (new_att.modification == testdate, "could not set modification time") + +io.write(".") +io.flush() + +-- Change access and modification time +local testdate1 = os.time({ year = 2007, day = 10, month = 2, hour=0}) +local testdate2 = os.time({ year = 2007, day = 11, month = 2, hour=0}) + +assert (lfs.touch (tmpfile, testdate2, testdate1)) +local new_att = assert (lfs.attributes (tmpfile)) +assert (new_att.access == testdate2, "could not set access time") +assert (new_att.modification == testdate1, "could not set modification time") + +io.write(".") +io.flush() + +-- Checking link (does not work on Windows) +if lfs.link (tmpfile, "_a_link_for_test_", true) then + assert (lfs.attributes"_a_link_for_test_".mode == "file") + assert (lfs.symlinkattributes"_a_link_for_test_".mode == "link") + assert (lfs.link (tmpfile, "_a_hard_link_for_test_")) + assert (lfs.attributes (tmpfile, "nlink") == 2) + assert (os.remove"_a_link_for_test_") + assert (os.remove"_a_hard_link_for_test_") +end + +io.write(".") +io.flush() + +-- Checking text/binary modes (only has an effect in Windows) +local f = io.open(tmpfile, "w") +local result, mode = lfs.setmode(f, "binary") +assert(result) -- on non-Windows platforms, mode is always returned as "binary" +result, mode = lfs.setmode(f, "text") +assert(result and mode == "binary") +f:close() + +io.write(".") +io.flush() + +-- Restore access time to current value +assert (lfs.touch (tmpfile, attrib.access, attrib.modification)) +new_att = assert (lfs.attributes (tmpfile)) +assert (new_att.access == attrib.access) +assert (new_att.modification == attrib.modification) + +io.write(".") +io.flush() + +-- Check consistency of lfs.attributes values +local attr = lfs.attributes (tmpfile) +for key, value in pairs(attr) do + assert (value == lfs.attributes (tmpfile, key), + "lfs.attributes values not consistent") +end + +-- Remove new file and directory +assert (os.remove (tmpfile), "could not remove new file") +assert (lfs.rmdir (tmpdir), "could not remove new directory") +assert (lfs.mkdir (tmpdir..sep.."lfs_tmp_dir") == nil, "could create a directory inside a non-existent one") + +io.write(".") +io.flush() + +-- Trying to get attributes of a non-existent file +assert (lfs.attributes ("this couldn't be an actual file") == nil, "could get attributes of a non-existent file") +assert (type(lfs.attributes (upper)) == "table", "couldn't get attributes of upper directory") + +io.write(".") +io.flush() + +-- Stressing directory iterator +count = 0 +for i = 1, 4000 do + for file in lfs.dir (tmp) do + count = count + 1 + end +end + +io.write(".") +io.flush() + +-- Stressing directory iterator, explicit version +count = 0 +for i = 1, 4000 do + local iter, dir = lfs.dir(tmp) + local file = dir:next() + while file do + count = count + 1 + file = dir:next() + end + assert(not pcall(dir.next, dir)) +end + +io.write(".") +io.flush() + +-- directory explicit close +local iter, dir = lfs.dir(tmp) +dir:close() +assert(not pcall(dir.next, dir)) +print"Ok!" diff --git a/3rdparty/luafilesystem/vc6/lfs.def b/3rdparty/luafilesystem/vc6/lfs.def new file mode 100644 index 00000000000..55ec688d3c3 --- /dev/null +++ b/3rdparty/luafilesystem/vc6/lfs.def @@ -0,0 +1,5 @@ +LIBRARY lfs.dll +DESCRIPTION "LuaFileSystem" +VERSION 1.2 +EXPORTS +luaopen_lfs diff --git a/3rdparty/luafilesystem/vc6/luafilesystem.dsw b/3rdparty/luafilesystem/vc6/luafilesystem.dsw new file mode 100644 index 00000000000..b4bb4b310f6 --- /dev/null +++ b/3rdparty/luafilesystem/vc6/luafilesystem.dsw @@ -0,0 +1,33 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "luafilesystem_dll"=.\luafilesystem_dll.dsp - Package Owner=<4> + +Package=<5> +{{{ + begin source code control + luafilesystem + .. + end source code control +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/3rdparty/luafilesystem/vc6/luafilesystem_dll.dsp b/3rdparty/luafilesystem/vc6/luafilesystem_dll.dsp new file mode 100644 index 00000000000..efe6c720b6c --- /dev/null +++ b/3rdparty/luafilesystem/vc6/luafilesystem_dll.dsp @@ -0,0 +1,127 @@ +# Microsoft Developer Studio Project File - Name="luafilesystem_dll" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=luafilesystem_dll - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "luafilesystem_dll.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "luafilesystem_dll.mak" CFG="luafilesystem_dll - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "luafilesystem_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "luafilesystem_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "luafilesystem_dll" +# PROP Scc_LocalPath ".." +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "luafilesystem_dll - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "../lib/vc6" +# PROP Intermediate_Dir "luafilesystem_dll/Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAFILESYSTEM_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../../external-src/lua50/include" /I "../../compat/src" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAFILESYSTEM_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x416 /d "NDEBUG" +# ADD RSC /l 0x416 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 lua50.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../bin/vc6/lfs.dll" /libpath:"../../external-src/lua50/lib/dll" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=cd ../bin/vc6 zip.exe luafilesystem-1.2-win32.zip lfs.dll +# End Special Build Tool + +!ELSEIF "$(CFG)" == "luafilesystem_dll - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../lib/vc6" +# PROP Intermediate_Dir "luafilesystem_dll/Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAFILESYSTEM_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "../../external-src/lua50/include" /I "../../compat/src" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LUAFILESYSTEM_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x416 /d "_DEBUG" +# ADD RSC /l 0x416 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 lua50.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../bin/vc6/lfsd.dll" /pdbtype:sept /libpath:"../../external-src/lua50/lib/dll" + +!ENDIF + +# Begin Target + +# Name "luafilesystem_dll - Win32 Release" +# Name "luafilesystem_dll - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\compat\src\compat-5.1.c" +# End Source File +# Begin Source File + +SOURCE=..\src\lfs.c +# End Source File +# Begin Source File + +SOURCE=.\lfs.def +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\compat\src\compat-5.1.h" +# End Source File +# Begin Source File + +SOURCE=..\src\lfs.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/3rdparty/luv/.ci/install.bat b/3rdparty/luv/.ci/install.bat new file mode 100644 index 00000000000..1ee346dccc9 --- /dev/null +++ b/3rdparty/luv/.ci/install.bat @@ -0,0 +1,270 @@ +@echo off + +cd %APPVEYOR_BUILD_FOLDER% + +:: ========================================================= +:: Set some defaults. Infer some variables. +:: +:: These are set globally +if "%LUA_VER%" NEQ "" ( + set LUA=lua + set LUA_SHORTV=%LUA_VER:~0,3% +) else ( + set LUA=luajit + set LJ_SHORTV=%LJ_VER:~0,3% + set LUA_SHORTV=5.1 +) + +:: defines LUA_DIR so Cmake can find this Lua install +if "%LUA%"=="luajit" ( + set LUA_DIR=c:\lua\%platform%\lj%LJ_SHORTV% +) else ( + set LUA_DIR=c:\lua\%platform%\%LUA_VER% +) + +:: Now we declare a scope +Setlocal EnableDelayedExpansion EnableExtensions + +if not defined LUAROCKS_URL set LUAROCKS_URL=http://keplerproject.github.io/luarocks/releases +if not defined LUAROCKS_REPO set LUAROCKS_REPO=https://luarocks.org +if not defined LUA_URL set LUA_URL=http://www.lua.org/ftp +if defined NOCOMPAT ( + set COMPATFLAG=--nocompat +) else ( + set COMPATFLAG= +) +if not defined LUAJIT_GIT_REPO set LUAJIT_GIT_REPO=https://github.com/LuaJIT/LuaJIT.git +if not defined LUAJIT_URL set LUAJIT_URL=https://github.com/LuaJIT/LuaJIT/archive + +if not defined LR_EXTERNAL set LR_EXTERNAL=c:\external +if not defined LUAROCKS_INSTALL set LUAROCKS_INSTALL=%LUA_DIR%\LuaRocks + + +:: LuaRocks <= 2.2.2 used a versioned directory +:: HEAD and newer versions do not, so act accordingly. +if defined LR_ROOT goto :skiplrver + +if "%LUAROCKS_VER%" EQU "HEAD" ( + set LR_ROOT=%LUAROCKS_INSTALL% + goto :skiplrver +) +set LR_ROOT=%LUAROCKS_INSTALL% +if %LUAROCKS_VER:~0,1% LEQ 2 ( + if %LUAROCKS_VER:~2,1% LEQ 2 ( + if %LUAROCKS_VER:~4,1% LEQ 3 ( + set LR_ROOT=%LUAROCKS_INSTALL%\!LUAROCKS_VER:~0,3! + ) + ) +) +:skiplrver + +if not defined LR_SYSTREE set LR_SYSTREE=%LUAROCKS_INSTALL%\systree + +if not defined SEVENZIP set SEVENZIP=7z +:: +:: ========================================================= + +:: first create some necessary directories: +mkdir downloads 2>NUL + +:: Download and compile Lua (or LuaJIT) +if "%LUA%"=="luajit" ( + if not exist %LUA_DIR% ( + if "%LJ_SHORTV%"=="2.1" ( + :: Clone repository and checkout 2.1 branch + set lj_source_folder=%APPVEYOR_BUILD_FOLDER%\downloads\luajit-%LJ_VER% + if not exist !lj_source_folder! ( + echo Cloning git repo %LUAJIT_GIT_REPO% !lj_source_folder! + git clone %LUAJIT_GIT_REPO% !lj_source_folder! || call :die "Failed to clone repository" + ) else ( + cd !lj_source_folder! + git pull || call :die "Failed to update repository" + ) + cd !lj_source_folder!\src + git checkout v2.1 || call :die + ) else ( + set lj_source_folder=%APPVEYOR_BUILD_FOLDER%\downloads\luajit-%LJ_VER% + if not exist !lj_source_folder! ( + echo Downloading... %LUAJIT_URL%/v%LJ_VER%.tar.gz + curl --location --silent --fail --max-time 120 --connect-timeout 30 %LUAJIT_URL%/v%LJ_VER%.tar.gz | %SEVENZIP% x -si -so -tgzip | %SEVENZIP% x -si -ttar -aoa -odownloads + ) + cd !lj_source_folder!\src + ) + :: Compiles LuaJIT + if "%Configuration%"=="MinGW" ( + call mingw32-make + ) else ( + call msvcbuild.bat + ) + + mkdir %LUA_DIR% 2> NUL + for %%a in (bin bin\lua bin\lua\jit include lib) do ( mkdir "%LUA_DIR%\%%a" ) + + for %%a in (luajit.exe lua51.dll) do ( move "!lj_source_folder!\src\%%a" "%LUA_DIR%\bin" ) + copy "%LUA_DIR%\bin\luajit.exe" "%LUA_DIR%\bin\lua.exe" + + move "!lj_source_folder!\src\lua51.lib" "%LUA_DIR%\lib" + for %%a in (lauxlib.h lua.h lua.hpp luaconf.h lualib.h luajit.h) do ( + copy "!lj_source_folder!\src\%%a" "%LUA_DIR%\include" + ) + + copy "!lj_source_folder!\src\jit\*.lua" "%LUA_DIR%\bin\lua\jit" + + ) else ( + echo LuaJIT %LJ_VER% already installed at %LUA_DIR% + ) +) else ( + if not exist %LUA_DIR% ( + :: Download and compile Lua + if not exist downloads\lua-%LUA_VER% ( + curl --silent --fail --max-time 120 --connect-timeout 30 %LUA_URL%/lua-%LUA_VER%.tar.gz | %SEVENZIP% x -si -so -tgzip | %SEVENZIP% x -si -ttar -aoa -odownloads + ) + + mkdir downloads\lua-%LUA_VER%\etc 2> NUL + copy %~dp0\winmake.bat downloads\lua-%LUA_VER%\etc\winmake.bat + + cd downloads\lua-%LUA_VER% + call etc\winmake %COMPATFLAG% + call etc\winmake install %LUA_DIR% + ) else ( + echo Lua %LUA_VER% already installed at %LUA_DIR% + ) +) + +if not exist %LUA_DIR%\bin\%LUA%.exe call :die "Missing Lua interpreter at %LUA_DIR%\bin\%LUA%.exe" + +set PATH=%LUA_DIR%\bin;%PATH% +call !LUA! -v + + + +:: ========================================================== +:: LuaRocks +:: ========================================================== + +if not exist "%LR_ROOT%" ( + :: Downloads and installs LuaRocks + cd %APPVEYOR_BUILD_FOLDER% + + if %LUAROCKS_VER%==HEAD ( + set lr_source_folder=%APPVEYOR_BUILD_FOLDER%\downloads\luarocks-%LUAROCKS_VER%-win32 + if not exist !lr_source_folder! ( + git clone https://github.com/keplerproject/luarocks.git --single-branch --depth 1 !lr_source_folder! || call :die "Failed to clone LuaRocks repository" + ) else ( + cd !lr_source_folder! + git pull || call :die "Failed to update LuaRocks repository" + ) + ) else ( + if not exist downloads\luarocks-%LUAROCKS_VER%-win32.zip ( + echo Downloading LuaRocks... + curl --silent --fail --max-time 120 --connect-timeout 30 --output downloads\luarocks-%LUAROCKS_VER%-win32.zip %LUAROCKS_URL%/luarocks-%LUAROCKS_VER%-win32.zip + %SEVENZIP% x -aoa -odownloads downloads\luarocks-%LUAROCKS_VER%-win32.zip + ) + ) + + cd downloads\luarocks-%LUAROCKS_VER%-win32 + if "%Configuration%"=="MinGW" ( + call install.bat /LUA %LUA_DIR% /Q /LV %LUA_SHORTV% /P "%LUAROCKS_INSTALL%" /TREE "%LR_SYSTREE%" /MW + ) else ( + call install.bat /LUA %LUA_DIR% /Q /LV %LUA_SHORTV% /P "%LUAROCKS_INSTALL%" /TREE "%LR_SYSTREE%" + ) + + :: Configures LuaRocks to instruct CMake the correct generator to use. Else, CMake will pick the highest + :: Visual Studio version installed + if "%Configuration%"=="MinGW" ( + echo cmake_generator = "MinGW Makefiles" >> %LUAROCKS_INSTALL%\config-%LUA_SHORTV%.lua + ) else ( + set MSVS_GENERATORS[2008]=Visual Studio 9 2008 + set MSVS_GENERATORS[2010]=Visual Studio 10 2010 + set MSVS_GENERATORS[2012]=Visual Studio 11 2012 + set MSVS_GENERATORS[2013]=Visual Studio 12 2013 + set MSVS_GENERATORS[2015]=Visual Studio 14 2015 + + set CMAKE_GENERATOR=!MSVS_GENERATORS[%Configuration%]! + if "%platform%" EQU "x64" (set CMAKE_GENERATOR=!CMAKE_GENERATOR! Win64) + + echo cmake_generator = "!CMAKE_GENERATOR!" >> %LUAROCKS_INSTALL%\config-%LUA_SHORTV%.lua + ) +) + +if not exist "%LR_ROOT%" call :die "LuaRocks not found at %LR_ROOT%" + +set PATH=%LR_ROOT%;%LR_SYSTREE%\bin;%PATH% + +:: Lua will use just the system rocks +set LUA_PATH=%LR_ROOT%\lua\?.lua;%LR_ROOT%\lua\?\init.lua +set LUA_PATH=%LUA_PATH%;%LR_SYSTREE%\share\lua\%LUA_SHORTV%\?.lua +set LUA_PATH=%LUA_PATH%;%LR_SYSTREE%\share\lua\%LUA_SHORTV%\?\init.lua +set LUA_PATH=%LUA_PATH%;.\?.lua;.\?\init.lua +set LUA_CPATH=%LR_SYSTREE%\lib\lua\%LUA_SHORTV%\?.dll;.\?.dll + +call luarocks --version || call :die "Error with LuaRocks installation" +call luarocks list + + +if not exist "%LR_EXTERNAL%" ( + mkdir "%LR_EXTERNAL%" + mkdir "%LR_EXTERNAL%\lib" + mkdir "%LR_EXTERNAL%\include" +) + +set PATH=%LR_EXTERNAL%;%PATH% + +:: Exports the following variables: +:: (beware of whitespace between & and ^ below) +endlocal & set PATH=%PATH%&^ +set LR_SYSTREE=%LR_SYSTREE%&^ +set LUA_PATH=%LUA_PATH%&^ +set LUA_CPATH=%LUA_CPATH%&^ +set LR_EXTERNAL=%LR_EXTERNAL% + +echo. +echo ====================================================== +if "%LUA%"=="luajit" ( + echo Installation of LuaJIT %LJ_VER% and LuaRocks %LUAROCKS_VER% done. +) else ( + echo Installation of Lua %LUA_VER% and LuaRocks %LUAROCKS_VER% done. + if defined NOCOMPAT echo Lua was built with compatibility flags disabled. +) +echo Platform - %platform% +echo LUA - %LUA% +echo LUA_SHORTV - %LUA_SHORTV% +echo LJ_SHORTV - %LJ_SHORTV% +echo LUA_PATH - %LUA_PATH% +echo LUA_CPATH - %LUA_CPATH% +echo. +echo LR_EXTERNAL - %LR_EXTERNAL% +echo ====================================================== +echo. + +goto :eof + + + + + + + + + + + + + + + + + + +:: This blank space is intentional. If you see errors like "The system cannot find the batch label specified 'foo'" +:: then try adding or removing blank lines lines above. +:: Yes, really. +:: http://stackoverflow.com/questions/232651/why-the-system-cannot-find-the-batch-label-specified-is-thrown-even-if-label-e + +:: helper functions: + +:: for bailing out when an error occurred +:die %1 +echo %1 +exit /B 1 +goto :eof diff --git a/3rdparty/luv/.ci/platform.sh b/3rdparty/luv/.ci/platform.sh new file mode 100644 index 00000000000..7259a7d6369 --- /dev/null +++ b/3rdparty/luv/.ci/platform.sh @@ -0,0 +1,15 @@ +if [ -z "${PLATFORM:-}" ]; then + PLATFORM=$TRAVIS_OS_NAME; +fi + +if [ "$PLATFORM" == "osx" ]; then + PLATFORM="macosx"; +fi + +if [ -z "$PLATFORM" ]; then + if [ "$(uname)" == "Linux" ]; then + PLATFORM="linux"; + else + PLATFORM="macosx"; + fi; +fi diff --git a/3rdparty/luv/.ci/set_compiler_env.bat b/3rdparty/luv/.ci/set_compiler_env.bat new file mode 100644 index 00000000000..7e8462ec57e --- /dev/null +++ b/3rdparty/luv/.ci/set_compiler_env.bat @@ -0,0 +1,40 @@ +@echo off + +:: Now we declare a scope +Setlocal EnableDelayedExpansion EnableExtensions + +if not defined Configuration set Configuration=2015 + +if "%Configuration%"=="MinGW" ( goto :mingw ) + +set arch=x86 + +if "%platform%" EQU "x64" ( set arch=x86_amd64 ) + +if "%Configuration%"=="2015" ( + set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" +) + +if "%Configuration%"=="2013" ( + set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" +) + +if "%Configuration%"=="2012" ( + set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" +) + +if "%Configuration%"=="2010" ( + set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" +) + +if "%Configuration%"=="2008" ( + set SET_VS_ENV="C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" +) + +:: Visual Studio detected +endlocal & call %SET_VS_ENV% %arch% +goto :eof + +:: MinGW detected +:mingw +endlocal & set PATH=c:\mingw\bin;%PATH% diff --git a/3rdparty/luv/.ci/setenv_lua.sh b/3rdparty/luv/.ci/setenv_lua.sh new file mode 100644 index 00000000000..55454389398 --- /dev/null +++ b/3rdparty/luv/.ci/setenv_lua.sh @@ -0,0 +1,3 @@ +export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/luarocks/bin +bash .ci/setup_lua.sh +eval `$HOME/.lua/luarocks path` diff --git a/3rdparty/luv/.ci/setup_lua.sh b/3rdparty/luv/.ci/setup_lua.sh new file mode 100644 index 00000000000..f8963331767 --- /dev/null +++ b/3rdparty/luv/.ci/setup_lua.sh @@ -0,0 +1,122 @@ +#! /bin/bash + +# A script for setting up environment for travis-ci testing. +# Sets up Lua and Luarocks. +# LUA must be "lua5.1", "lua5.2" or "luajit". +# luajit2.0 - master v2.0 +# luajit2.1 - master v2.1 + +set -eufo pipefail + +LUAJIT_VERSION="2.0.4" +LUAJIT_BASE="LuaJIT-$LUAJIT_VERSION" + +source .ci/platform.sh + +LUA_HOME_DIR=$TRAVIS_BUILD_DIR/install/lua + +LR_HOME_DIR=$TRAVIS_BUILD_DIR/install/luarocks + +mkdir $HOME/.lua + +LUAJIT="no" + +if [ "$PLATFORM" == "macosx" ]; then + if [ "$LUA" == "luajit" ]; then + LUAJIT="yes"; + fi + if [ "$LUA" == "luajit2.0" ]; then + LUAJIT="yes"; + fi + if [ "$LUA" == "luajit2.1" ]; then + LUAJIT="yes"; + fi; +elif [ "$(expr substr $LUA 1 6)" == "luajit" ]; then + LUAJIT="yes"; +fi + +mkdir -p "$LUA_HOME_DIR" + +if [ "$LUAJIT" == "yes" ]; then + + if [ "$LUA" == "luajit" ]; then + curl --location https://github.com/LuaJIT/LuaJIT/archive/v$LUAJIT_VERSION.tar.gz | tar xz; + else + git clone https://github.com/LuaJIT/LuaJIT.git $LUAJIT_BASE; + fi + + cd $LUAJIT_BASE + + if [ "$LUA" == "luajit2.1" ]; then + git checkout v2.1; + # force the INSTALL_TNAME to be luajit + perl -i -pe 's/INSTALL_TNAME=.+/INSTALL_TNAME= luajit/' Makefile + fi + + make && make install PREFIX="$LUA_HOME_DIR" + + ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/luajit + ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/lua; + +else + + if [ "$LUA" == "lua5.1" ]; then + curl http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz + cd lua-5.1.5; + elif [ "$LUA" == "lua5.2" ]; then + curl http://www.lua.org/ftp/lua-5.2.4.tar.gz | tar xz + cd lua-5.2.4; + elif [ "$LUA" == "lua5.3" ]; then + curl http://www.lua.org/ftp/lua-5.3.2.tar.gz | tar xz + cd lua-5.3.2; + fi + + # Build Lua without backwards compatibility for testing + perl -i -pe 's/-DLUA_COMPAT_(ALL|5_2)//' src/Makefile + make $PLATFORM + make INSTALL_TOP="$LUA_HOME_DIR" install; + + ln -s $LUA_HOME_DIR/bin/lua $HOME/.lua/lua + ln -s $LUA_HOME_DIR/bin/luac $HOME/.lua/luac; + +fi + +cd $TRAVIS_BUILD_DIR + +lua -v + +LUAROCKS_BASE=luarocks-$LUAROCKS + +curl --location http://luarocks.org/releases/$LUAROCKS_BASE.tar.gz | tar xz + +cd $LUAROCKS_BASE + +if [ "$LUA" == "luajit" ]; then + ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR"; +elif [ "$LUA" == "luajit2.0" ]; then + ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR"; +elif [ "$LUA" == "luajit2.1" ]; then + ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.1" --prefix="$LR_HOME_DIR"; +else + ./configure --with-lua="$LUA_HOME_DIR" --prefix="$LR_HOME_DIR" +fi + +make build && make install + +ln -s $LR_HOME_DIR/bin/luarocks $HOME/.lua/luarocks + +cd $TRAVIS_BUILD_DIR + +luarocks --version + +rm -rf $LUAROCKS_BASE + +if [ "$LUAJIT" == "yes" ]; then + rm -rf $LUAJIT_BASE; +elif [ "$LUA" == "lua5.1" ]; then + rm -rf lua-5.1.5; +elif [ "$LUA" == "lua5.2" ]; then + rm -rf lua-5.2.4; +elif [ "$LUA" == "lua5.3" ]; then + rm -rf lua-5.3.2; +fi diff --git a/3rdparty/luv/.ci/winmake.bat b/3rdparty/luv/.ci/winmake.bat new file mode 100644 index 00000000000..dcad55d36f7 --- /dev/null +++ b/3rdparty/luv/.ci/winmake.bat @@ -0,0 +1,457 @@ +@ECHO OFF +SETLOCAL ENABLEDELAYEDEXPANSION + +REM ***************************** +REM * Customization section * +REM ***************************** + +REM use the /help option for generic usage information + +REM Where is the source code located (the unpacked Lua source archive, toplevel dir) +SET SOURCETREE=.\ + +REM set the toolchain to either MS or GCC (allcaps), leave blank to autodetect +SET TOOLCHAIN= + +REM set the compatibility flags, defaults to empty for 5.1, -DLUA_COMPAT_ALL for 5.2, +REM and -DLUA_COMPAT_5_2 for 5.3, which are the same as the unix make files +REM This setting can be overridden with the --nocompat flag +SET COMPATFLAG= + + + + + + + + + +REM ********************************** +REM * Nothing to customize below * +REM ********************************** + +SET BATCHNAME=%~n0 +SET SOURCE=%SOURCETREE%src\ +SET LUA_H=%SOURCE%lua.h +SET CURDIR=%CD% + +REM the following line ends with a TAB. DO NOT REMOVE IT! +SET TABCHAR= +REM Define LF to contain a linefeed character +set ^"LFCHAR=^ + +^" The above empty line is critical. DO NOT REMOVE + + +REM Supported toolchains (allcaps) +SET TOOLCHAINS=MS GCC +REM Commands which, if exiting without error, indicate presence of the toolchain +SET CHECK_GCC=gcc --version +SET CHECK_MS=cl + +REM ********************************** +REM * Check for help request * +REM ********************************** + +SET HELPCMDS=help -help --help /help ? -? /? +for %%L in ("!LFCHAR!") do for /f %%a in ("!HELPCMDS: =%%~L!") do ( + if "%%a"=="%~1" ( + echo. + echo Builds a standalone Lua installation. Supports Lua version 5.1, 5.2 and 5.3. + echo Your compiler must be in the system path, and this "%BATCHNAME%.bat" file must be located + echo in ".\etc\" in the unpacked Lua source archive. + echo. + echo USAGE etc\%BATCHNAME% [FLAG] [COMMAND] [...] + echo ^(execute from the root of the unpacked archive^) + echo. + echo Commands; + echo clean : cleans the source tree of build ^(intermediate^) files + echo install [path] : installs the build results into "path" + echo local : installs into ".\local\" in the unpacked Lua source structure + echo [toolchain] : uses a specific toolchain to build. If not provided then supported + echo toolchains will be tested and the first available will be picked. + echo Supported toolchains are: "%TOOLCHAINS%" ^(must use ALLCAPS^) + echo. + echo Flags; + echo --nocompat : Specifies that no compatibility flags should be set when building. + echo If not specified, the default compatibility flags will be used. + echo. + echo Example use; + echo set PATH=C:\path\to\your\compiler\;%%PATH%% + echo etc\%BATCHNAME% clean + echo etc\%BATCHNAME% + echo etc\%BATCHNAME% --nocompat GCC + echo etc\%BATCHNAME% install "C:\Program Files\Lua" + echo. + goto :EXITOK + ) +) + +REM ********************************** +REM * Check commandline * +REM ********************************** + +SET CMDOK=FALSE +if "%~1"=="" ( + SET CMDOK=TRUE +) +for %%a in (local install clean) do ( + if "%%a"=="%~1" ( + SET CMDOK=TRUE + ) +) +for %%a in (--nocompat) do ( + if "%%a"=="%~1" ( + SET NOCOMPAT=TRUE + if "%~2"=="" ( + SET CMDOK=TRUE + ) + SHIFT + ) +) +for %%a in (%TOOLCHAINS%) do ( + if "%%a"=="%~1" ( + SET CMDOK=TRUE + SET TOOLCHAIN=%~1 + ) +) +if NOT %CMDOK%==TRUE ( + echo. + echo Unknown command or toolchain specified. + goto :EXITERROR +) + +REM ************************************** +REM * Check for cleaning * +REM ************************************** + +if "%1"=="clean" ( + if NOT [%2]==[] ( + echo. + echo ERROR: The clean command does not take extra parameters. + ) else ( + echo Cleaning... + if exist "%SOURCE%*.exe" del "%SOURCE%*.exe" + if exist "%SOURCE%*.dll" del "%SOURCE%*.dll" + if exist "%SOURCE%*.o" del "%SOURCE%*.o" + if exist "%SOURCE%*.a" del "%SOURCE%*.a" + if exist "%SOURCE%*.obj" del "%SOURCE%*.obj" + if exist "%SOURCE%*.manifest" del "%SOURCE%*.manifest" + if exist "%SOURCE%*.lib" del "%SOURCE%*.lib" + echo Done. + ) + goto :EXITOK +) + +REM ************************************************** +REM * Fetch the Lua version from the source code * +REM ************************************************** + +Echo. +Echo Checking source code to extract Lua version... +IF NOT EXIST %LUA_H% ( + Echo Cannot locate Lua header file; %LUA_H% + goto :EXITERROR +) + +findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MAJOR" %LUA_H% > NUL +if NOT %ERRORLEVEL%==0 ( + rem ECHO We've got a Lua version 5.1 + rem findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION[ %TABCHAR%]" %LUA_H% + SET LUA_VER=5.1 +) else ( + rem ECHO We've got a Lua version 5.2+ + rem findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MAJOR[ %TABCHAR%]" %LUA_H% + rem findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MINOR[ %TABCHAR%]" %LUA_H% + + for /F "delims=" %%a in ('findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MAJOR[ %TABCHAR%]" %LUA_H%') do set LUA_MAJOR=%%a + SET LUA_MAJOR=!LUA_MAJOR:#define=! + SET LUA_MAJOR=!LUA_MAJOR:LUA_VERSION_MAJOR=! + SET LUA_MAJOR=!LUA_MAJOR: =! + SET LUA_MAJOR=!LUA_MAJOR:%TABCHAR%=! + SET LUA_MAJOR=!LUA_MAJOR:"=! + SET LUA_MAJOR=!LUA_MAJOR:~0,1! + + for /F "delims=" %%a in ('findstr /R /C:"#define[ %TABCHAR%][ %TABCHAR%]*LUA_VERSION_MINOR[ %TABCHAR%]" %LUA_H%') do set LUA_MINOR=%%a + SET LUA_MINOR=!LUA_MINOR:#define=! + SET LUA_MINOR=!LUA_MINOR:LUA_VERSION_MINOR=! + SET LUA_MINOR=!LUA_MINOR: =! + SET LUA_MINOR=!LUA_MINOR:%TABCHAR%=! + SET LUA_MINOR=!LUA_MINOR:"=! + SET LUA_MINOR=!LUA_MINOR:~0,1! + + SET LUA_VER=!LUA_MAJOR!.!LUA_MINOR! +) +SET LUA_SVER=!LUA_VER:.=! + +Echo Lua version found: %LUA_VER% +Echo. + +REM ************************************** +REM * Set some Lua version specifics * +REM ************************************** + +REM FILES_CORE; files for Lua core (+lauxlib, needed for Luac) +REM FILES_LIB; files for Lua standard libraries +REM FILES_DLL; vm files to be build with dll option +REM FILES_OTH; vm files to be build without dll, for static linking + +if %LUA_SVER%==51 ( + set FILES_CORE=lapi lcode ldebug ldo ldump lfunc lgc llex lmem lobject lopcodes lparser lstate lstring ltable ltm lundump lvm lzio lauxlib + set FILES_LIB=lbaselib ldblib liolib lmathlib loslib ltablib lstrlib loadlib linit + set FILES_DLL=lua + set FILES_OTH=luac print + set INSTALL_H=lauxlib.h lua.h luaconf.h lualib.h ..\etc\lua.hpp +) +if %LUA_SVER%==52 ( + set FILES_CORE=lapi lcode lctype ldebug ldo ldump lfunc lgc llex lmem lobject lopcodes lparser lstate lstring ltable ltm lundump lvm lzio lauxlib + set FILES_LIB=lbaselib lbitlib lcorolib ldblib liolib lmathlib loslib lstrlib ltablib loadlib linit + set FILES_DLL=lua + set FILES_OTH=luac + set INSTALL_H=lauxlib.h lua.h lua.hpp luaconf.h lualib.h + if "%COMPATFLAG%"=="" ( + set COMPATFLAG=-DLUA_COMPAT_ALL + ) +) +if %LUA_SVER%==53 ( + set FILES_CORE=lapi lcode lctype ldebug ldo ldump lfunc lgc llex lmem lobject lopcodes lparser lstate lstring ltable ltm lundump lvm lzio lauxlib + set FILES_LIB=lbaselib lbitlib lcorolib ldblib liolib lmathlib loslib lstrlib ltablib lutf8lib loadlib linit + set FILES_DLL=lua + set FILES_OTH=luac + set INSTALL_H=lauxlib.h lua.h lua.hpp luaconf.h lualib.h + if "%COMPATFLAG%"=="" ( + set COMPATFLAG=-DLUA_COMPAT_5_2 + ) +) + +if "%NOCOMPAT%"=="TRUE" ( + set COMPATFLAG= +) + +SET FILES_BASE=%FILES_DLL% %FILES_CORE% %FILES_LIB% + +if "%FILES_BASE%"=="" ( + Echo Unknown Lua version; %LUA_VER% + goto :EXITERROR +) + +REM ********************************* +REM * Check available toolchain * +REM ********************************* + +if [%TOOLCHAIN%]==[] ( + Echo Testing for MS... + %CHECK_MS% + IF !ERRORLEVEL!==0 SET TOOLCHAIN=MS +) +if [%TOOLCHAIN%]==[] ( + Echo Testing for GCC... + %CHECK_GCC% + IF !ERRORLEVEL!==0 SET TOOLCHAIN=GCC +) +if [%TOOLCHAIN%]==[] ( + Echo No supported toolchain found ^(please make sure it is in the system path^) + goto :EXITERROR +) + +REM *************************** +REM * Configure toolchain * +REM *************************** + +if %TOOLCHAIN%==GCC ( + echo Using GCC toolchain... + SET OBJEXT=o + SET LIBFILE=liblua%LUA_SVER%.a +) +if %TOOLCHAIN%==MS ( + echo Using Microsoft toolchain... + SET OBJEXT=obj + SET LIBFILE=lua%LUA_SVER%.lib +) +echo. + +REM ************************************** +REM * Check for installing * +REM ************************************** + +if "%1"=="install" ( + if "%~2"=="" ( + echo. + echo ERROR: The install command requires a path where to install to. + goto :EXITERROR + ) + SET TARGETPATH=%~2 +) +if "%1"=="local" ( + if NOT "%~2"=="" ( + echo. + echo ERROR: The local command does not take extra parameters. + goto :EXITERROR + ) + SET TARGETPATH=%SOURCETREE%local +) +if NOT "%TARGETPATH%"=="" ( + mkdir "%TARGETPATH%\bin" + mkdir "%TARGETPATH%\include" + mkdir "%TARGETPATH%\lib\lua\%LUA_VER%" + mkdir "%TARGETPATH%\man\man1" + mkdir "%TARGETPATH%\share\lua\%LUA_VER%" + copy "%SOURCE%lua.exe" "%TARGETPATH%\bin" + copy "%SOURCE%luac.exe" "%TARGETPATH%\bin" + copy "%SOURCE%lua%LUA_SVER%.dll" "%TARGETPATH%\bin" + for %%a in (%INSTALL_H%) do ( copy "%SOURCE%%%a" "%TARGETPATH%\include" ) + copy "%SOURCE%%LIBFILE%" "%TARGETPATH%\lib" + copy "%SOURCETREE%doc\lua.1" "%TARGETPATH%\man\man1" + copy "%SOURCETREE%doc\luac.1" "%TARGETPATH%\man\man1" + + echo Installation completed in "%TARGETPATH%". + goto :EXITOK +) + +REM *********************** +REM * Compile sources * +REM *********************** +goto :after_compile_function +:compile_function + REM Params: %1 is filelist (must be quoted) + REM Return: same list, with the object file extension included, will be stored in global OBJLIST + + for %%a in (%~1) do ( + SET FILENAME=%%a + if %TOOLCHAIN%==GCC ( + SET COMPCMD=gcc -O2 -Wall !EXTRAFLAG! !COMPATFLAG! -c -o !FILENAME!.%OBJEXT% !FILENAME!.c + ) + if %TOOLCHAIN%==MS ( + SET COMPCMD=cl /nologo /MD /O2 /W3 /c /D_CRT_SECURE_NO_DEPRECATE !COMPATFLAG! !EXTRAFLAG! !FILENAME!.c + ) + echo !COMPCMD! + !COMPCMD! + SET OBJLIST=!OBJLIST! !FILENAME!.%OBJEXT% + ) + +goto :eof +:after_compile_function + +CD %SOURCE% +REM Traverse the 4 lists of source files + +for %%b in (CORE LIB DLL OTH) do ( + SET LTYPE=%%b + SET OBJLIST= + if !LTYPE!==OTH ( + REM OTH is the only list of files build without DLL option + SET EXTRAFLAG= + ) else ( + SET EXTRAFLAG=-DLUA_BUILD_AS_DLL + ) + if !LTYPE!==CORE SET FILELIST=%FILES_CORE% + if !LTYPE!==LIB SET FILELIST=%FILES_LIB% + if !LTYPE!==DLL SET FILELIST=%FILES_DLL% + if !LTYPE!==OTH SET FILELIST=%FILES_OTH% + + echo Now compiling !LTYPE! file set... + call:compile_function "!FILELIST!" + + if !LTYPE!==CORE SET FILES_CORE_O=!OBJLIST! + if !LTYPE!==LIB SET FILES_LIB_O=!OBJLIST! + if !LTYPE!==DLL SET FILES_DLL_O=!OBJLIST! + if !LTYPE!==OTH SET FILES_OTH_O=!OBJLIST! +) + + +REM **************************** +REM * Link GCC based files * +REM **************************** + +if %TOOLCHAIN%==GCC ( + REM Link the LuaXX.dll file + SET LINKCMD=gcc -shared -o lua%LUA_SVER%.dll %FILES_CORE_O% %FILES_LIB_O% + echo !LINKCMD! + !LINKCMD! + + REM strip from LuaXX.dll + SET RANCMD=strip --strip-unneeded lua%LUA_SVER%.dll + echo !RANCMD! + !RANCMD! + + REM Link the Lua.exe file + SET LINKCMD=gcc -o lua.exe -s lua.%OBJEXT% lua%LUA_SVER%.dll -lm + echo !LINKCMD! + !LINKCMD! + + REM create lib archive + SET LIBCMD=ar rcu liblua%LUA_SVER%.a %FILES_CORE_O% %FILES_LIB_O% + echo !LIBCMD! + !LIBCMD! + + REM Speedup index using ranlib + SET RANCMD=ranlib liblua%LUA_SVER%.a + echo !RANCMD! + !RANCMD! + + REM Link Luac.exe file + SET LINKCMD=gcc -o luac.exe %FILES_OTH_O% liblua%LUA_SVER%.a -lm + echo !LINKCMD! + !LINKCMD! + +) + + +REM **************************** +REM * Link MS based files * +REM **************************** + +if %TOOLCHAIN%==MS ( + REM Link the LuaXX.dll file, and LuaXX.obj + SET LINKCMD=link /nologo /DLL /out:lua%LUA_SVER%.dll %FILES_CORE_O% %FILES_LIB_O% + echo !LINKCMD! + !LINKCMD! + + REM handle dll manifest + if exist lua%LUA_SVER%.dll.manifest ( + SET MANICMD=mt /nologo -manifest lua%LUA_SVER%.dll.manifest -outputresource:lua%LUA_SVER%.dll;2 + echo !MANICMD! + !MANICMD! + ) + + REM Link Lua.exe + SET LINKCMD=link /nologo /out:lua.exe lua.%OBJEXT% lua%LUA_SVER%.lib + echo !LINKCMD! + !LINKCMD! + + REM handle manifest + if exist lua.exe.manifest ( + SET MANICMD=mt /nologo -manifest lua.exe.manifest -outputresource:lua.exe + echo !MANICMD! + !MANICMD! + ) + + REM Link Luac.exe + SET LINKCMD=link /nologo /out:luac.exe %FILES_OTH_O% %FILES_CORE_O% + echo !LINKCMD! + !LINKCMD! + + REM handle manifest + if exist luac.exe.manifest ( + SET MANICMD=mt /nologo -manifest luac.exe.manifest -outputresource:luac.exe + echo !MANICMD! + !MANICMD! + ) +) + +CD %CURDIR% + +REM **************************** +REM * Finished building * +REM **************************** + +echo. +echo Build completed. +goto :EXITOK + +:EXITOK +exit /B 0 + +:EXITERROR +echo For help try; etc\%BATCHNAME% /help +exit /B 1 diff --git a/3rdparty/luv/.gitignore b/3rdparty/luv/.gitignore new file mode 100644 index 00000000000..8bcf497a42c --- /dev/null +++ b/3rdparty/luv/.gitignore @@ -0,0 +1,10 @@ +build +libluv.a +libluv.so +luv.so +luv.dll +luajit.exe +luv-*.tar.gz +luv-*.src.rock +luv-*/ +build.luarocks/ diff --git a/3rdparty/luv/.travis.yml b/3rdparty/luv/.travis.yml new file mode 100644 index 00000000000..b6909b894cc --- /dev/null +++ b/3rdparty/luv/.travis.yml @@ -0,0 +1,36 @@ +language: c +sudo: false + +addons: + apt: + sources: + - kalakris-cmake + packages: + - cmake + +env: + global: + - LUAROCKS=2.3.0 + matrix: + - WITH_LUA_ENGINE=Lua LUA=lua5.3 + - WITH_LUA_ENGINE=LuaJIT LUA=luajit2.1 + - PROCESS_CLEANUP_TEST=1 LUA=lua5.2 + +os: + - linux + - osx + +before_install: + - git submodule update --init --recursive + - git submodule update --recursive + +script: + - if [ "x$PROCESS_CLEANUP_TEST" = "x" ]; then make && make test; else ./tests/test-sigchld-after-lua_close.sh; fi + # Test rock installation + - source .ci/setenv_lua.sh + - luarocks make + - test $PWD = `lua -e "print(require'luv'.cwd())"` + +notifications: + email: true + irc: "irc.freenode.org#luvit" diff --git a/3rdparty/luv/CMakeLists.txt b/3rdparty/luv/CMakeLists.txt new file mode 100644 index 00000000000..9f079670de2 --- /dev/null +++ b/3rdparty/luv/CMakeLists.txt @@ -0,0 +1,191 @@ +cmake_minimum_required(VERSION 2.8) + +if(POLICY CMP0053) + cmake_policy(SET CMP0053 NEW) # faster evaluation of variable references +endif() + +project (luv C ASM) + +set(LUV_VERSION_MAJOR 1) +set(LUV_VERSION_MINOR 8) +set(LUV_VERSION_PATCH 0) +set(LUV_VERSION ${LUV_VERSION_MAJOR}.${LUV_VERSION_MINOR}.${LUV_VERSION_PATCH}) + +option(BUILD_MODULE "Build as module" ON) +option(BUILD_SHARED_LIBS "Build shared library" OFF) +option(WITH_SHARED_LIBUV "Link to a shared libuv library instead of static linking" OFF) + +if (NOT WITH_LUA_ENGINE) + set(WITH_LUA_ENGINE "LuaJIT" + CACHE STRING "Link to LuaJIT or PUC Lua" FORCE) + set_property(CACHE WITH_LUA_ENGINE + PROPERTY STRINGS "Lua;LuaJIT") +endif (NOT WITH_LUA_ENGINE) + +if (NOT LUA_BUILD_TYPE) + set(LUA_BUILD_TYPE "Static" + CACHE STRING "Build Lua/LuaJIT as static, dynamic libary, or use system one" FORCE) + set_property(CACHE LUA_BUILD_TYPE + PROPERTY STRINGS "Static;Dynamic;System") +endif (NOT LUA_BUILD_TYPE) + +if (WITH_LUA_ENGINE STREQUAL Lua) + add_definitions(-DLUA_USE_DLOPEN) + set(USE_LUAJIT OFF) +else () + set(USE_LUAJIT ON) +endif () + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") + +if (WITH_SHARED_LIBUV) + find_package(Libuv) + if (LIBUV_FOUND) + include_directories(${LIBUV_INCLUDE_DIR}) + endif (LIBUV_FOUND) +else (WITH_SHARED_LIBUV) + include(deps/uv.cmake) + if (BUILD_MODULE) + add_definitions( -DBUILDING_UV_SHARED ) + endif (BUILD_MODULE) +endif (WITH_SHARED_LIBUV) + +if (LUA) + MESSAGE(STATUS "Lua: using information from luarocks") + + MESSAGE(STATUS "LUA_LIBDIR: " ${LUA_LIBDIR}) + MESSAGE(STATUS "LUA_INCDIR: " ${LUA_INCDIR}) + MESSAGE(STATUS "LUA: " ${LUA}) + + SET(LUA_EXECUTABLE "${LUA}") + SET(LUA_INCLUDE_DIR "${LUA_INCDIR}") + SET(LUA_PACKAGE_PATH "${LUADIR}") + SET(LUA_PACKAGE_CPATH "${LIBDIR}") + + SET(INSTALL_LIB_DIR ${LIBDIR}) + + GET_FILENAME_COMPONENT(LUA_EXEC_NAME ${LUA_EXECUTABLE} NAME_WE) + IF(LUA_EXEC_NAME STREQUAL "luajit") + FIND_LIBRARY(LUA_LIBRARIES + NAMES luajit libluajit + PATHS ${LUA_LIBDIR} + NO_DEFAULT_PATH) + ELSEIF(LUA_EXEC_NAME STREQUAL "lua") + FIND_LIBRARY(LUA_LIBRARIES + NAMES lua lua53 lua52 lua51 liblua liblua53 liblua52 liblua51 + PATHS ${LUA_LIBDIR} + NO_DEFAULT_PATH) + ENDIF() + MESSAGE(STATUS "Lua library: ${LUA_LIBRARIES}") + + include_directories(${LUA_INCLUDE_DIR}) +else (LUA) + if (LUA_BUILD_TYPE STREQUAL System) + if (USE_LUAJIT) + find_package(LuaJIT) + if (LUAJIT_FOUND) + include_directories(${LUAJIT_INCLUDE_DIR}) + link_directories(${LUAJIT_LIBRARIES}) + endif (LUAJIT_FOUND) + else (USE_LUAJIT) + find_package(Lua) + if (LUA_FOUND) + include_directories(${LUA_INCLUDE_DIR}) + endif (LUA_FOUND) + endif (USE_LUAJIT) + + else (LUA_BUILD_TYPE STREQUAL System) + if (LUA_BUILD_TYPE STREQUAL Static) + SET(WITH_SHARED_LUA OFF) + else (LUA_BUILD_TYPE STREQUAL Static) + SET(WITH_SHARED_LUA ON) + endif (LUA_BUILD_TYPE STREQUAL Static) + if (USE_LUAJIT) + include(deps/luajit.cmake) + include_directories(deps/luajit/src) + else(USE_LUAJIT) + include(deps/lua.cmake) + include_directories(deps/lua/src) + endif (USE_LUAJIT) + endif (LUA_BUILD_TYPE STREQUAL System) +endif (LUA) + +if (BUILD_MODULE) + add_library(luv MODULE src/luv.c) + set_target_properties(luv PROPERTIES PREFIX "") +else (BUILD_MODULE) + add_library(luv src/luv.c) + if (BUILD_SHARED_LIBS) + set_target_properties(luv + PROPERTIES VERSION ${LUV_VERSION} SOVERSION ${LUV_VERSION_MAJOR}) + endif (BUILD_SHARED_LIBS) +endif (BUILD_MODULE) + +if(APPLE) + set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS + "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -flat_namespace -undefined suppress" + ) + # execute_process(COMMAND which luajit OUTPUT_VARIABLE LUAJIT) + # set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS + # "${CMAKE_SHARED_MODULE_CREATE_C_FLAGS} -bundle_loader ${LUAJIT}" + # ) +endif() + +if(WIN32) + add_definitions(-DLUA_BUILD_AS_DLL -DLUA_LIB) + if (LUA) + target_link_libraries(luv uv ${LUA_LIBRARIES}) + else (LUA) + if (USE_LUAJIT) + target_link_libraries(luv uv luajit-5.1) + else (USE_LUAJIT) + if (LUA_BUILD_TYPE STREQUAL System) + target_link_libraries(luv uv ${LUA_LIBRARIES}) + else (LUA_BUILD_TYPE STREQUAL System) + target_link_libraries(luv uv lualib) + endif (LUA_BUILD_TYPE STREQUAL System) + endif (USE_LUAJIT) + endif (LUA) + # replace /MD to /MT to avoid link msvcr*.dll + set(CompilerFlags + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_MINSIZEREL + CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_C_FLAGS_RELEASE) + foreach(CompilerFlag ${CompilerFlags}) + string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") + endforeach() +elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + target_link_libraries(luv uv rt) +else() + target_link_libraries(luv uv) +endif() + +if (NOT LUA) + if (BUILD_MODULE) + if (WIN32) + set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + else (WIN32) + set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib/lua/${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}") + endif (WIN32) + else (BUILD_MODULE) + set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" + CACHE PATH "Installation directory for libraries") + set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include/luv" + CACHE PATH "Installation directory for headers") + endif (BUILD_MODULE) +endif () + +if (CMAKE_INSTALL_PREFIX) + install(TARGETS luv + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" + ) + if (NOT BUILD_MODULE) + install( + FILES src/luv.h src/util.h src/lhandle.h src/lreq.h + DESTINATION "${INSTALL_INC_DIR}" + ) + endif (NOT BUILD_MODULE) +endif (CMAKE_INSTALL_PREFIX) diff --git a/3rdparty/luv/LICENSE.txt b/3rdparty/luv/LICENSE.txt new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/3rdparty/luv/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/3rdparty/luv/Makefile b/3rdparty/luv/Makefile new file mode 100644 index 00000000000..1e7038c47ab --- /dev/null +++ b/3rdparty/luv/Makefile @@ -0,0 +1,61 @@ +LUV_TAG=$(shell git describe --tags) + +ifdef WITHOUT_AMALG + CMAKE_OPTIONS+= -DWITH_AMALG=OFF +endif + +BUILD_MODULE ?= ON +BUILD_SHARED_LIBS ?= OFF +WITH_SHARED_LIBUV ?= OFF +WITH_LUA_ENGINE ?= LuaJIT +LUA_BUILD_TYPE ?= Static + + +ifeq ($(WITH_LUA_ENGINE), LuaJIT) + LUABIN=build/luajit +else + LUABIN=build/lua +endif + +CMAKE_OPTIONS += \ + -DBUILD_MODULE=$(BUILD_MODULE) \ + -DBUILD_SHARED_LIBS=$(BUILD_SHARED_LIBS) \ + -DWITH_SHARED_LIBUV=$(WITH_SHARED_LIBUV) \ + -DWITH_LUA_ENGINE=$(WITH_LUA_ENGINE) \ + -DLUA_BUILD_TYPE=$(LUA_BUILD_TYPE) \ + +all: luv + +deps/libuv/include: + git submodule update --init deps/libuv + +deps/luajit/src: + git submodule update --init deps/luajit + +build/Makefile: deps/libuv/include deps/luajit/src + cmake -H. -Bbuild ${CMAKE_OPTIONS} -DWITH_AMALG=OFF + +luv: build/Makefile + cmake --build build --config Debug + ln -sf build/luv.so + +clean: + rm -rf build luv.so + +test: luv + ${LUABIN} tests/run.lua + +reset: + git submodule update --init --recursive && \ + git clean -f -d && \ + git checkout . + +publish-luarocks: + rm -rf luv-${LUV_TAG} + mkdir -p luv-${LUV_TAG}/deps + cp -r src cmake CMakeLists.txt LICENSE.txt README.md docs.md luv-${LUV_TAG}/ + cp -r deps/libuv deps/*.cmake deps/lua_one.c luv-${LUV_TAG}/deps/ + tar -czvf luv-${LUV_TAG}.tar.gz luv-${LUV_TAG} + github-release upload --user luvit --repo luv --tag ${LUV_TAG} \ + --file luv-${LUV_TAG}.tar.gz --name luv-${LUV_TAG}.tar.gz + luarocks upload luv-${LUV_TAG}.rockspec --api-key=${LUAROCKS_TOKEN} diff --git a/3rdparty/luv/README.md b/3rdparty/luv/README.md new file mode 100644 index 00000000000..47059d01ee7 --- /dev/null +++ b/3rdparty/luv/README.md @@ -0,0 +1,213 @@ +luv +=== + +[![Linux Build Status](https://travis-ci.org/luvit/luv.svg?branch=master)](https://travis-ci.org/luvit/luv) + +[![Windows Build status](https://ci.appveyor.com/api/projects/status/uo1qhdcc0vcqsiok/branch/master?svg=true)](https://ci.appveyor.com/project/racker-buildbot/luv/branch/master) + +[libuv](https://github.com/joyent/libuv) bindings for +[luajit](http://luajit.org/) and [lua](http://www.lua.org/) +[5.1](http://www.lua.org/manual/5.1/manual.html)/ +[5.2](http://www.lua.org/manual/5.2/manual.html)/ +[5.3](http://www.lua.org/manual/5.3/manual.html). + +This library makes libuv available to lua scripts. It was made for the [luvit](http://luvit.io/) project but should usable from nearly any lua project. + +The library can be used by multiple threads at once. Each thread is assumed to load the library from a different `lua_State`. Luv will create a unique `uv_loop_t` for each state. You can't share uv handles between states/loops. + +The best docs currently are the [libuv docs](http://docs.libuv.org/) themselves. Hopfully soon we'll have a copy locally tailored for lua. + +```lua +local uv = require('luv') + +-- Create a handle to a uv_timer_t +local timer = uv.new_timer() + +-- This will wait 1000ms and then continue inside the callback +timer:start(1000, 0, function () + -- timer here is the value we passed in before from new_timer. + + print ("Awake!") + + -- You must always close your uv handles or you'll leak memory + -- We can't depend on the GC since it doesn't know enough about libuv. + timer:close() +end) + +print("Sleeping"); + +-- uv.run will block and wait for all events to run. +-- When there are no longer any active handles, it will return +uv.run() +``` + + +Here is an example of an TCP echo server +```lua +local uv = require('luv') + +local function create_server(host, port, on_connection) + + local server = uv.new_tcp() + server:bind(host, port) + + server:listen(128, function(err) + -- Make sure there was no problem setting up listen + assert(not err, err) + + -- Accept the client + local client = uv.new_tcp() + server:accept(client) + + on_connection(client) + end) + + return server +end + +local server = create_server("0.0.0.0", 0, function (client) + + client:read_start(function (err, chunk) + + -- Crash on errors + assert(not err, err) + + if chunk then + -- Echo anything heard + client:write(chunk) + else + -- When the stream ends, close the socket + client:close() + end + end) +end) + +print("TCP Echo serverr listening on port " .. server:getsockname().port) + +uv.run() +``` + +More examples can be found in the [examples](examples) and [tests](tests) folders. + +## Building From Source + +To build, first install your compiler tools. + +### Get a Compiler + +On linux this probably means `gcc` and `make`. On Ubuntu, the `build-essential` +package is good for this. + +On OSX, you probably want XCode which comes with `clang` and `make` and friends. + +For windows the free Visual Studio Express works. If you get the 2013 edition, +make sure to get the `Windows Deskop` edition. The `Windows` version doesn't +include a working C compiler. Make sure to run all of setup including getting a +free license. + +### Install CMake + +Now install Cmake. The version in `brew` on OSX or most Linux package managers +is good. The version on Travis CI is too old and so I use a PPA there. On +windows use the installer and make sure to add cmake to your command prompt +path. + +### Install Git + +If you haven't already, install git and make sure it's in your path. This comes +with XCode on OSX. On Linux it's in your package manager. For windows, use the +installer at . Make sure it's available to your windows +command prompt. + +### Clone the Code + +Now open a terminal and clone the code. For windows I recommend the special +developer command prompt that came with Visual Studio. + +``` +git clone https://github.com/luvit/luv.git --recursive +cd luv +``` + +### Build the Code and Test + +On windows I wrote a small batch file that runs the correct cmake commands and +copies the output files for easy access. + +``` +C:\Code\luv> msvcbuild.bat +C:\Code\luv> luajit tests\run.lua +``` + +On unix systems, use the Makefile. + +``` +~/Code/luv> make test +``` + +This will build luv as a module library. Module libraries are plugins that are +not linked into other targets. + +#### Build with PUC Lua 5.3 +By default luv is linked with LuaJIT 2.0.4. If you rather like to link luv +with PUC Lua 5.3 you can run make with: + +``` +~/Code/luv> WITH_LUA_ENGINE=Lua make +``` + +#### Build as static library + +If you want to build luv as a static library run make with: + +``` +~/Code/luv> BUILD_MODULE=OFF make +``` + +This will create a static library `libluv.a`. + +#### Build as shared library + +If you want to build luv as a shared library run make with: + +``` +~/Code/luv> BUILD_MODULE=OFF BUILD_SHARED_LIBS=ON make +``` + +This will create a shared library `libluv.so`. + +#### Build with shared libraries + +By default the build system will build luv with the supplied dependencies. +These are: + * libuv + * LuaJIT or Lua + +However, if your target system has already one or more of these dependencies +installed you can link `luv` against them. + +##### Linking with shared libuv + +The default shared library name for libuv is `libuv`. To link against it use: + +``` +~/Code/luv> WITH_SHARED_LIBUV=ON make +``` + +##### Linking with shared LuaJIT + +The default shared library name for LuaJIT is `libluajit-5.1`. To link against +it use: + +``` +~/Code/luv> LUA_BUILD_TYPE=System make +``` + +##### Linking with shared Lua 5.x + +The default shared library name for Lua 5.x is `liblua5.x`. To link against +it use: + +``` +~/Code/luv> LUA_BUILD_TYPE=System WITH_LUA_ENGINE=Lua make +``` diff --git a/3rdparty/luv/appveyor.yml b/3rdparty/luv/appveyor.yml new file mode 100644 index 00000000000..b8d01898573 --- /dev/null +++ b/3rdparty/luv/appveyor.yml @@ -0,0 +1,42 @@ +os: Visual Studio 2015 + +# Test with the latest two releases of MSVC +configuration: + - 2015 + - 2013 + +# Test with the latest Lua and LuaJIT versions +environment: + LUAROCKS_VER: 2.3.0 + matrix: + - LUA_VER: 5.3.2 + NOCOMPAT: true # with compatibility flags disabled. + - LJ_VER: 2.1 + +platform: + - x86 + - x64 + +matrix: + fast_finish: true + +cache: + - c:\lua -> appveyor.yml + - c:\external -> appveyor.yml + +install: + - git submodule update --init + +build_script: + - msvcbuild.bat + - luajit.exe tests\run.lua + # Test rock installation + - call .ci\set_compiler_env.bat + - call .ci\install.bat + - luarocks make + - ps: if("$(Get-Location)" -eq $(lua -e "print(require'luv'.cwd())")) { "LuaRocks test OK" } else { "LuaRocks test failed"; exit 1 } + - luarocks remove luv + +artifacts: + - path: luv.dll + - path: luajit.exe diff --git a/3rdparty/luv/cmake/Modules/FindLibuv.cmake b/3rdparty/luv/cmake/Modules/FindLibuv.cmake new file mode 100644 index 00000000000..045362ae5db --- /dev/null +++ b/3rdparty/luv/cmake/Modules/FindLibuv.cmake @@ -0,0 +1,11 @@ +# Locate libuv library +# This module defines +# LIBUV_FOUND, if false, do not try to link to libuv +# LIBUV_LIBRARIES +# LIBUV_INCLUDE_DIR, where to find uv.h + +FIND_PATH(LIBUV_INCLUDE_DIR NAMES uv.h) +FIND_LIBRARY(LIBUV_LIBRARIES NAMES uv libuv) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUV DEFAULT_MSG LIBUV_LIBRARIES LIBUV_INCLUDE_DIR) diff --git a/3rdparty/luv/cmake/Modules/FindLuaJIT.cmake b/3rdparty/luv/cmake/Modules/FindLuaJIT.cmake new file mode 100644 index 00000000000..b9c2c3ee41a --- /dev/null +++ b/3rdparty/luv/cmake/Modules/FindLuaJIT.cmake @@ -0,0 +1,55 @@ +#============================================================================= +# Copyright 2007-2009 Kitware, Inc. +# Copyright 2013 Rolf Eike Beer +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# We use code from the CMake project to detect the Lua version. + +# Locate LuaJIT library +# This module defines +# LUAJIT_FOUND, if false, do not try to link to Lua JIT +# LUAJIT_LIBRARIES +# LUAJIT_INCLUDE_DIR, where to find lua.h +# +# Additionally it defines the Lua API/ABI version: +# LUA_VERSION_STRING - the version of Lua found +# LUA_VERSION_MAJOR - the major version of Lua +# LUA_VERSION_MINOR - the minor version of Lua +# LUA_VERSION_PATCH - the patch version of Lua + +FIND_PATH(LUAJIT_INCLUDE_DIR NAMES lua.h PATH_SUFFIXES luajit-2.0) +FIND_LIBRARY(LUAJIT_LIBRARIES NAMES luajit-5.1) + +if (LUAJIT_INCLUDE_DIR AND EXISTS "${LUAJIT_INCLUDE_DIR}/lua.h") + # At least 5.[012] have different ways to express the version + # so all of them need to be tested. Lua 5.2 defines LUA_VERSION + # and LUA_RELEASE as joined by the C preprocessor, so avoid those. + file(STRINGS "${LUAJIT_INCLUDE_DIR}/lua.h" lua_version_strings + REGEX "^#define[ \t]+LUA_(RELEASE[ \t]+\"Lua [0-9]|VERSION([ \t]+\"Lua [0-9]|_[MR])).*") + + string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MAJOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MAJOR ";${lua_version_strings};") + if (LUA_VERSION_MAJOR MATCHES "^[0-9]+$") + string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_MINOR[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_MINOR ";${lua_version_strings};") + string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION_RELEASE[ \t]+\"([0-9])\"[ \t]*;.*" "\\1" LUA_VERSION_PATCH ";${lua_version_strings};") + set(LUA_VERSION_STRING "${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}.${LUA_VERSION_PATCH}") + else () + string(REGEX REPLACE ".*;#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};") + if (NOT LUA_VERSION_STRING MATCHES "^[0-9.]+$") + string(REGEX REPLACE ".*;#define[ \t]+LUA_VERSION[ \t]+\"Lua ([0-9.]+)\"[ \t]*;.*" "\\1" LUA_VERSION_STRING ";${lua_version_strings};") + endif () + string(REGEX REPLACE "^([0-9]+)\\.[0-9.]*$" "\\1" LUA_VERSION_MAJOR "${LUA_VERSION_STRING}") + string(REGEX REPLACE "^[0-9]+\\.([0-9]+)[0-9.]*$" "\\1" LUA_VERSION_MINOR "${LUA_VERSION_STRING}") + string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]).*" "\\1" LUA_VERSION_PATCH "${LUA_VERSION_STRING}") + endif () + + unset(lua_version_strings) +endif() + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LUAJIT DEFAULT_MSG LUAJIT_LIBRARIES LUAJIT_INCLUDE_DIR) diff --git a/3rdparty/luv/deps/lua.cmake b/3rdparty/luv/deps/lua.cmake new file mode 100644 index 00000000000..393e67a107a --- /dev/null +++ b/3rdparty/luv/deps/lua.cmake @@ -0,0 +1,128 @@ +# Modfied from luajit.cmake +# Added LUAJIT_ADD_EXECUTABLE Ryan Phillips +# This CMakeLists.txt has been first taken from LuaDist +# Copyright (C) 2007-2011 LuaDist. +# Created by Peter Drahoš +# Redistribution and use of this file is allowed according to the terms of the MIT license. +# Debugged and (now seriously) modified by Ronan Collobert, for Torch7 + +#project(Lua53 C) + +SET(LUA_DIR ${CMAKE_CURRENT_LIST_DIR}/lua) + +SET(CMAKE_REQUIRED_INCLUDES + ${LUA_DIR} + ${LUA_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR} +) + +OPTION(WITH_AMALG "Build eveything in one shot (needs memory)" ON) + +# Ugly warnings +IF(MSVC) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) +ENDIF() + +# Various includes +INCLUDE(CheckLibraryExists) +INCLUDE(CheckFunctionExists) +INCLUDE(CheckCSourceCompiles) +INCLUDE(CheckTypeSize) + +CHECK_TYPE_SIZE("void*" SIZEOF_VOID_P) +IF(SIZEOF_VOID_P EQUAL 8) + ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE) +ENDIF() + +IF(NOT WIN32) + FIND_LIBRARY(DL_LIBRARY "dl") + IF(DL_LIBRARY) + SET(CMAKE_REQUIRED_LIBRARIES ${DL_LIBRARY}) + LIST(APPEND LIBS ${DL_LIBRARY}) + ENDIF(DL_LIBRARY) + CHECK_FUNCTION_EXISTS(dlopen LUA_USE_DLOPEN) + IF(NOT LUA_USE_DLOPEN) + MESSAGE(FATAL_ERROR "Cannot compile a useful lua. +Function dlopen() seems not to be supported on your platform. +Apparently you are not on a Windows platform as well. +So lua has no way to deal with shared libraries!") + ENDIF(NOT LUA_USE_DLOPEN) +ENDIF(NOT WIN32) + +check_library_exists(m sin "" LUA_USE_LIBM) +if ( LUA_USE_LIBM ) + list ( APPEND LIBS m ) +endif () + +## SOURCES +SET(SRC_LUALIB + ${LUA_DIR}/src/lbaselib.c + ${LUA_DIR}/src/lcorolib.c + ${LUA_DIR}/src/ldblib.c + ${LUA_DIR}/src/liolib.c + ${LUA_DIR}/src/lmathlib.c + ${LUA_DIR}/src/loadlib.c + ${LUA_DIR}/src/loslib.c + ${LUA_DIR}/src/lstrlib.c + ${LUA_DIR}/src/ltablib.c + ${LUA_DIR}/src/lutf8lib.c) + +SET(SRC_LUACORE + ${LUA_DIR}/src/lauxlib.c + ${LUA_DIR}/src/lapi.c + ${LUA_DIR}/src/lcode.c + ${LUA_DIR}/src/lctype.c + ${LUA_DIR}/src/ldebug.c + ${LUA_DIR}/src/ldo.c + ${LUA_DIR}/src/ldump.c + ${LUA_DIR}/src/lfunc.c + ${LUA_DIR}/src/lgc.c + ${LUA_DIR}/src/linit.c + ${LUA_DIR}/src/llex.c + ${LUA_DIR}/src/lmem.c + ${LUA_DIR}/src/lobject.c + ${LUA_DIR}/src/lopcodes.c + ${LUA_DIR}/src/lparser.c + ${LUA_DIR}/src/lstate.c + ${LUA_DIR}/src/lstring.c + ${LUA_DIR}/src/ltable.c + ${LUA_DIR}/src/ltm.c + ${LUA_DIR}/src/lundump.c + ${LUA_DIR}/src/lvm.c + ${LUA_DIR}/src/lzio.c + ${SRC_LUALIB}) + +## GENERATE + +IF(WITH_SHARED_LUA) + IF(WITH_AMALG) + add_library(lualib SHARED ${LUA_DIR}/../lua_one.c ${DEPS}) + ELSE() + add_library(lualib SHARED ${SRC_LUACORE} ${DEPS} ) + ENDIF() +ELSE() + IF(WITH_AMALG) + add_library(lualib STATIC ${LUA_DIR}/../lua_one.c ${DEPS} ) + ELSE() + add_library(lualib STATIC ${SRC_LUACORE} ${DEPS} ) + ENDIF() + set_target_properties(lualib PROPERTIES + PREFIX "lib" IMPORT_PREFIX "lib") +ENDIF() + +target_link_libraries (lualib ${LIBS} ) +set_target_properties (lualib PROPERTIES OUTPUT_NAME "lua53") + +IF(WIN32) + add_executable(lua ${LUA_DIR}/src/lua.c) + target_link_libraries(lua lualib) +ELSE() + IF(WITH_AMALG) + add_executable(lua ${LUA_DIR}/src/lua.c ${LUA_DIR}/lua_one.c ${DEPS}) + ELSE() + add_executable(lua ${LUA_DIR}/src/lua.c ${SRC_LUACORE} ${DEPS}) + ENDIF() + target_link_libraries(lua ${LIBS}) + SET_TARGET_PROPERTIES(lua PROPERTIES ENABLE_EXPORTS ON) +ENDIF(WIN32) + diff --git a/3rdparty/luv/deps/lua_one.c b/3rdparty/luv/deps/lua_one.c new file mode 100644 index 00000000000..2531883cc67 --- /dev/null +++ b/3rdparty/luv/deps/lua_one.c @@ -0,0 +1,97 @@ +/* +* one.c -- Lua core, libraries, and interpreter in a single file +*/ + +/* default is to build the full interpreter */ +#ifndef MAKE_LIB +#ifndef MAKE_LUAC +#ifndef MAKE_LUA +#define MAKE_LIB +#endif +#endif +#endif + +/* choose suitable platform-specific features */ +/* some of these may need extra libraries such as -ldl -lreadline -lncurses */ +#if 0 +#define LUA_USE_LINUX +#define LUA_USE_MACOSX +#define LUA_USE_POSIX +#define LUA_ANSI +#endif + +/* no need to change anything below this line ----------------------------- */ + +/* setup for luaconf.h */ +#if HAVE_LPREFIX +# include "lprefix.h" +#endif + +#define LUA_CORE +#define LUA_LIB +#define ltable_c +#define lvm_c +#include "luaconf.h" + +/* do not export internal symbols */ +#undef LUAI_FUNC +#undef LUAI_DDEC +#undef LUAI_DDEF +#define LUAI_FUNC static +#define LUAI_DDEC static +#define LUAI_DDEF static + +/* core -- used by all */ +#include "lapi.c" +#include "lcode.c" +#include "lctype.c" +#include "ldebug.c" +#include "ldo.c" +#include "ldump.c" +#include "lfunc.c" +#include "lgc.c" +#include "llex.c" +#include "lmem.c" +#include "lobject.c" +#include "lopcodes.c" +#include "lparser.c" +#include "lstate.c" +#include "lstring.c" +#include "ltable.c" +#include "ltm.c" +#include "lundump.c" +#include "lvm.c" +#include "lzio.c" + +/* auxiliary library -- used by all */ +#include "lauxlib.c" + +/* standard library -- not used by luac */ +#ifndef MAKE_LUAC +#include "lbaselib.c" +#if LUA_VERSION_NUM == 502 +# include "lbitlib.c" +#endif +#include "lcorolib.c" +#include "ldblib.c" +#include "liolib.c" +#include "lmathlib.c" +#include "loadlib.c" +#include "loslib.c" +#include "lstrlib.c" +#include "ltablib.c" +#if LUA_VERSION_NUM >= 503 +# include "lutf8lib.c" +#endif +#include "linit.c" +#endif + +/* lua */ +#ifdef MAKE_LUA +#include "lua.c" +#endif + +/* luac */ +#ifdef MAKE_LUAC +#include "luac.c" +#endif diff --git a/3rdparty/luv/deps/luajit.cmake b/3rdparty/luv/deps/luajit.cmake new file mode 100644 index 00000000000..e9d5b3582e1 --- /dev/null +++ b/3rdparty/luv/deps/luajit.cmake @@ -0,0 +1,407 @@ +# Added LUAJIT_ADD_EXECUTABLE Ryan Phillips +# This CMakeLists.txt has been first taken from LuaDist +# Copyright (C) 2007-2011 LuaDist. +# Created by Peter Drahoš +# Redistribution and use of this file is allowed according to the terms of the MIT license. +# Debugged and (now seriously) modified by Ronan Collobert, for Torch7 + +#project(LuaJIT C ASM) + +SET(LUAJIT_DIR ${CMAKE_CURRENT_LIST_DIR}/luajit) + +SET(CMAKE_REQUIRED_INCLUDES + ${LUAJIT_DIR} + ${LUAJIT_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR} +) + +OPTION(WITH_AMALG "Build eveything in one shot (needs memory)" ON) + +# Ugly warnings +IF(MSVC) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) +ENDIF() + +# Various includes +INCLUDE(CheckLibraryExists) +INCLUDE(CheckFunctionExists) +INCLUDE(CheckCSourceCompiles) +INCLUDE(CheckTypeSize) + +# LuaJIT specific +option(LUAJIT_DISABLE_FFI "Disable FFI." OFF) +option(LUAJIT_ENABLE_LUA52COMPAT "Enable Lua 5.2 compatibility." ON) +option(LUAJIT_DISABLE_JIT "Disable JIT." OFF) +option(LUAJIT_CPU_SSE2 "Use SSE2 instead of x87 instructions." ON) +option(LUAJIT_CPU_NOCMOV "Disable NOCMOV." OFF) +MARK_AS_ADVANCED(LUAJIT_DISABLE_FFI LUAJIT_ENABLE_LUA52COMPAT LUAJIT_DISABLE_JIT LUAJIT_CPU_SSE2 LUAJIT_CPU_NOCMOV) + +IF(LUAJIT_DISABLE_FFI) + ADD_DEFINITIONS(-DLUAJIT_DISABLE_FFI) +ENDIF() + +IF(LUAJIT_ENABLE_LUA52COMPAT) + ADD_DEFINITIONS(-DLUAJIT_ENABLE_LUA52COMPAT) +ENDIF() + +IF(LUAJIT_DISABLE_JIT) + ADD_DEFINITIONS(-DLUAJIT_DISABLE_JIT) +ENDIF() + +IF(LUAJIT_CPU_SSE2) + ADD_DEFINITIONS(-DLUAJIT_CPU_SSE2) +ENDIF() + +IF(LUAJIT_CPU_NOCMOV) + ADD_DEFINITIONS(-DLUAJIT_CPU_NOCMOV) +ENDIF() +###### + + +CHECK_TYPE_SIZE("void*" SIZEOF_VOID_P) +IF(SIZEOF_VOID_P EQUAL 8) + ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE) +ENDIF() + +if ( WIN32 AND NOT CYGWIN ) + add_definitions ( -DLUAJIT_OS=LUAJIT_OS_WINDOWS) + set ( LJVM_MODE coffasm ) +elseif ( APPLE ) + set ( CMAKE_EXE_LINKER_FLAGS "-pagezero_size 10000 -image_base 100000000 ${CMAKE_EXE_LINKER_FLAGS}" ) + set ( LJVM_MODE machasm ) +else () + set ( LJVM_MODE elfasm ) +endif () + +IF(NOT WIN32) + FIND_LIBRARY(DL_LIBRARY "dl") + IF(DL_LIBRARY) + SET(CMAKE_REQUIRED_LIBRARIES ${DL_LIBRARY}) + LIST(APPEND LIBS ${DL_LIBRARY}) + ENDIF(DL_LIBRARY) + CHECK_FUNCTION_EXISTS(dlopen LUA_USE_DLOPEN) + IF(NOT LUA_USE_DLOPEN) + MESSAGE(FATAL_ERROR "Cannot compile a useful lua. +Function dlopen() seems not to be supported on your platform. +Apparently you are not on a Windows platform as well. +So lua has no way to deal with shared libraries!") + ENDIF(NOT LUA_USE_DLOPEN) +ENDIF(NOT WIN32) + +check_library_exists(m sin "" LUA_USE_LIBM) +if ( LUA_USE_LIBM ) + list ( APPEND LIBS m ) +endif () + +## SOURCES +MACRO(LJ_TEST_ARCH stuff) + CHECK_C_SOURCE_COMPILES(" +#undef ${stuff} +#include \"lj_arch.h\" +#if ${stuff} +int main() { return 0; } +#else +#error \"not defined\" +#endif +" ${stuff}) +ENDMACRO() + +MACRO(LJ_TEST_ARCH_VALUE stuff value) + CHECK_C_SOURCE_COMPILES(" +#undef ${stuff} +#include \"lj_arch.h\" +#if ${stuff} == ${value} +int main() { return 0; } +#else +#error \"not defined\" +#endif +" ${stuff}_${value}) +ENDMACRO() + + +FOREACH(arch X64 X86 ARM PPC PPCSPE MIPS) + LJ_TEST_ARCH(LJ_TARGET_${arch}) + if(LJ_TARGET_${arch}) + STRING(TOLOWER ${arch} TARGET_LJARCH) + MESSAGE(STATUS "LuaJIT Target: ${TARGET_LJARCH}") + BREAK() + ENDIF() +ENDFOREACH() + +IF(NOT TARGET_LJARCH) + MESSAGE(FATAL_ERROR "architecture not supported") +ELSE() + MESSAGE(STATUS "LuaJIT target ${TARGET_LJARCH}") +ENDIF() + +FILE(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/jit) +FILE(GLOB jit_files ${LUAJIT_DIR}/src/jit/*.lua) +FILE(COPY ${jit_files} DESTINATION ${CMAKE_BINARY_DIR}/jit) + +SET(DASM_ARCH ${TARGET_LJARCH}) +SET(DASM_FLAGS) +SET(TARGET_ARCH) +LIST(APPEND TARGET_ARCH "LUAJIT_TARGET=LUAJIT_ARCH_${TARGET_LJARCH}") +LJ_TEST_ARCH_VALUE(LJ_ARCH_BITS 64) +IF(LJ_ARCH_BITS_64) + SET(DASM_FLAGS ${DASM_FLAGS} -D P64) +ENDIF() +LJ_TEST_ARCH_VALUE(LJ_HASJIT 1) +IF(LJ_HASJIT_1) + SET(DASM_FLAGS ${DASM_FLAGS} -D JIT) +ENDIF() +LJ_TEST_ARCH_VALUE(LJ_HASFFI 1) +IF(LJ_HASFFI_1) + SET(DASM_FLAGS ${DASM_FLAGS} -D FFI) +ENDIF() +LJ_TEST_ARCH_VALUE(LJ_DUALNUM 1) +IF(LJ_DUALNUM_1) + SET(DASM_FLAGS ${DASM_FLAGS} -D DUALNUM) +ENDIF() +LJ_TEST_ARCH_VALUE(LJ_ARCH_HASFPU 1) +IF(LJ_ARCH_HASFPU_1) + SET(DASM_FLAGS ${DASM_FLAGS} -D FPU) + LIST(APPEND TARGET_ARCH "LJ_ARCH_HASFPU=1") +ELSE() + LIST(APPEND TARGET_ARCH "LJ_ARCH_HASFPU=0") +ENDIF() +LJ_TEST_ARCH_VALUE(LJ_ABI_SOFTFP 1) +IF(NOT LJ_ABI_SOFTFP_1) + SET(DASM_FLAGS ${DASM_FLAGS} -D HFABI) + LIST(APPEND TARGET_ARCH "LJ_ABI_SOFTFP=0") +ELSE() + LIST(APPEND TARGET_ARCH "LJ_ABI_SOFTFP=1") +ENDIF() +IF(WIN32) + SET(DASM_FLAGS ${DASM_FLAGS} -LN -D WIN) +ENDIF() +IF(TARGET_LJARCH STREQUAL "x86") + LJ_TEST_ARCH_VALUE(__SSE2__ 1) + IF(__SSE2__1) + SET(DASM_FLAGS ${DASM_FLAGS} -D SSE) + ENDIF() +ENDIF() +IF(TARGET_LJARCH STREQUAL "x64") + SET(DASM_ARCH "x86") +ENDIF() +IF(TARGET_LJARCH STREQUAL "ppc") + LJ_TEST_ARCH_VALUE(LJ_ARCH_SQRT 1) + IF(NOT LJ_ARCH_SQRT_1) + SET(DASM_FLAGS ${DASM_FLAGS} -D SQRT) + ENDIF() + LJ_TEST_ARCH_VALUE(LJ_ARCH_PPC64 1) + IF(NOT LJ_ARCH_PPC64_1) + SET(DASM_FLAGS ${DASM_FLAGS} -D GPR64) + ENDIF() +ENDIF() + +add_executable(minilua ${LUAJIT_DIR}/src/host/minilua.c) +SET_TARGET_PROPERTIES(minilua PROPERTIES COMPILE_DEFINITIONS "${TARGET_ARCH}") +CHECK_LIBRARY_EXISTS(m sin "" MINILUA_USE_LIBM) +if(MINILUA_USE_LIBM) + TARGET_LINK_LIBRARIES(minilua m) +endif() + +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/buildvm_arch.h + COMMAND minilua ${LUAJIT_DIR}/dynasm/dynasm.lua ${DASM_FLAGS} -o ${CMAKE_CURRENT_BINARY_DIR}/buildvm_arch.h ${LUAJIT_DIR}/src/vm_${DASM_ARCH}.dasc + DEPENDS ${LUAJIT_DIR}/dynasm/dynasm.lua minilua +) + +SET(SRC_LJLIB + ${LUAJIT_DIR}/src/lib_base.c + ${LUAJIT_DIR}/src/lib_math.c + ${LUAJIT_DIR}/src/lib_bit.c + ${LUAJIT_DIR}/src/lib_string.c + ${LUAJIT_DIR}/src/lib_table.c + ${LUAJIT_DIR}/src/lib_io.c + ${LUAJIT_DIR}/src/lib_os.c + ${LUAJIT_DIR}/src/lib_package.c + ${LUAJIT_DIR}/src/lib_debug.c + ${LUAJIT_DIR}/src/lib_jit.c + ${LUAJIT_DIR}/src/lib_ffi.c) + +SET(SRC_LJCORE + ${LUAJIT_DIR}/src/lj_gc.c + ${LUAJIT_DIR}/src/lj_err.c + ${LUAJIT_DIR}/src/lj_char.c + ${LUAJIT_DIR}/src/lj_buf.c + ${LUAJIT_DIR}/src/lj_profile.c + ${LUAJIT_DIR}/src/lj_strfmt.c + ${LUAJIT_DIR}/src/lj_bc.c + ${LUAJIT_DIR}/src/lj_obj.c + ${LUAJIT_DIR}/src/lj_str.c + ${LUAJIT_DIR}/src/lj_tab.c + ${LUAJIT_DIR}/src/lj_func.c + ${LUAJIT_DIR}/src/lj_udata.c + ${LUAJIT_DIR}/src/lj_meta.c + ${LUAJIT_DIR}/src/lj_debug.c + ${LUAJIT_DIR}/src/lj_state.c + ${LUAJIT_DIR}/src/lj_dispatch.c + ${LUAJIT_DIR}/src/lj_vmevent.c + ${LUAJIT_DIR}/src/lj_vmmath.c + ${LUAJIT_DIR}/src/lj_strscan.c + ${LUAJIT_DIR}/src/lj_api.c + ${LUAJIT_DIR}/src/lj_lex.c + ${LUAJIT_DIR}/src/lj_parse.c + ${LUAJIT_DIR}/src/lj_bcread.c + ${LUAJIT_DIR}/src/lj_bcwrite.c + ${LUAJIT_DIR}/src/lj_load.c + ${LUAJIT_DIR}/src/lj_ir.c + ${LUAJIT_DIR}/src/lj_opt_mem.c + ${LUAJIT_DIR}/src/lj_opt_fold.c + ${LUAJIT_DIR}/src/lj_opt_narrow.c + ${LUAJIT_DIR}/src/lj_opt_dce.c + ${LUAJIT_DIR}/src/lj_opt_loop.c + ${LUAJIT_DIR}/src/lj_opt_split.c + ${LUAJIT_DIR}/src/lj_opt_sink.c + ${LUAJIT_DIR}/src/lj_mcode.c + ${LUAJIT_DIR}/src/lj_snap.c + ${LUAJIT_DIR}/src/lj_record.c + ${LUAJIT_DIR}/src/lj_crecord.c + ${LUAJIT_DIR}/src/lj_ffrecord.c + ${LUAJIT_DIR}/src/lj_asm.c + ${LUAJIT_DIR}/src/lj_trace.c + ${LUAJIT_DIR}/src/lj_gdbjit.c + ${LUAJIT_DIR}/src/lj_ctype.c + ${LUAJIT_DIR}/src/lj_cdata.c + ${LUAJIT_DIR}/src/lj_cconv.c + ${LUAJIT_DIR}/src/lj_ccall.c + ${LUAJIT_DIR}/src/lj_ccallback.c + ${LUAJIT_DIR}/src/lj_carith.c + ${LUAJIT_DIR}/src/lj_clib.c + ${LUAJIT_DIR}/src/lj_cparse.c + ${LUAJIT_DIR}/src/lj_lib.c + ${LUAJIT_DIR}/src/lj_alloc.c + ${LUAJIT_DIR}/src/lj_vmmath.c + ${LUAJIT_DIR}/src/lib_aux.c + ${LUAJIT_DIR}/src/lib_init.c + ${SRC_LJLIB}) + +SET(SRC_BUILDVM + ${LUAJIT_DIR}/src/host/buildvm.c + ${LUAJIT_DIR}/src/host/buildvm_asm.c + ${LUAJIT_DIR}/src/host/buildvm_peobj.c + ${LUAJIT_DIR}/src/host/buildvm_lib.c + ${LUAJIT_DIR}/src/host/buildvm_fold.c + ${CMAKE_CURRENT_BINARY_DIR}/buildvm_arch.h) + +## GENERATE +ADD_EXECUTABLE(buildvm ${SRC_BUILDVM}) +SET_TARGET_PROPERTIES(buildvm PROPERTIES COMPILE_DEFINITIONS "${TARGET_ARCH}") + +macro(add_buildvm_target _target _mode) + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_target} + COMMAND buildvm ARGS -m ${_mode} -o ${CMAKE_CURRENT_BINARY_DIR}/${_target} ${ARGN} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS buildvm ${ARGN} + ) +endmacro(add_buildvm_target) + +if (MSVC) + add_buildvm_target ( lj_vm.obj peobj ) + set (LJ_VM_SRC ${CMAKE_CURRENT_BINARY_DIR}/lj_vm.obj) +else () + add_buildvm_target ( lj_vm.S ${LJVM_MODE} ) + set (LJ_VM_SRC ${CMAKE_CURRENT_BINARY_DIR}/lj_vm.S) +endif () +add_buildvm_target ( lj_ffdef.h ffdef ${SRC_LJLIB} ) +add_buildvm_target ( lj_bcdef.h bcdef ${SRC_LJLIB} ) +add_buildvm_target ( lj_folddef.h folddef ${LUAJIT_DIR}/src/lj_opt_fold.c ) +add_buildvm_target ( lj_recdef.h recdef ${SRC_LJLIB} ) +add_buildvm_target ( lj_libdef.h libdef ${SRC_LJLIB} ) +add_buildvm_target ( vmdef.lua vmdef ${SRC_LJLIB} ) + +SET(DEPS + ${LJ_VM_SRC} + ${CMAKE_CURRENT_BINARY_DIR}/lj_ffdef.h + ${CMAKE_CURRENT_BINARY_DIR}/lj_bcdef.h + ${CMAKE_CURRENT_BINARY_DIR}/lj_libdef.h + ${CMAKE_CURRENT_BINARY_DIR}/lj_recdef.h + ${CMAKE_CURRENT_BINARY_DIR}/lj_folddef.h + ${CMAKE_CURRENT_BINARY_DIR}/vmdef.lua + ) + +## COMPILE +include_directories( + ${LUAJIT_DIR}/dynasm + ${LUAJIT_DIR}/src + ${CMAKE_CURRENT_BINARY_DIR} +) + +IF(WITH_SHARED_LUA) + IF(WITH_AMALG) + add_library(luajit-5.1 SHARED ${LUAJIT_DIR}/src/ljamalg.c ${DEPS} ) + ELSE() + add_library(luajit-5.1 SHARED ${SRC_LJCORE} ${DEPS} ) + ENDIF() + SET_TARGET_PROPERTIES(luajit-5.1 PROPERTIES OUTPUT_NAME "lua51") +ELSE() + IF(WITH_AMALG) + add_library(luajit-5.1 STATIC ${LUAJIT_DIR}/src/ljamalg.c ${DEPS} ) + ELSE() + add_library(luajit-5.1 STATIC ${SRC_LJCORE} ${DEPS} ) + ENDIF() + SET_TARGET_PROPERTIES(luajit-5.1 PROPERTIES + PREFIX "lib" IMPORT_PREFIX "lib" OUTPUT_NAME "luajit") +ENDIF() + +target_link_libraries (luajit-5.1 ${LIBS} ) + +IF(WIN32) + add_executable(luajit ${LUAJIT_DIR}/src/luajit.c) + target_link_libraries(luajit luajit-5.1) +ELSE() + IF(WITH_AMALG) + add_executable(luajit ${LUAJIT_DIR}/src/luajit.c ${LUAJIT_DIR}/src/ljamalg.c ${DEPS}) + ELSE() + add_executable(luajit ${LUAJIT_DIR}/src/luajit.c ${SRC_LJCORE} ${DEPS}) + ENDIF() + target_link_libraries(luajit ${LIBS}) + SET_TARGET_PROPERTIES(luajit PROPERTIES ENABLE_EXPORTS ON) +ENDIF() + +MACRO(LUAJIT_add_custom_commands luajit_target) + SET(target_srcs "") + FOREACH(file ${ARGN}) + IF(${file} MATCHES ".*\\.lua$") + set(file "${CMAKE_CURRENT_SOURCE_DIR}/${file}") + set(source_file ${file}) + string(LENGTH ${CMAKE_SOURCE_DIR} _luajit_source_dir_length) + string(LENGTH ${file} _luajit_file_length) + math(EXPR _begin "${_luajit_source_dir_length} + 1") + math(EXPR _stripped_file_length "${_luajit_file_length} - ${_luajit_source_dir_length} - 1") + string(SUBSTRING ${file} ${_begin} ${_stripped_file_length} stripped_file) + + set(generated_file "${CMAKE_BINARY_DIR}/jitted_tmp/${stripped_file}_${luajit_target}_generated${CMAKE_C_OUTPUT_EXTENSION}") + + add_custom_command( + OUTPUT ${generated_file} + MAIN_DEPENDENCY ${source_file} + DEPENDS luajit + COMMAND luajit + ARGS -bg + ${source_file} + ${generated_file} + COMMENT "Building Luajitted ${source_file}: ${generated_file}" + ) + + get_filename_component(basedir ${generated_file} PATH) + file(MAKE_DIRECTORY ${basedir}) + + set(target_srcs ${target_srcs} ${generated_file}) + set_source_files_properties( + ${generated_file} + properties + external_object true # this is an object file + generated true # to say that "it is OK that the obj-files do not exist before build time" + ) + ELSE() + set(target_srcs ${target_srcs} ${file}) + ENDIF(${file} MATCHES ".*\\.lua$") + ENDFOREACH(file) +ENDMACRO() + +MACRO(LUAJIT_ADD_EXECUTABLE luajit_target) + LUAJIT_add_custom_commands(${luajit_target} ${ARGN}) + add_executable(${luajit_target} ${target_srcs}) +ENDMACRO(LUAJIT_ADD_EXECUTABLE luajit_target) diff --git a/3rdparty/luv/deps/uv.cmake b/3rdparty/luv/deps/uv.cmake new file mode 100644 index 00000000000..b6570b26b60 --- /dev/null +++ b/3rdparty/luv/deps/uv.cmake @@ -0,0 +1,224 @@ +## Modifications +## Copyright 2014 The Luvit Authors. All Rights Reserved. + +## Original Copyright +# Copyright (c) 2014 David Capello +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +include(CheckTypeSize) + +cmake_minimum_required(VERSION 2.8.9) + +set(LIBUVDIR ${CMAKE_CURRENT_LIST_DIR}/libuv) + +include_directories( + ${LIBUVDIR}/src + ${LIBUVDIR}/include +) + +set(SOURCES + ${LIBUVDIR}/include/uv.h + ${LIBUVDIR}/include/tree.h + ${LIBUVDIR}/include/uv-errno.h + ${LIBUVDIR}/include/uv-threadpool.h + ${LIBUVDIR}/include/uv-version.h + ${LIBUVDIR}/src/fs-poll.c + ${LIBUVDIR}/src/heap-inl.h + ${LIBUVDIR}/src/inet.c + ${LIBUVDIR}/src/queue.h + ${LIBUVDIR}/src/threadpool.c + ${LIBUVDIR}/src/uv-common.c + ${LIBUVDIR}/src/uv-common.h + ${LIBUVDIR}/src/version.c +) + +if(WIN32) + add_definitions( + -D_WIN32_WINNT=0x0600 + -D_CRT_SECURE_NO_WARNINGS + -D_GNU_SOURCE + ) + set(SOURCES ${SOURCES} + ${LIBUVDIR}/include/uv-win.h + ${LIBUVDIR}/src/win/async.c + ${LIBUVDIR}/src/win/atomicops-inl.h + ${LIBUVDIR}/src/win/core.c + ${LIBUVDIR}/src/win/dl.c + ${LIBUVDIR}/src/win/error.c + ${LIBUVDIR}/src/win/fs.c + ${LIBUVDIR}/src/win/fs-event.c + ${LIBUVDIR}/src/win/getaddrinfo.c + ${LIBUVDIR}/src/win/getnameinfo.c + ${LIBUVDIR}/src/win/handle.c + ${LIBUVDIR}/src/win/handle-inl.h + ${LIBUVDIR}/src/win/internal.h + ${LIBUVDIR}/src/win/loop-watcher.c + ${LIBUVDIR}/src/win/pipe.c + ${LIBUVDIR}/src/win/thread.c + ${LIBUVDIR}/src/win/poll.c + ${LIBUVDIR}/src/win/process.c + ${LIBUVDIR}/src/win/process-stdio.c + ${LIBUVDIR}/src/win/req.c + ${LIBUVDIR}/src/win/req-inl.h + ${LIBUVDIR}/src/win/signal.c + ${LIBUVDIR}/src/win/snprintf.c + ${LIBUVDIR}/src/win/stream.c + ${LIBUVDIR}/src/win/stream-inl.h + ${LIBUVDIR}/src/win/tcp.c + ${LIBUVDIR}/src/win/tty.c + ${LIBUVDIR}/src/win/timer.c + ${LIBUVDIR}/src/win/udp.c + ${LIBUVDIR}/src/win/util.c + ${LIBUVDIR}/src/win/winapi.c + ${LIBUVDIR}/src/win/winapi.h + ${LIBUVDIR}/src/win/winsock.c + ${LIBUVDIR}/src/win/winsock.h + ) +else() + include_directories(${LIBUVDIR}/src/unix) + set(SOURCES ${SOURCES} + ${LIBUVDIR}/include/uv-unix.h + ${LIBUVDIR}/include/uv-linux.h + ${LIBUVDIR}/include/uv-sunos.h + ${LIBUVDIR}/include/uv-darwin.h + ${LIBUVDIR}/include/uv-bsd.h + ${LIBUVDIR}/include/uv-aix.h + ${LIBUVDIR}/src/unix/async.c + ${LIBUVDIR}/src/unix/atomic-ops.h + ${LIBUVDIR}/src/unix/core.c + ${LIBUVDIR}/src/unix/dl.c + ${LIBUVDIR}/src/unix/fs.c + ${LIBUVDIR}/src/unix/getaddrinfo.c + ${LIBUVDIR}/src/unix/getnameinfo.c + ${LIBUVDIR}/src/unix/internal.h + ${LIBUVDIR}/src/unix/loop.c + ${LIBUVDIR}/src/unix/loop-watcher.c + ${LIBUVDIR}/src/unix/pipe.c + ${LIBUVDIR}/src/unix/poll.c + ${LIBUVDIR}/src/unix/process.c + ${LIBUVDIR}/src/unix/signal.c + ${LIBUVDIR}/src/unix/spinlock.h + ${LIBUVDIR}/src/unix/stream.c + ${LIBUVDIR}/src/unix/tcp.c + ${LIBUVDIR}/src/unix/thread.c + ${LIBUVDIR}/src/unix/timer.c + ${LIBUVDIR}/src/unix/tty.c + ${LIBUVDIR}/src/unix/udp.c + ) +endif() + +check_type_size("void*" SIZEOF_VOID_P) +if(SIZEOF_VOID_P EQUAL 8) + add_definitions(-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE) +endif() + +## Freebsd +if("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD") + set(SOURCES ${SOURCES} + ${LIBUVDIR}/src/unix/kqueue.c + ${LIBUVDIR}/src/unix/freebsd.c + ) +endif() + +## Linux +if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + add_definitions( + -D_GNU_SOURCE + ) + set(SOURCES ${SOURCES} + ${LIBUVDIR}/src/unix/proctitle.c + ${LIBUVDIR}/src/unix/linux-core.c + ${LIBUVDIR}/src/unix/linux-inotify.c + ${LIBUVDIR}/src/unix/linux-syscalls.c + ${LIBUVDIR}/src/unix/linux-syscalls.h + ) +endif() + +## SunOS +if("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS") + add_definitions( + -D__EXTENSIONS__ + -D_XOPEN_SOURCE=500 + ) + set(SOURCES ${SOURCES} + ${LIBUVDIR}/src/unix/sunos.c + ) +endif() + +## Darwin +if(APPLE) + add_definitions( + -D=_DARWIN_USE_64_BIT_INODE + ) + set(SOURCES ${SOURCES} + ${LIBUVDIR}/src/unix/proctitle.c + ${LIBUVDIR}/src/unix/darwin.c + ${LIBUVDIR}/src/unix/fsevents.c + ${LIBUVDIR}/src/unix/darwin-proctitle.c + ${LIBUVDIR}/src/unix/kqueue.c + ) +endif() + +add_library(uv STATIC ${SOURCES}) +set_property(TARGET uv PROPERTY POSITION_INDEPENDENT_CODE ON) + +if("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD") + target_link_libraries(uv + pthread + kvm + ) +endif() + +if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + target_link_libraries(uv + pthread + ) +endif() + +if(WIN32) + target_link_libraries(uv + ws2_32.lib + shell32.lib + psapi.lib + iphlpapi.lib + advapi32.lib + Userenv.lib + ) +endif() + +if("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS") + target_link_libraries(uv + kstat + socket + sendfile + ) +endif() + +if(APPLE) + find_library(FOUNDATION_LIBRARY Foundation) + find_library(CORESERVICES_LIBRARY CoreServices) + find_library(APPLICATION_SERVICES_LIBRARY ApplicationServices) + target_link_libraries(uv + ${FOUNDATION_LIBRARY} + ${CORESERVICES_LIBRARY} + ${APPLICATION_SERVICES_LIBRARY} + ) +endif() diff --git a/3rdparty/luv/docs.md b/3rdparty/luv/docs.md new file mode 100644 index 00000000000..187dec24ff1 --- /dev/null +++ b/3rdparty/luv/docs.md @@ -0,0 +1,1309 @@ +# LibUV in Lua + +The [luv][] project provides access to the multi-platform support library +[libuv][] to lua code. It was primariliy developed for the [luvit][] project as +the `uv` builtin module, but can be used in other lua environments. + +### TCP Echo Server Example + +Here is a small example showing a TCP echo server: + +```lua +local uv = require('uv') + +local server = uv.new_tcp() +server:bind("127.0.0.1", 1337) +server:listen(128, function (err) + assert(not err, err) + local client = uv.new_tcp() + server:accept(client) + client:read_start(function (err, chunk) + assert(not err, err) + if chunk then + client:write(chunk) + else + client:shutdown() + client:close() + end + end) +end) +print("TCP server listening at 127.0.0.1 port 1337") +uv.run() +``` + +### Methods vs Functions + +As a quick note, [libuv][] is a C library and as such, there are no such things +as methods. The [luv][] bindings allow calling the libuv functions as either +functions or methods. For example, calling `server:bind(host, port)` is +equivalent to calling `uv.tcp_bind(server, host, port)`. All wrapped uv types +in lua have method shortcuts where is makes sense. Some are even renamed +shorter like the `tcp_` prefix that removed in method form. Under the hood it's +the exact same C function. + +## Table Of Contents + +The rest of the docs are organized by libuv type. There is some hierarchy as +most types are considered handles and some are considered streams. + + - [`uv_loop_t`][] — Event loop + - [`uv_handle_t`][] — Base handle + - [`uv_timer_t`][] — Timer handle + - [`uv_prepare_t`][] — Prepare handle + - [`uv_check_t`][] — Check handle + - [`uv_idle_t`][] — Idle handle + - [`uv_async_t`][] — Async handle + - [`uv_poll_t`][] — Poll handle + - [`uv_signal_t`][] — Signal handle + - [`uv_process_t`][] — Process handle + - [`uv_stream_t`][] — Stream handle + - [`uv_tcp_t`][] — TCP handle + - [`uv_pipe_t`][] — Pipe handle + - [`uv_tty_t`][] — TTY handle + - [`uv_udp_t`][] — UDP handle + - [`uv_fs_event_t`][] — FS Event handle + - [`uv_fs_poll_t`][] — FS Poll handle + - [Filesystem operations][] + - [DNS utility functions][] + - [Miscellaneous utilities][] + +## `uv_loop_t` — Event loop + +[`uv_loop_t`]: #uv_loop_t--event-loop + +The event loop is the central part of libuv’s functionality. It takes care of +polling for i/o and scheduling callbacks to be run based on different sources of +events. + +In [luv][], there is an implicit uv loop for every lua state that loads the +library. You can use this library in an multithreaded environment as long as +each thread has it's own lua state with corresponsding own uv loop. + +### `uv.loop_close()` + +Closes all internal loop resources. This function must only be called once the +loop has finished its execution or it will raise a UV_EBUSY error. + +### `uv.run([mode])` + +> optional `mode` defaults to `"default"` + +This function runs the event loop. It will act differently depending on the +specified mode: + + - `"default"`: Runs the event loop until there are no more active and + referenced handles or requests. Always returns `false`. + + - `"once"`: Poll for i/o once. Note that this function blocks if there are no + pending callbacks. Returns `false` when done (no active handles or requests + left), or `true` if more callbacks are expected (meaning you should run + the event loop again sometime in the future). + + - `"nowait"`: Poll for i/o once but don’t block if there are no + pending callbacks. Returns `false` if done (no active handles or requests + left), or `true` if more callbacks are expected (meaning you should run + the event loop again sometime in the future). + +Luvit will implicitly call `uv.run()` after loading user code, but if you use +the `luv` bindings directly, you need to call this after registering your +initial set of event callbacks to start the event loop. + +### `uv.loop_alive()` + +Returns true if there are active handles or request in the loop. + +### `uv.stop()` + +Stop the event loop, causing `uv_run()` to end as soon as possible. This +will happen not sooner than the next loop iteration. If this function was called +before blocking for i/o, the loop won’t block for i/o on this iteration. + +### `uv.backend_fd()` + +Get backend file descriptor. Only kqueue, epoll and event ports are supported. + +This can be used in conjunction with `uv_run("nowait")` to poll in one thread +and run the event loop’s callbacks in another. + +**Note**: Embedding a kqueue fd in another kqueue pollset doesn’t work on all +platforms. It’s not an error to add the fd but it never generates events. + +### `uv.backend_timeout()` + +Get the poll timeout. The return value is in milliseconds, or -1 for no timeout. + +### `uv.now()` + +Return the current timestamp in milliseconds. The timestamp is cached at the +start of the event loop tick, see `uv.update_time()` for details and rationale. + +The timestamp increases monotonically from some arbitrary point in time. Don’t +make assumptions about the starting point, you will only get disappointed. + +**Note**: Use `uv.hrtime()` if you need sub-millisecond granularity. + +### `uv.update_time()` + +Update the event loop’s concept of “now”. Libuv caches the current time at the +start of the event loop tick in order to reduce the number of time-related +system calls. + +You won’t normally need to call this function unless you have callbacks that +block the event loop for longer periods of time, where “longer” is somewhat +subjective but probably on the order of a millisecond or more. + +### `uv.walk(callback)` + +Walk the list of handles: `callback` will be executed with the handle. + +```lua +-- Example usage of uv.walk to close all handles that aren't already closing. +uv.walk(function (handle) + if not handle:is_closing() then + handle:close() + end +end) +``` + +## `uv_handle_t` — Base handle + +[`uv_handle_t`]: #uv_handle_t--base-handle + +`uv_handle_t` is the base type for all libuv handle types. + +Structures are aligned so that any libuv handle can be cast to `uv_handle_t`. +All API functions defined here work with any handle type. + +### `uv.is_active(handle)` + +> method form `handle:is_active()` + +Returns `true` if the handle is active, `false` if it’s inactive. What “active” +means depends on the type of handle: + + - A [`uv_async_t`][] handle is always active and cannot be deactivated, except + by closing it with uv_close(). + + - A [`uv_pipe_t`][], [`uv_tcp_t`][], [`uv_udp_t`][], etc. handlebasically any + handle that deals with i/ois active when it is doing something that + involves i/o, like reading, writing, connecting, accepting new connections, + etc. + + - A [`uv_check_t`][], [`uv_idle_t`][], [`uv_timer_t`][], etc. handle is active + when it has been started with a call to `uv.check_start()`, + `uv.idle_start()`, etc. + +Rule of thumb: if a handle of type `uv_foo_t` has a `uv.foo_start()` function, +then it’s active from the moment that function is called. Likewise, +`uv.foo_stop()` deactivates the handle again. + +### `uv.is_closing(handle)` + +> method form `handle:is_closing()` + +Returns `true` if the handle is closing or closed, `false` otherwise. + +**Note**: This function should only be used between the initialization of the +handle and the arrival of the close callback. + +### `uv.close(handle, callback)` + +> method form `handle:close(callback)` + +Request handle to be closed. `callback` will be called asynchronously after this +call. This MUST be called on each handle before memory is released. + +Handles that wrap file descriptors are closed immediately but `callback` will +still be deferred to the next iteration of the event loop. It gives you a chance +to free up any resources associated with the handle. + +In-progress requests, like `uv_connect_t` or `uv_write_t`, are cancelled and +have their callbacks called asynchronously with `status=UV_ECANCELED`. + +### `uv.ref(handle)` + +> method form `handle:ref()` + +Reference the given handle. References are idempotent, that is, if a handle is +already referenced calling this function again will have no effect. + +See [Reference counting][]. + +### `uv.unref(handle)` + +> method form `handle:unref()` + +Un-reference the given handle. References are idempotent, that is, if a handle +is not referenced calling this function again will have no effect. + +See [Reference counting][]. + +### `uv.has_ref(handle)` + +> method form `handle:has_ref()` + +Returns `true` if the handle referenced, `false` otherwise. + +See [Reference counting][]. + +### `uv.send_buffer_size(handle, [size]) -> size` + +> method form `handle:send_buffer_size(size)` + +Gets or sets the size of the send buffer that the operating system uses for the +socket. + +If `size` is omitted, it will return the current send buffer size, otherwise it +will use `size` to set the new send buffer size. + +This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP +handles on Windows. + +**Note**: Linux will set double the size and return double the size of the +original set value. + +### `uv.recv_buffer_size(handle, [size])` + +> method form `handle:recv_buffer_size(size)` + +Gets or sets the size of the receive buffer that the operating system uses for +the socket. + +If `size` is omitted, it will return the current receive buffer size, otherwise +it will use `size` to set the new receive buffer size. + +This function works for TCP, pipe and UDP handles on Unix and for TCP and UDP +handles on Windows. + +**Note**: Linux will set double the size and return double the size of the +original set value. + +### `uv.fileno(handle)` + +> method form `handle:fileno()` + +Gets the platform dependent file descriptor equivalent. + +The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing any +other handle type will fail with UV_EINVAL. + +If a handle doesn’t have an attached file descriptor yet or the handle itself +has been closed, this function will return UV_EBADF. + +**Warning**: Be very careful when using this function. libuv assumes it’s in +control of the file descriptor so any change to it may lead to malfunction. + +## Reference counting + +[reference counting]: #reference-counting + +The libuv event loop (if run in the default mode) will run until there are no +active and referenced handles left. The user can force the loop to exit early by +unreferencing handles which are active, for example by calling `uv.unref()` +after calling `uv.timer_start()`. + +A handle can be referenced or unreferenced, the refcounting scheme doesn’t use a +counter, so both operations are idempotent. + +All handles are referenced when active by default, see `uv.is_active()` for a +more detailed explanation on what being active involves. + +## `uv_timer_t` — Timer handle + +[`uv_timer_t`]: #uv_timer_t--timer-handle + +Timer handles are used to schedule callbacks to be called in the future. + +### `uv.new_timer() -> timer` + +Creates and initializes a new `uv_timer_t`. Returns the lua userdata wrapping +it. + +```lua +-- Creating a simple setTimeout wrapper +local function setTimeout(timeout, callback) + local timer = uv.new_timer() + timer:start(timeout, 0, function () + timer:stop() + timer:close() + callback() + end) + return timer +end + +-- Creating a simple setInterval wrapper +local function setInterval(interval, callback) + local timer = uv.new_timer() + timer:start(interval, interval, function () + timer:stop() + timer:close() + callback() + end) + return timer +end + +-- And clearInterval +local function clearInterval(timer) + timer:stop() + timer:close() +end +``` + +### `uv.timer_start(timer, timeout, repeat, callback)` + +> method form `timer:start(timeout, repeat, callback)` + +Start the timer. `timeout` and `repeat` are in milliseconds. + +If `timeout` is zero, the callback fires on the next event loop iteration. If +`repeat` is non-zero, the callback fires first after timeout milliseconds and +then repeatedly after repeat milliseconds. + +### `uv.timer_stop(timer)` + +> method form `timer:stop()` + +Stop the timer, the callback will not be called anymore. + +### `uv.timer_again(timer)` + +> method form `timer:again()` + +Stop the timer, and if it is repeating restart it using the repeat value as the +timeout. If the timer has never been started before it raises `EINVAL`. + +### `uv.timer_set_repeat(timer, repeat)` + +> method form `timer:set_repeat(repeat)` + +Set the repeat value in milliseconds. + +**Note**: If the repeat value is set from a timer callback it does not +immediately take effect. If the timer was non-repeating before, it will have +been stopped. If it was repeating, then the old repeat value will have been +used to schedule the next timeout. + +### `uv.timer_get_repeat(timer) -> repeat` + +> method form `timer:get_repeat() -> repeat` + +Get the timer repeat value. + +## `uv_prepare_t` — Prepare handle + +[`uv_prepare_t`]: #uv_prepare_t--prepare-handle + +Prepare handles will run the given callback once per loop iteration, right before polling for i/o. + +```lua +local prepare = uv.new_prepare() +prepare:start(function() + print("Before I/O polling") +end) +``` + +### `uv.new_prepare() -> prepare` + +Creates and initializes a new `uv_prepare_t`. Returns the lua userdata wrapping +it. + +### `uv.prepare_start(prepare, callback)` + +> method form `prepare:start(callback)` + +Start the handle with the given callback. + +### `uv.prepare_stop(prepare)` + +> method form `prepare:stop()` + +Stop the handle, the callback will no longer be called. + +## `uv_check_t` — Check handle + +[`uv_check_t`]: #uv_check_t--check-handle + +Check handles will run the given callback once per loop iteration, right after +polling for i/o. + +```lua +local check = uv.new_check() +check:start(function() + print("After I/O polling") +end) +``` + +### `uv.new_check() -> check` + +Creates and initializes a new `uv_check_t`. Returns the lua userdata wrapping +it. + +### `uv.check_start(check, callback)` + +> method form `check:start(callback)` + +Start the handle with the given callback. + +### `uv.check_stop(check)` + +> method form `check:stop()` + +Stop the handle, the callback will no longer be called. + +## `uv_idle_t` — Idle handle + +[`uv_idle_t`]: #uv_idle_t--idle-handle + +Idle handles will run the given callback once per loop iteration, right before +the [`uv_prepare_t`][] handles. + +**Note**: The notable difference with prepare handles is that when there are +active idle handles, the loop will perform a zero timeout poll instead of +blocking for i/o. + +**Warning**: Despite the name, idle handles will get their callbacks called on +every loop iteration, not when the loop is actually “idle”. + +```lua +local idle = uv.new_idle() +idle:start(function() + print("Before I/O polling, no blocking") +end) +``` +### `uv.new_idle() -> idle` + +Creates and initializes a new `uv_idle_t`. Returns the lua userdata wrapping +it. + +### `uv.idle_start(idle, callback)` + +> method form `idle:start(callback)` + +Start the handle with the given callback. + +### `uv.idle_stop(check)` + +> method form `idle:stop()` + +Stop the handle, the callback will no longer be called. + +## `uv_async_t` — Async handle + +[`uv_async_t`]: #uv_async_t--async-handle + +Async handles allow the user to “wakeup” the event loop and get a callback +called from another thread. + +```lua +local async +async = uv.new_async(function() + print("async operation ran") + async:close() +end) + +async:send() +``` + +### `uv.new_async(callback) -> async` + +Creates and initializes a new `uv_async_t`. Returns the lua userdata wrapping +it. A NULL callback is allowed. + +**Note**: Unlike other handle initialization functions, it immediately starts +the handle. + +### `uv.async_send(async)` + +> method form `async:send()` + +Wakeup the event loop and call the async handle’s callback. + +**Note**: It’s safe to call this function from any thread. The callback will be +called on the loop thread. + +**Warning**: libuv will coalesce calls to `uv.async_send(async)`, that is, not +every call to it will yield an execution of the callback, the only guarantee is +that it will be called at least once. Thus, calling this function may not +wakeup the event loop if it was already called previously within a short period +of time. + +## `uv_poll_t` — Poll handle + +[`uv_poll_t`]: #uv_poll_t--poll-handle + +Poll handles are used to watch file descriptors for readability and writability, +similar to the purpose of [poll(2)](http://linux.die.net/man/2/poll). + +The purpose of poll handles is to enable integrating external libraries that +rely on the event loop to signal it about the socket status changes, like c-ares +or libssh2. Using `uv_poll_t` for any other purpose is not recommended; +`uv_tcp_t`, `uv_udp_t`, etc. provide an implementation that is faster and more +scalable than what can be achieved with `uv_poll_t`, especially on Windows. + +It is possible that poll handles occasionally signal that a file descriptor is +readable or writable even when it isn’t. The user should therefore always be +prepared to handle EAGAIN or equivalent when it attempts to read from or write +to the fd. + +It is not okay to have multiple active poll handles for the same socket, this +can cause libuv to busyloop or otherwise malfunction. + +The user should not close a file descriptor while it is being polled by an +active poll handle. This can cause the handle to report an error, but it might +also start polling another socket. However the fd can be safely closed +immediately after a call to `uv.poll_stop()` or `uv.close()`. + +**Note** On windows only sockets can be polled with poll handles. On Unix any +file descriptor that would be accepted by poll(2) can be used. + + +### `uv.new_poll(fd) -> poll` + +Initialize the handle using a file descriptor. + +The file descriptor is set to non-blocking mode. + +### `uv.new_socket_poll(fd) -> poll` + +Initialize the handle using a socket descriptor. On Unix this is identical to +`uv.poll_init()`. On windows it takes a SOCKET handle. + +The socket is set to non-blocking mode. + +### `uv.poll_start(poll, events, callback)` + +> method form `poll:start()` + +Starts polling the file descriptor. `events` is `"r"`, `"w"`, or `"rw"` and +translates to a bitmask made up of UV_READABLE and UV_WRITABLE. As soon as an +event is detected the callback will be called with status set to 0, and the +detected events set on the events field. + +The user should not close the socket while the handle is active. If the user +does that anyway, the callback may be called reporting an error status, but this +is not guaranteed. + +**Note** Calling `uv.poll_start()`` on a handle that is already active is fine. +Doing so will update the events mask that is being watched for. + +## `uv.poll_stop(poll)` + +> method form `poll:stop()` + +Stop polling the file descriptor, the callback will no longer be called. + +## `uv_signal_t` — Signal handle + +[`uv_signal_t`]: #uv_signal_t--signal-handle + +Signal handles implement Unix style signal handling on a per-event loop bases. + +Reception of some signals is emulated on Windows: +* SIGINT is normally delivered when the user presses CTRL+C. However, like on +Unix, it is not generated when terminal raw mode is enabled. +* SIGBREAK is delivered when the user pressed CTRL + BREAK. +* SIGHUP is generated when the user closes the console window. On SIGHUP the +program is given approximately 10 seconds to perform cleanup. After that +Windows will unconditionally terminate it. +* SIGWINCH is raised whenever libuv detects that the console has been resized. +SIGWINCH is emulated by libuv when the program uses a uv_tty_t handle to write +to the console. SIGWINCH may not always be delivered in a timely manner; libuv +will only detect size changes when the cursor is being moved. When a readable +[`uv_tty_t`][] handle is used in raw mode, resizing the console buffer will +also trigger a SIGWINCH signal. + +Watchers for other signals can be successfully created, but these signals are +never received. These signals are: SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGTERM +and SIGKILL. + +Calls to raise() or abort() to programmatically raise a signal are not detected +by libuv; these will not trigger a signal watcher. + +**Note**: On Linux SIGRT0 and SIGRT1 (signals 32 and 33) are used by the NPTL +pthreads library to manage threads. Installing watchers for those signals will +lead to unpredictable behavior and is strongly discouraged. Future versions of +libuv may simply reject them. + +```lua +-- Create a new signal handler +local sigint = uv.new_signal() +-- Define a handler function +uv.signal_start(sigint, "sigint", function(signal) +print("got " .. signal .. ", shutting down") +os.exit(1) +end) +``` + +### `uv.new_signal() -> signal` + +Creates and initializes a new `uv_signal_t`. Returns the lua userdata wrapping +it. + +### `uv.signal_start(signal, signum, callback)` + +> method form `signal:start(signum, callback)` + +Start the handle with the given callback, watching for the given signal. + +### `uv.signal_stop(signal)` + +> method form `signal:stop()` + +Stop the handle, the callback will no longer be called. + +## `uv_process_t` — Process handle + +[`uv_process_t`]: #uv_process_t--process-handle + +Process handles will spawn a new process and allow the user to control it and +establish communication channels with it using streams. + +### `uv.disable_stdio_inheritance()` + +Disables inheritance for file descriptors / handles that this process inherited +from its parent. The effect is that child processes spawned by this process +don’t accidentally inherit these handles. + +It is recommended to call this function as early in your program as possible, +before the inherited file descriptors can be closed or duplicated. + +**Note** This function works on a best-effort basis: there is no guarantee that +libuv can discover all file descriptors that were inherited. In general it does +a better job on Windows than it does on Unix. + +### `uv.spawn(file, options, onexit) -> process, pid` + +Initializes the process handle and starts the process. If the process is +successfully spawned, this function will return the handle and pid of the child +process. + +Possible reasons for failing to spawn would include (but not be limited to) the +file to execute not existing, not having permissions to use the setuid or setgid +specified, or not having enough memory to allocate for the new process. + + +```lua +local stdout = uv.new_pipe(false) +local stderr = uv.new_pipe(false) +local stdin = uv.new_pipe(false) + +local handle, pid + +local function onexit(code, signal) + p("exit", {code=code,signal=signal}) +end + +local function onclose() + p("close") +end + +local function onread(err, chunk) + assert(not err, err) + if (chunk) then + p("data", {data=chunk}) + else + p("end") + end +end + +local function onshutdown() + uv.close(handle, onclose) +end + +handle, pid = uv.spawn("cat", { + stdio = {stdin, stdout, stderr} +}, onexit) + +p{ + handle=handle, + pid=pid +} + +uv.read_start(stdout, onread) +uv.read_start(stderr, onread) +uv.write(stdin, "Hello World") +uv.shutdown(stdin, onshutdown) +``` + + - `options.args` - Command line arguments as a list of string. The first string + should be the path to the program. On Windows this uses CreateProcess which + concatenates the arguments into a string this can cause some strange errors. + (See `options.verbatim` below for Windows.) + - `options.stdio` - Set the file descriptors that will be made available to the + child process. The convention is that the first entries are stdin, stdout, + and stderr. (**Note** On Windows file descriptors after the third are + available to the child process only if the child processes uses the MSVCRT + runtime.) + - `options.env` - Set environment variables for the new process. + - `options.cwd` - Set current working directory for the subprocess. + - `options.uid` - Set the child process' user id. + - `options.gid` - Set the child process' group id. + - `options.verbatim` - If true, do not wrap any arguments in quotes, or perform + any other escaping, when converting the argument list into a command line + string. This option is only meaningful on Windows systems. On Unix it is + silently ignored. + - `options.detached` - If true, spawn the child process in a detached state - + this will make it a process group leader, and will effectively enable the + child to keep running after the parent exits. Note that the child process + will still keep the parent's event loop alive unless the parent process calls + `uv.unref()` on the child's process handle. + - `options.hide` - If true, hide the subprocess console window that would + normally be created. This option is only meaningful on Windows systems. On + Unix it is silently ignored. + +The `options.stdio` entries can take many shapes. + +- If they are numbers, then the child process inherits that same zero-indexed fd + from the parent process. +- If `uv_stream_h` handles are passed in, those are used as a read-write pipe or + inherited stream depending if the stream has a valid fd. +- Including `nil` placeholders means to ignore that fd in the child. + +When the child process exits, the `onexit` callback will be called with exit +code and signal. + +### `uv.process_kill(process, sigmun)` + +> method form `process:kill(sigmun)` + +Sends the specified signal to the given process handle. + +### `uv.kill(pid, sigmun)` + +Sends the specified signal to the given PID. + +## `uv_stream_t` — Stream handle + +[`uv_stream_t`]: #uv_stream_t--stream-handle + +Stream handles provide an abstraction of a duplex communication channel. +[`uv_stream_t`][] is an abstract type, libuv provides 3 stream implementations in +the form of [`uv_tcp_t`][], [`uv_pipe_t`][] and [`uv_tty_t`][]. + +### `uv.shutdown(stream, [callback]) -> req` + +> (method form `stream:shutdown([callback]) -> req`) + +Shutdown the outgoing (write) side of a duplex stream. It waits for pending +write requests to complete. The callback is called after +shutdown is complete. + +### `uv.listen(stream, backlog, callback)` + +> (method form `stream:listen(backlog, callback)`) + +Start listening for incoming connections. `backlog` indicates the number of +connections the kernel might queue, same as `listen(2)`. When a new incoming +connection is received the callback is called. + +### `uv.accept(stream, client_stream)` + +> (method form `stream:accept(client_stream)`) + +This call is used in conjunction with `uv.listen()` to accept incoming +connections. Call this function after receiving a callback to accept the +connection. + +When the connection callback is called it is guaranteed that this function +will complete successfully the first time. If you attempt to use it more than +once, it may fail. It is suggested to only call this function once per +connection call. + +```lua +server:listen(128, function (err) + local client = uv.new_tcp() + server:accept(client) +end) +``` + +### `uv.read_start(stream, callback)` + +> (method form `stream:read_start(callback)`) + +Callback is of the form `(err, data)`. + +Read data from an incoming stream. The callback will be made several times until +there is no more data to read or `uv.read_stop()` is called. When we’ve reached +EOF, `data` will be `nil`. + +```lua +stream:read_start(function (err, chunk) + if err then + -- handle read error + elseif chunk then + -- handle data + else + -- handle disconnect + end +end) +``` + +### `uv.read_stop(stream)` + +> (method form `stream:read_stop()`) + +Stop reading data from the stream. The read callback will no longer be called. + +### `uv.write(stream, data, [callback])` + +> (method form `stream:write(data, [callback])`) + +Write data to stream. + +`data` can either be a lua string or a table of strings. If a table is passed +in, the C backend will use writev to send all strings in a single system call. + +The optional `callback` is for knowing when the write is +complete. + +### `uv.write2(stream, data, send_handle, callback)` + +> (method form `stream:write2(data, send_handle, callback)`) + +Extended write function for sending handles over a pipe. The pipe must be +initialized with ip option to `true`. + +**Note: `send_handle` must be a TCP socket or pipe, which is a server or a +connection (listening or connected state). Bound sockets or pipes will be +assumed to be servers. + +### `uv.try_write(stream, data)` + +> (method form `stream:try_write(data)`) + +Same as `uv.write()`, but won’t queue a write request if it can’t be completed +immediately. + +Will return number of bytes written (can be less than the supplied buffer size). + +### `uv.is_readable(stream)` + +> (method form `stream:is_readable()`) + +Returns `true` if the stream is readable, `false` otherwise. + +### `uv.is_writable(stream)` + +> (method form `stream:is_writable()`) + +Returns `true` if the stream is writable, `false` otherwise. + +### `uv.stream_set_blocking(stream, blocking)` + +> (method form `stream:set_blocking(blocking)`) + +Enable or disable blocking mode for a stream. + +When blocking mode is enabled all writes complete synchronously. The interface +remains unchanged otherwise, e.g. completion or failure of the operation will +still be reported through a callback which is made asynchronously. + +**Warning**: Relying too much on this API is not recommended. It is likely to +change significantly in the future. Currently this only works on Windows and +only for uv_pipe_t handles. Also libuv currently makes no ordering guarantee +when the blocking mode is changed after write requests have already been +submitted. Therefore it is recommended to set the blocking mode immediately +after opening or creating the stream. + +## `uv_tcp_t` — TCP handle + +[`uv_tcp_t`]: #uv_tcp_t--tcp-handle + +TCP handles are used to represent both TCP streams and servers. + +`uv_tcp_t` is a ‘subclass’ of [`uv_stream_t`][](#uv_stream_t--stream-handle). + +### `uv.new_tcp() -> tcp` + +Creates and initializes a new `uv_tcp_t`. Returns the lua userdata wrapping it. + +### `uv.tcp_open(tcp, sock)` + +> (method form `tcp:open(sock)`) + +Open an existing file descriptor or SOCKET as a TCP handle. + +**Note: The user is responsible for setting the file descriptor in non-blocking +mode. + +### `uv.tcp_nodelay(tcp, enable)` + +> (method form `tcp:nodelay(enable)`) + +Enable / disable Nagle’s algorithm. + +### `uv.tcp_keepalive(tcp, enable, [delay])` + +> (method form `tcp:keepalive(enable, [delay])`) + +Enable / disable TCP keep-alive. `delay` is the initial delay in seconds, ignored +when enable is `false`. + +### `uv.tcp_simultaneous_accepts(tcp, enable)` + +> (method form `tcp:simultaneous_accepts(enable)`) + +Enable / disable simultaneous asynchronous accept requests that are queued by +the operating system when listening for new TCP connections. + +This setting is used to tune a TCP server for the desired performance. Having +simultaneous accepts can significantly improve the rate of accepting connections +(which is why it is enabled by default) but may lead to uneven load distribution +in multi-process setups. + +### `uv.tcp_bind(tcp, address, port)` + +> (method form `tcp:bind(address, port)`) + +Bind the handle to an address and port. `address` should be an IP address and +not a domain name. + +When the port is already taken, you can expect to see an UV_EADDRINUSE error +from either `uv.tcp_bind()`, `uv.listen()` or `uv.tcp_connect()`. That is, a +successful call to this function does not guarantee that the call to `uv.listen()` +or `uv.tcp_connect()` will succeed as well. + +Use a port of `0` to let the OS assign an ephemeral port. You can look it up +later using `uv.tcp_getsockname()`. + +### `uv.tcp_getsockname(tcp)` + +> (method form `tcp:getsockname()`) + +Get the current address to which the handle is bound. + +### `uv.tcp_getpeername(tcp)` + +> (method form `tcp:getpeername()`) + +Get the address of the peer connected to the handle. + +### `uv.tcp_connect(tcp, address, port, callback) -> req` + +> (method form `tcp:connect(host, port, callback) -> req`) + +### `uv.tcp_write_queue_size(tcp) -> size` + +> (method form `tcp:write_queue_size() -> size`) + +Establish an IPv4 or IPv6 TCP connection. + +The callback is made when the connection has been established or when a +connection error happened. + +```lua +local client = uv.new_tcp() +client:connect("127.0.0.1", 8080, function (err) + -- check error and carry on. +end) +``` + +## `uv_pipe_t` — Pipe handle + +[`uv_pipe_t`]: #uv_pipe_t--pipe-handle + +Pipe handles provide an abstraction over local domain sockets on Unix and named +pipes on Windows. + +```lua +local pipe = uv.new_pipe(false) + +pipe:bind('/tmp/sock.test') + +pipe:listen(128, function() + local client = uv.new_pipe(false) + pipe:accept(client) + client:write("hello!\n") + client:close() +end) +``` + +### `uv.new_pipe(ipc) -> pipe` + +Creates and initializes a new `uv_pipe_t`. Returns the lua userdata wrapping +it. The `ipc` argument is a boolean to indicate if this pipe will be used for +handle passing between processes. + +### `uv.pipe_open(file) -> pipe` + +Open an existing file descriptor or [`uv_handle_t`][] as a pipe. + +**Note**: The file descriptor is set to non-blocking mode. + +### `uv.pipe_bind(pipe, name)` + +> (method form `pipe:bind(name)`) + +Bind the pipe to a file path (Unix) or a name (Windows). + +**Note**: Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +typically between 92 and 108 bytes. + +### `uv.pipe_connect(pipe, name, callback)` + +> (method form `pipe:connect(name, callback)`) + +Connect to the Unix domain socket or the named pipe. + +**Note**: Paths on Unix get truncated to sizeof(sockaddr_un.sun_path) bytes, +typically between 92 and 108 bytes. + +### `uv.pipe_getsockname(pipe)` + +> (method form `pipe:getsockname()`) + +Returns the name of the Unix domain socket or the named pipe. + +### `uv.pipe_pending_instances(pipe, count)` + +> (method form `pipe:pending_instances(count)`) + +Set the number of pending pipe instance handles when the pipe server is waiting for connections. + +**Note**: This setting applies to Windows only. + +### `uv.pipe_pending_count(pipe)` + +> (method form `pipe:pending_count()`) + +Returns the pending pipe count for the named pipe. + +### `uv.pipe_pending_type(pipe)` + +> (method form `pipe:pending_type()`) + +Used to receive handles over IPC pipes. + +First - call [`uv.pipe_pending_count`][], if it’s > 0 then initialize a handle +of the given type, returned by [`uv.pipe_pending_type`][] and call +[`uv.accept(pipe, handle)`][]. + +## `uv_tty_t` — TTY handle + +[`uv_tty_t`]: #uv_tty_t--tty-handle + +TTY handles represent a stream for the console. + +```lua +-- Simple echo program +local stdin = uv.new_tty(0, true) +local stdout = uv.new_tty(1, false) + +stdin:read_start(function (err, data) + assert(not err, err) + if data then + stdout:write(data) + else + stdin:close() + stdout:close() + end +end) +``` + +### uv.new_tty(fd, readable) -> tty + +Initialize a new TTY stream with the given file descriptor. Usually the file +descriptor will be: + + - 0 - stdin + - 1 - stdout + - 2 - stderr + +`readable, specifies if you plan on calling uv_read_start() with this stream. +`stdin is readable, stdout is not. + +On Unix this function will try to open /dev/tty and use it if the passed file +descriptor refers to a TTY. This lets libuv put the tty in non-blocking mode +without affecting other processes that share the tty. + +Note: If opening `/dev/tty` fails, libuv falls back to blocking writes for +non-readable TTY streams. + +### uv.tty_set_mode(mode) + +> (method form `tty:set_mode(mode)`) + +Set the TTY using the specified terminal mode. + +Parameter `mode` is a C enum with the following values: + +- 0 - UV_TTY_MODE_NORMAL: Initial/normal terminal mode + +- 1 - UV_TTY_MODE_RAW: Raw input mode (On Windows, ENABLE_WINDOW_INPUT is + also enabled) + +- 2 - UV_TTY_MODE_IO: Binary-safe I/O mode for IPC (Unix-only) + +## uv.tty_reset_mode() + +To be called when the program exits. Resets TTY settings to default values for +the next process to take over. + +This function is async signal-safe on Unix platforms but can fail with error +code UV_EBUSY if you call it when execution is inside uv_tty_set_mode(). + +## uv.tty_get_winsize() -> w, h + +> (method form `tty:get_winsize() -> w, h`) + +Gets the current Window size. + +## `uv_udp_t` — UDP handle + +[`uv_udp_t`]: #uv_udp_t--udp-handle + +UDP handles encapsulate UDP communication for both clients and servers. + +### uv.new_udp() -> udp + +Initialize a new UDP handle. The actual socket is created lazily. + +### uv.udp_open(udp, fd) + +> (method form `udp:open(fd)`) + +Opens an existing file descriptor or Windows SOCKET as a UDP handle. + +Unix only: The only requirement of the sock argument is that it follows the +datagram contract (works in unconnected mode, supports sendmsg()/recvmsg(), +etc). In other words, other datagram-type sockets like raw sockets or netlink +sockets can also be passed to this function. + +The file descriptor is set to non-blocking mode. + +Note: The passed file descriptor or SOCKET is not checked for its type, but +it’s required that it represents a valid datagram socket. + +### uv.udp_bind(udp, host, port) + +> (method form `udp:bind(host, port)`) + +Bind the UDP handle to an IP address and port. + +### uv.udp_getsockname(udp) + +> (method form `udp:getsockname()`) + +Get the local IP and port of the UDP handle. + +### uv.udp_set_membership(udp, multicast_addr, interface_addr, membership) + +> (method form `udp:set_membership(multicast_addr, interface_addr, membership)`) + +Set membership for a multicast address. + +`multicast_addr` is multicast address to set membership for. + +`interface_addr` is interface address. + +`membership` can be the string `"leave"` or `"join"`. + +### uv.udp_set_multicast_loop(udp, on) + +> (method form `udp:set_multicast_loop(on)`) + +Set IP multicast loop flag. Makes multicast packets loop back to local +sockets. + +`on` is a boolean. + +### uv.udp_set_multicast_ttl(udp, tty) + +> (method form `udp:set_multicast_ttl(tty)`) + +Set the multicast ttl. + +`ttl` is an integer 1 through 255. + +### uv.udp_set_multicast_interface(udp, interface_addr) + +> (method form `udp:set_multicast_interface(interface_addr)`) + +Set the multicast interface to send or receive data on. + +### uv.udp_set_broadcast(udp, on) + +Set broadcast on or off. + +> (method form `udp:set_broadcast(, on)`) + +### uv.udp_set_ttl(udp, ttl) + +> (method form `udp:set_ttl(ttl)`) + +Set the time to live. + +`ttl` is an integer 1 through 255. + +### uv.udp_send(udp, data, host, port, callback) + +> (method form `udp:send(data, host, port, callback)`) + +Send data over the UDP socket. If the socket has not previously been bound +with `uv_udp_bind()` it will be bound to `0.0.0.0` (the “all interfaces” IPv4 +address) and a random port number. + +### uv.udp_try_send(udp, data, host, port) + +> (method form `udp:try_send(data, host, port)`) + +Same as `uv_udp_send()`, but won’t queue a send request if it can’t be +completed immediately. + +### uv.udp_recv_start(udp, callback) + +> (method form `udp:recv_start(callback)`) + +Prepare for receiving data. If the socket has not previously been bound with +`uv_udp_bind()` it is bound to `0.0.0.0` (the “all interfaces” IPv4 address) +and a random port number. + +### uv.udp_recv_stop(udp) + +> (method form `udp:recv_stop()`) + +## `uv_fs_event_t` — FS Event handle + +[`uv_fs_event_t`]: #uv_fs_event_t--fs-event-handle + +**TODO**: port docs from [docs.libuv.org](http://docs.libuv.org/en/v1.x/fs_event.html) +using [functions](https://github.com/luvit/luv/blob/25278a3871962cab29763692fdc3b270a7e96fe9/src/luv.c#L174-L177) +and [methods](https://github.com/luvit/luv/blob/25278a3871962cab29763692fdc3b270a7e96fe9/src/luv.c#L265-L270) +from [fs_event.c](https://github.com/luvit/luv/blob/master/src/fs_event.c) + +## `uv_fs_poll_t` — FS Poll handle + +[`uv_fs_poll_t`]: #uv_fs_poll_t--fs-poll-handle + +**TODO**: port docs from [docs.libuv.org](http://docs.libuv.org/en/v1.x/fs_poll.html) +using [functions](https://github.com/luvit/luv/blob/25278a3871962cab29763692fdc3b270a7e96fe9/src/luv.c#L180-L183) +and [methods](https://github.com/luvit/luv/blob/25278a3871962cab29763692fdc3b270a7e96fe9/src/luv.c#L272-L277) +from [fs_poll.c](https://github.com/luvit/luv/blob/master/src/fs_poll.c) + +## Filesystem operations + +[Filesystem operations]:#filesystem-operations + +**TODO**: port docs from [docs.libuv.org](http://docs.libuv.org/en/v1.x/fs.html) +using [functions](https://github.com/luvit/luv/blob/25278a3871962cab29763692fdc3b270a7e96fe9/src/luv.c#L186-L213) +from [fs.c](https://github.com/luvit/luv/blob/master/src/fs.c) + +## DNS utility functions + +[DNS utility functions]: #dns-utility-functions + +**TODO**: port docs from [docs.libuv.org](http://docs.libuv.org/en/v1.x/dns.html) +using [functions](https://github.com/luvit/luv/blob/25278a3871962cab29763692fdc3b270a7e96fe9/src/luv.c#L216-L217) +from [dns.c](https://github.com/luvit/luv/blob/master/src/dns.c) + +## Miscellaneous utilities + +[Miscellaneous utilities]: #miscellaneous-utilities + +**TODO**: port docs from [docs.libuv.org](http://docs.libuv.org/en/v1.x/misc.html) +using [functions](https://github.com/luvit/luv/blob/25278a3871962cab29763692fdc3b270a7e96fe9/src/luv.c#L220-L235) +from [misc.c](https://github.com/luvit/luv/blob/master/src/misc.c) + +[luv]: https://github.com/luvit/luv +[luvit]: https://github.com/luvit/luvit +[libuv]: https://github.com/libuv/libuv diff --git a/3rdparty/luv/examples/cqueues-main.lua b/3rdparty/luv/examples/cqueues-main.lua new file mode 100644 index 00000000000..ff60ec2b1c9 --- /dev/null +++ b/3rdparty/luv/examples/cqueues-main.lua @@ -0,0 +1,31 @@ +--[[ +Demonstrates using luv with a cqueues mainloop +]] + +local cqueues = require "cqueues" +local uv = require "luv" + +local cq = cqueues.new() + +cq:wrap(function() + while cqueues.poll({ + pollfd = uv.backend_fd(); + timeout = uv.backend_timeout() / 1000; + events = "r"; + }) do + uv.run("nowait") + end +end) + +cq:wrap(function() + while true do + cqueues.sleep(1) + print("HELLO FROM CQUEUES") + end +end) + +uv.new_timer():start(1000, 1000, function() + print("HELLO FROM LUV") +end) + +assert(cq:loop()) diff --git a/3rdparty/luv/examples/cqueues-slave.lua b/3rdparty/luv/examples/cqueues-slave.lua new file mode 100644 index 00000000000..599e7c6ded7 --- /dev/null +++ b/3rdparty/luv/examples/cqueues-slave.lua @@ -0,0 +1,55 @@ +--[[ +Demonstrates using cqueues with a luv mainloop + +Starts a simple sleep+print loop using each library's native form. +They should print intertwined. +]] + +local cqueues = require "cqueues" +local uv = require "luv" + +local cq = cqueues.new() + +do + local timer = uv.new_timer() + local function reset_timer() + local timeout = cq:timeout() + if timeout then + -- libuv takes milliseconds as an integer, + -- while cqueues gives timeouts as a floating point number + -- use `math.ceil` as we'd rather wake up late than early + timer:set_repeat(math.ceil(timeout * 1000)) + timer:again() + else + -- stop timer for now; it may be restarted later. + timer:stop() + end + end + local function onready() + -- Step the cqueues loop once (sleeping for max 0 seconds) + assert(cq:step(0)) + reset_timer() + end + -- Need to call `start` on libuv timer now + -- to provide callback and so that `again` works + timer:start(0, 0, onready) + -- Ask libuv to watch the cqueue pollfd + uv.new_poll(cq:pollfd()):start(cq:events(), onready) +end + +-- Adds a new function to the scheduler `cq` +-- The functions is an infinite loop that sleeps for 1 second and prints +cq:wrap(function() + while true do + cqueues.sleep(1) + print("HELLO FROM CQUEUES") + end +end) + +-- Start a luv timer that fires every 1 second +uv.new_timer():start(1000, 1000, function() + print("HELLO FROM LUV") +end) + +-- Run luv mainloop +uv.run() diff --git a/3rdparty/luv/examples/echo-server-client.lua b/3rdparty/luv/examples/echo-server-client.lua new file mode 100644 index 00000000000..ea4e6d2132d --- /dev/null +++ b/3rdparty/luv/examples/echo-server-client.lua @@ -0,0 +1,68 @@ +local p = require('lib/utils').prettyPrint +local uv = require('luv') + +local function create_server(host, port, on_connection) + + local server = uv.new_tcp() + p(1, server) + uv.tcp_bind(server, host, port) + + uv.listen(server, 128, function(err) + assert(not err, err) + local client = uv.new_tcp() + uv.accept(server, client) + on_connection(client) + end) + + return server +end + +local server = create_server("0.0.0.0", 0, function (client) + p("new client", client, uv.tcp_getsockname(client), uv.tcp_getpeername(client)) + uv.read_start(client, function (err, chunk) + p("onread", {err=err,chunk=chunk}) + + -- Crash on errors + assert(not err, err) + + if chunk then + -- Echo anything heard + uv.write(client, chunk) + else + -- When the stream ends, close the socket + uv.close(client) + end + end) +end) + +local address = uv.tcp_getsockname(server) +p("server", server, address) + +local client = uv.new_tcp() +uv.tcp_connect(client, "127.0.0.1", address.port, function (err) + assert(not err, err) + + uv.read_start(client, function (err, chunk) + p("received at client", {err=err,chunk=chunk}) + assert(not err, err) + if chunk then + uv.shutdown(client) + p("client done shutting down") + else + uv.close(client) + uv.close(server) + end + end) + + p("writing from client") + uv.write(client, "Hello") + uv.write(client, "World") + +end) + +-- Start the main event loop +uv.run() +-- Close any stray handles when done +uv.walk(uv.close) +uv.run() +uv.loop_close() diff --git a/3rdparty/luv/examples/killing-children.lua b/3rdparty/luv/examples/killing-children.lua new file mode 100644 index 00000000000..6aab693d0c1 --- /dev/null +++ b/3rdparty/luv/examples/killing-children.lua @@ -0,0 +1,24 @@ +local p = require('lib/utils').prettyPrint +local uv = require('luv') + + + +local child, pid +child, pid = uv.spawn("sleep", { + args = {"100"} +}, function (code, signal) + p("EXIT", {code=code,signal=signal}) + uv.close(child) +end) + +p{child=child, pid=pid} + +-- uv.kill(pid, "SIGTERM") +uv.process_kill(child, "SIGTERM") + +repeat + print("\ntick.") +until uv.run('once') == 0 + +print("done") + diff --git a/3rdparty/luv/examples/lots-o-dns.lua b/3rdparty/luv/examples/lots-o-dns.lua new file mode 100644 index 00000000000..59a1b0fe534 --- /dev/null +++ b/3rdparty/luv/examples/lots-o-dns.lua @@ -0,0 +1,49 @@ +local p = require('lib/utils').prettyPrint +local uv = require('luv') + +uv.getaddrinfo(nil, 80, nil, p) + +local domains = { + "facebook.com", + "google.com", + "mail.google.com", + "maps.google.com", + "plus.google.com", + "play.google.com", + "apple.com", + "hp.com", + "yahoo.com", + "mozilla.com", + "developer.mozilla.com", + "luvit.io", + "creationix.com", + "howtonode.org", + "github.com", + "gist.github.com" +} + +local i = 1 +local function next() + uv.getaddrinfo(domains[i], nil, { + v4mapped = true, + all = true, + addrconfig = true, + canonname = true, + numericserv = true, + socktype = "STREAM" + }, function (err, data) + assert(not err, err) + p(data) + i = i + 1 + if i <= #domains then + next() + end + end) +end +next(); + +repeat + print("\nTick..") +until uv.run('once') == 0 + +print("done") diff --git a/3rdparty/luv/examples/repl.lua b/3rdparty/luv/examples/repl.lua new file mode 100644 index 00000000000..92be0f17d87 --- /dev/null +++ b/3rdparty/luv/examples/repl.lua @@ -0,0 +1,89 @@ +local uv = require('luv') +local utils = require('lib/utils') + +if uv.guess_handle(0) ~= "tty" or + uv.guess_handle(1) ~= "tty" then + error "stdio must be a tty" +end +local stdin = uv.new_tty(0, true) +local stdout = require('lib/utils').stdout + +local debug = require('debug') +local c = utils.color + +local function gatherResults(success, ...) + local n = select('#', ...) + return success, { n = n, ... } +end + +local function printResults(results) + for i = 1, results.n do + results[i] = utils.dump(results[i]) + end + print(table.concat(results, '\t')) +end + +local buffer = '' + +local function evaluateLine(line) + if line == "<3\n" then + print("I " .. c("Bred") .. "♥" .. c() .. " you too!") + return '>' + end + local chunk = buffer .. line + local f, err = loadstring('return ' .. chunk, 'REPL') -- first we prefix return + + if not f then + f, err = loadstring(chunk, 'REPL') -- try again without return + end + + if f then + buffer = '' + local success, results = gatherResults(xpcall(f, debug.traceback)) + + if success then + -- successful call + if results.n > 0 then + printResults(results) + end + else + -- error + print(results[1]) + end + else + + if err:match "''$" then + -- Lua expects some more input; stow it away for next time + buffer = chunk .. '\n' + return '>>' + else + print(err) + buffer = '' + end + end + + return '>' +end + +local function displayPrompt(prompt) + uv.write(stdout, prompt .. ' ') +end + +local function onread(err, line) + if err then error(err) end + if line then + local prompt = evaluateLine(line) + displayPrompt(prompt) + else + uv.close(stdin) + end +end + +coroutine.wrap(function() + displayPrompt '>' + uv.read_start(stdin, onread) +end)() + +uv.run() + +print("") diff --git a/3rdparty/luv/examples/talking-to-children.lua b/3rdparty/luv/examples/talking-to-children.lua new file mode 100644 index 00000000000..10a53ef8c88 --- /dev/null +++ b/3rdparty/luv/examples/talking-to-children.lua @@ -0,0 +1,47 @@ +local p = require('lib/utils').prettyPrint +local uv = require('luv') + +local stdout = uv.new_pipe(false) +local stderr = uv.new_pipe( false) +local stdin = uv.new_pipe(false) + +local handle, pid + +local function onexit(code, signal) + p("exit", {code=code,signal=signal}) +end + +local function onclose() + p("close") +end + +local function onread(err, chunk) + assert(not err, err) + if (chunk) then + p("data", {data=chunk}) + else + p("end") + end +end + +local function onshutdown() + uv.close(handle, onclose) +end + +handle, pid = uv.spawn("cat", { + stdio = {stdin, stdout, stderr} +}, onexit) + +p{ + handle=handle, + pid=pid +} + +uv.read_start(stdout, onread) +uv.read_start(stderr, onread) +uv.write(stdin, "Hello World") +uv.shutdown(stdin, onshutdown) + +uv.run() +uv.walk(uv.close) +uv.run() diff --git a/3rdparty/luv/examples/tcp-cluster.lua b/3rdparty/luv/examples/tcp-cluster.lua new file mode 100644 index 00000000000..e69ceffc62d --- /dev/null +++ b/3rdparty/luv/examples/tcp-cluster.lua @@ -0,0 +1,84 @@ + +-- This function will be run in a child process +local child_code = string.dump(function () + local p = require('lib/utils').prettyPrint + local uv = require('luv') + + -- The parent is going to pass us the server handle over a pipe + -- This will be our local file descriptor at PIPE_FD + local pipe = uv.new_pipe(true) + local pipe_fd = tonumber(os.getenv("PIPE_FD")) + assert(uv.pipe_open(pipe, pipe_fd)) + + -- Configure the server handle + local server = uv.new_tcp() + local function onconnection() + local client = uv.new_tcp() + uv.accept(server, client) + p("New TCP", client, "on", server) + p{client=client} + uv.write(client, "BYE!\n"); + uv.shutdown(client, function () + uv.close(client) + uv.close(server) + end) + end + + -- Read the server handle from the parent + local function onread(err, data) + p("onread", {err=err,data=data}) + assert(not err, err) + if uv.pipe_pending_count(pipe) > 0 then + local pending_type = uv.pipe_pending_type(pipe) + p("pending_type", pending_type) + assert(pending_type == "tcp") + assert(uv.accept(pipe, server)) + assert(uv.listen(server, 128, onconnection)) + p("Received server handle from parent process", server) + elseif data then + p("ondata", data) + else + p("onend", data) + end + end + uv.read_start(pipe, onread) + + -- Start the event loop! + uv.run() +end) + +local p = require('lib/utils').prettyPrint +local uv = require('luv') + +local exepath = assert(uv.exepath()) +local cpu_count = # assert(uv.cpu_info()) + +local server = uv.new_tcp() +assert(uv.tcp_bind(server, "::1", 1337)) +print("Master process bound to TCP port 1337 on ::1") + + +local function onexit(status, signal) + p("Child exited", {status=status,signal=signal}) +end + +local function spawnChild() + local pipe = uv.new_pipe(true) + local input = uv.new_pipe(false) + local _, pid = assert(uv.spawn(exepath, { + stdio = {input,1,2,pipe}, + env= {"PIPE_FD=3"} + }, onexit)) + uv.write(input, child_code) + uv.shutdown(input) + p("Spawned child", pid, "and sending handle", server) + assert(uv.write2(pipe, "123", server)) + assert(uv.shutdown(pipe)) +end + +-- Spawn a child process for each CPU core +for _ = 1, cpu_count do + spawnChild() +end + +uv.run() diff --git a/3rdparty/luv/examples/timers.lua b/3rdparty/luv/examples/timers.lua new file mode 100644 index 00000000000..049235e6fb1 --- /dev/null +++ b/3rdparty/luv/examples/timers.lua @@ -0,0 +1,68 @@ +local p = require('lib/utils').prettyPrint +local uv = require('luv') + +local function set_timeout(timeout, callback) + local timer = uv.new_timer() + local function ontimeout() + p("ontimeout", timer) + uv.timer_stop(timer) + uv.close(timer) + callback(timer) + end + uv.timer_start(timer, timeout, 0, ontimeout) + return timer +end + +local function clear_timeout(timer) + uv.timer_stop(timer) + uv.close(timer) +end + +local function set_interval(interval, callback) + local timer = uv.new_timer() + local function ontimeout() + p("interval", timer) + callback(timer) + end + uv.timer_start(timer, interval, interval, ontimeout) + return timer +end + +local clear_interval = clear_timeout + +local i = set_interval(300, function() + print("interval...") +end) + +set_timeout(1000, function() + clear_interval(i) +end) + + +local handle = uv.new_timer() +local delay = 1024 +local function ontimeout() + p("tick", delay) + delay = delay / 2 + if delay >= 1 then + uv.timer_set_repeat(handle, delay) + uv.timer_again(handle) + else + uv.timer_stop(handle) + uv.close(handle) + p("done") + end +end +uv.timer_start(handle, delay, 0, ontimeout) + + +repeat + print("\ntick.") +until uv.run('once') == 0 + +print("done") + +uv.walk(uv.close) +uv.run() +uv.loop_close() + diff --git a/3rdparty/luv/examples/uvbook/helloworld.lua b/3rdparty/luv/examples/uvbook/helloworld.lua new file mode 100644 index 00000000000..2c77d0c51bc --- /dev/null +++ b/3rdparty/luv/examples/uvbook/helloworld.lua @@ -0,0 +1,5 @@ +local uv = require('luv') + +print('Now quitting.') +uv.run('default') +uv.loop_close() diff --git a/3rdparty/luv/examples/uvbook/idle-basic.lua b/3rdparty/luv/examples/uvbook/idle-basic.lua new file mode 100644 index 00000000000..dc2a47b3c30 --- /dev/null +++ b/3rdparty/luv/examples/uvbook/idle-basic.lua @@ -0,0 +1,14 @@ +local uv = require('luv') + +local counter = 0 +local idle = uv.new_idle() +idle:start(function() + counter = counter + 1 + if counter >= 10e6 then + idle:stop() + end +end) + +print("Idling...") +uv.run('default') +uv.loop_close() \ No newline at end of file diff --git a/3rdparty/luv/examples/uvbook/onchange.lua b/3rdparty/luv/examples/uvbook/onchange.lua new file mode 100644 index 00000000000..07b3f9b1d78 --- /dev/null +++ b/3rdparty/luv/examples/uvbook/onchange.lua @@ -0,0 +1,30 @@ +local uv = require('luv') + +if #arg==0 then + print(string.format("Usage: %s [file2 ...]",arg[0])); + return +end + +for i=1,#arg do + local fse = uv.new_fs_event() + assert(uv.fs_event_start(fse,arg[i],{ + --"watch_entry"=true,"stat"=true, + recursive=true + },function (err,fname,status) + if(err) then + print("Error "..err) + else + print(string.format('Change detected in %s', + uv.fs_event_getpath(fse))) + for k,v in pairs(status) do + print(k,v) + end + print('file changed:'..(fname and fname or '')) + end + end)) + +end + +uv.run('default') +uv.loop_close() + diff --git a/3rdparty/luv/examples/uvbook/queue-work.lua b/3rdparty/luv/examples/uvbook/queue-work.lua new file mode 100644 index 00000000000..cf52abfb216 --- /dev/null +++ b/3rdparty/luv/examples/uvbook/queue-work.lua @@ -0,0 +1,19 @@ +local uv = require('luv') + +local ctx = uv.new_work( + function(n) --work,in threadpool + local uv = require('luv') + local t = uv.thread_self() + uv.sleep(100) + return n*n,n + end, + function(r,n) print(string.format('%d => %d',n,r)) end --after work, in loop thread +) +uv.queue_work(ctx,2) +uv.queue_work(ctx,4) +uv.queue_work(ctx,6) +uv.queue_work(ctx,8) +uv.queue_work(ctx,10) + +uv.run('default') +uv.loop_close() diff --git a/3rdparty/luv/examples/uvbook/tcp-echo-client.lua b/3rdparty/luv/examples/uvbook/tcp-echo-client.lua new file mode 100644 index 00000000000..40dd22a311f --- /dev/null +++ b/3rdparty/luv/examples/uvbook/tcp-echo-client.lua @@ -0,0 +1,21 @@ +local uv = require('luv') + + +local client = uv.new_tcp() +uv.tcp_connect(client, "127.0.0.1", 1337, function (err) + assert(not err, err) + uv.read_start(client, function (err, chunk) + assert(not err, err) + if chunk then + print(chunk) + else + uv.close(client) + end + end) + + uv.write(client, "Hello") + uv.write(client, "World") +end) +print('CTRL-C to break') +uv.run('default') +uv.loop_close() diff --git a/3rdparty/luv/examples/uvbook/tcp-echo-server.lua b/3rdparty/luv/examples/uvbook/tcp-echo-server.lua new file mode 100644 index 00000000000..269c49114cf --- /dev/null +++ b/3rdparty/luv/examples/uvbook/tcp-echo-server.lua @@ -0,0 +1,22 @@ +local uv = require('luv') + + +local server = uv.new_tcp() +server:bind("127.0.0.1", 1337) +server:listen(128, function (err) + assert(not err, err) + local client = uv.new_tcp() + server:accept(client) + client:read_start(function (err, chunk) + assert(not err, err) + if chunk then + client:write(chunk) + else + client:shutdown() + client:close() + end + end) +end) + +uv.run('default') +uv.loop_close() diff --git a/3rdparty/luv/examples/uvbook/thread-create.lua b/3rdparty/luv/examples/uvbook/thread-create.lua new file mode 100644 index 00000000000..4b42587adbf --- /dev/null +++ b/3rdparty/luv/examples/uvbook/thread-create.lua @@ -0,0 +1,38 @@ +local uv = require('luv') + +local step = 10 + +local hare_id = uv.new_thread(function(step,...) + local ffi = require'ffi' + local uv = require('luv') + local sleep + if ffi.os=='Windows' then + ffi.cdef "void Sleep(int ms);" + sleep = ffi.C.Sleep + else + ffi.cdef "unsigned int usleep(unsigned int seconds);" + sleep = ffi.C.usleep + end + while (step>0) do + step = step - 1 + uv.sleep(math.random(1000)) + print("Hare ran another step") + end + print("Hare done running!") +end, step,true,'abcd','false') + +local tortoise_id = uv.new_thread(function(step,...) + local uv = require('luv') + while (step>0) do + step = step - 1 + uv.sleep(math.random(100)) + print("Tortoise ran another step") + end + print("Tortoise done running!") +end,step,'abcd','false') + +print(hare_id==hare_id,uv.thread_equal(hare_id,hare_id)) +print(tortoise_id==hare_id,uv.thread_equal(tortoise_id,hare_id)) + +uv.thread_join(hare_id) +uv.thread_join(tortoise_id) diff --git a/3rdparty/luv/examples/uvbook/uvcat.lua b/3rdparty/luv/examples/uvbook/uvcat.lua new file mode 100644 index 00000000000..99fdd68000b --- /dev/null +++ b/3rdparty/luv/examples/uvbook/uvcat.lua @@ -0,0 +1,37 @@ +local uv = require('luv') + + +local fname = arg[1] and arg[1] or arg[0] + +uv.fs_open(fname, 'r', tonumber('644', 8), function(err,fd) + if err then + print("error opening file:"..err) + else + local stat = uv.fs_fstat(fd) + local off = 0 + local block = 10 + + local function on_read(err,chunk) + if(err) then + print("Read error: "..err); + elseif #chunk==0 then + uv.fs_close(fd) + else + off = block + off + uv.fs_write(1,chunk,-1,function(err,chunk) + if err then + print("Write error: "..err) + else + uv.fs_read(fd, block, off, on_read) + end + end) + end + end + uv.fs_read(fd, block, off, on_read) + end +end) + + + +uv.run('default') +uv.loop_close() diff --git a/3rdparty/luv/examples/uvbook/uvtee.lua b/3rdparty/luv/examples/uvbook/uvtee.lua new file mode 100644 index 00000000000..c91b066ae21 --- /dev/null +++ b/3rdparty/luv/examples/uvbook/uvtee.lua @@ -0,0 +1,35 @@ +local uv = require('luv') + +if not arg[1] then + print(string.format("please run %s filename",arg[0])) + return +end + + +local stdin = uv.new_tty(0, true) +local stdout = uv.new_tty(1, true) +--local stdin_pipe = uv.new_pipe(false) +--uv.pipe_open(stdin_pipe,0) + +local fname = arg[1] + +uv.fs_open(fname, 'w+', tonumber('644', 8), function(err,fd) + if err then + print("error opening file:"..err) + else + local fpipe = uv.new_pipe(false) + uv.pipe_open(fpipe, fd) + + uv.read_start(stdin, function(err,chunk) + if err then + print('Read error: '..err) + else + uv.write(stdout,chunk) + uv.write(fpipe,chunk) + end + end); + end +end) + +uv.run('default') +uv.loop_close() diff --git a/3rdparty/luv/lib/tap.lua b/3rdparty/luv/lib/tap.lua new file mode 100644 index 00000000000..d1cfb59c249 --- /dev/null +++ b/3rdparty/luv/lib/tap.lua @@ -0,0 +1,165 @@ +local uv = require('luv') +local dump = require('lib/utils').dump +local stdout = require('lib/utils').stdout + +local function protect(...) + local n = select('#', ...) + local arguments = {...} + for i = 1, n do + arguments[i] = tostring(arguments[i]) + end + + local text = table.concat(arguments, "\t") + text = " " .. string.gsub(text, "\n", "\n ") + print(text) +end + +local function pprotect(...) + local n = select('#', ...) + local arguments = { ... } + + for i = 1, n do + arguments[i] = dump(arguments[i]) + end + + protect(table.concat(arguments, "\t")) +end + + +local tests = {}; + +local function run() + local passed = 0 + + if #tests < 1 then + error("No tests specified!") + end + + print("1.." .. #tests) + for i = 1, #tests do + local test = tests[i] + local cwd = uv.cwd() + local pass, err = xpcall(function () + local expected = 0 + local function expect(fn, count) + expected = expected + (count or 1) + return function (...) + expected = expected - 1 + local ret = fn(...) + collectgarbage() + return ret + end + end + test.fn(protect, pprotect, expect, uv) + collectgarbage() + uv.run() + collectgarbage() + if expected > 0 then + error("Missing " .. expected .. " expected call" .. (expected == 1 and "" or "s")) + elseif expected < 0 then + error("Found " .. -expected .. " unexpected call" .. (expected == -1 and "" or "s")) + end + collectgarbage() + local unclosed = 0 + uv.walk(function (handle) + if handle == stdout then return end + unclosed = unclosed + 1 + print("UNCLOSED", handle) + end) + if unclosed > 0 then + error(unclosed .. " unclosed handle" .. (unclosed == 1 and "" or "s")) + end + if uv.cwd() ~= cwd then + error("Test moved cwd from " .. cwd .. " to " .. uv.cwd()) + end + collectgarbage() + end, debug.traceback) + + -- Flush out any more opened handles + uv.stop() + uv.walk(function (handle) + if handle == stdout then return end + if not uv.is_closing(handle) then uv.close(handle) end + end) + uv.run() + uv.chdir(cwd) + + if pass then + print("ok " .. i .. " " .. test.name) + passed = passed + 1 + else + protect(err) + print("not ok " .. i .. " " .. test.name) + end + end + + local failed = #tests - passed + if failed == 0 then + print("# All tests passed") + else + print("#" .. failed .. " failed test" .. (failed == 1 and "" or "s")) + end + + -- Close all then handles, including stdout + uv.walk(uv.close) + uv.run() + + os.exit(-failed) +end + +local single = true +local prefix + +local function tap(suite) + + if type(suite) == "function" then + -- Pass in suite directly for single mode + suite(function (name, fn) + if prefix then + name = prefix .. ' - ' .. name + end + tests[#tests + 1] = { + name = name, + fn = fn + } + end) + prefix = nil + elseif type(suite) == "string" then + prefix = suite + single = false + else + -- Or pass in false to collect several runs of tests + -- And then pass in true in a later call to flush tests queue. + single = suite + end + + if single then run() end + +end + + +--[[ +-- Sample Usage + +local passed, failed, total = tap(function (test) + + test("add 1 to 2", function(print) + print("Adding 1 to 2") + assert(1 + 2 == 3) + end) + + test("close handle", function (print, p, expect, uv) + local handle = uv.new_timer() + uv.close(handle, expect(function (self) + assert(self == handle) + end)) + end) + + test("simulate failure", function () + error("Oopsie!") + end) + +end) +]] + +return tap diff --git a/3rdparty/luv/lib/utils.lua b/3rdparty/luv/lib/utils.lua new file mode 100644 index 00000000000..777879ec28c --- /dev/null +++ b/3rdparty/luv/lib/utils.lua @@ -0,0 +1,165 @@ + +local uv = require('luv') +local utils = {} +local usecolors + +if uv.guess_handle(1) == "tty" then + utils.stdout = uv.new_tty(1, false) + usecolors = true +else + utils.stdout = uv.new_pipe(false) + uv.pipe_open(utils.stdout, 1) + usecolors = false +end + +local colors = { + black = "0;30", + red = "0;31", + green = "0;32", + yellow = "0;33", + blue = "0;34", + magenta = "0;35", + cyan = "0;36", + white = "0;37", + B = "1;", + Bblack = "1;30", + Bred = "1;31", + Bgreen = "1;32", + Byellow = "1;33", + Bblue = "1;34", + Bmagenta = "1;35", + Bcyan = "1;36", + Bwhite = "1;37" +} + +function utils.color(color_name) + if usecolors then + return "\27[" .. (colors[color_name] or "0") .. "m" + else + return "" + end +end + +function utils.colorize(color_name, string, reset_name) + return utils.color(color_name) .. tostring(string) .. utils.color(reset_name) +end + +local backslash, null, newline, carriage, tab, quote, quote2, obracket, cbracket + +function utils.loadColors(n) + if n ~= nil then usecolors = n end + backslash = utils.colorize("Bgreen", "\\\\", "green") + null = utils.colorize("Bgreen", "\\0", "green") + newline = utils.colorize("Bgreen", "\\n", "green") + carriage = utils.colorize("Bgreen", "\\r", "green") + tab = utils.colorize("Bgreen", "\\t", "green") + quote = utils.colorize("Bgreen", '"', "green") + quote2 = utils.colorize("Bgreen", '"') + obracket = utils.colorize("B", '[') + cbracket = utils.colorize("B", ']') +end + +utils.loadColors() + +function utils.dump(o, depth) + local t = type(o) + if t == 'string' then + return quote .. o:gsub("\\", backslash):gsub("%z", null):gsub("\n", newline):gsub("\r", carriage):gsub("\t", tab) .. quote2 + end + if t == 'nil' then + return utils.colorize("Bblack", "nil") + end + if t == 'boolean' then + return utils.colorize("yellow", tostring(o)) + end + if t == 'number' then + return utils.colorize("blue", tostring(o)) + end + if t == 'userdata' then + return utils.colorize("magenta", tostring(o)) + end + if t == 'thread' then + return utils.colorize("Bred", tostring(o)) + end + if t == 'function' then + return utils.colorize("cyan", tostring(o)) + end + if t == 'cdata' then + return utils.colorize("Bmagenta", tostring(o)) + end + if t == 'table' then + if type(depth) == 'nil' then + depth = 0 + end + if depth > 1 then + return utils.colorize("yellow", tostring(o)) + end + local indent = (" "):rep(depth) + + -- Check to see if this is an array + local is_array = true + local i = 1 + for k,v in pairs(o) do + if not (k == i) then + is_array = false + end + i = i + 1 + end + + local first = true + local lines = {} + i = 1 + local estimated = 0 + for k,v in (is_array and ipairs or pairs)(o) do + local s + if is_array then + s = "" + else + if type(k) == "string" and k:find("^[%a_][%a%d_]*$") then + s = k .. ' = ' + else + s = '[' .. utils.dump(k, 100) .. '] = ' + end + end + s = s .. utils.dump(v, depth + 1) + lines[i] = s + estimated = estimated + #s + i = i + 1 + end + if estimated > 200 then + return "{\n " .. indent .. table.concat(lines, ",\n " .. indent) .. "\n" .. indent .. "}" + else + return "{ " .. table.concat(lines, ", ") .. " }" + end + end + -- This doesn't happen right? + return tostring(o) +end + + + +-- Print replacement that goes through libuv. This is useful on windows +-- to use libuv's code to translate ansi escape codes to windows API calls. +function print(...) + local n = select('#', ...) + local arguments = {...} + for i = 1, n do + arguments[i] = tostring(arguments[i]) + end + uv.write(utils.stdout, table.concat(arguments, "\t") .. "\n") +end + +-- A nice global data dumper +function utils.prettyPrint(...) + local n = select('#', ...) + local arguments = { ... } + + for i = 1, n do + arguments[i] = utils.dump(arguments[i]) + end + + print(table.concat(arguments, "\t")) +end + +return utils + diff --git a/3rdparty/luv/luv-1.8.0-4.rockspec b/3rdparty/luv/luv-1.8.0-4.rockspec new file mode 100644 index 00000000000..23855203e0d --- /dev/null +++ b/3rdparty/luv/luv-1.8.0-4.rockspec @@ -0,0 +1,34 @@ +package = "luv" +version = "1.8.0-4" +source = { + url = 'https://github.com/luvit/luv/releases/download/1.8.0-4/luv-1.8.0-4.tar.gz', +} + +description = { + summary = "Bare libuv bindings for lua", + detailed = [[ +libuv bindings for luajit and lua 5.1/5.2/5.3. + +This library makes libuv available to lua scripts. It was made for the luvit +project but should usable from nearly any lua project. + ]], + homepage = "https://github.com/luvit/luv", + license = "Apache 2.0" +} + +dependencies = { + "lua >= 5.1" +} + +build = { + type = 'cmake', + variables = { + CMAKE_C_FLAGS="$(CFLAGS)", + CMAKE_MODULE_LINKER_FLAGS="$(LIBFLAG)", + LUA_LIBDIR="$(LUA_LIBDIR)", + LUA_INCDIR="$(LUA_INCDIR)", + LUA="$(LUA)", + LIBDIR="$(LIBDIR)", + LUADIR="$(LUADIR)", + }, +} diff --git a/3rdparty/luv/msvcbuild.bat b/3rdparty/luv/msvcbuild.bat new file mode 100644 index 00000000000..7a5c7bd4c31 --- /dev/null +++ b/3rdparty/luv/msvcbuild.bat @@ -0,0 +1,13 @@ +@echo off + +set VS=12 +if "%configuration%"=="2015" (set VS=14) +if "%configuration%"=="2013" (set VS=12) + +if not defined platform set platform=x64 +if "%platform%" EQU "x64" (set VS=%VS% Win64) + +cmake -H. -Bbuild -G"Visual Studio %VS%" +cmake --build build --config Release +copy build\Release\luv.dll . +copy build\Release\luajit.exe . diff --git a/3rdparty/luv/src/async.c b/3rdparty/luv/src/async.c new file mode 100644 index 00000000000..87ae0cc0460 --- /dev/null +++ b/3rdparty/luv/src/async.c @@ -0,0 +1,63 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" +#include "lthreadpool.h" + +static uv_async_t* luv_check_async(lua_State* L, int index) { + uv_async_t* handle = luv_checkudata(L, index, "uv_async"); + luaL_argcheck(L, handle->type == UV_ASYNC && handle->data, index, "Expected uv_async_t"); + return handle; +} + +static void luv_async_cb(uv_async_t* handle) { + lua_State* L = luv_state(handle->loop); + luv_handle_t* data = handle->data; + int n = luv_thread_arg_push(L, data->extra); + luv_call_callback(L, data, LUV_ASYNC, n); + luv_thread_arg_clear(data->extra); +} + +static int luv_new_async(lua_State* L) { + uv_async_t* handle; + luv_handle_t* data; + int ret; + luaL_checktype(L, 1, LUA_TFUNCTION); + handle = luv_newuserdata(L, sizeof(*handle)); + ret = uv_async_init(luv_loop(L), handle, luv_async_cb); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + data = luv_setup_handle(L); + data->extra = malloc(sizeof(luv_thread_arg_t)); + memset(data->extra, 0, sizeof(luv_thread_arg_t)); + handle->data = data; + luv_check_callback(L, handle->data, LUV_ASYNC, 1); + return 1; +} + +static int luv_async_send(lua_State* L) { + int ret; + uv_async_t* handle = luv_check_async(L, 1); + luv_thread_arg_t* arg = ((luv_handle_t*) handle->data)->extra; + + luv_thread_arg_set(L, arg, 2, lua_gettop(L), 0); + ret = uv_async_send(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} diff --git a/3rdparty/luv/src/check.c b/3rdparty/luv/src/check.c new file mode 100644 index 00000000000..dbd330ae255 --- /dev/null +++ b/3rdparty/luv/src/check.c @@ -0,0 +1,59 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_check_t* luv_check_check(lua_State* L, int index) { + uv_check_t* handle = luv_checkudata(L, index, "uv_check"); + luaL_argcheck(L, handle->type == UV_CHECK && handle->data, index, "Expected uv_check_t"); + return handle; +} + +static int luv_new_check(lua_State* L) { + uv_check_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_check_init(luv_loop(L), handle); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static void luv_check_cb(uv_check_t* handle) { + lua_State* L = luv_state(handle->loop); + luv_handle_t* data = handle->data; + luv_call_callback(L, data, LUV_CHECK, 0); +} + +static int luv_check_start(lua_State* L) { + uv_check_t* handle = luv_check_check(L, 1); + int ret; + luv_check_callback(L, handle->data, LUV_CHECK, 2); + ret = uv_check_start(handle, luv_check_cb); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_check_stop(lua_State* L) { + uv_check_t* handle = luv_check_check(L, 1); + int ret = uv_check_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + diff --git a/3rdparty/luv/src/constants.c b/3rdparty/luv/src/constants.c new file mode 100644 index 00000000000..3417028c438 --- /dev/null +++ b/3rdparty/luv/src/constants.c @@ -0,0 +1,649 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "luv.h" + +static int luv_constants(lua_State* L) { + lua_newtable(L); + + // File open bitwise flags O_* +#ifdef O_RDONLY + lua_pushinteger(L, O_RDONLY); + lua_setfield(L, -2, "O_RDONLY"); +#endif +#ifdef O_WRONLY + lua_pushinteger(L, O_WRONLY); + lua_setfield(L, -2, "O_WRONLY"); +#endif +#ifdef O_RDWR + lua_pushinteger(L, O_RDWR); + lua_setfield(L, -2, "O_RDWR"); +#endif +#ifdef O_APPEND + lua_pushinteger(L, O_APPEND); + lua_setfield(L, -2, "O_APPEND"); +#endif +#ifdef O_CREAT + lua_pushinteger(L, O_CREAT); + lua_setfield(L, -2, "O_CREAT"); +#endif +#ifdef O_DSYNC + lua_pushinteger(L, O_DSYNC); + lua_setfield(L, -2, "O_DSYNC"); +#endif +#ifdef O_EXCL + lua_pushinteger(L, O_EXCL); + lua_setfield(L, -2, "O_EXCL"); +#endif +#ifdef O_EXLOCK + lua_pushinteger(L, O_EXLOCK); + lua_setfield(L, -2, "O_EXLOCK"); +#endif +#ifdef O_NOCTTY + lua_pushinteger(L, O_NOCTTY); + lua_setfield(L, -2, "O_NOCTTY"); +#endif +#ifdef O_NONBLOCK + lua_pushinteger(L, O_NONBLOCK); + lua_setfield(L, -2, "O_NONBLOCK"); +#endif +#ifdef O_RSYNC + lua_pushinteger(L, O_RSYNC); + lua_setfield(L, -2, "O_RSYNC"); +#endif +#ifdef O_SYNC + lua_pushinteger(L, O_SYNC); + lua_setfield(L, -2, "O_SYNC"); +#endif +#ifdef O_TRUNC + lua_pushinteger(L, O_TRUNC); + lua_setfield(L, -2, "O_TRUNC"); +#endif + + // Socket types SOCK_* +#ifdef SOCK_STREAM + lua_pushinteger(L, SOCK_STREAM); + lua_setfield(L, -2, "SOCK_STREAM"); +#endif +#ifdef SOCK_DGRAM + lua_pushinteger(L, SOCK_DGRAM); + lua_setfield(L, -2, "SOCK_DGRAM"); +#endif +#ifdef SOCK_SEQPACKET + lua_pushinteger(L, SOCK_SEQPACKET); + lua_setfield(L, -2, "SOCK_SEQPACKET"); +#endif +#ifdef SOCK_RAW + lua_pushinteger(L, SOCK_RAW); + lua_setfield(L, -2, "SOCK_RAW"); +#endif +#ifdef SOCK_RDM + lua_pushinteger(L, SOCK_RDM); + lua_setfield(L, -2, "SOCK_RDM"); +#endif + + // AF_* +#ifdef AF_UNIX + lua_pushinteger(L, AF_UNIX); + lua_setfield(L, -2, "AF_UNIX"); +#endif +#ifdef AF_INET + lua_pushinteger(L, AF_INET); + lua_setfield(L, -2, "AF_INET"); +#endif +#ifdef AF_INET6 + lua_pushinteger(L, AF_INET6); + lua_setfield(L, -2, "AF_INET6"); +#endif +#ifdef AF_IPX + lua_pushinteger(L, AF_IPX); + lua_setfield(L, -2, "AF_IPX"); +#endif +#ifdef AF_NETLINK + lua_pushinteger(L, AF_NETLINK); + lua_setfield(L, -2, "AF_NETLINK"); +#endif +#ifdef AF_X25 + lua_pushinteger(L, AF_X25); + lua_setfield(L, -2, "AF_X25"); +#endif +#ifdef AF_AX25 + lua_pushinteger(L, AF_AX25); + lua_setfield(L, -2, "AF_AX25"); +#endif +#ifdef AF_ATMPVC + lua_pushinteger(L, AF_ATMPVC); + lua_setfield(L, -2, "AF_ATMPVC"); +#endif +#ifdef AF_APPLETALK + lua_pushinteger(L, AF_APPLETALK); + lua_setfield(L, -2, "AF_APPLETALK"); +#endif +#ifdef AF_PACKET + lua_pushinteger(L, AF_PACKET); + lua_setfield(L, -2, "AF_PACKET"); +#endif + + // AI_* +#ifdef AI_ADDRCONFIG + lua_pushinteger(L, AI_ADDRCONFIG); + lua_setfield(L, -2, "AI_ADDRCONFIG"); +#endif +#ifdef AI_V4MAPPED + lua_pushinteger(L, AI_V4MAPPED); + lua_setfield(L, -2, "AI_V4MAPPED"); +#endif +#ifdef AI_ALL + lua_pushinteger(L, AI_ALL); + lua_setfield(L, -2, "AI_ALL"); +#endif +#ifdef AI_NUMERICHOST + lua_pushinteger(L, AI_NUMERICHOST); + lua_setfield(L, -2, "AI_NUMERICHOST"); +#endif +#ifdef AI_PASSIVE + lua_pushinteger(L, AI_PASSIVE); + lua_setfield(L, -2, "AI_PASSIVE"); +#endif +#ifdef AI_NUMERICSERV + lua_pushinteger(L, AI_NUMERICSERV); + lua_setfield(L, -2, "AI_NUMERICSERV"); +#endif + + // Signals +#ifdef SIGHUP + lua_pushinteger(L, SIGHUP); + lua_setfield(L, -2, "SIGHUP"); +#endif +#ifdef SIGINT + lua_pushinteger(L, SIGINT); + lua_setfield(L, -2, "SIGINT"); +#endif +#ifdef SIGQUIT + lua_pushinteger(L, SIGQUIT); + lua_setfield(L, -2, "SIGQUIT"); +#endif +#ifdef SIGILL + lua_pushinteger(L, SIGILL); + lua_setfield(L, -2, "SIGILL"); +#endif +#ifdef SIGTRAP + lua_pushinteger(L, SIGTRAP); + lua_setfield(L, -2, "SIGTRAP"); +#endif +#ifdef SIGABRT + lua_pushinteger(L, SIGABRT); + lua_setfield(L, -2, "SIGABRT"); +#endif +#ifdef SIGIOT + lua_pushinteger(L, SIGIOT); + lua_setfield(L, -2, "SIGIOT"); +#endif +#ifdef SIGBUS + lua_pushinteger(L, SIGBUS); + lua_setfield(L, -2, "SIGBUS"); +#endif +#ifdef SIGFPE + lua_pushinteger(L, SIGFPE); + lua_setfield(L, -2, "SIGFPE"); +#endif +#ifdef SIGKILL + lua_pushinteger(L, SIGKILL); + lua_setfield(L, -2, "SIGKILL"); +#endif +#ifdef SIGUSR1 + lua_pushinteger(L, SIGUSR1); + lua_setfield(L, -2, "SIGUSR1"); +#endif +#ifdef SIGSEGV + lua_pushinteger(L, SIGSEGV); + lua_setfield(L, -2, "SIGSEGV"); +#endif +#ifdef SIGUSR2 + lua_pushinteger(L, SIGUSR2); + lua_setfield(L, -2, "SIGUSR2"); +#endif +#ifdef SIGPIPE + lua_pushinteger(L, SIGPIPE); + lua_setfield(L, -2, "SIGPIPE"); +#endif +#ifdef SIGALRM + lua_pushinteger(L, SIGALRM); + lua_setfield(L, -2, "SIGALRM"); +#endif +#ifdef SIGTERM + lua_pushinteger(L, SIGTERM); + lua_setfield(L, -2, "SIGTERM"); +#endif +#ifdef SIGCHLD + lua_pushinteger(L, SIGCHLD); + lua_setfield(L, -2, "SIGCHLD"); +#endif +#ifdef SIGSTKFLT + lua_pushinteger(L, SIGSTKFLT); + lua_setfield(L, -2, "SIGSTKFLT"); +#endif +#ifdef SIGCONT + lua_pushinteger(L, SIGCONT); + lua_setfield(L, -2, "SIGCONT"); +#endif +#ifdef SIGSTOP + lua_pushinteger(L, SIGSTOP); + lua_setfield(L, -2, "SIGSTOP"); +#endif +#ifdef SIGTSTP + lua_pushinteger(L, SIGTSTP); + lua_setfield(L, -2, "SIGTSTP"); +#endif +#ifdef SIGBREAK + lua_pushinteger(L, SIGBREAK); + lua_setfield(L, -2, "SIGBREAK"); +#endif +#ifdef SIGTTIN + lua_pushinteger(L, SIGTTIN); + lua_setfield(L, -2, "SIGTTIN"); +#endif +#ifdef SIGTTOU + lua_pushinteger(L, SIGTTOU); + lua_setfield(L, -2, "SIGTTOU"); +#endif +#ifdef SIGURG + lua_pushinteger(L, SIGURG); + lua_setfield(L, -2, "SIGURG"); +#endif +#ifdef SIGXCPU + lua_pushinteger(L, SIGXCPU); + lua_setfield(L, -2, "SIGXCPU"); +#endif +#ifdef SIGXFSZ + lua_pushinteger(L, SIGXFSZ); + lua_setfield(L, -2, "SIGXFSZ"); +#endif +#ifdef SIGVTALRM + lua_pushinteger(L, SIGVTALRM); + lua_setfield(L, -2, "SIGVTALRM"); +#endif +#ifdef SIGPROF + lua_pushinteger(L, SIGPROF); + lua_setfield(L, -2, "SIGPROF"); +#endif +#ifdef SIGWINCH + lua_pushinteger(L, SIGWINCH); + lua_setfield(L, -2, "SIGWINCH"); +#endif +#ifdef SIGIO + lua_pushinteger(L, SIGIO); + lua_setfield(L, -2, "SIGIO"); +#endif +#ifdef SIGPOLL + lua_pushinteger(L, SIGPOLL); + lua_setfield(L, -2, "SIGPOLL"); +#endif +#ifdef SIGLOST + lua_pushinteger(L, SIGLOST); + lua_setfield(L, -2, "SIGLOST"); +#endif +#ifdef SIGPWR + lua_pushinteger(L, SIGPWR); + lua_setfield(L, -2, "SIGPWR"); +#endif +#ifdef SIGSYS + lua_pushinteger(L, SIGSYS); + lua_setfield(L, -2, "SIGSYS"); +#endif + return 1; +} + +static int luv_af_string_to_num(const char* string) { + if (!string) return AF_UNSPEC; +#ifdef AF_UNIX + if (strcmp(string, "unix") == 0) return AF_UNIX; +#endif +#ifdef AF_INET + if (strcmp(string, "inet") == 0) return AF_INET; +#endif +#ifdef AF_INET6 + if (strcmp(string, "inet6") == 0) return AF_INET6; +#endif +#ifdef AF_IPX + if (strcmp(string, "ipx") == 0) return AF_IPX; +#endif +#ifdef AF_NETLINK + if (strcmp(string, "netlink") == 0) return AF_NETLINK; +#endif +#ifdef AF_X25 + if (strcmp(string, "x25") == 0) return AF_X25; +#endif +#ifdef AF_AX25 + if (strcmp(string, "ax25") == 0) return AF_AX25; +#endif +#ifdef AF_ATMPVC + if (strcmp(string, "atmpvc") == 0) return AF_ATMPVC; +#endif +#ifdef AF_APPLETALK + if (strcmp(string, "appletalk") == 0) return AF_APPLETALK; +#endif +#ifdef AF_PACKET + if (strcmp(string, "packet") == 0) return AF_PACKET; +#endif + return 0; +} + +static const char* luv_af_num_to_string(const int num) { + switch (num) { +#ifdef AF_UNIX + case AF_UNIX: return "unix"; +#endif +#ifdef AF_INET + case AF_INET: return "inet"; +#endif +#ifdef AF_INET6 + case AF_INET6: return "inet6"; +#endif +#ifdef AF_IPX + case AF_IPX: return "ipx"; +#endif +#ifdef AF_NETLINK + case AF_NETLINK: return "netlink"; +#endif +#ifdef AF_X25 + case AF_X25: return "x25"; +#endif +#ifdef AF_AX25 + case AF_AX25: return "ax25"; +#endif +#ifdef AF_ATMPVC + case AF_ATMPVC: return "atmpvc"; +#endif +#ifdef AF_APPLETALK + case AF_APPLETALK: return "appletalk"; +#endif +#ifdef AF_PACKET + case AF_PACKET: return "packet"; +#endif + } + return NULL; +} + + +static int luv_sock_string_to_num(const char* string) { + if (!string) return 0; +#ifdef SOCK_STREAM + if (strcmp(string, "stream") == 0) return SOCK_STREAM; +#endif +#ifdef SOCK_DGRAM + if (strcmp(string, "dgram") == 0) return SOCK_DGRAM; +#endif +#ifdef SOCK_SEQPACKET + if (strcmp(string, "seqpacket") == 0) return SOCK_SEQPACKET; +#endif +#ifdef SOCK_RAW + if (strcmp(string, "raw") == 0) return SOCK_RAW; +#endif +#ifdef SOCK_RDM + if (strcmp(string, "rdm") == 0) return SOCK_RDM; +#endif + return 0; +} + +static const char* luv_sock_num_to_string(const int num) { + switch (num) { +#ifdef SOCK_STREAM + case SOCK_STREAM: return "stream"; +#endif +#ifdef SOCK_DGRAM + case SOCK_DGRAM: return "dgram"; +#endif +#ifdef SOCK_SEQPACKET + case SOCK_SEQPACKET: return "seqpacket"; +#endif +#ifdef SOCK_RAW + case SOCK_RAW: return "raw"; +#endif +#ifdef SOCK_RDM + case SOCK_RDM: return "rdm"; +#endif + } + return NULL; +} + +static int luv_sig_string_to_num(const char* string) { + if (!string) return 0; +#ifdef SIGHUP + if (strcmp(string, "sighup") == 0) return SIGHUP; +#endif +#ifdef SIGINT + if (strcmp(string, "sigint") == 0) return SIGINT; +#endif +#ifdef SIGQUIT + if (strcmp(string, "sigquit") == 0) return SIGQUIT; +#endif +#ifdef SIGILL + if (strcmp(string, "sigill") == 0) return SIGILL; +#endif +#ifdef SIGTRAP + if (strcmp(string, "sigtrap") == 0) return SIGTRAP; +#endif +#ifdef SIGABRT + if (strcmp(string, "sigabrt") == 0) return SIGABRT; +#endif +#ifdef SIGIOT + if (strcmp(string, "sigiot") == 0) return SIGIOT; +#endif +#ifdef SIGBUS + if (strcmp(string, "sigbus") == 0) return SIGBUS; +#endif +#ifdef SIGFPE + if (strcmp(string, "sigfpe") == 0) return SIGFPE; +#endif +#ifdef SIGKILL + if (strcmp(string, "sigkill") == 0) return SIGKILL; +#endif +#ifdef SIGUSR1 + if (strcmp(string, "sigusr1") == 0) return SIGUSR1; +#endif +#ifdef SIGSEGV + if (strcmp(string, "sigsegv") == 0) return SIGSEGV; +#endif +#ifdef SIGUSR2 + if (strcmp(string, "sigusr2") == 0) return SIGUSR2; +#endif +#ifdef SIGPIPE + if (strcmp(string, "sigpipe") == 0) return SIGPIPE; +#endif +#ifdef SIGALRM + if (strcmp(string, "sigalrm") == 0) return SIGALRM; +#endif +#ifdef SIGTERM + if (strcmp(string, "sigterm") == 0) return SIGTERM; +#endif +#ifdef SIGCHLD + if (strcmp(string, "sigchld") == 0) return SIGCHLD; +#endif +#ifdef SIGSTKFLT + if (strcmp(string, "sigstkflt") == 0) return SIGSTKFLT; +#endif +#ifdef SIGCONT + if (strcmp(string, "sigcont") == 0) return SIGCONT; +#endif +#ifdef SIGSTOP + if (strcmp(string, "sigstop") == 0) return SIGSTOP; +#endif +#ifdef SIGTSTP + if (strcmp(string, "sigtstp") == 0) return SIGTSTP; +#endif +#ifdef SIGBREAK + if (strcmp(string, "sigbreak") == 0) return SIGBREAK; +#endif +#ifdef SIGTTIN + if (strcmp(string, "sigttin") == 0) return SIGTTIN; +#endif +#ifdef SIGTTOU + if (strcmp(string, "sigttou") == 0) return SIGTTOU; +#endif +#ifdef SIGURG + if (strcmp(string, "sigurg") == 0) return SIGURG; +#endif +#ifdef SIGXCPU + if (strcmp(string, "sigxcpu") == 0) return SIGXCPU; +#endif +#ifdef SIGXFSZ + if (strcmp(string, "sigxfsz") == 0) return SIGXFSZ; +#endif +#ifdef SIGVTALRM + if (strcmp(string, "sigvtalrm") == 0) return SIGVTALRM; +#endif +#ifdef SIGPROF + if (strcmp(string, "sigprof") == 0) return SIGPROF; +#endif +#ifdef SIGWINCH + if (strcmp(string, "sigwinch") == 0) return SIGWINCH; +#endif +#ifdef SIGIO + if (strcmp(string, "sigio") == 0) return SIGIO; +#endif +#ifdef SIGPOLL + if (strcmp(string, "sigpoll") == 0) return SIGPOLL; +#endif +#ifdef SIGLOST + if (strcmp(string, "siglost") == 0) return SIGLOST; +#endif +#ifdef SIGPWR + if (strcmp(string, "sigpwr") == 0) return SIGPWR; +#endif +#ifdef SIGSYS + if (strcmp(string, "sigsys") == 0) return SIGSYS; +#endif + return 0; +} + +static const char* luv_sig_num_to_string(const int num) { + switch (num) { +#ifdef SIGHUP + case SIGHUP: return "sighup"; +#endif +#ifdef SIGINT + case SIGINT: return "sigint"; +#endif +#ifdef SIGQUIT + case SIGQUIT: return "sigquit"; +#endif +#ifdef SIGILL + case SIGILL: return "sigill"; +#endif +#ifdef SIGTRAP + case SIGTRAP: return "sigtrap"; +#endif +#ifdef SIGABRT + case SIGABRT: return "sigabrt"; +#endif +#ifdef SIGIOT +# if SIGIOT != SIGABRT + case SIGIOT: return "sigiot"; +# endif +#endif +#ifdef SIGBUS + case SIGBUS: return "sigbus"; +#endif +#ifdef SIGFPE + case SIGFPE: return "sigfpe"; +#endif +#ifdef SIGKILL + case SIGKILL: return "sigkill"; +#endif +#ifdef SIGUSR1 + case SIGUSR1: return "sigusr1"; +#endif +#ifdef SIGSEGV + case SIGSEGV: return "sigsegv"; +#endif +#ifdef SIGUSR2 + case SIGUSR2: return "sigusr2"; +#endif +#ifdef SIGPIPE + case SIGPIPE: return "sigpipe"; +#endif +#ifdef SIGALRM + case SIGALRM: return "sigalrm"; +#endif +#ifdef SIGTERM + case SIGTERM: return "sigterm"; +#endif +#ifdef SIGCHLD + case SIGCHLD: return "sigchld"; +#endif +#ifdef SIGSTKFLT + case SIGSTKFLT: return "sigstkflt"; +#endif +#ifdef SIGCONT + case SIGCONT: return "sigcont"; +#endif +#ifdef SIGSTOP + case SIGSTOP: return "sigstop"; +#endif +#ifdef SIGTSTP + case SIGTSTP: return "sigtstp"; +#endif +#ifdef SIGBREAK + case SIGBREAK: return "sigbreak"; +#endif +#ifdef SIGTTIN + case SIGTTIN: return "sigttin"; +#endif +#ifdef SIGTTOU + case SIGTTOU: return "sigttou"; +#endif +#ifdef SIGURG + case SIGURG: return "sigurg"; +#endif +#ifdef SIGXCPU + case SIGXCPU: return "sigxcpu"; +#endif +#ifdef SIGXFSZ + case SIGXFSZ: return "sigxfsz"; +#endif +#ifdef SIGVTALRM + case SIGVTALRM: return "sigvtalrm"; +#endif +#ifdef SIGPROF + case SIGPROF: return "sigprof"; +#endif +#ifdef SIGWINCH + case SIGWINCH: return "sigwinch"; +#endif +#ifdef SIGIO + case SIGIO: return "sigio"; +#endif +#ifdef SIGPOLL +# if SIGPOLL != SIGIO + case SIGPOLL: return "sigpoll"; +# endif +#endif +#ifdef SIGLOST + case SIGLOST: return "siglost"; +#endif +#ifdef SIGPWR +# if SIGPWR != SIGLOST + case SIGPWR: return "sigpwr"; +# endif +#endif +#ifdef SIGSYS + case SIGSYS: return "sigsys"; +#endif + } + return NULL; +} diff --git a/3rdparty/luv/src/dns.c b/3rdparty/luv/src/dns.c new file mode 100644 index 00000000000..f3446f30985 --- /dev/null +++ b/3rdparty/luv/src/dns.c @@ -0,0 +1,296 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "luv.h" +#ifndef WIN32 +#include +#include +#include +#endif + +static void luv_pushaddrinfo(lua_State* L, struct addrinfo* res) { + char ip[INET6_ADDRSTRLEN]; + int port, i = 0; + const char *addr; + struct addrinfo* curr = res; + lua_newtable(L); + for (curr = res; curr; curr = curr->ai_next) { + if (curr->ai_family == AF_INET || curr->ai_family == AF_INET6) { + lua_newtable(L); + if (curr->ai_family == AF_INET) { + addr = (char*) &((struct sockaddr_in*) curr->ai_addr)->sin_addr; + port = ((struct sockaddr_in*) curr->ai_addr)->sin_port; + } else { + addr = (char*) &((struct sockaddr_in6*) curr->ai_addr)->sin6_addr; + port = ((struct sockaddr_in6*) curr->ai_addr)->sin6_port; + } + lua_pushstring(L, luv_af_num_to_string(curr->ai_family)); + lua_setfield(L, -2, "family"); + uv_inet_ntop(curr->ai_family, addr, ip, INET6_ADDRSTRLEN); + lua_pushstring(L, ip); + lua_setfield(L, -2, "addr"); + if (ntohs(port)) { + lua_pushinteger(L, ntohs(port)); + lua_setfield(L, -2, "port"); + } + lua_pushstring(L, luv_sock_num_to_string(curr->ai_socktype)); + lua_setfield(L, -2, "socktype"); + lua_pushstring(L, luv_af_num_to_string(curr->ai_protocol)); + lua_setfield(L, -2, "protocol"); + if (curr->ai_canonname) { + lua_pushstring(L, curr->ai_canonname); + lua_setfield(L, -2, "canonname"); + } + lua_rawseti(L, -2, ++i); + } + } +} + +static void luv_getaddrinfo_cb(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { + lua_State* L = luv_state(req->loop); + int nargs; + + if (status < 0) { + luv_status(L, status); + nargs = 1; + } + else { + lua_pushnil(L); + luv_pushaddrinfo(L, res); + nargs = 2; + } + luv_fulfill_req(L, req->data, nargs); + luv_cleanup_req(L, req->data); + req->data = NULL; + if (res) uv_freeaddrinfo(res); +} + + +static int luv_getaddrinfo(lua_State* L) { + uv_getaddrinfo_t* req; + const char* node; + const char* service; + struct addrinfo hints_s; + struct addrinfo* hints = &hints_s; + int ret, ref; + if (lua_isnoneornil(L, 1)) node = NULL; + else node = luaL_checkstring(L, 1); + if (lua_isnoneornil(L, 2)) service = NULL; + else service = luaL_checkstring(L, 2); + if (!lua_isnoneornil(L, 3)) luaL_checktype(L, 3, LUA_TTABLE); + else hints = NULL; + ref = lua_isnoneornil(L, 4) ? LUA_NOREF : luv_check_continuation(L, 4); + if (hints) { + // Initialize the hints + memset(hints, 0, sizeof(*hints)); + + // Process the `family` hint. + lua_getfield(L, 3, "family"); + if (lua_isnumber(L, -1)) { + hints->ai_family = lua_tointeger(L, -1); + } + else if (lua_isstring(L, -1)) { + hints->ai_family = luv_af_string_to_num(lua_tostring(L, -1)); + } + else if (lua_isnil(L, -1)) { + hints->ai_family = AF_UNSPEC; + } + else { + luaL_argerror(L, 3, "family hint must be string if set"); + } + lua_pop(L, 1); + + // Process `socktype` hint + lua_getfield(L, 3, "socktype"); + if (lua_isnumber(L, -1)) { + hints->ai_socktype = lua_tointeger(L, -1); + } + else if (lua_isstring(L, -1)) { + hints->ai_socktype = luv_sock_string_to_num(lua_tostring(L, -1)); + } + else if (!lua_isnil(L, -1)) { + return luaL_argerror(L, 3, "socktype hint must be string if set"); + } + lua_pop(L, 1); + + // Process the `protocol` hint + lua_getfield(L, 3, "protocol"); + if (lua_isnumber(L, -1)) { + hints->ai_protocol = lua_tointeger(L, -1); + } + else if (lua_isstring(L, -1)) { + int protocol = luv_af_string_to_num(lua_tostring(L, -1)); + if (protocol) { + hints->ai_protocol = protocol; + } + else { + return luaL_argerror(L, 3, "Invalid protocol hint"); + } + } + else if (!lua_isnil(L, -1)) { + return luaL_argerror(L, 3, "protocol hint must be string if set"); + } + lua_pop(L, 1); + + lua_getfield(L, 3, "addrconfig"); + if (lua_toboolean(L, -1)) hints->ai_flags |= AI_ADDRCONFIG; + lua_pop(L, 1); + + lua_getfield(L, 3, "v4mapped"); + if (lua_toboolean(L, -1)) hints->ai_flags |= AI_V4MAPPED; + lua_pop(L, 1); + + lua_getfield(L, 3, "all"); + if (lua_toboolean(L, -1)) hints->ai_flags |= AI_ALL; + lua_pop(L, 1); + + lua_getfield(L, 3, "numerichost"); + if (lua_toboolean(L, -1)) hints->ai_flags |= AI_NUMERICHOST; + lua_pop(L, 1); + + lua_getfield(L, 3, "passive"); + if (lua_toboolean(L, -1)) hints->ai_flags |= AI_PASSIVE; + lua_pop(L, 1); + + lua_getfield(L, 3, "numericserv"); + if (lua_toboolean(L, -1)) { + hints->ai_flags |= AI_NUMERICSERV; + /* On OS X upto at least OSX 10.9, getaddrinfo crashes + * if AI_NUMERICSERV is set and the servname is NULL or "0". + * This workaround avoids a segfault in libsystem. + */ + if (NULL == service) service = "00"; + } + lua_pop(L, 1); + + lua_getfield(L, 3, "canonname"); + if (lua_toboolean(L, -1)) hints->ai_flags |= AI_CANONNAME; + lua_pop(L, 1); + } + + req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + + ret = uv_getaddrinfo(luv_loop(L), req, ref == LUA_NOREF ? NULL : luv_getaddrinfo_cb, node, service, hints); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + if (ref == LUA_NOREF) { + + lua_pop(L, 1); + luv_pushaddrinfo(L, req->addrinfo); + uv_freeaddrinfo(req->addrinfo); + luv_cleanup_req(L, req->data); + } + return 1; +} + +static void luv_getnameinfo_cb(uv_getnameinfo_t* req, int status, const char* hostname, const char* service) { + lua_State* L = luv_state(req->loop); + + int nargs; + + if (status < 0) { + luv_status(L, status); + nargs = 1; + } + else { + lua_pushnil(L); + lua_pushstring(L, hostname); + lua_pushstring(L, service); + nargs = 3; + } + + luv_fulfill_req(L, req->data, nargs); + luv_cleanup_req(L, req->data); + req->data = NULL; +} + +static int luv_getnameinfo(lua_State* L) { + uv_getnameinfo_t* req; + struct sockaddr_storage addr; + const char* ip = NULL; + int flags = 0; + int ret, ref, port = 0; + + luaL_checktype(L, 1, LUA_TTABLE); + memset(&addr, 0, sizeof(addr)); + + lua_getfield(L, 1, "ip"); + if (lua_isstring(L, -1)) { + ip = lua_tostring(L, -1); + } + else if (!lua_isnil(L, -1)) { + luaL_argerror(L, 1, "ip property must be string if set"); + } + lua_pop(L, 1); + + lua_getfield(L, 1, "port"); + if (lua_isnumber(L, -1)) { + port = lua_tointeger(L, -1); + } + else if (!lua_isnil(L, -1)) { + luaL_argerror(L, 1, "port property must be integer if set"); + } + lua_pop(L, 1); + + if (ip || port) { + if (!ip) ip = "0.0.0.0"; + if (!uv_ip4_addr(ip, port, (struct sockaddr_in*)&addr)) { + addr.ss_family = AF_INET; + } + else if (!uv_ip6_addr(ip, port, (struct sockaddr_in6*)&addr)) { + addr.ss_family = AF_INET6; + } + else { + return luaL_argerror(L, 1, "Invalid ip address or port"); + } + } + + lua_getfield(L, 1, "family"); + if (lua_isnumber(L, -1)) { + addr.ss_family = lua_tointeger(L, -1); + } + else if (lua_isstring(L, -1)) { + addr.ss_family = luv_af_string_to_num(lua_tostring(L, -1)); + } + else if (!lua_isnil(L, -1)) { + luaL_argerror(L, 1, "family must be string if set"); + } + lua_pop(L, 1); + + ref = lua_isnoneornil(L, 2) ? LUA_NOREF : luv_check_continuation(L, 2); + + req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + + ret = uv_getnameinfo(luv_loop(L), req, ref == LUA_NOREF ? NULL : luv_getnameinfo_cb, (struct sockaddr*)&addr, flags); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + if (ref == LUA_NOREF) { + lua_pop(L, 1); + lua_pushstring(L, req->host); + lua_pushstring(L, req->service); + luv_cleanup_req(L, req->data); + return 2; + } + return 1; +} + diff --git a/3rdparty/luv/src/fs.c b/3rdparty/luv/src/fs.c new file mode 100644 index 00000000000..bacf11ea647 --- /dev/null +++ b/3rdparty/luv/src/fs.c @@ -0,0 +1,614 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "luv.h" + +static uv_fs_t* luv_check_fs(lua_State* L, int index) { + uv_fs_t* req = luaL_checkudata(L, index, "uv_req"); + luaL_argcheck(L, req->type = UV_FS && req->data, index, "Expected uv_fs_t"); + return req; +} + +static void luv_push_timespec_table(lua_State* L, const uv_timespec_t* t) { + lua_createtable(L, 0, 2); + lua_pushinteger(L, t->tv_sec); + lua_setfield(L, -2, "sec"); + lua_pushinteger(L, t->tv_nsec); + lua_setfield(L, -2, "nsec"); +} + +static void luv_push_stats_table(lua_State* L, const uv_stat_t* s) { + const char* type = NULL; + lua_createtable(L, 0, 23); + lua_pushinteger(L, s->st_dev); + lua_setfield(L, -2, "dev"); + lua_pushinteger(L, s->st_mode); + lua_setfield(L, -2, "mode"); + lua_pushinteger(L, s->st_nlink); + lua_setfield(L, -2, "nlink"); + lua_pushinteger(L, s->st_uid); + lua_setfield(L, -2, "uid"); + lua_pushinteger(L, s->st_gid); + lua_setfield(L, -2, "gid"); + lua_pushinteger(L, s->st_rdev); + lua_setfield(L, -2, "rdev"); + lua_pushinteger(L, s->st_ino); + lua_setfield(L, -2, "ino"); + lua_pushinteger(L, s->st_size); + lua_setfield(L, -2, "size"); + lua_pushinteger(L, s->st_blksize); + lua_setfield(L, -2, "blksize"); + lua_pushinteger(L, s->st_blocks); + lua_setfield(L, -2, "blocks"); + lua_pushinteger(L, s->st_flags); + lua_setfield(L, -2, "flags"); + lua_pushinteger(L, s->st_gen); + lua_setfield(L, -2, "gen"); + luv_push_timespec_table(L, &s->st_atim); + lua_setfield(L, -2, "atime"); + luv_push_timespec_table(L, &s->st_mtim); + lua_setfield(L, -2, "mtime"); + luv_push_timespec_table(L, &s->st_ctim); + lua_setfield(L, -2, "ctime"); + luv_push_timespec_table(L, &s->st_birthtim); + lua_setfield(L, -2, "birthtime"); + if (S_ISREG(s->st_mode)) { + type = "file"; + } + else if (S_ISDIR(s->st_mode)) { + type = "directory"; + } + else if (S_ISLNK(s->st_mode)) { + type = "link"; + } + else if (S_ISFIFO(s->st_mode)) { + type = "fifo"; + } +#ifdef S_ISSOCK + else if (S_ISSOCK(s->st_mode)) { + type = "socket"; + } +#endif + else if (S_ISCHR(s->st_mode)) { + type = "char"; + } + else if (S_ISBLK(s->st_mode)) { + type = "block"; + } + if (type) { + lua_pushstring(L, type); + lua_setfield(L, -2, "type"); + } +} + +static int luv_check_flags(lua_State* L, int index) { + const char* string; + if (lua_isnumber(L, index)) { + return lua_tointeger(L, index); + } + else if (!lua_isstring(L, index)) { + return luaL_argerror(L, index, "Expected string or integer for file open mode"); + } + string = lua_tostring(L, index); + + if (strcmp(string, "r") == 0) return O_RDONLY; +#ifdef O_SYNC + if (strcmp(string, "rs") == 0 || + strcmp(string, "sr") == 0) return O_RDONLY | O_SYNC; +#endif + if (strcmp(string, "r+") == 0) return O_RDWR; +#ifdef O_SYNC + if (strcmp(string, "rs+") == 0 || + strcmp(string, "sr+") == 0) return O_RDWR | O_SYNC; +#endif + if (strcmp(string, "w") == 0) return O_TRUNC | O_CREAT | O_WRONLY; + if (strcmp(string, "wx") == 0 || + strcmp(string, "xw") == 0) return O_TRUNC | O_CREAT | O_WRONLY | O_EXCL; + if (strcmp(string, "w+") == 0) return O_TRUNC | O_CREAT | O_RDWR; + if (strcmp(string, "wx+") == 0 || + strcmp(string, "xw+") == 0) return O_TRUNC | O_CREAT | O_RDWR | O_EXCL; + if (strcmp(string, "a") == 0) return O_APPEND | O_CREAT | O_WRONLY; + if (strcmp(string, "ax") == 0 || + strcmp(string, "xa") == 0) return O_APPEND | O_CREAT | O_WRONLY | O_EXCL; + if (strcmp(string, "a+") == 0) return O_APPEND | O_CREAT | O_RDWR; + if (strcmp(string, "ax+") == 0 || + strcmp(string, "xa+") == 0) return O_APPEND | O_CREAT | O_RDWR | O_EXCL; + + return luaL_error(L, "Unknown file open flag '%s'", string); +} + +static int luv_check_amode(lua_State* L, int index) { + size_t i; + int mode; + const char* string; + if (lua_isnumber(L, index)) { + return lua_tointeger(L, index); + } + else if (!lua_isstring(L, index)) { + return luaL_argerror(L, index, "Expected string or integer for file access mode check"); + } + string = lua_tostring(L, index); + mode = 0; + for (i = 0; i < strlen(string); ++i) { + switch (string[i]) { + case 'r': case 'R': + mode |= R_OK; + break; + case 'w': case 'W': + mode |= W_OK; + break; + case 'x': case 'X': + mode |= X_OK; + break; + default: + return luaL_argerror(L, index, "Unknown character in access mode string"); + } + } + return mode; +} + +/* Processes a result and pushes the data onto the stack + returns the number of items pushed */ +static int push_fs_result(lua_State* L, uv_fs_t* req) { + luv_req_t* data = req->data; + + if (req->fs_type == UV_FS_ACCESS) { + lua_pushboolean(L, req->result >= 0); + return 1; + } + + if (req->result < 0) { + lua_pushnil(L); + if (req->path) { + lua_pushfstring(L, "%s: %s: %s", uv_err_name(req->result), uv_strerror(req->result), req->path); + } + else { + lua_pushfstring(L, "%s: %s", uv_err_name(req->result), uv_strerror(req->result)); + } + return 2; + } + + switch (req->fs_type) { + case UV_FS_CLOSE: + case UV_FS_RENAME: + case UV_FS_UNLINK: + case UV_FS_RMDIR: + case UV_FS_MKDIR: + case UV_FS_FTRUNCATE: + case UV_FS_FSYNC: + case UV_FS_FDATASYNC: + case UV_FS_LINK: + case UV_FS_SYMLINK: + case UV_FS_CHMOD: + case UV_FS_FCHMOD: + case UV_FS_CHOWN: + case UV_FS_FCHOWN: + case UV_FS_UTIME: + case UV_FS_FUTIME: + lua_pushboolean(L, 1); + return 1; + + case UV_FS_OPEN: + case UV_FS_SENDFILE: + case UV_FS_WRITE: + lua_pushinteger(L, req->result); + return 1; + + case UV_FS_STAT: + case UV_FS_LSTAT: + case UV_FS_FSTAT: + luv_push_stats_table(L, &req->statbuf); + return 1; + + case UV_FS_MKDTEMP: + lua_pushstring(L, req->path); + return 1; + + case UV_FS_READLINK: + case UV_FS_REALPATH: + lua_pushstring(L, (char*)req->ptr); + return 1; + + case UV_FS_READ: + lua_pushlstring(L, data->data, req->result); + return 1; + + case UV_FS_SCANDIR: + // Expose the userdata for the request. + lua_rawgeti(L, LUA_REGISTRYINDEX, data->req_ref); + return 1; + + default: + lua_pushnil(L); + lua_pushfstring(L, "UNKNOWN FS TYPE %d\n", req->fs_type); + return 2; + } + +} + +static void luv_fs_cb(uv_fs_t* req) { + lua_State* L = luv_state(req->loop); + + int nargs = push_fs_result(L, req); + if (nargs == 2 && lua_isnil(L, -nargs)) { + // If it was an error, convert to (err, value) format. + lua_remove(L, -nargs); + nargs--; + } + else { + // Otherwise insert a nil in front to convert to (err, value) format. + lua_pushnil(L); + lua_insert(L, -nargs - 1); + nargs++; + } + luv_fulfill_req(L, req->data, nargs); + if (req->fs_type != UV_FS_SCANDIR) { + luv_cleanup_req(L, req->data); + req->data = NULL; + uv_fs_req_cleanup(req); + } +} + +#define FS_CALL(func, req, ...) { \ + int ret, sync; \ + luv_req_t* data = req->data; \ + sync = data->callback_ref == LUA_NOREF; \ + ret = uv_fs_##func(luv_loop(L), req, __VA_ARGS__, \ + sync ? NULL : luv_fs_cb); \ + if (req->fs_type != UV_FS_ACCESS && ret < 0) { \ + lua_pushnil(L); \ + if (req->path) { \ + lua_pushfstring(L, "%s: %s: %s", uv_err_name(req->result), uv_strerror(req->result), req->path); \ + } \ + else { \ + lua_pushfstring(L, "%s: %s", uv_err_name(req->result), uv_strerror(req->result)); \ + } \ + lua_pushstring(L, uv_err_name(req->result)); \ + luv_cleanup_req(L, req->data); \ + req->data = NULL; \ + uv_fs_req_cleanup(req); \ + return 3; \ + } \ + if (sync) { \ + int nargs = push_fs_result(L, req); \ + if (req->fs_type != UV_FS_SCANDIR) { \ + luv_cleanup_req(L, req->data); \ + req->data = NULL; \ + uv_fs_req_cleanup(req); \ + } \ + return nargs; \ + } \ + lua_rawgeti(L, LUA_REGISTRYINDEX, data->req_ref); \ + return 1; \ +} + +static int luv_fs_close(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(close, req, file); +} + +static int luv_fs_open(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int flags = luv_check_flags(L, 2); + int mode = luaL_checkinteger(L, 3); + int ref = luv_check_continuation(L, 4); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(open, req, path, flags, mode); +} + +static int luv_fs_read(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + int64_t len = luaL_checkinteger(L, 2); + int64_t offset = luaL_checkinteger(L, 3); + uv_buf_t buf; + int ref; + uv_fs_t* req; + char* data = malloc(len); + if (!data) return luaL_error(L, "Failure to allocate buffer"); + buf = uv_buf_init(data, len); + ref = luv_check_continuation(L, 4); + req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + // TODO: find out why we can't just use req->ptr for the base + ((luv_req_t*)req->data)->data = buf.base; + FS_CALL(read, req, file, &buf, 1, offset); +} + +static int luv_fs_unlink(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(unlink, req, path); +} + +static int luv_fs_write(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + uv_buf_t buf; + int64_t offset; + int ref; + uv_fs_t* req; + size_t count; + uv_buf_t *bufs = NULL; + + if (lua_istable(L, 2)) { + bufs = luv_prep_bufs(L, 2, &count); + buf.base = NULL; + } + else if (lua_isstring(L, 2)) { + luv_check_buf(L, 2, &buf); + count = 1; + } + else { + return luaL_argerror(L, 2, "data must be string or table of strings"); + } + + offset = luaL_checkinteger(L, 3); + ref = luv_check_continuation(L, 4); + req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + req->ptr = buf.base; + ((luv_req_t*)req->data)->data = bufs; + FS_CALL(write, req, file, bufs ? bufs : &buf, count, offset); +} + +static int luv_fs_mkdir(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int mode = luaL_checkinteger(L, 2); + int ref = luv_check_continuation(L, 3); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(mkdir, req, path, mode); +} + +static int luv_fs_mkdtemp(lua_State* L) { + const char* tpl = luaL_checkstring(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(mkdtemp, req, tpl); +} + +static int luv_fs_rmdir(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(rmdir, req, path); +} + +static int luv_fs_scandir(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int flags = 0; // TODO: find out what these flags are. + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(scandir, req, path, flags); +} + +static int luv_fs_scandir_next(lua_State* L) { + uv_fs_t* req = luv_check_fs(L, 1); + uv_dirent_t ent; + int ret = uv_fs_scandir_next(req, &ent); + const char* type; + if (ret == UV_EOF) { + luv_cleanup_req(L, req->data); + req->data = NULL; + uv_fs_req_cleanup(req); + return 0; + } + if (ret < 0) return luv_error(L, ret); + lua_pushstring(L, ent.name); + switch (ent.type) { + case UV_DIRENT_UNKNOWN: return 1; + case UV_DIRENT_FILE: type = "file"; break; + case UV_DIRENT_DIR: type = "directory"; break; + case UV_DIRENT_LINK: type = "link"; break; + case UV_DIRENT_FIFO: type = "fifo"; break; + case UV_DIRENT_SOCKET: type = "socket"; break; + case UV_DIRENT_CHAR: type = "char"; break; + case UV_DIRENT_BLOCK: type = "block"; break; + default: assert(0); + } + lua_pushstring(L, type); + return 2; +} + +static int luv_fs_stat(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(stat, req, path); +} + +static int luv_fs_fstat(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(fstat, req, file); +} + +static int luv_fs_lstat(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(lstat, req, path); +} + +static int luv_fs_rename(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + const char* new_path = luaL_checkstring(L, 2); + int ref = luv_check_continuation(L, 3); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(rename, req, path, new_path); +} + +static int luv_fs_fsync(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(fsync, req, file); +} + +static int luv_fs_fdatasync(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(fdatasync, req, file); +} + +static int luv_fs_ftruncate(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + int64_t offset = luaL_checkinteger(L, 2); + int ref = luv_check_continuation(L, 3); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(ftruncate, req, file, offset); +} + +static int luv_fs_sendfile(lua_State* L) { + uv_file out_fd = luaL_checkinteger(L, 1); + uv_file in_fd = luaL_checkinteger(L, 2); + int64_t in_offset = luaL_checkinteger(L, 3); + size_t length = luaL_checkinteger(L, 4); + int ref = luv_check_continuation(L, 5); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(sendfile, req, out_fd, in_fd, in_offset, length); +} + +static int luv_fs_access(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int amode = luv_check_amode(L, 2); + int ref = luv_check_continuation(L, 3); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(access, req, path, amode); +} + +static int luv_fs_chmod(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int mode = luaL_checkinteger(L, 2); + int ref = luv_check_continuation(L, 3); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(chmod, req, path, mode); +} + +static int luv_fs_fchmod(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + int mode = luaL_checkinteger(L, 2); + int ref = luv_check_continuation(L, 3); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(fchmod, req, file, mode); +} + +static int luv_fs_utime(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + double atime = luaL_checknumber(L, 2); + double mtime = luaL_checknumber(L, 3); + int ref = luv_check_continuation(L, 4); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(utime, req, path, atime, mtime); +} + +static int luv_fs_futime(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + double atime = luaL_checknumber(L, 2); + double mtime = luaL_checknumber(L, 3); + int ref = luv_check_continuation(L, 4); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(futime, req, file, atime, mtime); +} + +static int luv_fs_link(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + const char* new_path = luaL_checkstring(L, 2); + int ref = luv_check_continuation(L, 3); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(link, req, path, new_path); +} + +static int luv_fs_symlink(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + const char* new_path = luaL_checkstring(L, 2); + int flags = 0, ref; + uv_fs_t* req; + if (lua_type(L, 3) == LUA_TTABLE) { + lua_getfield(L, 3, "dir"); + if (lua_toboolean(L, -1)) flags |= UV_FS_SYMLINK_DIR; + lua_pop(L, 1); + lua_getfield(L, 3, "junction"); + if (lua_toboolean(L, -1)) flags |= UV_FS_SYMLINK_JUNCTION; + lua_pop(L, 1); + } + ref = luv_check_continuation(L, 4); + req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + + FS_CALL(symlink, req, path, new_path, flags); +} + +static int luv_fs_readlink(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(readlink, req, path); +} + +static int luv_fs_realpath(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + int ref = luv_check_continuation(L, 2); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(realpath, req, path); +} + +static int luv_fs_chown(lua_State* L) { + const char* path = luaL_checkstring(L, 1); + uv_uid_t uid = luaL_checkinteger(L, 2); + uv_uid_t gid = luaL_checkinteger(L, 3); + int ref = luv_check_continuation(L, 4); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(chown, req, path, uid, gid); +} + +static int luv_fs_fchown(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + uv_uid_t uid = luaL_checkinteger(L, 2); + uv_uid_t gid = luaL_checkinteger(L, 3); + int ref = luv_check_continuation(L, 4); + uv_fs_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + FS_CALL(fchown, req, file, uid, gid); +} diff --git a/3rdparty/luv/src/fs_event.c b/3rdparty/luv/src/fs_event.c new file mode 100644 index 00000000000..52bda788421 --- /dev/null +++ b/3rdparty/luv/src/fs_event.c @@ -0,0 +1,97 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "luv.h" + +static uv_fs_event_t* luv_check_fs_event(lua_State* L, int index) { + uv_fs_event_t* handle = luv_checkudata(L, index, "uv_fs_event"); + luaL_argcheck(L, handle->type == UV_FS_EVENT && handle->data, index, "Expected uv_fs_event_t"); + return handle; +} + +static int luv_new_fs_event(lua_State* L) { + uv_fs_event_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_fs_event_init(luv_loop(L), handle); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static void luv_fs_event_cb(uv_fs_event_t* handle, const char* filename, int events, int status) { + lua_State* L = luv_state(handle->loop); + + // err + luv_status(L, status); + + // filename + lua_pushstring(L, filename); + + // events + lua_newtable(L); + if (events & UV_RENAME) { + lua_pushboolean(L, 1); + lua_setfield(L, -2, "rename"); + } + if (events & UV_CHANGE) { + lua_pushboolean(L, 1); + lua_setfield(L, -2, "change"); + } + + luv_call_callback(L, handle->data, LUV_FS_EVENT, 3); +} + +static int luv_fs_event_start(lua_State* L) { + uv_fs_event_t* handle = luv_check_fs_event(L, 1); + const char* path = luaL_checkstring(L, 2); + int flags = 0, ret; + luaL_checktype(L, 3, LUA_TTABLE); + lua_getfield(L, 3, "watch_entry"); + if (lua_toboolean(L, -1)) flags |= UV_FS_EVENT_WATCH_ENTRY; + lua_pop(L, 1); + lua_getfield(L, 3, "stat"); + if (lua_toboolean(L, -1)) flags |= UV_FS_EVENT_STAT; + lua_pop(L, 1); + lua_getfield(L, 3, "recursive"); + if (lua_toboolean(L, -1)) flags |= UV_FS_EVENT_RECURSIVE; + lua_pop(L, 1); + luv_check_callback(L, handle->data, LUV_FS_EVENT, 4); + ret = uv_fs_event_start(handle, luv_fs_event_cb, path, flags); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_fs_event_stop(lua_State* L) { + uv_fs_event_t* handle = luv_check_fs_event(L, 1); + int ret = uv_fs_event_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_fs_event_getpath(lua_State* L) { + uv_fs_event_t* handle = luv_check_fs_event(L, 1); + size_t len = 2*PATH_MAX; + char buf[2*PATH_MAX]; + int ret = uv_fs_event_getpath(handle, buf, &len); + if (ret < 0) return luv_error(L, ret); + lua_pushlstring(L, buf, len); + return 1; +} diff --git a/3rdparty/luv/src/fs_poll.c b/3rdparty/luv/src/fs_poll.c new file mode 100644 index 00000000000..7ead32f322c --- /dev/null +++ b/3rdparty/luv/src/fs_poll.c @@ -0,0 +1,90 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "luv.h" + +static uv_fs_poll_t* luv_check_fs_poll(lua_State* L, int index) { + uv_fs_poll_t* handle = luv_checkudata(L, index, "uv_fs_poll"); + luaL_argcheck(L, handle->type == UV_FS_POLL && handle->data, index, "Expected uv_fs_poll_t"); + return handle; +} + +static int luv_new_fs_poll(lua_State* L) { + uv_fs_poll_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_fs_poll_init(luv_loop(L), handle); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static void luv_fs_poll_cb(uv_fs_poll_t* handle, int status, const uv_stat_t* prev, const uv_stat_t* curr) { + lua_State* L = luv_state(handle->loop); + + // err + luv_status(L, status); + + // prev + if (prev) { + luv_push_stats_table(L, prev); + } + else { + lua_pushnil(L); + } + + // curr + if (curr) { + luv_push_stats_table(L, curr); + } + else { + lua_pushnil(L); + } + + luv_call_callback(L, handle->data, LUV_FS_POLL, 3); +} + +static int luv_fs_poll_start(lua_State* L) { + uv_fs_poll_t* handle = luv_check_fs_poll(L, 1); + const char* path = luaL_checkstring(L, 2); + unsigned int interval = luaL_checkinteger(L, 3); + int ret; + luv_check_callback(L, handle->data, LUV_FS_POLL, 4); + ret = uv_fs_poll_start(handle, luv_fs_poll_cb, path, interval); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_fs_poll_stop(lua_State* L) { + uv_fs_poll_t* handle = luv_check_fs_poll(L, 1); + int ret = uv_fs_poll_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_fs_poll_getpath(lua_State* L) { + uv_fs_poll_t* handle = luv_check_fs_poll(L, 1); + size_t len = 2*PATH_MAX; + char buf[2*PATH_MAX]; + int ret = uv_fs_poll_getpath(handle, buf, &len); + if (ret < 0) return luv_error(L, ret); + lua_pushlstring(L, buf, len); + return 1; +} diff --git a/3rdparty/luv/src/handle.c b/3rdparty/luv/src/handle.c new file mode 100644 index 00000000000..3efd2982641 --- /dev/null +++ b/3rdparty/luv/src/handle.c @@ -0,0 +1,173 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static void* luv_newuserdata(lua_State* L, size_t sz) { + void* handle = malloc(sz); + if (handle) { + *(void**)lua_newuserdata(L, sizeof(void*)) = handle; + } + return handle; +} + +static void* luv_checkudata(lua_State* L, int ud, const char* tname) { + return *(void**) luaL_checkudata(L, ud, tname); +} + +static uv_handle_t* luv_check_handle(lua_State* L, int index) { + int isHandle; + uv_handle_t* handle; + if (!(handle = *(void**)lua_touserdata(L, index))) { goto fail; } + lua_getfield(L, LUA_REGISTRYINDEX, "uv_handle"); + lua_getmetatable(L, index < 0 ? index - 1 : index); + lua_rawget(L, -2); + isHandle = lua_toboolean(L, -1); + lua_pop(L, 2); + if (isHandle) { return handle; } + fail: luaL_argerror(L, index, "Expected uv_handle userdata"); + return NULL; +} + +// Show the libuv type instead of generic "userdata" +static int luv_handle_tostring(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + switch (handle->type) { +#define XX(uc, lc) case UV_##uc: lua_pushfstring(L, "uv_"#lc"_t: %p", handle); break; + UV_HANDLE_TYPE_MAP(XX) +#undef XX + default: lua_pushfstring(L, "uv_handle_t: %p", handle); break; + } + return 1; +} + +static int luv_is_active(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + int ret = uv_is_active(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushboolean(L, ret); + return 1; +} + +static int luv_is_closing(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + int ret = uv_is_closing(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushboolean(L, ret); + return 1; +} + +static void luv_close_cb(uv_handle_t* handle) { + lua_State* L = luv_state(handle->loop); + luv_handle_t* data = handle->data; + if (!data) return; + luv_call_callback(L, data, LUV_CLOSED, 0); + luv_cleanup_handle(L, data); + handle->data = NULL; +} + +static int luv_close(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + if (uv_is_closing(handle)) { + luaL_error(L, "handle %p is already closing", handle); + } + if (!lua_isnoneornil(L, 2)) { + luv_check_callback(L, handle->data, LUV_CLOSED, 2); + } + uv_close(handle, luv_close_cb); + return 0; +} + +static void luv_gc_cb(uv_handle_t* handle) { + luv_close_cb(handle); + free(handle); +} + +static int luv_handle_gc(lua_State* L) { + void** udata = lua_touserdata(L, 1); + uv_handle_t* handle = *udata; + if (handle != NULL) { + if (!uv_is_closing(handle)) + uv_close(handle, luv_gc_cb); + else + free(*udata); + + *udata = NULL; + } + + return 0; +} + +static int luv_ref(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + uv_ref(handle); + return 0; +} + +static int luv_unref(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + uv_unref(handle); + return 0; +} + +static int luv_has_ref(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + int ret = uv_has_ref(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushboolean(L, ret); + return 1; +} + +static int luv_send_buffer_size(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + int value; + int ret; + if (lua_isnoneornil(L, 2)) { + value = 0; + } + else { + value = luaL_checkinteger(L, 2); + } + ret = uv_send_buffer_size(handle, &value); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_recv_buffer_size(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + int value; + int ret; + if (lua_isnoneornil(L, 2)) { + value = 0; + } + else { + value = luaL_checkinteger(L, 2); + } + ret = uv_recv_buffer_size(handle, &value); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_fileno(lua_State* L) { + uv_handle_t* handle = luv_check_handle(L, 1); + uv_os_fd_t fd; + int ret = uv_fileno(handle, &fd); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, (LUA_INTEGER)(ptrdiff_t)fd); + return 1; +} diff --git a/3rdparty/luv/src/idle.c b/3rdparty/luv/src/idle.c new file mode 100644 index 00000000000..132cbe43c33 --- /dev/null +++ b/3rdparty/luv/src/idle.c @@ -0,0 +1,59 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_idle_t* luv_check_idle(lua_State* L, int index) { + uv_idle_t* handle = luv_checkudata(L, index, "uv_idle"); + luaL_argcheck(L, handle->type == UV_IDLE && handle->data, index, "Expected uv_idle_t"); + return handle; +} + +static int luv_new_idle(lua_State* L) { + uv_idle_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_idle_init(luv_loop(L), handle); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static void luv_idle_cb(uv_idle_t* handle) { + lua_State* L = luv_state(handle->loop); + luv_handle_t* data = handle->data; + luv_call_callback(L, data, LUV_IDLE, 0); +} + +static int luv_idle_start(lua_State* L) { + uv_idle_t* handle = luv_check_idle(L, 1); + int ret; + luv_check_callback(L, handle->data, LUV_IDLE, 2); + ret = uv_idle_start(handle, luv_idle_cb); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_idle_stop(lua_State* L) { + uv_idle_t* handle = luv_check_idle(L, 1); + int ret = uv_idle_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + diff --git a/3rdparty/luv/src/lhandle.c b/3rdparty/luv/src/lhandle.c new file mode 100644 index 00000000000..c8cf294504e --- /dev/null +++ b/3rdparty/luv/src/lhandle.c @@ -0,0 +1,116 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "lhandle.h" + +static luv_handle_t* luv_setup_handle(lua_State* L) { + luv_handle_t* data; + const uv_handle_t* handle = *(void**)lua_touserdata(L, -1); + luaL_checktype(L, -1, LUA_TUSERDATA); + + data = malloc(sizeof(*data)); + if (!data) luaL_error(L, "Can't allocate luv handle"); + + #define XX(uc, lc) case UV_##uc: \ + luaL_getmetatable(L, "uv_"#lc); \ + break; + switch (handle->type) { + UV_HANDLE_TYPE_MAP(XX) + default: + luaL_error(L, "Unknown handle type"); + return NULL; + } + #undef XX + + lua_setmetatable(L, -2); + + lua_pushvalue(L, -1); + + data->ref = luaL_ref(L, LUA_REGISTRYINDEX); + data->callbacks[0] = LUA_NOREF; + data->callbacks[1] = LUA_NOREF; + data->extra = NULL; + return data; +} + +static void luv_check_callback(lua_State* L, luv_handle_t* data, luv_callback_id id, int index) { + luaL_checktype(L, index, LUA_TFUNCTION); + luaL_unref(L, LUA_REGISTRYINDEX, data->callbacks[id]); + lua_pushvalue(L, index); + data->callbacks[id] = luaL_ref(L, LUA_REGISTRYINDEX); +} + +static int traceback (lua_State *L) { + if (!lua_isstring(L, 1)) /* 'message' not a string? */ + return 1; /* keep it intact */ + lua_pushglobaltable(L); + lua_getfield(L, -1, "debug"); + lua_remove(L, -2); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); /* pass error message */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback */ + return 1; +} + +static void luv_call_callback(lua_State* L, luv_handle_t* data, luv_callback_id id, int nargs) { + int ref = data->callbacks[id]; + if (ref == LUA_NOREF) { + lua_pop(L, nargs); + } + else { + // Get the traceback function in case of error + lua_pushcfunction(L, traceback); + // And insert it before the args if there are any. + if (nargs) { + lua_insert(L, -1 - nargs); + } + // Get the callback + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + // And insert it before the args if there are any. + if (nargs) { + lua_insert(L, -1 - nargs); + } + + if (lua_pcall(L, nargs, 0, -2 - nargs)) { + fprintf(stderr, "Uncaught Error: %s\n", lua_tostring(L, -1)); + exit(-1); + } + // Remove the traceback function + lua_pop(L, 1); + } +} + +static void luv_cleanup_handle(lua_State* L, luv_handle_t* data) { + luaL_unref(L, LUA_REGISTRYINDEX, data->ref); + luaL_unref(L, LUA_REGISTRYINDEX, data->callbacks[0]); + luaL_unref(L, LUA_REGISTRYINDEX, data->callbacks[1]); + if (data->extra) + free(data->extra); + free(data); +} + +static void luv_find_handle(lua_State* L, luv_handle_t* data) { + lua_rawgeti(L, LUA_REGISTRYINDEX, data->ref); +} diff --git a/3rdparty/luv/src/lhandle.h b/3rdparty/luv/src/lhandle.h new file mode 100644 index 00000000000..f6c0733719b --- /dev/null +++ b/3rdparty/luv/src/lhandle.h @@ -0,0 +1,67 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef LUV_LHANDLE_H +#define LUV_LHANDLE_H + +#include "luv.h" + +/* There are two slots for holding callbacks. One is for the CLOSED event. + The other slot is for all others since they never conflict in practice. +*/ +#define luv_callback_id int +#define LUV_CLOSED 0 +#define LUV_TIMEOUT 1 +#define LUV_PREPARE 1 +#define LUV_IDLE 1 +#define LUV_CHECK 1 +#define LUV_ASYNC 1 +#define LUV_POLL 1 +#define LUV_SIGNAL 1 +#define LUV_EXIT 1 +#define LUV_CONNECTION 1 +#define LUV_READ 1 +#define LUV_RECV 1 +#define LUV_FS_EVENT 1 +#define LUV_FS_POLL 1 + +/* Ref for userdata and event callbacks */ +typedef struct { + int ref; + int callbacks[2]; + void* extra; +} luv_handle_t; + +/* Setup the handle at the top of the stack */ +static luv_handle_t* luv_setup_handle(lua_State* L); + +/* Store a lua callback in a luv_handle for future callbacks. + Either replace an existing callback by id or append a new one at the end. +*/ +static void luv_check_callback(lua_State* L, luv_handle_t* data, luv_callback_id id, int index); + +/* Lookup a function and call it with nargs + If there is no such function, pop the args. +*/ +static void luv_call_callback(lua_State* L, luv_handle_t* data, luv_callback_id id, int nargs); + +/* Push a userdata on the stack from a handle */ +static void luv_find_handle(lua_State* L, luv_handle_t* data); + +/* Recursivly free the luv_handle and all event handlers */ +static void luv_cleanup_handle(lua_State* L, luv_handle_t* data); + +#endif diff --git a/3rdparty/luv/src/loop.c b/3rdparty/luv/src/loop.c new file mode 100644 index 00000000000..33c49d3f64c --- /dev/null +++ b/3rdparty/luv/src/loop.c @@ -0,0 +1,92 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static int luv_loop_close(lua_State* L) { + int ret = uv_loop_close(luv_loop(L)); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +// These are the same order as uv_run_mode which also starts at 0 +static const char *const luv_runmodes[] = { + "default", "once", "nowait", NULL +}; + +static int luv_run(lua_State* L) { + int mode = luaL_checkoption(L, 1, "default", luv_runmodes); + int ret = uv_run(luv_loop(L), mode); + if (ret < 0) return luv_error(L, ret); + lua_pushboolean(L, ret); + return 1; +} + +static int luv_loop_alive(lua_State* L) { + int ret = uv_loop_alive(luv_loop(L)); + if (ret < 0) return luv_error(L, ret); + lua_pushboolean(L, ret); + return 1; +} + +static int luv_stop(lua_State* L) { + uv_stop(luv_loop(L)); + return 0; +} + +static int luv_backend_fd(lua_State* L) { + int ret = uv_backend_fd(luv_loop(L)); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_backend_timeout(lua_State* L) { + int ret = uv_backend_timeout(luv_loop(L)); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_now(lua_State* L) { + uint64_t now = uv_now(luv_loop(L)); + lua_pushinteger(L, now); + return 1; +} + +static int luv_update_time(lua_State* L) { + uv_update_time(luv_loop(L)); + return 0; +} + +static void luv_walk_cb(uv_handle_t* handle, void* arg) { + lua_State* L = arg; + luv_handle_t* data = handle->data; + + // Sanity check + // Most invalid values are large and refs are small, 0x1000000 is arbitrary. + assert(data && data->ref < 0x1000000); + + lua_pushvalue(L, 1); // Copy the function + luv_find_handle(L, data); // Get the userdata + lua_call(L, 1, 0); // Call the function +} + +static int luv_walk(lua_State* L) { + luaL_checktype(L, 1, LUA_TFUNCTION); + uv_walk(luv_loop(L), luv_walk_cb, L); + return 0; +} diff --git a/3rdparty/luv/src/lreq.c b/3rdparty/luv/src/lreq.c new file mode 100644 index 00000000000..38ed6a77eb0 --- /dev/null +++ b/3rdparty/luv/src/lreq.c @@ -0,0 +1,71 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "lreq.h" + + +static int luv_check_continuation(lua_State* L, int index) { + if (lua_isnoneornil(L, index)) return LUA_NOREF; + luaL_checktype(L, index, LUA_TFUNCTION); + lua_pushvalue(L, index); + return luaL_ref(L, LUA_REGISTRYINDEX); +} + +// Store a lua callback in a luv_req for the continuation. +// The uv_req_t is assumed to be at the top of the stack +static luv_req_t* luv_setup_req(lua_State* L, int callback_ref) { + luv_req_t* data; + + luaL_checktype(L, -1, LUA_TUSERDATA); + + data = malloc(sizeof(*data)); + if (!data) luaL_error(L, "Problem allocating luv request"); + + luaL_getmetatable(L, "uv_req"); + lua_setmetatable(L, -2); + + lua_pushvalue(L, -1); + data->req_ref = luaL_ref(L, LUA_REGISTRYINDEX); + data->callback_ref = callback_ref; + data->data_ref = LUA_NOREF; + data->data = NULL; + + return data; +} + + +static void luv_fulfill_req(lua_State* L, luv_req_t* data, int nargs) { + if (data->callback_ref == LUA_NOREF) { + lua_pop(L, nargs); + } + else { + // Get the callback + lua_rawgeti(L, LUA_REGISTRYINDEX, data->callback_ref); + // And insert it before the args if there are any. + if (nargs) { + lua_insert(L, -1 - nargs); + } + lua_call(L, nargs, 0); + } +} + +static void luv_cleanup_req(lua_State* L, luv_req_t* data) { + luaL_unref(L, LUA_REGISTRYINDEX, data->req_ref); + luaL_unref(L, LUA_REGISTRYINDEX, data->callback_ref); + luaL_unref(L, LUA_REGISTRYINDEX, data->data_ref); + free(data->data); + free(data); +} diff --git a/3rdparty/luv/src/lreq.h b/3rdparty/luv/src/lreq.h new file mode 100644 index 00000000000..a8b147e057b --- /dev/null +++ b/3rdparty/luv/src/lreq.h @@ -0,0 +1,43 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef LUV_LREQ_H +#define LUV_LREQ_H + +#include "luv.h" + +typedef struct { + int req_ref; /* ref for uv_req_t's userdata */ + int callback_ref; /* ref for callback */ + int data_ref; /* ref for write data */ + void* data; /* extra data */ +} luv_req_t; + +/* Used in the top of a setup function to check the arg + and ref the callback to an integer. +*/ +static int luv_check_continuation(lua_State* L, int index); + +/* setup a luv_req_t. The userdata is assumed to be at the + top of the stack. +*/ +static luv_req_t* luv_setup_req(lua_State* L, int ref); + +static void luv_fulfill_req(lua_State* L, luv_req_t* data, int nargs); + +static void luv_cleanup_req(lua_State* L, luv_req_t* data); + +#endif diff --git a/3rdparty/luv/src/lthreadpool.h b/3rdparty/luv/src/lthreadpool.h new file mode 100644 index 00000000000..0994746bc52 --- /dev/null +++ b/3rdparty/luv/src/lthreadpool.h @@ -0,0 +1,48 @@ +/* +* Copyright 2014 The Luvit Authors. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ +#ifndef LUV_LTHREADPOOL_H +#define LUV_LTHREADPOOL_H + +#include "luv.h" + +#define LUV_THREAD_MAXNUM_ARG 9 + +typedef struct { + /* only support LUA_TNIL, LUA_TBOOLEAN, LUA_TLIGHTUSERDATA, LUA_TNUMBER, LUA_TSTRING*/ + int type; + union + { + lua_Number num; + int boolean; + void* userdata; + struct { + const char* base; + size_t len; + } str; + } val; +} luv_val_t; + +typedef struct { + int argc; + luv_val_t argv[LUV_THREAD_MAXNUM_ARG]; +} luv_thread_arg_t; + +static int luv_thread_arg_set(lua_State* L, luv_thread_arg_t* args, int idx, int top, int flag); +static int luv_thread_arg_push(lua_State* L, const luv_thread_arg_t* args); +static void luv_thread_arg_clear(luv_thread_arg_t* args); + +#endif //LUV_LTHREADPOOL_H diff --git a/3rdparty/luv/src/luv.c b/3rdparty/luv/src/luv.c new file mode 100644 index 00000000000..7b552d68d53 --- /dev/null +++ b/3rdparty/luv/src/luv.c @@ -0,0 +1,519 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "luv.h" +#include "util.c" +#include "lhandle.c" +#include "lreq.c" +#include "loop.c" +#include "req.c" +#include "handle.c" +#include "timer.c" +#include "prepare.c" +#include "check.c" +#include "idle.c" +#include "async.c" +#include "poll.c" +#include "signal.c" +#include "process.c" +#include "stream.c" +#include "tcp.c" +#include "pipe.c" +#include "tty.c" +#include "udp.c" +#include "fs_event.c" +#include "fs_poll.c" +#include "fs.c" +#include "dns.c" +#include "thread.c" +#include "work.c" +#include "misc.c" +#include "constants.c" + +static const luaL_Reg luv_functions[] = { + // loop.c + {"loop_close", luv_loop_close}, + {"run", luv_run}, + {"loop_alive", luv_loop_alive}, + {"stop", luv_stop}, + {"backend_fd", luv_backend_fd}, + {"backend_timeout", luv_backend_timeout}, + {"now", luv_now}, + {"update_time", luv_update_time}, + {"walk", luv_walk}, + + // req.c + {"cancel", luv_cancel}, + + // handle.c + {"is_active", luv_is_active}, + {"is_closing", luv_is_closing}, + {"close", luv_close}, + {"ref", luv_ref}, + {"unref", luv_unref}, + {"has_ref", luv_has_ref}, + {"send_buffer_size", luv_send_buffer_size}, + {"recv_buffer_size", luv_recv_buffer_size}, + {"fileno", luv_fileno}, + + // timer.c + {"new_timer", luv_new_timer}, + {"timer_start", luv_timer_start}, + {"timer_stop", luv_timer_stop}, + {"timer_again", luv_timer_again}, + {"timer_set_repeat", luv_timer_set_repeat}, + {"timer_get_repeat", luv_timer_get_repeat}, + + // prepare.c + {"new_prepare", luv_new_prepare}, + {"prepare_start", luv_prepare_start}, + {"prepare_stop", luv_prepare_stop}, + + // check.c + {"new_check", luv_new_check}, + {"check_start", luv_check_start}, + {"check_stop", luv_check_stop}, + + // idle.c + {"new_idle", luv_new_idle}, + {"idle_start", luv_idle_start}, + {"idle_stop", luv_idle_stop}, + + // async.c + {"new_async", luv_new_async}, + {"async_send", luv_async_send}, + + // poll.c + {"new_poll", luv_new_poll}, + {"new_socket_poll", luv_new_socket_poll}, + {"poll_start", luv_poll_start}, + {"poll_stop", luv_poll_stop}, + + // signal.c + {"new_signal", luv_new_signal}, + {"signal_start", luv_signal_start}, + {"signal_stop", luv_signal_stop}, + + // process.c + {"disable_stdio_inheritance", luv_disable_stdio_inheritance}, + {"spawn", luv_spawn}, + {"process_kill", luv_process_kill}, + {"kill", luv_kill}, + + // stream.c + {"shutdown", luv_shutdown}, + {"listen", luv_listen}, + {"accept", luv_accept}, + {"read_start", luv_read_start}, + {"read_stop", luv_read_stop}, + {"write", luv_write}, + {"write2", luv_write2}, + {"try_write", luv_try_write}, + {"is_readable", luv_is_readable}, + {"is_writable", luv_is_writable}, + {"stream_set_blocking", luv_stream_set_blocking}, + + // tcp.c + {"new_tcp", luv_new_tcp}, + {"tcp_open", luv_tcp_open}, + {"tcp_nodelay", luv_tcp_nodelay}, + {"tcp_keepalive", luv_tcp_keepalive}, + {"tcp_simultaneous_accepts", luv_tcp_simultaneous_accepts}, + {"tcp_bind", luv_tcp_bind}, + {"tcp_getpeername", luv_tcp_getpeername}, + {"tcp_getsockname", luv_tcp_getsockname}, + {"tcp_connect", luv_tcp_connect}, + {"tcp_write_queue_size", luv_write_queue_size}, + + // pipe.c + {"new_pipe", luv_new_pipe}, + {"pipe_open", luv_pipe_open}, + {"pipe_bind", luv_pipe_bind}, + {"pipe_connect", luv_pipe_connect}, + {"pipe_getsockname", luv_pipe_getsockname}, + {"pipe_getpeername", luv_pipe_getpeername}, + {"pipe_pending_instances", luv_pipe_pending_instances}, + {"pipe_pending_count", luv_pipe_pending_count}, + {"pipe_pending_type", luv_pipe_pending_type}, + + // tty.c + {"new_tty", luv_new_tty}, + {"tty_set_mode", luv_tty_set_mode}, + {"tty_reset_mode", luv_tty_reset_mode}, + {"tty_get_winsize", luv_tty_get_winsize}, + + // udp.c + {"new_udp", luv_new_udp}, + {"udp_open", luv_udp_open}, + {"udp_bind", luv_udp_bind}, + {"udp_getsockname", luv_udp_getsockname}, + {"udp_set_membership", luv_udp_set_membership}, + {"udp_set_multicast_loop", luv_udp_set_multicast_loop}, + {"udp_set_multicast_ttl", luv_udp_set_multicast_ttl}, + {"udp_set_multicast_interface", luv_udp_set_multicast_interface}, + {"udp_set_broadcast", luv_udp_set_broadcast}, + {"udp_set_ttl", luv_udp_set_ttl}, + {"udp_send", luv_udp_send}, + {"udp_try_send", luv_udp_try_send}, + {"udp_recv_start", luv_udp_recv_start}, + {"udp_recv_stop", luv_udp_recv_stop}, + + // fs_event.c + {"new_fs_event", luv_new_fs_event}, + {"fs_event_start", luv_fs_event_start}, + {"fs_event_stop", luv_fs_event_stop}, + {"fs_event_getpath", luv_fs_event_getpath}, + + // fs_poll.c + {"new_fs_poll", luv_new_fs_poll}, + {"fs_poll_start", luv_fs_poll_start}, + {"fs_poll_stop", luv_fs_poll_stop}, + {"fs_poll_getpath", luv_fs_poll_getpath}, + + // fs.c + {"fs_close", luv_fs_close}, + {"fs_open", luv_fs_open}, + {"fs_read", luv_fs_read}, + {"fs_unlink", luv_fs_unlink}, + {"fs_write", luv_fs_write}, + {"fs_mkdir", luv_fs_mkdir}, + {"fs_mkdtemp", luv_fs_mkdtemp}, + {"fs_rmdir", luv_fs_rmdir}, + {"fs_scandir", luv_fs_scandir}, + {"fs_scandir_next", luv_fs_scandir_next}, + {"fs_stat", luv_fs_stat}, + {"fs_fstat", luv_fs_fstat}, + {"fs_lstat", luv_fs_lstat}, + {"fs_rename", luv_fs_rename}, + {"fs_fsync", luv_fs_fsync}, + {"fs_fdatasync", luv_fs_fdatasync}, + {"fs_ftruncate", luv_fs_ftruncate}, + {"fs_sendfile", luv_fs_sendfile}, + {"fs_access", luv_fs_access}, + {"fs_chmod", luv_fs_chmod}, + {"fs_fchmod", luv_fs_fchmod}, + {"fs_utime", luv_fs_utime}, + {"fs_futime", luv_fs_futime}, + {"fs_link", luv_fs_link}, + {"fs_symlink", luv_fs_symlink}, + {"fs_readlink", luv_fs_readlink}, + {"fs_realpath", luv_fs_realpath}, + {"fs_chown", luv_fs_chown}, + {"fs_fchown", luv_fs_fchown}, + + // dns.c + {"getaddrinfo", luv_getaddrinfo}, + {"getnameinfo", luv_getnameinfo}, + + // misc.c + {"chdir", luv_chdir}, + {"os_homedir", luv_os_homedir}, + {"cpu_info", luv_cpu_info}, + {"cwd", luv_cwd}, + {"exepath", luv_exepath}, + {"get_process_title", luv_get_process_title}, + {"get_total_memory", luv_get_total_memory}, + {"get_free_memory", luv_get_free_memory}, + {"getpid", luv_getpid}, +#ifndef _WIN32 + {"getuid", luv_getuid}, + {"setuid", luv_setuid}, + {"getgid", luv_getgid}, + {"setgid", luv_setgid}, +#endif + {"getrusage", luv_getrusage}, + {"guess_handle", luv_guess_handle}, + {"hrtime", luv_hrtime}, + {"interface_addresses", luv_interface_addresses}, + {"loadavg", luv_loadavg}, + {"resident_set_memory", luv_resident_set_memory}, + {"set_process_title", luv_set_process_title}, + {"uptime", luv_uptime}, + {"version", luv_version}, + {"version_string", luv_version_string}, + + // thread.c + {"new_thread", luv_new_thread}, + {"thread_equal", luv_thread_equal}, + {"thread_self", luv_thread_self}, + {"thread_join", luv_thread_join}, + {"sleep", luv_thread_sleep}, + + // work.c + {"new_work", luv_new_work}, + {"queue_work", luv_queue_work}, + + {NULL, NULL} +}; + +static const luaL_Reg luv_handle_methods[] = { + // handle.c + {"is_active", luv_is_active}, + {"is_closing", luv_is_closing}, + {"close", luv_close}, + {"ref", luv_ref}, + {"unref", luv_unref}, + {"has_ref", luv_has_ref}, + {"send_buffer_size", luv_send_buffer_size}, + {"recv_buffer_size", luv_recv_buffer_size}, + {"fileno", luv_fileno}, + {NULL, NULL} +}; + +static const luaL_Reg luv_async_methods[] = { + {"send", luv_async_send}, + {NULL, NULL} +}; + +static const luaL_Reg luv_check_methods[] = { + {"start", luv_check_start}, + {"stop", luv_check_stop}, + {NULL, NULL} +}; + +static const luaL_Reg luv_fs_event_methods[] = { + {"start", luv_fs_event_start}, + {"stop", luv_fs_event_stop}, + {"getpath", luv_fs_event_getpath}, + {NULL, NULL} +}; + +static const luaL_Reg luv_fs_poll_methods[] = { + {"start", luv_fs_poll_start}, + {"stop", luv_fs_poll_stop}, + {"getpath", luv_fs_poll_getpath}, + {NULL, NULL} +}; + +static const luaL_Reg luv_idle_methods[] = { + {"start", luv_idle_start}, + {"stop", luv_idle_stop}, + {NULL, NULL} +}; + +static const luaL_Reg luv_stream_methods[] = { + {"shutdown", luv_shutdown}, + {"listen", luv_listen}, + {"accept", luv_accept}, + {"read_start", luv_read_start}, + {"read_stop", luv_read_stop}, + {"write", luv_write}, + {"write2", luv_write2}, + {"try_write", luv_try_write}, + {"is_readable", luv_is_readable}, + {"is_writable", luv_is_writable}, + {"set_blocking", luv_stream_set_blocking}, + {NULL, NULL} +}; + +static const luaL_Reg luv_pipe_methods[] = { + {"open", luv_pipe_open}, + {"bind", luv_pipe_bind}, + {"connect", luv_pipe_connect}, + {"getsockname", luv_pipe_getsockname}, + {"getpeername", luv_pipe_getpeername}, + {"pending_instances", luv_pipe_pending_instances}, + {"pending_count", luv_pipe_pending_count}, + {"pending_type", luv_pipe_pending_type}, + {NULL, NULL} +}; + +static const luaL_Reg luv_poll_methods[] = { + {"start", luv_poll_start}, + {"stop", luv_poll_stop}, + {NULL, NULL} +}; + +static const luaL_Reg luv_prepare_methods[] = { + {"start", luv_prepare_start}, + {"stop", luv_prepare_stop}, + {NULL, NULL} +}; + +static const luaL_Reg luv_process_methods[] = { + {"kill", luv_process_kill}, + {NULL, NULL} +}; + +static const luaL_Reg luv_tcp_methods[] = { + {"open", luv_tcp_open}, + {"nodelay", luv_tcp_nodelay}, + {"keepalive", luv_tcp_keepalive}, + {"simultaneous_accepts", luv_tcp_simultaneous_accepts}, + {"bind", luv_tcp_bind}, + {"getpeername", luv_tcp_getpeername}, + {"getsockname", luv_tcp_getsockname}, + {"connect", luv_tcp_connect}, + {"write_queue_size", luv_write_queue_size}, + {NULL, NULL} +}; + +static const luaL_Reg luv_timer_methods[] = { + {"start", luv_timer_start}, + {"stop", luv_timer_stop}, + {"again", luv_timer_again}, + {"set_repeat", luv_timer_set_repeat}, + {"get_repeat", luv_timer_get_repeat}, + {NULL, NULL} +}; + +static const luaL_Reg luv_tty_methods[] = { + {"set_mode", luv_tty_set_mode}, + {"get_winsize", luv_tty_get_winsize}, + {NULL, NULL} +}; + +static const luaL_Reg luv_udp_methods[] = { + {"open", luv_udp_open}, + {"bind", luv_udp_bind}, + {"bindgetsockname", luv_udp_getsockname}, + {"set_membership", luv_udp_set_membership}, + {"set_multicast_loop", luv_udp_set_multicast_loop}, + {"set_multicast_ttl", luv_udp_set_multicast_ttl}, + {"set_multicast_interface", luv_udp_set_multicast_interface}, + {"set_broadcast", luv_udp_set_broadcast}, + {"set_ttl", luv_udp_set_ttl}, + {"send", luv_udp_send}, + {"try_send", luv_udp_try_send}, + {"recv_start", luv_udp_recv_start}, + {"recv_stop", luv_udp_recv_stop}, + {NULL, NULL} +}; + +static const luaL_Reg luv_signal_methods[] = { + {"start", luv_signal_start}, + {"stop", luv_signal_stop}, + {NULL, NULL} +}; + +static void luv_handle_init(lua_State* L) { + + lua_newtable(L); +#define XX(uc, lc) \ + luaL_newmetatable (L, "uv_"#lc); \ + lua_pushcfunction(L, luv_handle_tostring); \ + lua_setfield(L, -2, "__tostring"); \ + lua_pushcfunction(L, luv_handle_gc); \ + lua_setfield(L, -2, "__gc"); \ + luaL_newlib(L, luv_##lc##_methods); \ + luaL_setfuncs(L, luv_handle_methods, 0); \ + lua_setfield(L, -2, "__index"); \ + lua_pushboolean(L, 1); \ + lua_rawset(L, -3); + + UV_HANDLE_TYPE_MAP(XX) +#undef XX + lua_setfield(L, LUA_REGISTRYINDEX, "uv_handle"); + + lua_newtable(L); + + luaL_getmetatable(L, "uv_pipe"); + lua_getfield(L, -1, "__index"); + luaL_setfuncs(L, luv_stream_methods, 0); + lua_pop(L, 1); + lua_pushboolean(L, 1); + lua_rawset(L, -3); + + luaL_getmetatable(L, "uv_tcp"); + lua_getfield(L, -1, "__index"); + luaL_setfuncs(L, luv_stream_methods, 0); + lua_pop(L, 1); + lua_pushboolean(L, 1); + lua_rawset(L, -3); + + luaL_getmetatable(L, "uv_tty"); + lua_getfield(L, -1, "__index"); + luaL_setfuncs(L, luv_stream_methods, 0); + lua_pop(L, 1); + lua_pushboolean(L, 1); + lua_rawset(L, -3); + + lua_setfield(L, LUA_REGISTRYINDEX, "uv_stream"); +} + +LUALIB_API lua_State* luv_state(uv_loop_t* loop) { + return loop->data; +} + +// TODO: find out if storing this somehow in an upvalue is faster +LUALIB_API uv_loop_t* luv_loop(lua_State* L) { + uv_loop_t* loop; + lua_pushstring(L, "uv_loop"); + lua_rawget(L, LUA_REGISTRYINDEX); + loop = lua_touserdata(L, -1); + lua_pop(L, 1); + return loop; +} + +static void walk_cb(uv_handle_t *handle, void *arg) +{ + (void)arg; + if (!uv_is_closing(handle)) { + uv_close(handle, luv_close_cb); + } +} + +static int loop_gc(lua_State *L) { + uv_loop_t* loop = luv_loop(L); + // Call uv_close on every active handle + uv_walk(loop, walk_cb, NULL); + // Run the event loop until all handles are successfully closed + while (uv_loop_close(loop)) { + uv_run(loop, UV_RUN_DEFAULT); + } + return 0; +} + +LUALIB_API int luaopen_luv (lua_State *L) { + + uv_loop_t* loop; + int ret; + + // Setup the uv_loop meta table for a proper __gc + luaL_newmetatable(L, "uv_loop.meta"); + lua_pushstring(L, "__gc"); + lua_pushcfunction(L, loop_gc); + lua_settable(L, -3); + + loop = lua_newuserdata(L, sizeof(*loop)); + ret = uv_loop_init(loop); + if (ret < 0) { + return luaL_error(L, "%s: %s\n", uv_err_name(ret), uv_strerror(ret)); + } + // setup the metatable for __gc + luaL_getmetatable(L, "uv_loop.meta"); + lua_setmetatable(L, -2); + // Tell the state how to find the loop. + lua_pushstring(L, "uv_loop"); + lua_insert(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + lua_pop(L, 1); + + // Tell the loop how to find the state. + loop->data = L; + + luv_req_init(L); + luv_handle_init(L); + luv_thread_init(L); + luv_work_init(L); + + luaL_newlib(L, luv_functions); + luv_constants(L); + lua_setfield(L, -2, "constants"); + + return 1; +} diff --git a/3rdparty/luv/src/luv.h b/3rdparty/luv/src/luv.h new file mode 100644 index 00000000000..681384da363 --- /dev/null +++ b/3rdparty/luv/src/luv.h @@ -0,0 +1,109 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef LUV_H +#define LUV_H +#include +#include +#include +#include "uv.h" + +#include +#include +#include + +#if defined(_WIN32) +# include +# include +# include +# ifndef __MINGW32__ +# define S_ISREG(x) (((x) & _S_IFMT) == _S_IFREG) +# define S_ISDIR(x) (((x) & _S_IFMT) == _S_IFDIR) +# define S_ISFIFO(x) (((x) & _S_IFMT) == _S_IFIFO) +# define S_ISCHR(x) (((x) & _S_IFMT) == _S_IFCHR) +# define S_ISBLK(x) 0 +# endif +# define S_ISLNK(x) (((x) & S_IFLNK) == S_IFLNK) +# define S_ISSOCK(x) 0 +#else +# include +#endif + +#ifndef PATH_MAX +#define PATH_MAX (8096) +#endif + +#ifndef MAX_TITLE_LENGTH +#define MAX_TITLE_LENGTH (8192) +#endif + +#if LUA_VERSION_NUM < 502 +# define lua_rawlen lua_objlen +/* lua_...uservalue: Something very different, but it should get the job done */ +# define lua_getuservalue lua_getfenv +# define lua_setuservalue lua_setfenv +# define luaL_newlib(L,l) (lua_newtable(L), luaL_register(L,NULL,l)) +# define luaL_setfuncs(L,l,n) (assert(n==0), luaL_register(L,NULL,l)) +# define lua_resume(L,F,n) lua_resume(L,n) +# define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX) +#endif + +/* There is a 1-1 relation between a lua_State and a uv_loop_t + These helpers will give you one if you have the other + These are exposed for extensions built with luv + This allows luv to be used in multithreaded applications. +*/ +LUALIB_API lua_State* luv_state(uv_loop_t* loop); +/* All libuv callbacks will lua_call directly from this root-per-thread state +*/ +LUALIB_API uv_loop_t* luv_loop(lua_State* L); + +/* This is the main hook to load the library. + This can be called multiple times in a process as long + as you use a different lua_State and thread for each. +*/ +LUALIB_API int luaopen_luv (lua_State *L); + +#include "util.h" +#include "lhandle.h" +#include "lreq.h" + +/* From stream.c */ +static uv_stream_t* luv_check_stream(lua_State* L, int index); +static void luv_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf); +static void luv_check_buf(lua_State *L, int idx, uv_buf_t *pbuf); +static uv_buf_t* luv_prep_bufs(lua_State* L, int index, size_t *count); + +/* from tcp.c */ +static void parse_sockaddr(lua_State* L, struct sockaddr_storage* address, int addrlen); +static void luv_connect_cb(uv_connect_t* req, int status); + +/* From fs.c */ +static void luv_push_stats_table(lua_State* L, const uv_stat_t* s); + +/* from constants.c */ +static int luv_af_string_to_num(const char* string); +static const char* luv_af_num_to_string(const int num); +static int luv_sock_string_to_num(const char* string); +static const char* luv_sock_num_to_string(const int num); +static int luv_sig_string_to_num(const char* string); +static const char* luv_sig_num_to_string(const int num); + +typedef lua_State* (*luv_acquire_vm)(); +typedef void (*luv_release_vm)(lua_State* L); +LUALIB_API void luv_set_thread_cb(luv_acquire_vm acquire, luv_release_vm release); + +#endif diff --git a/3rdparty/luv/src/misc.c b/3rdparty/luv/src/misc.c new file mode 100644 index 00000000000..64c9e3d5822 --- /dev/null +++ b/3rdparty/luv/src/misc.c @@ -0,0 +1,316 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "luv.h" +#ifdef _WIN32 +#include +#endif + +static int luv_guess_handle(lua_State* L) { + uv_file file = luaL_checkinteger(L, 1); + switch (uv_guess_handle(file)) { +#define XX(uc, lc) case UV_##uc: lua_pushstring(L, #lc); break; + UV_HANDLE_TYPE_MAP(XX) +#undef XX + case UV_FILE: lua_pushstring(L, "file"); break; + default: return 0; + } + return 1; +} + +static int luv_version(lua_State* L) { + lua_pushinteger(L, uv_version()); + return 1; +} + +static int luv_version_string(lua_State* L) { + lua_pushstring(L, uv_version_string()); + return 1; +} + +static int luv_get_process_title(lua_State* L) { + char title[MAX_TITLE_LENGTH]; + int ret = uv_get_process_title(title, MAX_TITLE_LENGTH); + if (ret < 0) return luv_error(L, ret); + lua_pushstring(L, title); + return 1; +} + +static int luv_set_process_title(lua_State* L) { + const char* title = luaL_checkstring(L, 1); + int ret = uv_set_process_title(title); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_resident_set_memory(lua_State* L) { + size_t rss; + int ret = uv_resident_set_memory(&rss); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, rss); + return 1; +} + +static int luv_uptime(lua_State* L) { + double uptime; + int ret = uv_uptime(&uptime); + if (ret < 0) return luv_error(L, ret); + lua_pushnumber(L, uptime); + return 1; +} + +static void luv_push_timeval_table(lua_State* L, const uv_timeval_t* t) { + lua_createtable(L, 0, 2); + lua_pushinteger(L, t->tv_sec); + lua_setfield(L, -2, "sec"); + lua_pushinteger(L, t->tv_usec); + lua_setfield(L, -2, "usec"); +} + +static int luv_getrusage(lua_State* L) { + uv_rusage_t rusage; + int ret = uv_getrusage(&rusage); + if (ret < 0) return luv_error(L, ret); + lua_createtable(L, 0, 16); + // user CPU time used + luv_push_timeval_table(L, &rusage.ru_utime); + lua_setfield(L, -2, "utime"); + // system CPU time used + luv_push_timeval_table(L, &rusage.ru_stime); + lua_setfield(L, -2, "stime"); + // maximum resident set size + lua_pushinteger(L, rusage.ru_maxrss); + lua_setfield(L, -2, "maxrss"); + // integral shared memory size + lua_pushinteger(L, rusage.ru_ixrss); + lua_setfield(L, -2, "ixrss"); + // integral unshared data size + lua_pushinteger(L, rusage.ru_idrss); + lua_setfield(L, -2, "idrss"); + // integral unshared stack size + lua_pushinteger(L, rusage.ru_isrss); + lua_setfield(L, -2, "isrss"); + // page reclaims (soft page faults) + lua_pushinteger(L, rusage.ru_minflt); + lua_setfield(L, -2, "minflt"); + // page faults (hard page faults) + lua_pushinteger(L, rusage.ru_majflt); + lua_setfield(L, -2, "majflt"); + // swaps + lua_pushinteger(L, rusage.ru_nswap); + lua_setfield(L, -2, "nswap"); + // block input operations + lua_pushinteger(L, rusage.ru_inblock); + lua_setfield(L, -2, "inblock"); + // block output operations + lua_pushinteger(L, rusage.ru_oublock); + lua_setfield(L, -2, "oublock"); + // IPC messages sent + lua_pushinteger(L, rusage.ru_msgsnd); + lua_setfield(L, -2, "msgsnd"); + // IPC messages received + lua_pushinteger(L, rusage.ru_msgrcv); + lua_setfield(L, -2, "msgrcv"); + // signals received + lua_pushinteger(L, rusage.ru_nsignals); + lua_setfield(L, -2, "nsignals"); + // voluntary context switches + lua_pushinteger(L, rusage.ru_nvcsw); + lua_setfield(L, -2, "nvcsw"); + // involuntary context switches + lua_pushinteger(L, rusage.ru_nivcsw); + lua_setfield(L, -2, "nivcsw"); + return 1; +} + +static int luv_cpu_info(lua_State* L) { + uv_cpu_info_t* cpu_infos; + int count, i; + int ret = uv_cpu_info(&cpu_infos, &count); + if (ret < 0) return luv_error(L, ret); + lua_newtable(L); + + for (i = 0; i < count; i++) { + lua_newtable(L); + lua_pushstring(L, cpu_infos[i].model); + lua_setfield(L, -2, "model"); + lua_pushnumber(L, cpu_infos[i].speed); + lua_setfield(L, -2, "speed"); + lua_newtable(L); + lua_pushnumber(L, cpu_infos[i].cpu_times.user); + lua_setfield(L, -2, "user"); + lua_pushnumber(L, cpu_infos[i].cpu_times.nice); + lua_setfield(L, -2, "nice"); + lua_pushnumber(L, cpu_infos[i].cpu_times.sys); + lua_setfield(L, -2, "sys"); + lua_pushnumber(L, cpu_infos[i].cpu_times.idle); + lua_setfield(L, -2, "idle"); + lua_pushnumber(L, cpu_infos[i].cpu_times.irq); + lua_setfield(L, -2, "irq"); + lua_setfield(L, -2, "times"); + lua_rawseti(L, -2, i + 1); + } + + uv_free_cpu_info(cpu_infos, count); + return 1; +} + +static int luv_interface_addresses(lua_State* L) { + uv_interface_address_t* interfaces; + int count, i; + char ip[INET6_ADDRSTRLEN]; + char netmask[INET6_ADDRSTRLEN]; + + uv_interface_addresses(&interfaces, &count); + + lua_newtable(L); + + for (i = 0; i < count; i++) { + lua_getfield(L, -1, interfaces[i].name); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + lua_newtable(L); + lua_pushvalue(L, -1); + lua_setfield(L, -3, interfaces[i].name); + } + lua_newtable(L); + lua_pushboolean(L, interfaces[i].is_internal); + lua_setfield(L, -2, "internal"); + + lua_pushlstring(L, interfaces[i].phys_addr, sizeof(interfaces[i].phys_addr)); + lua_setfield(L, -2, "mac"); + + if (interfaces[i].address.address4.sin_family == AF_INET) { + uv_ip4_name(&interfaces[i].address.address4, ip, sizeof(ip)); + uv_ip4_name(&interfaces[i].netmask.netmask4, netmask, sizeof(netmask)); + } else if (interfaces[i].address.address4.sin_family == AF_INET6) { + uv_ip6_name(&interfaces[i].address.address6, ip, sizeof(ip)); + uv_ip6_name(&interfaces[i].netmask.netmask6, netmask, sizeof(netmask)); + } else { + strncpy(ip, "", INET6_ADDRSTRLEN); + strncpy(netmask, "", INET6_ADDRSTRLEN); + } + lua_pushstring(L, ip); + lua_setfield(L, -2, "ip"); + lua_pushstring(L, netmask); + lua_setfield(L, -2, "netmask"); + + lua_pushstring(L, luv_af_num_to_string(interfaces[i].address.address4.sin_family)); + lua_setfield(L, -2, "family"); + lua_rawseti(L, -2, lua_rawlen (L, -2) + 1); + lua_pop(L, 1); + } + uv_free_interface_addresses(interfaces, count); + return 1; +} + +static int luv_loadavg(lua_State* L) { + double avg[3]; + uv_loadavg(avg); + lua_pushnumber(L, avg[0]); + lua_pushnumber(L, avg[1]); + lua_pushnumber(L, avg[2]); + return 3; +} + +static int luv_exepath(lua_State* L) { + size_t size = 2*PATH_MAX; + char exe_path[2*PATH_MAX]; + int ret = uv_exepath(exe_path, &size); + if (ret < 0) return luv_error(L, ret); + lua_pushlstring(L, exe_path, size); + return 1; +} + +static int luv_cwd(lua_State* L) { + size_t size = 2*PATH_MAX; + char path[2*PATH_MAX]; + int ret = uv_cwd(path, &size); + if (ret < 0) return luv_error(L, ret); + lua_pushlstring(L, path, size); + return 1; +} + +static int luv_chdir(lua_State* L) { + int ret = uv_chdir(luaL_checkstring(L, 1)); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_os_homedir(lua_State* L) { + size_t size = 2*PATH_MAX; + char homedir[2*PATH_MAX]; + int ret = uv_os_homedir(homedir, &size); + if (ret < 0) return luv_error(L, ret); + lua_pushlstring(L, homedir, size); + return 1; +} + +static int luv_get_total_memory(lua_State* L) { + lua_pushnumber(L, uv_get_total_memory()); + return 1; +} + +static int luv_get_free_memory(lua_State* L) { + lua_pushnumber(L, uv_get_free_memory()); + return 1; +} + +static int luv_hrtime(lua_State* L) { + lua_pushnumber(L, uv_hrtime()); + return 1; +} + +static int luv_getpid(lua_State* L){ + int pid = getpid(); + lua_pushinteger(L, pid); + return 1; +} + +#ifndef _WIN32 +static int luv_getuid(lua_State* L){ + int uid = getuid(); + lua_pushinteger(L, uid); + return 1; +} + +static int luv_getgid(lua_State* L){ + int gid = getgid(); + lua_pushinteger(L, gid); + return 1; +} + +static int luv_setuid(lua_State* L){ + int uid = luaL_checkinteger(L, 1); + int r = setuid(uid); + if (-1 == r) { + luaL_error(L, "Error setting UID"); + } + return 0; +} + +static int luv_setgid(lua_State* L){ + int gid = luaL_checkinteger(L, 1); + int r = setgid(gid); + if (-1 == r) { + luaL_error(L, "Error setting GID"); + } + return 0; +} +#endif diff --git a/3rdparty/luv/src/pipe.c b/3rdparty/luv/src/pipe.c new file mode 100644 index 00000000000..b490c1597b3 --- /dev/null +++ b/3rdparty/luv/src/pipe.c @@ -0,0 +1,114 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_pipe_t* luv_check_pipe(lua_State* L, int index) { + uv_pipe_t* handle = luv_checkudata(L, index, "uv_pipe"); + luaL_argcheck(L, handle->type == UV_NAMED_PIPE && handle->data, index, "Expected uv_pipe_t"); + return handle; +} + +static int luv_new_pipe(lua_State* L) { + uv_pipe_t* handle; + int ipc, ret; + luaL_checktype(L, 1, LUA_TBOOLEAN); + ipc = lua_toboolean(L, 1); + handle = luv_newuserdata(L, sizeof(*handle)); + ret = uv_pipe_init(luv_loop(L), handle, ipc); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static int luv_pipe_open(lua_State* L) { + uv_pipe_t* handle = luv_check_pipe(L, 1); + uv_file file = luaL_checkinteger(L, 2); + int ret = uv_pipe_open(handle, file); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_pipe_bind(lua_State* L) { + uv_pipe_t* handle = luv_check_pipe(L, 1); + const char* name = luaL_checkstring(L, 2); + int ret = uv_pipe_bind(handle, name); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_pipe_connect(lua_State* L) { + uv_pipe_t* handle = luv_check_pipe(L, 1); + const char* name = luaL_checkstring(L, 2); + int ref = luv_check_continuation(L, 3); + uv_connect_t* req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + uv_pipe_connect(req, handle, name, luv_connect_cb); + return 1; +} + +static int luv_pipe_getsockname(lua_State* L) { + uv_pipe_t* handle = luv_check_pipe(L, 1); + size_t len = 2*PATH_MAX; + char buf[2*PATH_MAX]; + int ret = uv_pipe_getsockname(handle, buf, &len); + if (ret < 0) return luv_error(L, ret); + lua_pushlstring(L, buf, len); + return 1; +} + +static int luv_pipe_getpeername(lua_State* L) { + uv_pipe_t* handle = luv_check_pipe(L, 1); + size_t len = 2*PATH_MAX; + char buf[2*PATH_MAX]; + int ret = uv_pipe_getpeername(handle, buf, &len); + if (ret < 0) return luv_error(L, ret); + lua_pushlstring(L, buf, len); + return 1; +} + +static int luv_pipe_pending_instances(lua_State* L) { + uv_pipe_t* handle = luv_check_pipe(L, 1); + int count = luaL_checkinteger(L, 2); + uv_pipe_pending_instances(handle, count); + return 0; +} + +static int luv_pipe_pending_count(lua_State* L) { + uv_pipe_t* handle = luv_check_pipe(L, 1); + lua_pushinteger(L, uv_pipe_pending_count(handle)); + return 1; +} + +static int luv_pipe_pending_type(lua_State* L) { + uv_pipe_t* handle = luv_check_pipe(L, 1); + uv_handle_type type = uv_pipe_pending_type(handle); + const char* type_name; + switch (type) { +#define XX(uc, lc) \ + case UV_##uc: type_name = #lc; break; + UV_HANDLE_TYPE_MAP(XX) +#undef XX + default: return 0; + } + lua_pushstring(L, type_name); + return 1; +} diff --git a/3rdparty/luv/src/poll.c b/3rdparty/luv/src/poll.c new file mode 100644 index 00000000000..e007c9f9634 --- /dev/null +++ b/3rdparty/luv/src/poll.c @@ -0,0 +1,100 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_poll_t* luv_check_poll(lua_State* L, int index) { + uv_poll_t* handle = luv_checkudata(L, index, "uv_poll"); + luaL_argcheck(L, handle->type == UV_POLL && handle->data, index, "Expected uv_poll_t"); + return handle; +} + +static int luv_new_poll(lua_State* L) { + int fd = luaL_checkinteger(L, 1); + uv_poll_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_poll_init(luv_loop(L), handle, fd); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static int luv_new_socket_poll(lua_State* L) { + int fd = luaL_checkinteger(L, 1); + uv_poll_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_poll_init_socket(luv_loop(L), handle, fd); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +// These are the same order as uv_run_mode which also starts at 0 +static const char *const luv_pollevents[] = { + "r", "w", "rw", NULL +}; + +static void luv_poll_cb(uv_poll_t* handle, int status, int events) { + lua_State* L = luv_state(handle->loop); + luv_handle_t* data = handle->data; + const char* evtstr; + + if (status < 0) { + fprintf(stderr, "%s: %s\n", uv_err_name(status), uv_strerror(status)); + lua_pushstring(L, uv_err_name(status)); + } + else { + lua_pushnil(L); + } + + switch (events) { + case UV_READABLE: evtstr = "r"; break; + case UV_WRITABLE: evtstr = "w"; break; + case UV_READABLE|UV_WRITABLE: evtstr = "rw"; break; + default: evtstr = ""; break; + } + lua_pushstring(L, evtstr); + + luv_call_callback(L, data, LUV_POLL, 2); +} + +static int luv_poll_start(lua_State* L) { + uv_poll_t* handle = luv_check_poll(L, 1); + int events, ret; + switch (luaL_checkoption(L, 2, "rw", luv_pollevents)) { + case 0: events = UV_READABLE; break; + case 1: events = UV_WRITABLE; break; + case 2: events = UV_READABLE | UV_WRITABLE; break; + default: events = 0; /* unreachable */ + } + luv_check_callback(L, handle->data, LUV_POLL, 3); + ret = uv_poll_start(handle, events, luv_poll_cb); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_poll_stop(lua_State* L) { + uv_poll_t* handle = luv_check_poll(L, 1); + int ret = uv_poll_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} diff --git a/3rdparty/luv/src/prepare.c b/3rdparty/luv/src/prepare.c new file mode 100644 index 00000000000..6577439a466 --- /dev/null +++ b/3rdparty/luv/src/prepare.c @@ -0,0 +1,59 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_prepare_t* luv_check_prepare(lua_State* L, int index) { + uv_prepare_t* handle = luv_checkudata(L, index, "uv_prepare"); + luaL_argcheck(L, handle->type == UV_PREPARE && handle->data, index, "Expected uv_prepare_t"); + return handle; +} + +static int luv_new_prepare(lua_State* L) { + uv_prepare_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_prepare_init(luv_loop(L), handle); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static void luv_prepare_cb(uv_prepare_t* handle) { + lua_State* L = luv_state(handle->loop); + luv_handle_t* data = handle->data; + luv_call_callback(L, data, LUV_PREPARE, 0); +} + +static int luv_prepare_start(lua_State* L) { + uv_prepare_t* handle = luv_check_prepare(L, 1); + int ret; + luv_check_callback(L, handle->data, LUV_PREPARE, 2); + ret = uv_prepare_start(handle, luv_prepare_cb); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_prepare_stop(lua_State* L) { + uv_prepare_t* handle = luv_check_prepare(L, 1); + int ret = uv_prepare_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + diff --git a/3rdparty/luv/src/process.c b/3rdparty/luv/src/process.c new file mode 100644 index 00000000000..d939503868b --- /dev/null +++ b/3rdparty/luv/src/process.c @@ -0,0 +1,266 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static int luv_disable_stdio_inheritance(lua_State* L) { + (void)L; + uv_disable_stdio_inheritance(); + return 0; +} + +static uv_process_t* luv_check_process(lua_State* L, int index) { + uv_process_t* handle = luv_checkudata(L, index, "uv_process"); + luaL_argcheck(L, handle->type == UV_PROCESS && handle->data, index, "Expected uv_process_t"); + return handle; +} + +static void exit_cb(uv_process_t* handle, int64_t exit_status, int term_signal) { + lua_State* L = luv_state(handle->loop); + luv_handle_t* data = handle->data; + lua_pushinteger(L, exit_status); + lua_pushinteger(L, term_signal); + luv_call_callback(L, data, LUV_EXIT, 2); +} + +static void luv_spawn_close_cb(uv_handle_t* handle) { + lua_State *L = luv_state(handle->loop); + luv_cleanup_handle(L, handle->data); +} + +static void luv_clean_options(uv_process_options_t* options) { + free(options->args); + free(options->stdio); + free(options->env); +} + +static int luv_spawn(lua_State* L) { + uv_process_t* handle; + uv_process_options_t options; + size_t i, len = 0; + int ret; + + memset(&options, 0, sizeof(options)); + options.exit_cb = exit_cb; + options.file = luaL_checkstring(L, 1); + options.flags = 0; + + // Make sure the 2nd argument is a table + luaL_checktype(L, 2, LUA_TTABLE); + + // get the args list + lua_getfield(L, 2, "args"); + // +1 for inserted command at front + if (lua_type(L, -1) == LUA_TTABLE) { + len = 1 + lua_rawlen(L, -1); + } + else if (lua_type(L, -1) != LUA_TNIL) { + luv_clean_options(&options); + return luaL_argerror(L, 3, "args option must be table"); + } + else { + len = 1; + } + // +1 for null terminator at end + options.args = malloc((len + 1) * sizeof(*options.args)); + if (!options.args) { + luv_clean_options(&options); + return luaL_error(L, "Problem allocating args"); + } + options.args[0] = (char*)options.file; + for (i = 1; i < len; ++i) { + lua_rawgeti(L, -1, i); + options.args[i] = (char*)lua_tostring(L, -1); + lua_pop(L, 1); + } + options.args[len] = NULL; + lua_pop(L, 1); + + // get the stdio list + lua_getfield(L, 2, "stdio"); + if (lua_type(L, -1) == LUA_TTABLE) { + options.stdio_count = len = lua_rawlen(L, -1); + options.stdio = malloc(len * sizeof(*options.stdio)); + if (!options.stdio) { + luv_clean_options(&options); + return luaL_error(L, "Problem allocating stdio"); + } + for (i = 0; i < len; ++i) { + lua_rawgeti(L, -1, i + 1); + // integers are assumed to be file descripters + if (lua_type(L, -1) == LUA_TNUMBER) { + options.stdio[i].flags = UV_INHERIT_FD; + options.stdio[i].data.fd = lua_tointeger(L, -1); + } + // userdata is assumed to be a uv_stream_t instance + else if (lua_type(L, -1) == LUA_TUSERDATA) { + uv_os_fd_t fd; + uv_stream_t* stream = luv_check_stream(L, -1); + int err = uv_fileno((uv_handle_t*)stream, &fd); + if (err == UV_EINVAL || err == UV_EBADF) { + // stdin (fd 0) is read-only, stdout and stderr (fds 1 & 2) are + // write-only, and all fds > 2 are read-write + int flags = UV_CREATE_PIPE; + if (i == 0 || i > 2) + flags |= UV_READABLE_PIPE; + if (i != 0) + flags |= UV_WRITABLE_PIPE; + options.stdio[i].flags = flags; + } + else { + options.stdio[i].flags = UV_INHERIT_STREAM; + } + options.stdio[i].data.stream = stream; + } + else if (lua_type(L, -1) == LUA_TNIL) { + options.stdio[i].flags = UV_IGNORE; + } + else { + luv_clean_options(&options); + return luaL_argerror(L, 2, "stdio table entries must be nil, uv_stream_t, or integer"); + } + lua_pop(L, 1); + } + } + else if (lua_type(L, -1) != LUA_TNIL) { + luv_clean_options(&options); + return luaL_argerror(L, 2, "stdio option must be table"); + } + lua_pop(L, 1); + + // Get the env + lua_getfield(L, 2, "env"); + if (lua_type(L, -1) == LUA_TTABLE) { + len = lua_rawlen(L, -1); + options.env = malloc((len + 1) * sizeof(*options.env)); + if (!options.env) { + luv_clean_options(&options); + return luaL_error(L, "Problem allocating env"); + } + for (i = 0; i < len; ++i) { + lua_rawgeti(L, -1, i + 1); + options.env[i] = (char*)lua_tostring(L, -1); + lua_pop(L, 1); + } + options.env[len] = NULL; + } + else if (lua_type(L, -1) != LUA_TNIL) { + luv_clean_options(&options); + return luaL_argerror(L, 2, "env option must be table"); + } + lua_pop(L, 1); + + // Get the cwd + lua_getfield(L, 2, "cwd"); + if (lua_type(L, -1) == LUA_TSTRING) { + options.cwd = (char*)lua_tostring(L, -1); + } + else if (lua_type(L, -1) != LUA_TNIL) { + luv_clean_options(&options); + return luaL_argerror(L, 2, "cwd option must be string"); + } + lua_pop(L, 1); + + // Check for uid + lua_getfield(L, 2, "uid"); + if (lua_type(L, -1) == LUA_TNUMBER) { + options.uid = lua_tointeger(L, -1); + options.flags |= UV_PROCESS_SETUID; + } + else if (lua_type(L, -1) != LUA_TNIL) { + luv_clean_options(&options); + return luaL_argerror(L, 2, "uid option must be number"); + } + lua_pop(L, 1); + + // Check for gid + lua_getfield(L, 2, "gid"); + if (lua_type(L, -1) == LUA_TNUMBER) { + options.gid = lua_tointeger(L, -1); + options.flags |= UV_PROCESS_SETGID; + } + else if (lua_type(L, -1) != LUA_TNIL) { + luv_clean_options(&options); + return luaL_argerror(L, 2, "gid option must be number"); + } + lua_pop(L, 1); + + // Check for the boolean flags + lua_getfield(L, 2, "verbatim"); + if (lua_toboolean(L, -1)) { + options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS; + } + lua_pop(L, 1); + lua_getfield(L, 2, "detached"); + if (lua_toboolean(L, -1)) { + options.flags |= UV_PROCESS_DETACHED; + } + lua_pop(L, 1); + lua_getfield(L, 2, "hide"); + if (lua_toboolean(L, -1)) { + options.flags |= UV_PROCESS_WINDOWS_HIDE; + } + lua_pop(L, 1); + + handle = luv_newuserdata(L, sizeof(*handle)); + handle->type = UV_PROCESS; + handle->data = luv_setup_handle(L); + + if (!lua_isnoneornil(L, 3)) { + luv_check_callback(L, handle->data, LUV_EXIT, 3); + } + + ret = uv_spawn(luv_loop(L), handle, &options); + + luv_clean_options(&options); + if (ret < 0) { + /* The async callback is required here because luajit GC may reclaim the + * luv handle before libuv is done closing it down. + */ + uv_close((uv_handle_t*)handle, luv_spawn_close_cb); + return luv_error(L, ret); + } + lua_pushinteger(L, handle->pid); + return 2; +} + +static int luv_parse_signal(lua_State* L, int slot) { + if (lua_isnumber(L, slot)) { + return lua_tonumber(L, slot); + } + if (lua_isstring(L, slot)) { + return luv_sig_string_to_num(lua_tostring(L, slot)); + } + return SIGTERM; +} + +static int luv_process_kill(lua_State* L) { + uv_process_t* handle = luv_check_process(L, 1); + int signum = luv_parse_signal(L, 2); + int ret = uv_process_kill(handle, signum); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_kill(lua_State* L) { + int pid = luaL_checkinteger(L, 1); + int signum = luv_parse_signal(L, 2); + int ret = uv_kill(pid, signum); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} diff --git a/3rdparty/luv/src/req.c b/3rdparty/luv/src/req.c new file mode 100644 index 00000000000..6d7b7e4a30b --- /dev/null +++ b/3rdparty/luv/src/req.c @@ -0,0 +1,52 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_req_t* luv_check_req(lua_State* L, int index) { + uv_req_t* req = luaL_checkudata(L, index, "uv_req"); + luaL_argcheck(L, req->data, index, "Expected uv_req_t"); + return req; +} + +static int luv_req_tostring(lua_State* L) { + uv_req_t* req = luaL_checkudata(L, 1, "uv_req"); + switch (req->type) { +#define XX(uc, lc) case UV_##uc: lua_pushfstring(L, "uv_"#lc"_t: %p", req); break; + UV_REQ_TYPE_MAP(XX) +#undef XX + default: lua_pushfstring(L, "uv_req_t: %p", req); break; + } + return 1; +} + +static void luv_req_init(lua_State* L) { + luaL_newmetatable (L, "uv_req"); + lua_pushcfunction(L, luv_req_tostring); + lua_setfield(L, -2, "__tostring"); + lua_pop(L, 1); +} + +// Metamethod to allow storing anything in the userdata's environment +static int luv_cancel(lua_State* L) { + uv_req_t* req = luv_check_req(L, 1); + int ret = uv_cancel(req); + if (ret < 0) return luv_error(L, ret); + luv_cleanup_req(L, req->data); + req->data = NULL; + lua_pushinteger(L, ret); + return 1; +} diff --git a/3rdparty/luv/src/schema.c b/3rdparty/luv/src/schema.c new file mode 100644 index 00000000000..e7b82e11d66 --- /dev/null +++ b/3rdparty/luv/src/schema.c @@ -0,0 +1,16 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ diff --git a/3rdparty/luv/src/signal.c b/3rdparty/luv/src/signal.c new file mode 100644 index 00000000000..48ace2bf601 --- /dev/null +++ b/3rdparty/luv/src/signal.c @@ -0,0 +1,72 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_signal_t* luv_check_signal(lua_State* L, int index) { + uv_signal_t* handle = luv_checkudata(L, index, "uv_signal"); + luaL_argcheck(L, handle->type == UV_SIGNAL && handle->data, index, "Expected uv_signal_t"); + return handle; +} + +static int luv_new_signal(lua_State* L) { + uv_signal_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_signal_init(luv_loop(L), handle); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static void luv_signal_cb(uv_signal_t* handle, int signum) { + lua_State* L = luv_state(handle->loop); + luv_handle_t* data = handle->data; + lua_pushstring(L, luv_sig_num_to_string(signum)); + luv_call_callback(L, data, LUV_SIGNAL, 1); +} + +static int luv_signal_start(lua_State* L) { + uv_signal_t* handle = luv_check_signal(L, 1); + int signum, ret; + if (lua_isnumber(L, 2)) { + signum = lua_tointeger(L, 2); + } + else if (lua_isstring(L, 2)) { + signum = luv_sig_string_to_num(luaL_checkstring(L, 2)); + luaL_argcheck(L, signum, 2, "Invalid Signal name"); + } + else { + return luaL_argerror(L, 2, "Missing Signal name"); + } + + if (!lua_isnoneornil(L, 3)) { + luv_check_callback(L, handle->data, LUV_SIGNAL, 3); + } + ret = uv_signal_start(handle, luv_signal_cb, signum); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_signal_stop(lua_State* L) { + uv_signal_t* handle = luv_check_signal(L, 1); + int ret = uv_signal_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} diff --git a/3rdparty/luv/src/stream.c b/3rdparty/luv/src/stream.c new file mode 100644 index 00000000000..5009e04f097 --- /dev/null +++ b/3rdparty/luv/src/stream.c @@ -0,0 +1,263 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static void luv_check_buf(lua_State *L, int idx, uv_buf_t *pbuf) { + size_t len; + pbuf->base = (char*)luaL_checklstring(L, idx, &len); + pbuf->len = len; +} + +static uv_stream_t* luv_check_stream(lua_State* L, int index) { + int isStream; + uv_stream_t* handle; + if (!(handle = *(void**) lua_touserdata(L, index))) { goto fail; } + lua_getfield(L, LUA_REGISTRYINDEX, "uv_stream"); + lua_getmetatable(L, index < 0 ? index - 1 : index); + lua_rawget(L, -2); + isStream = lua_toboolean(L, -1); + lua_pop(L, 2); + if (isStream) { return handle; } + fail: luaL_argerror(L, index, "Expected uv_stream userdata"); + return NULL; +} + +static void luv_shutdown_cb(uv_shutdown_t* req, int status) { + lua_State* L = luv_state(req->handle->loop); + luv_status(L, status); + luv_fulfill_req(L, req->data, 1); + luv_cleanup_req(L, req->data); + req->data = NULL; +} + +static int luv_shutdown(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + int ref = luv_check_continuation(L, 2); + uv_shutdown_t* req = lua_newuserdata(L, sizeof(*req)); + int ret; + req->data = luv_setup_req(L, ref); + ret = uv_shutdown(req, handle, luv_shutdown_cb); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + return 1; +} + +static void luv_connection_cb(uv_stream_t* handle, int status) { + lua_State* L = luv_state(handle->loop); + luv_status(L, status); + luv_call_callback(L, handle->data, LUV_CONNECTION, 1); +} + +static int luv_listen(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + int backlog = luaL_checkinteger(L, 2); + int ret; + luv_check_callback(L, handle->data, LUV_CONNECTION, 3); + ret = uv_listen(handle, backlog, luv_connection_cb); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_accept(lua_State* L) { + uv_stream_t* server = luv_check_stream(L, 1); + uv_stream_t* client = luv_check_stream(L, 2); + int ret = uv_accept(server, client); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static void luv_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { + (void)handle; + buf->base = malloc(suggested_size); + assert(buf->base); + buf->len = suggested_size; +} + +static void luv_read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { + lua_State* L = luv_state(handle->loop); + int nargs; + + if (nread > 0) { + lua_pushnil(L); + lua_pushlstring(L, buf->base, nread); + nargs = 2; + } + + free(buf->base); + if (nread == 0) return; + + if (nread == UV_EOF) { + nargs = 0; + } + else if (nread < 0) { + luv_status(L, nread); + nargs = 1; + } + + luv_call_callback(L, handle->data, LUV_READ, nargs); +} + +static int luv_read_start(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + int ret; + luv_check_callback(L, handle->data, LUV_READ, 2); + ret = uv_read_start(handle, luv_alloc_cb, luv_read_cb); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_read_stop(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + int ret = uv_read_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static void luv_write_cb(uv_write_t* req, int status) { + lua_State* L = luv_state(req->handle->loop); + luv_status(L, status); + luv_fulfill_req(L, req->data, 1); + luv_cleanup_req(L, req->data); + req->data = NULL; +} + +static uv_buf_t* luv_prep_bufs(lua_State* L, int index, size_t *count) { + uv_buf_t *bufs; + size_t i; + *count = lua_rawlen(L, index); + bufs = malloc(sizeof(uv_buf_t) * *count); + for (i = 0; i < *count; ++i) { + lua_rawgeti(L, index, i + 1); + luv_check_buf(L, -1, &bufs[i]); + lua_pop(L, 1); + } + return bufs; +} + +static int luv_write(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + uv_write_t* req; + int ret, ref; + ref = luv_check_continuation(L, 3); + req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + if (lua_istable(L, 2)) { + size_t count; + uv_buf_t *bufs = luv_prep_bufs(L, 2, &count); + ret = uv_write(req, handle, bufs, count, luv_write_cb); + free(bufs); + } + else if (lua_isstring(L, 2)) { + uv_buf_t buf; + luv_check_buf(L, 2, &buf); + ret = uv_write(req, handle, &buf, 1, luv_write_cb); + } + else { + return luaL_argerror(L, 2, "data must be string or table of strings"); + } + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + lua_pushvalue(L, 2); + ((luv_req_t*)req->data)->data_ref = luaL_ref(L, LUA_REGISTRYINDEX); + return 1; +} + +static int luv_write2(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + uv_write_t* req; + int ret, ref; + uv_stream_t* send_handle; + send_handle = luv_check_stream(L, 3); + ref = luv_check_continuation(L, 4); + req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + if (lua_istable(L, 2)) { + size_t count; + uv_buf_t *bufs = luv_prep_bufs(L, 2, &count); + ret = uv_write2(req, handle, bufs, count, send_handle, luv_write_cb); + free(bufs); + } + else if (lua_isstring(L, 2)) { + uv_buf_t buf; + luv_check_buf(L, 2, &buf); + ret = uv_write2(req, handle, &buf, 1, send_handle, luv_write_cb); + } + else { + return luaL_argerror(L, 2, "data must be string or table of strings"); + } + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + lua_pushvalue(L, 2); + ((luv_req_t*)req->data)->data_ref = luaL_ref(L, LUA_REGISTRYINDEX); + return 1; +} + +static int luv_try_write(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + int ret; + if (lua_istable(L, 2)) { + size_t count; + uv_buf_t *bufs = luv_prep_bufs(L, 2, &count); + ret = uv_try_write(handle, bufs, count); + free(bufs); + } + else if (lua_isstring(L, 2)) { + uv_buf_t buf; + luv_check_buf(L, 2, &buf); + ret = uv_try_write(handle, &buf, 1); + } + else { + return luaL_argerror(L, 2, "data must be string or table of strings"); + } + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_is_readable(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + lua_pushboolean(L, uv_is_readable(handle)); + return 1; +} + +static int luv_is_writable(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + lua_pushboolean(L, uv_is_writable(handle)); + return 1; +} + +static int luv_stream_set_blocking(lua_State* L) { + uv_stream_t* handle = luv_check_stream(L, 1); + int blocking, ret; + luaL_checktype(L, 2, LUA_TBOOLEAN); + blocking = lua_toboolean(L, 2); + ret = uv_stream_set_blocking(handle, blocking); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + diff --git a/3rdparty/luv/src/tcp.c b/3rdparty/luv/src/tcp.c new file mode 100644 index 00000000000..7ffef5ae763 --- /dev/null +++ b/3rdparty/luv/src/tcp.c @@ -0,0 +1,182 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_tcp_t* luv_check_tcp(lua_State* L, int index) { + uv_tcp_t* handle = luv_checkudata(L, index, "uv_tcp"); + luaL_argcheck(L, handle->type == UV_TCP && handle->data, index, "Expected uv_tcp_t"); + return handle; +} + +static int luv_new_tcp(lua_State* L) { + uv_tcp_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_tcp_init(luv_loop(L), handle); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static int luv_tcp_open(lua_State* L) { + uv_tcp_t* handle = luv_check_tcp(L, 1); + uv_os_sock_t sock = luaL_checkinteger(L, 2); + int ret = uv_tcp_open(handle, sock); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_tcp_nodelay(lua_State* L) { + uv_tcp_t* handle = luv_check_tcp(L, 1); + int ret, enable; + luaL_checktype(L, 2, LUA_TBOOLEAN); + enable = lua_toboolean(L, 2); + ret = uv_tcp_nodelay(handle, enable); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_tcp_keepalive(lua_State* L) { + uv_tcp_t* handle = luv_check_tcp(L, 1); + int ret, enable; + unsigned int delay = 0; + luaL_checktype(L, 2, LUA_TBOOLEAN); + enable = lua_toboolean(L, 2); + if (enable) { + delay = luaL_checkinteger(L, 3); + } + ret = uv_tcp_keepalive(handle, enable, delay); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_tcp_simultaneous_accepts(lua_State* L) { + uv_tcp_t* handle = luv_check_tcp(L, 1); + int ret, enable; + luaL_checktype(L, 2, LUA_TBOOLEAN); + enable = lua_toboolean(L, 2); + ret = uv_tcp_simultaneous_accepts(handle, enable); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_tcp_bind(lua_State* L) { + uv_tcp_t* handle = luv_check_tcp(L, 1); + const char* host = luaL_checkstring(L, 2); + int port = luaL_checkinteger(L, 3); + unsigned int flags = 0; + struct sockaddr_storage addr; + int ret; + if (uv_ip4_addr(host, port, (struct sockaddr_in*)&addr) && + uv_ip6_addr(host, port, (struct sockaddr_in6*)&addr)) { + return luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); + } + if (lua_type(L, 4) == LUA_TTABLE) { + lua_getfield(L, 4, "ipv6only"); + if (lua_toboolean(L, -1)) flags |= UV_TCP_IPV6ONLY; + lua_pop(L, 1); + } + ret = uv_tcp_bind(handle, (struct sockaddr*)&addr, flags); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static void parse_sockaddr(lua_State* L, struct sockaddr_storage* address, int addrlen) { + char ip[INET6_ADDRSTRLEN]; + int port = 0; + lua_newtable(L); + if (address->ss_family == AF_INET) { + struct sockaddr_in* addrin = (struct sockaddr_in*)address; + uv_inet_ntop(AF_INET, &(addrin->sin_addr), ip, addrlen); + port = ntohs(addrin->sin_port); + } else if (address->ss_family == AF_INET6) { + struct sockaddr_in6* addrin6 = (struct sockaddr_in6*)address; + uv_inet_ntop(AF_INET6, &(addrin6->sin6_addr), ip, addrlen); + port = ntohs(addrin6->sin6_port); + } + + lua_pushstring(L, luv_af_num_to_string(address->ss_family)); + lua_setfield(L, -2, "family"); + lua_pushinteger(L, port); + lua_setfield(L, -2, "port"); + lua_pushstring(L, ip); + lua_setfield(L, -2, "ip"); +} + +static int luv_tcp_getsockname(lua_State* L) { + uv_tcp_t* handle = luv_check_tcp(L, 1); + struct sockaddr_storage address; + int addrlen = sizeof(address); + int ret = uv_tcp_getsockname(handle, (struct sockaddr*)&address, &addrlen); + if (ret < 0) return luv_error(L, ret); + parse_sockaddr(L, &address, addrlen); + return 1; +} + +static int luv_tcp_getpeername(lua_State* L) { + uv_tcp_t* handle = luv_check_tcp(L, 1); + struct sockaddr_storage address; + int addrlen = sizeof(address); + int ret = uv_tcp_getpeername(handle, (struct sockaddr*)&address, &addrlen); + if (ret < 0) return luv_error(L, ret); + parse_sockaddr(L, &address, addrlen); + return 1; +} + + +static void luv_connect_cb(uv_connect_t* req, int status) { + lua_State* L = luv_state(req->handle->loop); + luv_status(L, status); + luv_fulfill_req(L, req->data, 1); + luv_cleanup_req(L, req->data); + req->data = NULL; +} + +static int luv_write_queue_size(lua_State* L) { + uv_tcp_t* handle = luv_check_tcp(L, 1); + lua_pushinteger(L, handle->write_queue_size); + return 1; +} + +static int luv_tcp_connect(lua_State* L) { + uv_tcp_t* handle = luv_check_tcp(L, 1); + const char* host = luaL_checkstring(L, 2); + int port = luaL_checkinteger(L, 3); + struct sockaddr_storage addr; + uv_connect_t* req; + int ret, ref; + if (uv_ip4_addr(host, port, (struct sockaddr_in*)&addr) && + uv_ip6_addr(host, port, (struct sockaddr_in6*)&addr)) { + return luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); + } + ref = luv_check_continuation(L, 4); + + req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + ret = uv_tcp_connect(req, handle, (struct sockaddr*)&addr, luv_connect_cb); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + return 1; +} diff --git a/3rdparty/luv/src/thread.c b/3rdparty/luv/src/thread.c new file mode 100644 index 00000000000..cc53011e6ed --- /dev/null +++ b/3rdparty/luv/src/thread.c @@ -0,0 +1,353 @@ +/* +* Copyright 2014 The Luvit Authors. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ +#include "luv.h" +#include "lthreadpool.h" + +typedef struct { + uv_thread_t handle; + char* code; + int len; + int argc; + luv_thread_arg_t arg; +} luv_thread_t; + +static luv_acquire_vm acquire_vm_cb = NULL; +static luv_release_vm release_vm_cb = NULL; + +static lua_State* luv_thread_acquire_vm() { + lua_State* L = luaL_newstate(); + + // Add in the lua standard libraries + luaL_openlibs(L); + + // Get package.loaded, so we can store uv in it. + lua_getglobal(L, "package"); + lua_getfield(L, -1, "loaded"); + lua_remove(L, -2); // Remove package + + // Store uv module definition at loaded.uv + luaopen_luv(L); + lua_setfield(L, -2, "luv"); + lua_pop(L, 1); + + return L; +} + +static void luv_thread_release_vm(lua_State* L) { + lua_close(L); +} + +static int luv_thread_arg_set(lua_State* L, luv_thread_arg_t* args, int idx, int top, int flag) +{ + int i; + idx = idx > 0 ? idx : 1; + i = idx; + while (i <= top && i <= LUV_THREAD_MAXNUM_ARG + idx) + { + luv_val_t *arg = args->argv + i - idx; + arg->type = lua_type(L, i); + switch (arg->type) + { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + arg->val.boolean = lua_toboolean(L, i); + break; + case LUA_TNUMBER: + arg->val.num = lua_tonumber(L, i); + break; + case LUA_TLIGHTUSERDATA: + arg->val.userdata = lua_touserdata(L, i); + break; + case LUA_TSTRING: + { + const char* p = lua_tolstring(L, i, &arg->val.str.len); + arg->val.str.base = malloc(arg->val.str.len); + if (arg->val.str.base == NULL) + { + perror("out of memory"); + return 0; + } + memcpy((void*)arg->val.str.base, p, arg->val.str.len); + break; + } + case LUA_TUSERDATA: + if (flag == 1) { + arg->val.userdata = luv_check_handle(L, i); + break; + } + default: + fprintf(stderr, "Error: thread arg not support type '%s' at %d", + luaL_typename(L, arg->type), i); + exit(-1); + break; + } + i++; + } + args->argc = i - idx; + return args->argc; +} + +static void luv_thread_arg_clear(luv_thread_arg_t* args) { + int i; + for (i = 0; i < args->argc; i++) + { + if (args->argv[i].type == LUA_TSTRING) + { + free((void*)args->argv[i].val.str.base); + } + } + memset(args, 0, sizeof(*args)); + args->argc = 0; +} + +static void luv_thread_setup_handle(lua_State* L, uv_handle_t* handle) { + *(void**) lua_newuserdata(L, sizeof(void*)) = handle; + +#define XX(uc, lc) case UV_##uc: \ + luaL_getmetatable(L, "uv_"#lc); \ + break; + switch (handle->type) { + UV_HANDLE_TYPE_MAP(XX) + default: + luaL_error(L, "Unknown handle type"); + } +#undef XX + + lua_setmetatable(L, -2); +} + +static int luv_thread_arg_push(lua_State* L, const luv_thread_arg_t* args) { + int i = 0; + while (i < args->argc) + { + const luv_val_t* arg = args->argv + i; + switch (arg->type) + { + case LUA_TNIL: + lua_pushnil(L); + break; + case LUA_TBOOLEAN: + lua_pushboolean(L, arg->val.boolean); + break; + case LUA_TLIGHTUSERDATA: + lua_pushlightuserdata(L, arg->val.userdata); + break; + case LUA_TNUMBER: + lua_pushnumber(L, arg->val.num); + break; + case LUA_TSTRING: + lua_pushlstring(L, arg->val.str.base, arg->val.str.len); + break; + case LUA_TUSERDATA: + luv_thread_setup_handle(L, arg->val.userdata); + break; + default: + fprintf(stderr, "Error: thread arg not support type %s at %d", + luaL_typename(L, arg->type), i + 1); + } + i++; + }; + return i; +} + +int thread_dump(lua_State* L, const void* p, size_t sz, void* B) +{ + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char*) p, sz); + return 0; +} + +static const char* luv_thread_dumped(lua_State* L, int idx, size_t* l) { + if (lua_isstring(L, idx)) { + return lua_tolstring(L, idx, l); + } else { + const char* buff = NULL; + int top = lua_gettop(L); + luaL_Buffer b; + luaL_checktype(L, idx, LUA_TFUNCTION); + lua_pushvalue(L, idx); + luaL_buffinit(L, &b); +#if LUA_VERSION_NUM>=503 + int test_lua_dump = (lua_dump(L, thread_dump, &b, 1) == 0); +#else + int test_lua_dump = (lua_dump(L, thread_dump, &b) == 0); +#endif + if (test_lua_dump) { + luaL_pushresult(&b); + buff = lua_tolstring(L, -1, l); + } else + luaL_error(L, "Error: unable to dump given function"); + lua_settop(L, top); + + return buff; + } +} + +static luv_thread_t* luv_check_thread(lua_State* L, int index) +{ + luv_thread_t* thread = luaL_checkudata(L, index, "uv_thread"); + return thread; +} + +static int luv_thread_gc(lua_State* L) { + luv_thread_t* tid = luv_check_thread(L, 1); + free(tid->code); + tid->code = NULL; + tid->len = 0; + luv_thread_arg_clear(&tid->arg); + return 0; +} + +static int luv_thread_tostring(lua_State* L) +{ + luv_thread_t* thd = luv_check_thread(L, 1); + lua_pushfstring(L, "uv_thread_t: %p", thd->handle); + return 1; +} + +static void luv_thread_cb(void* varg) { + luv_thread_t* thd = (luv_thread_t*)varg; + lua_State* L = acquire_vm_cb(); + if (luaL_loadbuffer(L, thd->code, thd->len, "=thread") == 0) + { + int top = lua_gettop(L); + int i = luv_thread_arg_push(L, &thd->arg); + + for (i = 0; i < thd->arg.argc; i++) { + if (thd->arg.argv[i].type == LUA_TUSERDATA) { + lua_pushlightuserdata(L, thd->arg.argv[i].val.userdata); + lua_pushvalue(L, top + i + 1); + lua_rawset(L, LUA_REGISTRYINDEX); + } + } + + if (lua_pcall(L, i, 0, 0)) { + fprintf(stderr, "Uncaught Error in thread: %s\n", lua_tostring(L, -1)); + } + + for (i = 0; i < thd->arg.argc; i++) { + if (thd->arg.argv[i].type == LUA_TUSERDATA) { + lua_pushlightuserdata(L, thd->arg.argv[i].val.userdata); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushnil(L); + lua_setmetatable(L, -2); + lua_pop(L, 1); + + lua_pushlightuserdata(L, thd->arg.argv[i].val.userdata); + lua_pushnil(L); + lua_rawset(L, LUA_REGISTRYINDEX); + } + } + + } else { + fprintf(stderr, "Uncaught Error: %s\n", lua_tostring(L, -1)); + } + release_vm_cb(L); +} + +static int luv_new_thread(lua_State* L) { + int ret; + size_t len; + const char* buff; + luv_thread_t* thread; + thread = lua_newuserdata(L, sizeof(*thread)); + memset(thread, 0, sizeof(*thread)); + luaL_getmetatable(L, "uv_thread"); + lua_setmetatable(L, -2); + + buff = luv_thread_dumped(L, 1, &len); + + thread->argc = luv_thread_arg_set(L, &thread->arg, 2, lua_gettop(L) - 1, 1); + thread->len = len; + thread->code = malloc(thread->len); + memcpy(thread->code, buff, len); + + ret = uv_thread_create(&thread->handle, luv_thread_cb, thread); + if (ret < 0) return luv_error(L, ret); + + return 1; +} + +static int luv_thread_join(lua_State* L) { + luv_thread_t* tid = luv_check_thread(L, 1); + int ret = uv_thread_join(&tid->handle); + if (ret < 0) return luv_error(L, ret); + lua_pushboolean(L, 1); + return 1; +} + +static int luv_thread_self(lua_State* L) +{ + luv_thread_t* thread; + uv_thread_t t = uv_thread_self(); + thread = lua_newuserdata(L, sizeof(*thread)); + memset(thread, 0, sizeof(*thread)); + memcpy(&thread->handle, &t, sizeof(t)); + luaL_getmetatable(L, "uv_thread"); + lua_setmetatable(L, -2); + return 1; +} + +static int luv_thread_equal(lua_State* L) { + luv_thread_t* t1 = luv_check_thread(L, 1); + luv_thread_t* t2 = luv_check_thread(L, 2); + int ret = uv_thread_equal(&t1->handle, &t2->handle); + lua_pushboolean(L, ret); + return 1; +} + +/* Pause the calling thread for a number of milliseconds. */ +static int luv_thread_sleep(lua_State* L) { +#ifdef _WIN32 + DWORD msec = luaL_checkinteger(L, 1); + Sleep(msec); +#else + lua_Integer msec = luaL_checkinteger(L, 1); + usleep(msec * 1000); +#endif + return 0; +} + +static const luaL_Reg luv_thread_methods[] = { + {"equal", luv_thread_equal}, + {"join", luv_thread_join}, + {NULL, NULL} +}; + +static void luv_thread_init(lua_State* L) { + luaL_newmetatable(L, "uv_thread"); + lua_pushcfunction(L, luv_thread_tostring); + lua_setfield(L, -2, "__tostring"); + lua_pushcfunction(L, luv_thread_equal); + lua_setfield(L, -2, "__eq"); + lua_pushcfunction(L, luv_thread_gc); + lua_setfield(L, -2, "__gc"); + lua_newtable(L); + luaL_setfuncs(L, luv_thread_methods, 0); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + + if (acquire_vm_cb == NULL) acquire_vm_cb = luv_thread_acquire_vm; + if (release_vm_cb == NULL) release_vm_cb = luv_thread_release_vm; +} + +LUALIB_API void luv_set_thread_cb(luv_acquire_vm acquire, luv_release_vm release) +{ + acquire_vm_cb = acquire; + release_vm_cb = release; +} diff --git a/3rdparty/luv/src/timer.c b/3rdparty/luv/src/timer.c new file mode 100644 index 00000000000..b283f1fc8b2 --- /dev/null +++ b/3rdparty/luv/src/timer.c @@ -0,0 +1,84 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_timer_t* luv_check_timer(lua_State* L, int index) { + uv_timer_t* handle = luv_checkudata(L, index, "uv_timer"); + luaL_argcheck(L, handle->type == UV_TIMER && handle->data, index, "Expected uv_timer_t"); + return handle; +} + +static int luv_new_timer(lua_State* L) { + uv_timer_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_timer_init(luv_loop(L), handle); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static void luv_timer_cb(uv_timer_t* handle) { + lua_State* L = luv_state(handle->loop); + luv_handle_t* data = handle->data; + luv_call_callback(L, data, LUV_TIMEOUT, 0); +} + +static int luv_timer_start(lua_State* L) { + uv_timer_t* handle = luv_check_timer(L, 1); + uint64_t timeout; + uint64_t repeat; + int ret; + timeout = luaL_checkinteger(L, 2); + repeat = luaL_checkinteger(L, 3); + luv_check_callback(L, handle->data, LUV_TIMEOUT, 4); + ret = uv_timer_start(handle, luv_timer_cb, timeout, repeat); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_timer_stop(lua_State* L) { + uv_timer_t* handle = luv_check_timer(L, 1); + int ret = uv_timer_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_timer_again(lua_State* L) { + uv_timer_t* handle = luv_check_timer(L, 1); + int ret = uv_timer_again(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_timer_set_repeat(lua_State* L) { + uv_timer_t* handle = luv_check_timer(L, 1); + uint64_t repeat = luaL_checkinteger(L, 2); + uv_timer_set_repeat(handle, repeat); + return 0; +} + +static int luv_timer_get_repeat(lua_State* L) { + uv_timer_t* handle = luv_check_timer(L, 1); + uint64_t repeat = uv_timer_get_repeat(handle); + lua_pushinteger(L, repeat); + return 1; +} diff --git a/3rdparty/luv/src/tty.c b/3rdparty/luv/src/tty.c new file mode 100644 index 00000000000..9232dc07603 --- /dev/null +++ b/3rdparty/luv/src/tty.c @@ -0,0 +1,65 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_tty_t* luv_check_tty(lua_State* L, int index) { + uv_tty_t* handle = luv_checkudata(L, index, "uv_tty"); + luaL_argcheck(L, handle->type == UV_TTY && handle->data, index, "Expected uv_tty_t"); + return handle; +} + +static int luv_new_tty(lua_State* L) { + int readable, ret; + uv_tty_t* handle; + uv_file fd = luaL_checkinteger(L, 1); + luaL_checktype(L, 2, LUA_TBOOLEAN); + readable = lua_toboolean(L, 2); + handle = luv_newuserdata(L, sizeof(*handle)); + ret = uv_tty_init(luv_loop(L), handle, fd, readable); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static int luv_tty_set_mode(lua_State* L) { + uv_tty_t* handle = luv_check_tty(L, 1); + int mode = luaL_checkinteger(L, 2); + int ret = uv_tty_set_mode(handle, mode); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_tty_reset_mode(lua_State* L) { + int ret = uv_tty_reset_mode(); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_tty_get_winsize(lua_State* L) { + uv_tty_t* handle = luv_check_tty(L, 1); + int width, height; + int ret = uv_tty_get_winsize(handle, &width, &height); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, width); + lua_pushinteger(L, height); + return 2; +} diff --git a/3rdparty/luv/src/udp.c b/3rdparty/luv/src/udp.c new file mode 100644 index 00000000000..9cc25555559 --- /dev/null +++ b/3rdparty/luv/src/udp.c @@ -0,0 +1,260 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +static uv_udp_t* luv_check_udp(lua_State* L, int index) { + uv_udp_t* handle = luv_checkudata(L, index, "uv_udp"); + luaL_argcheck(L, handle->type == UV_UDP && handle->data, index, "Expected uv_udp_t"); + return handle; +} + +static int luv_new_udp(lua_State* L) { + uv_udp_t* handle = luv_newuserdata(L, sizeof(*handle)); + int ret = uv_udp_init(luv_loop(L), handle); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + handle->data = luv_setup_handle(L); + return 1; +} + +static int luv_udp_open(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + uv_os_sock_t sock = luaL_checkinteger(L, 2); + int ret = uv_udp_open(handle, sock); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_udp_bind(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + const char* host = luaL_checkstring(L, 2); + int port = luaL_checkinteger(L, 3); + unsigned int flags = 0; + struct sockaddr_storage addr; + int ret; + if (uv_ip4_addr(host, port, (struct sockaddr_in*)&addr) && + uv_ip6_addr(host, port, (struct sockaddr_in6*)&addr)) { + return luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); + } + if (lua_type(L, 4) == LUA_TTABLE) { + luaL_checktype(L, 4, LUA_TTABLE); + lua_getfield(L, 4, "reuseaddr"); + if (lua_toboolean(L, -1)) flags |= UV_UDP_REUSEADDR; + lua_pop(L, 1); + lua_getfield(L, 4, "ipv6only"); + if (lua_toboolean(L, -1)) flags |= UV_UDP_IPV6ONLY; + lua_pop(L, 1); + } + ret = uv_udp_bind(handle, (struct sockaddr*)&addr, flags); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_udp_getsockname(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + struct sockaddr_storage address; + int addrlen = sizeof(address); + int ret = uv_udp_getsockname(handle, (struct sockaddr*)&address, &addrlen); + if (ret < 0) return luv_error(L, ret); + parse_sockaddr(L, &address, addrlen); + return 1; +} + +// These are the same order as uv_membership which also starts at 0 +static const char *const luv_membership_opts[] = { + "leave", "join", NULL +}; + +static int luv_udp_set_membership(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + const char* multicast_addr = luaL_checkstring(L, 2); + const char* interface_addr = luaL_checkstring(L, 3); + uv_membership membership = luaL_checkoption(L, 4, NULL, luv_membership_opts); + int ret = uv_udp_set_membership(handle, multicast_addr, interface_addr, membership); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_udp_set_multicast_loop(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + int on, ret; + luaL_checktype(L, 2, LUA_TBOOLEAN); + on = lua_toboolean(L, 2); + ret = uv_udp_set_multicast_loop(handle, on); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_udp_set_multicast_ttl(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + int ttl, ret; + ttl = luaL_checkinteger(L, 2); + ret = uv_udp_set_multicast_ttl(handle, ttl); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_udp_set_multicast_interface(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + const char* interface_addr = luaL_checkstring(L, 2); + int ret = uv_udp_set_multicast_interface(handle, interface_addr); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_udp_set_broadcast(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + int on, ret; + luaL_checktype(L, 2, LUA_TBOOLEAN); + on = lua_toboolean(L, 2); + ret =uv_udp_set_broadcast(handle, on); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_udp_set_ttl(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + int ttl, ret; + ttl = luaL_checknumber(L, 2); + ret = uv_udp_set_ttl(handle, ttl); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static void luv_udp_send_cb(uv_udp_send_t* req, int status) { + lua_State* L = luv_state(req->handle->loop); + luv_status(L, status); + luv_fulfill_req(L, req->data, 1); + luv_cleanup_req(L, req->data); + req->data = NULL; +} + +static int luv_udp_send(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + uv_udp_send_t* req; + uv_buf_t buf; + int ret, port, ref; + const char* host; + struct sockaddr_storage addr; + luv_check_buf(L, 2, &buf); + host = luaL_checkstring(L, 3); + port = luaL_checkinteger(L, 4); + if (uv_ip4_addr(host, port, (struct sockaddr_in*)&addr) && + uv_ip6_addr(host, port, (struct sockaddr_in6*)&addr)) { + return luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); + } + ref = luv_check_continuation(L, 5); + req = lua_newuserdata(L, sizeof(*req)); + req->data = luv_setup_req(L, ref); + ret = uv_udp_send(req, handle, &buf, 1, (struct sockaddr*)&addr, luv_udp_send_cb); + if (ret < 0) { + lua_pop(L, 1); + return luv_error(L, ret); + } + return 1; + +} + +static int luv_udp_try_send(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + uv_buf_t buf; + int ret, port; + const char* host; + struct sockaddr_storage addr; + luv_check_buf(L, 2, &buf); + host = luaL_checkstring(L, 3); + port = luaL_checkinteger(L, 4); + if (uv_ip4_addr(host, port, (struct sockaddr_in*)&addr) && + uv_ip6_addr(host, port, (struct sockaddr_in6*)&addr)) { + return luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); + } + ret = uv_udp_try_send(handle, &buf, 1, (struct sockaddr*)&addr); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static void luv_udp_recv_cb(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags) { + lua_State* L = luv_state(handle->loop); + + // err + if (nread < 0) { + luv_status(L, nread); + } + else { + lua_pushnil(L); + } + + // data + if (nread == 0) { + if (addr) { + lua_pushstring(L, ""); + } + else { + lua_pushnil(L); + } + } + else if (nread > 0) { + lua_pushlstring(L, buf->base, nread); + } + if (buf) free(buf->base); + + // address + if (addr) { + parse_sockaddr(L, (struct sockaddr_storage*)addr, sizeof *addr); + } + else { + lua_pushnil(L); + } + + // flags + lua_newtable(L); + if (flags & UV_UDP_PARTIAL) { + lua_pushboolean(L, 1); + lua_setfield(L, -2, "partial"); + } + + luv_call_callback(L, handle->data, LUV_RECV, 4); +} + +static int luv_udp_recv_start(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + int ret; + luv_check_callback(L, handle->data, LUV_RECV, 2); + ret = uv_udp_recv_start(handle, luv_alloc_cb, luv_udp_recv_cb); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} + +static int luv_udp_recv_stop(lua_State* L) { + uv_udp_t* handle = luv_check_udp(L, 1); + int ret = uv_udp_recv_stop(handle); + if (ret < 0) return luv_error(L, ret); + lua_pushinteger(L, ret); + return 1; +} diff --git a/3rdparty/luv/src/util.c b/3rdparty/luv/src/util.c new file mode 100644 index 00000000000..c7b98c1759a --- /dev/null +++ b/3rdparty/luv/src/util.c @@ -0,0 +1,56 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "luv.h" + +void luv_stack_dump(lua_State* L, const char* name) { + int i, l; + fprintf(stderr, "\nAPI STACK DUMP %p %d: %s\n", L, lua_status(L), name); + for (i = 1, l = lua_gettop(L); i <= l; i++) { + int type = lua_type(L, i); + switch (type) { + case LUA_TSTRING: + fprintf(stderr, " %d %s \"%s\"\n", i, lua_typename(L, type), lua_tostring(L, i)); + break; + case LUA_TNUMBER: + fprintf(stderr, " %d %s %ld\n", i, lua_typename(L, type), (long int) lua_tointeger(L, i)); + break; + case LUA_TUSERDATA: + fprintf(stderr, " %d %s %p\n", i, lua_typename(L, type), lua_touserdata(L, i)); + break; + default: + fprintf(stderr, " %d %s\n", i, lua_typename(L, type)); + break; + } + } + assert(l == lua_gettop(L)); +} + +static int luv_error(lua_State* L, int status) { + lua_pushnil(L); + lua_pushfstring(L, "%s: %s", uv_err_name(status), uv_strerror(status)); + lua_pushstring(L, uv_err_name(status)); + return 3; +} + +static void luv_status(lua_State* L, int status) { + if (status < 0) { + lua_pushstring(L, uv_err_name(status)); + } + else { + lua_pushnil(L); + } +} diff --git a/3rdparty/luv/src/util.h b/3rdparty/luv/src/util.h new file mode 100644 index 00000000000..c669c0430db --- /dev/null +++ b/3rdparty/luv/src/util.h @@ -0,0 +1,26 @@ +/* + * Copyright 2014 The Luvit Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef LUV_UTIL_H +#define LUV_UTIL_H + +#include "luv.h" + +void luv_stack_dump(lua_State* L, const char* name); +static int luv_error(lua_State* L, int ret); +static void luv_status(lua_State* L, int status); + +#endif diff --git a/3rdparty/luv/src/work.c b/3rdparty/luv/src/work.c new file mode 100644 index 00000000000..e40212f1e7c --- /dev/null +++ b/3rdparty/luv/src/work.c @@ -0,0 +1,224 @@ +/* +* Copyright 2014 The Luvit Authors. All Rights Reserved. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +*/ +#include "luv.h" + +#include "lthreadpool.h" + +typedef struct { + lua_State* L; /* vm in main */ + char* code; /* thread entry code */ + size_t len; + + uv_async_t async; + int async_cb; /* ref, run in main, call when async message received, NYI */ + int after_work_cb; /* ref, run in main ,call after work cb*/ +} luv_work_ctx_t; + +typedef struct { + uv_work_t work; + luv_work_ctx_t* ctx; + + luv_thread_arg_t arg; +} luv_work_t; + +static uv_key_t L_key; + +static luv_work_ctx_t* luv_check_work_ctx(lua_State* L, int index) +{ + luv_work_ctx_t* ctx = luaL_checkudata(L, index, "luv_work_ctx"); + return ctx; +} + +static int luv_work_ctx_gc(lua_State *L) +{ + luv_work_ctx_t* ctx = luv_check_work_ctx(L, 1); + free(ctx->code); + luaL_unref(L, LUA_REGISTRYINDEX, ctx->after_work_cb); + luaL_unref(L, LUA_REGISTRYINDEX, ctx->async_cb); + + return 0; +} + +static int luv_work_ctx_tostring(lua_State* L) +{ + luv_work_ctx_t* ctx = luv_check_work_ctx(L, 1); + lua_pushfstring(L, "luv_work_ctx_t: %p", ctx); + return 1; +} + +static void luv_work_cb(uv_work_t* req) +{ + luv_work_t* work = req->data; + luv_work_ctx_t* ctx = work->ctx; + lua_State *L = uv_key_get(&L_key); + int top; + if (L == NULL) { + /* vm reuse in threadpool */ + L = acquire_vm_cb(); + uv_key_set(&L_key, L); + } + + top = lua_gettop(L); + lua_pushlstring(L, ctx->code, ctx->len); + lua_rawget(L, LUA_REGISTRYINDEX); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + + lua_pushlstring(L, ctx->code, ctx->len); + if (luaL_loadbuffer(L, ctx->code, ctx->len, "=pool") != 0) + { + fprintf(stderr, "Uncaught Error: %s\n", lua_tostring(L, -1)); + lua_pop(L, 2); + + lua_pushnil(L); + } else + { + lua_pushvalue(L, -1); + lua_insert(L, lua_gettop(L) - 2); + lua_rawset(L, LUA_REGISTRYINDEX); + } + } + + if (lua_isfunction(L, -1)) + { + int i = luv_thread_arg_push(L, &work->arg); + if (lua_pcall(L, i, LUA_MULTRET, 0)) { + fprintf(stderr, "Uncaught Error in thread: %s\n", lua_tostring(L, -1)); + } + luv_thread_arg_clear(&work->arg); + luv_thread_arg_set(L, &work->arg, top + 1, lua_gettop(L), 0); + lua_settop(L, top); + } else { + fprintf(stderr, "Uncaught Error: %s can't be work entry\n", + lua_typename(L, lua_type(L,-1))); + } +} + +static void luv_after_work_cb(uv_work_t* req, int status) { + luv_work_t* work = req->data; + luv_work_ctx_t* ctx = work->ctx; + lua_State*L = ctx->L; + int i; + (void)status; + lua_rawgeti(L, LUA_REGISTRYINDEX, ctx->after_work_cb); + i = luv_thread_arg_push(L, &work->arg); + if (lua_pcall(L, i, 0, 0)) + { + fprintf(stderr, "Uncaught Error in thread: %s\n", lua_tostring(L, -1)); + } + + //ref down to ctx + lua_pushlightuserdata(L, work); + lua_pushnil(L); + lua_rawset(L, LUA_REGISTRYINDEX); + + luv_thread_arg_clear(&work->arg); + free(work); +} + +static void async_cb(uv_async_t *handle) +{ + luv_work_t*work = handle->data; + luv_work_ctx_t* ctx = work->ctx; + lua_State*L = ctx->L; + int i; + lua_rawgeti(L, LUA_REGISTRYINDEX, ctx->async_cb); + i = luv_thread_arg_push(L, &work->arg); + if (lua_pcall(L, i, 0, 0)) + { + fprintf(stderr, "Uncaught Error in thread: %s\n", lua_tostring(L, -1)); + } +} + +static int luv_new_work(lua_State* L) { + size_t len; + const char* buff; + luv_work_ctx_t* ctx; + + buff = luv_thread_dumped(L, 1, &len); + luaL_checktype(L, 2, LUA_TFUNCTION); + if(!lua_isnoneornil(L, 3)) + luaL_checktype(L, 3, LUA_TFUNCTION); + + ctx = lua_newuserdata(L, sizeof(*ctx)); + memset(ctx, 0, sizeof(*ctx)); + + ctx->len = len; + ctx->code = malloc(ctx->len); + memcpy(ctx->code, buff, len); + + lua_pushvalue(L, 2); + ctx->after_work_cb = luaL_ref(L, LUA_REGISTRYINDEX); + if (lua_gettop(L) == 4) { + lua_pushvalue(L, 3); + ctx->async_cb = luaL_ref(L, LUA_REGISTRYINDEX); + uv_async_init(luv_loop(L), &ctx->async, async_cb); + } else + ctx->async_cb = LUA_REFNIL; + ctx->L = L; + luaL_getmetatable(L, "luv_work_ctx"); + lua_setmetatable(L, -2); + return 1; +} + +static int luv_queue_work(lua_State* L) { + int top = lua_gettop(L); + luv_work_ctx_t* ctx = luv_check_work_ctx(L, 1); + luv_work_t* work = malloc(sizeof(*work)); + int ret; + + luv_thread_arg_set(L, &work->arg, 2, top, 0); + work->ctx = ctx; + work->work.data = work; + ret = uv_queue_work(luv_loop(L), &work->work, luv_work_cb, luv_after_work_cb); + if (ret < 0) { + free(work); + return luv_error(L, ret); + } + + //ref up to ctx + lua_pushlightuserdata(L, work); + lua_pushvalue(L, 1); + lua_rawset(L, LUA_REGISTRYINDEX); + + lua_pushboolean(L, 1); + return 1; +} + +static const luaL_Reg luv_work_ctx_methods[] = { + {"queue", luv_queue_work}, + {NULL, NULL} +}; + +static int key_inited = 0; +static void luv_work_init(lua_State* L) { + luaL_newmetatable(L, "luv_work_ctx"); + lua_pushcfunction(L, luv_work_ctx_tostring); + lua_setfield(L, -2, "__tostring"); + lua_pushcfunction(L, luv_work_ctx_gc); + lua_setfield(L, -2, "__gc"); + lua_newtable(L); + luaL_setfuncs(L, luv_work_ctx_methods, 0); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + + if (key_inited==0) { + key_inited = 1; + uv_key_create(&L_key); + } +} diff --git a/3rdparty/luv/tests/manual-test-cluster.lua b/3rdparty/luv/tests/manual-test-cluster.lua new file mode 100644 index 00000000000..304e4be634d --- /dev/null +++ b/3rdparty/luv/tests/manual-test-cluster.lua @@ -0,0 +1,213 @@ +-- This is quite the involved test. Basically it binds +-- to a tcp port, spawns n children (one per CPU core) +-- who all listen on the same shared port and act as a +-- load balancing cluster. +-- Then N clients are spawned that connect to the cluster +-- The application itself kills the worker upon connection +-- All N workers should accept exactly one request and all close. + +return require('lib/tap')(function (test) + + -- This function will be run in a child process + local worker_code = string.dump(function () + local dump = require('lib/utils').dump + + local function print(...) + local n = select('#', ...) + local arguments = {...} + for i = 1, n do + arguments[i] = tostring(arguments[i]) + end + + local text = table.concat(arguments, "\t") + text = " " .. string.gsub(text, "\n", "\n ") + _G.print(text) + end + + local function p(...) + local n = select('#', ...) + local arguments = { ... } + + for i = 1, n do + arguments[i] = dump(arguments[i]) + end + + print(table.concat(arguments, "\t")) + end + + local uv = require('luv') + local answer = -1 + + -- The parent is going to pass us the server handle over a pipe + -- This will be our local file descriptor at PIPE_FD + local pipe = uv.new_pipe(true) + local pipe_fd = tonumber(os.getenv("PIPE_FD")) + assert(uv.pipe_open(pipe, pipe_fd)) + + -- Configure the server handle + local server = uv.new_tcp() + local done = false + local function onconnection() + print("NOT ACCEPTING, already done") + if done then return end + local client = uv.new_tcp() + assert(uv.accept(server, client)) + p("New TCP", client, "on", server) + p{client=client} + assert(uv.write(client, "BYE!\n")); + assert(uv.shutdown(client, function () + uv.close(client) + uv.unref(server) + done = true + answer = 42 + end)) + end + + -- Read the server handle from the parent + local function onread(err, data) + p("onread", {err=err,data=data}) + assert(not err, err) + if uv.pipe_pending_count(pipe) > 0 then + local pending_type = uv.pipe_pending_type(pipe) + p("pending_type", pending_type) + assert(pending_type == "tcp") + assert(uv.accept(pipe, server)) + assert(uv.listen(server, 0, onconnection)) + p("Received server handle from parent process", server) + elseif data then + p("ondata", data) + else + p("onend", data) + end + end + uv.read_start(pipe, onread) + + -- Start the event loop! + uv.run() + + os.exit(answer) + end) + + local client_code = string.dump(function () + local dump = require('lib/utils').dump + + local function print(...) + local n = select('#', ...) + local arguments = {...} + for i = 1, n do + arguments[i] = tostring(arguments[i]) + end + + local text = table.concat(arguments, "\t") + text = " " .. string.gsub(text, "\n", "\n ") + _G.print(text) + end + + local function p(...) + local n = select('#', ...) + local arguments = { ... } + + for i = 1, n do + arguments[i] = dump(arguments[i]) + end + + print(table.concat(arguments, "\t")) + end + + local uv = require('luv') + + local host = os.getenv("HOST") + local port = tonumber(os.getenv("PORT")) + + local socket = uv.new_tcp() + + assert(uv.tcp_connect(socket, host, port, function (err) + p("client connected", {err=err}) + assert(not err, err) + end)) + + -- Start the event loop! + uv.run() + end) + + test("tcp cluster", function (print, p, expect, uv) + + local exepath = assert(uv.exepath()) + local cpu_count = # assert(uv.cpu_info()) + local left = cpu_count + + local server = uv.new_tcp() + assert(uv.tcp_bind(server, "::1", 0)) + + local address = uv.tcp_getsockname(server) + p{server=server,address=address} + + print("Master process bound to TCP port " .. address.port .. " on " .. address.ip) + + local function spawnWorker() + local pipe = uv.new_pipe(true) + local input = uv.new_pipe(false) + local child, pid + child, pid = assert(uv.spawn(exepath, { + cwd = uv.cwd(), + stdio = {input,1,2,pipe}, + env= {"PIPE_FD=3"} + }, expect(function (status, signal) + p("Worker exited", {status=status,signal=signal}) + assert(status == 42, "worker should return 42") + assert(signal == 0) + left = left - 1 + uv.close(child) + uv.close(input) + uv.close(pipe) + if left == 0 then + p("All workers are now dead") + uv.close(server) + end + end))) + p("Spawned worker", pid, "and sending handle", server) + assert(uv.write(input, worker_code)) + assert(uv.write2(pipe, "123", server)) + assert(uv.shutdown(input)) + assert(uv.shutdown(pipe)) + end + + local function spawnClient() + local input = uv.new_pipe(false) + local child, pid + child, pid = assert(uv.spawn(exepath, { + stdio = {input,1,2}, + cwd = uv.cwd(), + env= { + "HOST=" .. address.ip, + "PORT=" .. address.port, + } + }, expect(function (status, signal) + p("Client exited", {status=status,signal=signal}) + assert(status == 0) + assert(signal == 0) + uv.close(child) + end, left))) + p("Spawned client", pid) + assert(uv.write(input, client_code)) + assert(uv.shutdown(input)) + uv.close(input) + end + + -- Spawn a child process for each CPU core + for _ = 1, cpu_count do + spawnWorker() + end + + -- Spawn the clients after a short delay + local timer = uv.new_timer() + uv.timer_start(timer, 1000, 0, expect(function () + for _ = 1, cpu_count do + spawnClient() + end + uv.close(timer) + end)) + + end) +end) + diff --git a/3rdparty/luv/tests/run.lua b/3rdparty/luv/tests/run.lua new file mode 100644 index 00000000000..ea94e9bd58b --- /dev/null +++ b/3rdparty/luv/tests/run.lua @@ -0,0 +1,33 @@ +-- Run this from the parent directory as +-- +-- luajit tests/run.lua +-- + +local tap = require("lib/tap") +local uv = require("luv") + +local isWindows +if jit and jit.os then + -- Luajit provides explicit platform detection + isWindows = jit.os == "Windows" +else + -- Normal lua will only have \ for path separator on windows. + isWindows = package.config:find("\\") and true or false +end +_G.isWindows = isWindows + +local req = uv.fs_scandir("tests") + +while true do + local name = uv.fs_scandir_next(req) + if not name then break end + local match = string.match(name, "^test%-(.*).lua$") + if match then + local path = "tests/test-" .. match + tap(match) + require(path) + end +end + +-- run the tests! +tap(true) diff --git a/3rdparty/luv/tests/test-async.lua b/3rdparty/luv/tests/test-async.lua new file mode 100644 index 00000000000..88527cdb88d --- /dev/null +++ b/3rdparty/luv/tests/test-async.lua @@ -0,0 +1,32 @@ +return require('lib/tap')(function (test) + + test("test pass async between threads", function(p, p, expect, uv) + local before = os.time() + local async + async = uv.new_async(expect(function (a,b,c) + p('in async notify callback') + p(a,b,c) + assert(a=='a') + assert(b==true) + assert(c==250) + uv.close(async) + end)) + local args = {500, 'string', nil, false, 5, "helloworld",async} + local unpack = unpack or table.unpack + uv.new_thread(function(num,s,null,bool,five,hw,asy) + local uv = require'luv' + assert(type(num) == "number") + assert(type(s) == "string") + assert(null == nil) + assert(bool == false) + assert(five == 5) + assert(hw == 'helloworld') + assert(type(asy)=='userdata') + assert(uv.async_send(asy,'a',true,250)==0) + uv.sleep(1000) + end, unpack(args)):join() + local elapsed = (os.time() - before) * 1000 + assert(elapsed >= 1000, "elapsed should be at least delay ") + end) + +end) diff --git a/3rdparty/luv/tests/test-conversions.lua b/3rdparty/luv/tests/test-conversions.lua new file mode 100644 index 00000000000..f14056ddfb5 --- /dev/null +++ b/3rdparty/luv/tests/test-conversions.lua @@ -0,0 +1,6 @@ +return require('lib/tap')(function (test) + test("basic 64bit conversions", function (print, p, expect, uv) + assert(string.format("%x", 29913653248) == "6f6fe2000") + assert(string.format("%x", 32207650816) == "77fb9c000") + end) +end) diff --git a/3rdparty/luv/tests/test-dns.lua b/3rdparty/luv/tests/test-dns.lua new file mode 100644 index 00000000000..c24adba7164 --- /dev/null +++ b/3rdparty/luv/tests/test-dns.lua @@ -0,0 +1,125 @@ +return require('lib/tap')(function (test) + + test("Get all local http addresses", function (print, p, expect, uv) + assert(uv.getaddrinfo(nil, "http", nil, expect(function (err, res) + p(res, #res) + assert(not err, err) + assert(res[1].port == 80) + end))) + end) + + test("Get all local http addresses sync", function (print, p, expect, uv) + local res = assert(uv.getaddrinfo(nil, "http")) + p(res, #res) + assert(res[1].port == 80) + end) + + test("Get only ipv4 tcp adresses for luvit.io", function (print, p, expect, uv) + assert(uv.getaddrinfo("luvit.io", nil, { + socktype = "stream", + family = "inet", + }, expect(function (err, res) + assert(not err, err) + p(res, #res) + assert(#res == 1) + end))) + end) + + -- FIXME: this test always fails on AppVeyor for some reason + if _G.isWindows and not os.getenv'APPVEYOR' then + test("Get only ipv6 tcp adresses for luvit.io", function (print, p, expect, uv) + assert(uv.getaddrinfo("luvit.io", nil, { + socktype = "stream", + family = "inet6", + }, expect(function (err, res) + assert(not err, err) + p(res, #res) + assert(#res == 1) + end))) + end) + end + + test("Get ipv4 and ipv6 tcp adresses for luvit.io", function (print, p, expect, uv) + assert(uv.getaddrinfo("luvit.io", nil, { + socktype = "stream", + }, expect(function (err, res) + assert(not err, err) + p(res, #res) + assert(#res > 0) + end))) + end) + + test("Get all adresses for luvit.io", function (print, p, expect, uv) + assert(uv.getaddrinfo("luvit.io", nil, nil, expect(function (err, res) + assert(not err, err) + p(res, #res) + assert(#res > 0) + end))) + end) + + test("Lookup local ipv4 address", function (print, p, expect, uv) + assert(uv.getnameinfo({ + family = "inet", + }, expect(function (err, hostname, service) + p{err=err,hostname=hostname,service=service} + assert(not err, err) + assert(hostname) + assert(service) + end))) + end) + + test("Lookup local ipv4 address sync", function (print, p, expect, uv) + local hostname, service = assert(uv.getnameinfo({ + family = "inet", + })) + p{hostname=hostname,service=service} + assert(hostname) + assert(service) + end) + + test("Lookup local 127.0.0.1 ipv4 address", function (print, p, expect, uv) + assert(uv.getnameinfo({ + ip = "127.0.0.1", + }, expect(function (err, hostname, service) + p{err=err,hostname=hostname,service=service} + assert(not err, err) + assert(hostname) + assert(service) + end))) + end) + + test("Lookup local ipv6 address", function (print, p, expect, uv) + assert(uv.getnameinfo({ + family = "inet6", + }, expect(function (err, hostname, service) + p{err=err,hostname=hostname,service=service} + assert(not err, err) + assert(hostname) + assert(service) + end))) + end) + + test("Lookup local ::1 ipv6 address", function (print, p, expect, uv) + assert(uv.getnameinfo({ + ip = "::1", + }, expect(function (err, hostname, service) + p{err=err,hostname=hostname,service=service} + assert(not err, err) + assert(hostname) + assert(service) + end))) + end) + + test("Lookup local port 80 service", function (print, p, expect, uv) + assert(uv.getnameinfo({ + port = 80, + family = "inet6", + }, expect(function (err, hostname, service) + p{err=err,hostname=hostname,service=service} + assert(not err, err) + assert(hostname) + assert(service == "http") + end))) + end) + +end) diff --git a/3rdparty/luv/tests/test-fs.lua b/3rdparty/luv/tests/test-fs.lua new file mode 100644 index 00000000000..4bfd67e6578 --- /dev/null +++ b/3rdparty/luv/tests/test-fs.lua @@ -0,0 +1,90 @@ +return require('lib/tap')(function (test) + + test("read a file sync", function (print, p, expect, uv) + local fd = assert(uv.fs_open('README.md', 'r', tonumber('644', 8))) + p{fd=fd} + local stat = assert(uv.fs_fstat(fd)) + p{stat=stat} + local chunk = assert(uv.fs_read(fd, stat.size, 0)) + assert(#chunk == stat.size) + assert(uv.fs_close(fd)) + end) + + test("read a file async", function (print, p, expect, uv) + uv.fs_open('README.md', 'r', tonumber('644', 8), expect(function (err, fd) + assert(not err, err) + p{fd=fd} + uv.fs_fstat(fd, expect(function (err, stat) + assert(not err, err) + p{stat=stat} + uv.fs_read(fd, stat.size, 0, expect(function (err, chunk) + assert(not err, err) + p{chunk=#chunk} + assert(#chunk == stat.size) + uv.fs_close(fd, expect(function (err) + assert(not err, err) + end)) + end)) + end)) + end)) + end) + + test("fs.write", function (print, p, expect, uv) + local path = "_test_" + local fd = assert(uv.fs_open(path, "w", 438)) + uv.fs_write(fd, "Hello World\n", -1) + uv.fs_write(fd, {"with\n", "more\n", "lines\n"}, -1) + uv.fs_close(fd) + uv.fs_unlink(path) + end) + + test("fs.stat sync", function (print, p, expect, uv) + local stat = assert(uv.fs_stat("README.md")) + assert(stat.size) + end) + + test("fs.stat async", function (print, p, expect, uv) + assert(uv.fs_stat("README.md", expect(function (err, stat) + assert(not err, err) + assert(stat.size) + end))) + end) + + test("fs.stat sync error", function (print, p, expect, uv) + local stat, err, code = uv.fs_stat("BAD_FILE!") + p{err=err,code=code,stat=stat} + assert(not stat) + assert(err) + assert(code == "ENOENT") + end) + + test("fs.stat async error", function (print, p, expect, uv) + assert(uv.fs_stat("BAD_FILE@", expect(function (err, stat) + p{err=err,stat=stat} + assert(err) + assert(not stat) + end))) + end) + + test("fs.scandir", function (print, p, expect, uv) + local req = uv.fs_scandir('.') + local function iter() + return uv.fs_scandir_next(req) + end + for name, ftype in iter do + p{name=name, ftype=ftype} + assert(name) + -- ftype is not available in all filesystems; for example it's + -- provided for HFS+ (OSX), NTFS (Windows) but not for ext4 (Linux). + end + end) + + test("fs.realpath", function (print, p, expect, uv) + p(assert(uv.fs_realpath('.'))) + assert(uv.fs_realpath('.', expect(function (err, path) + assert(not err, err) + p(path) + end))) + end) + +end) diff --git a/3rdparty/luv/tests/test-leaks.lua b/3rdparty/luv/tests/test-leaks.lua new file mode 100644 index 00000000000..06c6e49a0cf --- /dev/null +++ b/3rdparty/luv/tests/test-leaks.lua @@ -0,0 +1,186 @@ +return require('lib/tap')(function (test) + + local function bench(uv, p, count, fn) + collectgarbage() + local before + local notify = count / 8 + for i = 1, count do + fn() + if i % notify == 0 then + uv.run() + collectgarbage() + local now = uv.resident_set_memory() + if not before then before = now end + p(i, now) + end + end + uv.run() + collectgarbage() + local after = uv.resident_set_memory() + p{ + before = before, + after = after, + } + assert(after < before * 1.5) + end + + test("fs-write", function (print, p, expect, uv) + bench(uv, p, 0x7000, function () + local path = "_test_" + local fd = assert(uv.fs_open(path, "w", 438)) + uv.fs_write(fd, "Hello World\n", -1) + uv.fs_write(fd, {"with\n", "more\n", "lines\n"}, -1) + uv.fs_close(fd) + uv.fs_unlink(path) + end) + end) + + test("lots-o-timers", function (print, p, expect, uv) + bench(uv, p, 0x10000, function () + local timer = uv.new_timer() + uv.close(timer) + end) + end) + + test("lots-o-timers with canceled callbacks", function (print, p, expect, uv) + bench(uv, p, 0x10000, function () + local timer = uv.new_timer() + uv.timer_start(timer, 100, 100, function () + end) + uv.timer_stop(timer) + uv.close(timer, function () + end) + uv.run() + end) + end) + + test("lots-o-timers with real timeouts", function (print, p, expect, uv) + bench(uv, p, 0x500, function () + local timer = uv.new_timer() + uv.timer_start(timer, 10, 0, expect(function () + uv.timer_stop(timer) + uv.close(timer, function () + end) + end)) + end) + end) + + test("reading file async", function (print, p, expect, uv) + local mode = tonumber("644", 8) + bench(uv, p, 0x500, function () + local onOpen, onStat, onRead, onClose + local fd, stat + + onOpen = expect(function (err, result) + assert(not err, err) + fd = result + uv.fs_fstat(fd, onStat) + end) + + onStat = expect(function (err, result) + assert(not err, err) + stat = result + uv.fs_read(fd, stat.size, 0, onRead) + end) + + onRead = expect(function (err, data) + assert(not err, err) + assert(#data == stat.size) + uv.fs_close(fd, onClose) + end) + + onClose = expect(function (err) + assert(not err, err) + end) + + assert(uv.fs_open("README.md", "r", mode, onOpen)) + end) + end) + + test("reading file sync", function (print, p, expect, uv) + local mode = tonumber("644", 8) + bench(uv, p, 0x2000, function () + local fd = assert(uv.fs_open("README.md", "r", mode)) + local stat = assert(uv.fs_fstat(fd)) + local data = assert(uv.fs_read(fd, stat.size, 0)) + assert(#data == stat.size) + assert(uv.fs_close(fd)) + end) + end) + + test("invalid file", function (print, p, expect, uv) + local mode = tonumber("644", 8) + bench(uv, p, 0x1500, function () + local req = uv.fs_open("BAD_FILE", "r", mode, expect(function (err, fd) + assert(not fd) + assert(err) + end)) + end) + end) + + test("invalid file sync", function (print, p, expect, uv) + local mode = tonumber("644", 8) + bench(uv, p, 0x20000, function () + local fd, err = uv.fs_open("BAD_FILE", "r", mode) + assert(not fd) + assert(err) + end) + end) + + test("invalid spawn args", function (print, p, expect, uv) + -- Regression test for #73 + bench(uv, p, 0x10000, function () + local ret, err = pcall(function () + return uv.spawn("ls", { + args = {"-l", "-h"}, + stdio = {0, 1, 2}, + env = {"EXTRA=true"}, + gid = false, -- Should be integer + }) + end) + assert(not ret) + assert(err) + end) + end) + + test("stream writing with string and array", function (print, p, expect, uv) + local port = 0 + local server = uv.new_tcp() + local data + local count = 0x800 + server:unref() + server:bind("127.0.0.1", port) + server:listen(128, expect(function (err) + assert(not err, err) + local client = uv.new_tcp() + server:accept(client) + client:write(data) + client:read_start(expect(function (err, data) + assert(not err, err) + assert(data) + client:close() + end)) + end, count)) + local address = server:getsockname() + bench(uv, p, count, function () + data = string.rep("Hello", 500) + local socket = uv.new_tcp() + socket:connect(address.ip, address.port, expect(function (err) + assert(not err, err) + socket:read_start(expect(function (err, chunk) + assert(not err, err) + assert(chunk) + local data = {} + for i = 0, 100 do + data[i + 1] = string.rep(string.char(i), 100) + end + socket:write(data) + socket:close() + end)) + end)) + uv.run() + end) + server:close() + end) + +end) diff --git a/3rdparty/luv/tests/test-misc.lua b/3rdparty/luv/tests/test-misc.lua new file mode 100644 index 00000000000..72a7b30785e --- /dev/null +++ b/3rdparty/luv/tests/test-misc.lua @@ -0,0 +1,85 @@ +return require('lib/tap')(function (test) + + test("uv.guess_handle", function (print, p, expect, uv) + local types = { + [0] = assert(uv.guess_handle(0)), + assert(uv.guess_handle(1)), + assert(uv.guess_handle(2)), + } + p("stdio fd types", types) + end) + + test("uv.version and uv.version_string", function (print, p, expect, uv) + local version = assert(uv.version()) + local version_string = assert(uv.version_string()) + p{version=version, version_string=version_string} + assert(type(version) == "number") + assert(type(version_string) == "string") + end) + + test("memory size", function (print, p, expect, uv) + local rss = uv.resident_set_memory() + local total = uv.get_total_memory() + local free = uv.get_free_memory() + p{rss=rss,total=total,free=free} + assert(rss < total) + end) + + test("uv.uptime", function (print, p, expect, uv) + local uptime = assert(uv.uptime()) + p{uptime=uptime} + end) + + test("uv.getrusage", function (print, p, expect, uv) + local rusage = assert(uv.getrusage()) + p(rusage) + end) + + test("uv.cpu_info", function (print, p, expect, uv) + local info = assert(uv.cpu_info()) + p(info) + end) + + test("uv.interface_addresses", function (print, p, expect, uv) + local addresses = assert(uv.interface_addresses()) + for name, info in pairs(addresses) do + p(name, addresses[name]) + end + end) + + test("uv.loadavg", function (print, p, expect, uv) + local avg = {assert(uv.loadavg())} + p(avg) + assert(#avg == 3) + end) + + test("uv.exepath", function (print, p, expect, uv) + local path = assert(uv.exepath()) + p(path) + end) + + test("uv.os_homedir", function (print, p, expect, uv) + local path = assert(uv.os_homedir()) + p(path) + end) + + test("uv.cwd and uv.chdir", function (print, p, expect, uv) + local old = assert(uv.cwd()) + p(old) + assert(uv.chdir("/")) + local cwd = assert(uv.cwd()) + p(cwd) + assert(cwd ~= old) + assert(uv.chdir(old)) + end) + + test("uv.hrtime", function (print, p, expect, uv) + local time = assert(uv.hrtime()) + p(time) + end) + + test("test_getpid", function (print, p, expect, uv) + assert(uv.getpid()) + end) + +end) diff --git a/3rdparty/luv/tests/test-prepare-check-idle-async.lua b/3rdparty/luv/tests/test-prepare-check-idle-async.lua new file mode 100644 index 00000000000..389c2633efb --- /dev/null +++ b/3rdparty/luv/tests/test-prepare-check-idle-async.lua @@ -0,0 +1,49 @@ +return require('lib/tap')(function (test) + + test("simple prepare", function (print, p, expect, uv) + local prepare = uv.new_prepare() + uv.prepare_start(prepare, expect(function () + p("prepare", prepare) + uv.prepare_stop(prepare) + uv.close(prepare, expect(function () + end)) + end)) + end) + + test("simple check", function (print, p, expect, uv) + local check = uv.new_check() + uv.check_start(check, expect(function () + p("check", check) + uv.check_stop(check) + uv.close(check, expect(function () + end)) + end)) + + -- Trigger with a timer + local timer = uv.new_timer() + uv.timer_start(timer, 10, 0, expect(function() + p("timeout", timer) + uv.timer_stop(timer) + uv.close(timer) + end)) + end) + + test("simple idle", function (print, p, expect, uv) + local idle = uv.new_idle() + uv.idle_start(idle, expect(function () + p("idle", idle) + uv.idle_stop(idle) + uv.close(idle, expect(function () + end)) + end)) + end) + + test("simple async", function (print, p, expect, uv) + local async + async = uv.new_async(expect(function () + uv.close(async) + end)) + uv.async_send(async) + end) + +end) diff --git a/3rdparty/luv/tests/test-process.lua b/3rdparty/luv/tests/test-process.lua new file mode 100644 index 00000000000..4d2b6fbfdab --- /dev/null +++ b/3rdparty/luv/tests/test-process.lua @@ -0,0 +1,101 @@ +return require('lib/tap')(function (test) + + test("test disable_stdio_inheritance", function (print, p, expect, uv) + uv.disable_stdio_inheritance() + end) + + test("process stdout", function (print, p, expect, uv) + local stdout = uv.new_pipe(false) + + local handle, pid + handle, pid = uv.spawn(uv.exepath(), { + args = {"-e", "print 'Hello World'"}, + stdio = {nil, stdout}, + }, expect(function (code, signal) + p("exit", {code=code, signal=signal}) + uv.close(handle) + end)) + + p{ + handle=handle, + pid=pid + } + + uv.read_start(stdout, expect(function (err, chunk) + p("stdout", {err=err,chunk=chunk}) + assert(not err, err) + uv.close(stdout) + end)) + + end) + + if _G.isWindows then return end + + test("spawn and kill by pid", function (print, p, expect, uv) + local handle, pid + handle, pid = uv.spawn("sleep", { + args = {1}, + }, expect(function (status, signal) + p("exit", handle, {status=status,signal=signal}) + assert(status == 0) + assert(signal == 2) + uv.close(handle) + end)) + p{handle=handle,pid=pid} + uv.kill(pid, "sigint") + end) + + test("spawn and kill by handle", function (print, p, expect, uv) + local handle, pid + handle, pid = uv.spawn("sleep", { + args = {1}, + }, expect(function (status, signal) + p("exit", handle, {status=status,signal=signal}) + assert(status == 0) + assert(signal == 15) + uv.close(handle) + end)) + p{handle=handle,pid=pid} + uv.process_kill(handle, "sigterm") + end) + + test("invalid command", function (print, p, expect, uv) + local handle, err + handle, err = uv.spawn("ksjdfksjdflkjsflksdf", {}, function(exit, code) + assert(false) + end) + assert(handle == nil) + assert(err) + end) + + test("process stdio", function (print, p, expect, uv) + local stdin = uv.new_pipe(false) + local stdout = uv.new_pipe(false) + + local handle, pid + handle, pid = uv.spawn("cat", { + stdio = {stdin, stdout}, + }, expect(function (code, signal) + p("exit", {code=code, signal=signal}) + uv.close(handle) + end)) + + p{ + handle=handle, + pid=pid + } + + uv.read_start(stdout, expect(function (err, chunk) + p("stdout", {err=err,chunk=chunk}) + assert(not err, err) + uv.close(stdout) + end)) + + uv.write(stdin, "Hello World") + uv.shutdown(stdin, expect(function () + uv.close(stdin) + end)) + + end) + +end) diff --git a/3rdparty/luv/tests/test-sigchld-after-lua_close.sh b/3rdparty/luv/tests/test-sigchld-after-lua_close.sh new file mode 100644 index 00000000000..e7d22d3df36 --- /dev/null +++ b/3rdparty/luv/tests/test-sigchld-after-lua_close.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# Verifies that luv will cleanup libuv process handles correctly even if +# not done by "userspace". +# Details: https://github.com/luvit/luv/issues/193 + +# This test modifies one of the examples to skip libuv process cleanup, +# purposely making it leave SIGCHLD signal handler. +# +patch -p1 << "EOF" +diff --git a/examples/talking-to-children.lua b/examples/talking-to-children.lua +index 10a53ef..6c6c53f 100644 +--- a/examples/talking-to-children.lua ++++ b/examples/talking-to-children.lua +@@ -41,7 +41,3 @@ uv.read_start(stdout, onread) + uv.read_start(stderr, onread) + uv.write(stdin, "Hello World") + uv.shutdown(stdin, onshutdown) +- +-uv.run() +-uv.walk(uv.close) +-uv.run() +EOF + +# It also requires a patched lua standalone interpreter that sends SIGCHLD to +# itself after calling lua_close, which would have freed all memory of the libuv +# event loop associated with the lua state. +( +cd deps/lua +patch -p1 << "EOF" +diff --git a/src/lua.c b/src/lua.c +index 7a47582..4dc19d5 100644 +--- a/src/lua.c ++++ b/src/lua.c +@@ -608,6 +608,7 @@ int main (int argc, char **argv) { + result = lua_toboolean(L, -1); /* get result */ + report(L, status); + lua_close(L); ++ kill(0, SIGCHLD); + return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; + } +EOF +) + +WITH_LUA_ENGINE=Lua make +./build/lua examples/talking-to-children.lua diff --git a/3rdparty/luv/tests/test-signal.lua b/3rdparty/luv/tests/test-signal.lua new file mode 100644 index 00000000000..c05db77c888 --- /dev/null +++ b/3rdparty/luv/tests/test-signal.lua @@ -0,0 +1,40 @@ +local child_code = string.dump(function () + local uv = require('luv') + local signal = uv.new_signal() + uv.ref(signal) + uv.signal_start(signal, "sigint", function () + uv.unref(signal) + end) + uv.run() + os.exit(7) +end) + +return require('lib/tap')(function (test) + + if _G.isWindows then return end + + test("Catch SIGINT", function (print, p, expect, uv) + local child, pid + local input = uv.new_pipe(false) + child, pid = assert(uv.spawn(uv.exepath(), { + args = {"-"}, + -- cwd = uv.cwd(), + stdio = {input,1,2} + }, expect(function (code, signal) + p("exit", {pid=pid,code=code,signal=signal}) + assert(code == 7) + assert(signal == 0) + uv.close(input) + uv.close(child) + end))) + uv.write(input, child_code) + uv.shutdown(input) + local timer = uv.new_timer() + uv.timer_start(timer, 200, 0, expect(function () + print("Sending child SIGINT") + uv.process_kill(child, "sigint") + uv.close(timer) + end)) + end) + +end) diff --git a/3rdparty/luv/tests/test-tcp.lua b/3rdparty/luv/tests/test-tcp.lua new file mode 100644 index 00000000000..885d381ebce --- /dev/null +++ b/3rdparty/luv/tests/test-tcp.lua @@ -0,0 +1,114 @@ +return require('lib/tap')(function (test) + test("basic tcp server and client", function (print, p, expect, uv) + local server = uv.new_tcp() + uv.tcp_bind(server, "::", 0) + uv.listen(server, 128, expect(function (err) + p("server on connection", server) + assert(not err, err) + uv.close(server) + end)) + + local address = uv.tcp_getsockname(server) + p{server=server,address=address} + + local client = uv.new_tcp() + local req = uv.tcp_connect(client, "::1", address.port, expect(function (err) + p("client on connect", client, err) + assert(not err, err) + uv.shutdown(client, expect(function (err) + p("client on shutdown", client, err) + assert(not err, err) + uv.close(client, expect(function () + p("client on close", client) + end)) + end)) + end)) + p{client=client,req=req} + end) + + test("tcp echo server and client", function (print, p, expect, uv) + local server = uv.new_tcp() + assert(uv.tcp_bind(server, "127.0.0.1", 0)) + assert(uv.listen(server, 1, expect(function () + local client = uv.new_tcp() + assert(uv.accept(server, client)) + assert(uv.read_start(client, expect(function (err, data) + p("server read", {err=err,data=data}) + assert(not err, err) + if data then + assert(uv.write(client, data)) + else + assert(uv.read_stop(client)) + uv.close(client) + uv.close(server) + end + end, 2))) + end))) + + local address = uv.tcp_getsockname(server) + p{server=server,address=address} + + local socket = assert(uv.new_tcp()) + assert(uv.tcp_connect(socket, "127.0.0.1", address.port, expect(function () + assert(uv.read_start(socket, expect(function (err, data) + p("client read", {err=err,data=data}) + assert(not err, err) + assert(uv.read_stop(socket)) + uv.close(socket) + end))) + local req = assert(uv.write(socket, "Hello", function (err) + p("client onwrite", socket, err) + assert(not err, err) + end)) + p{socket=socket,req=req} + end))) + end) + + test("tcp echo server and client with methods", function (print, p, expect, uv) + local server = uv.new_tcp() + assert(server:bind("127.0.0.1", 0)) + assert(server:listen(1, expect(function () + local client = uv.new_tcp() + assert(server:accept(client)) + assert(client:read_start(expect(function (err, data) + p("server read", {err=err,data=data}) + assert(not err, err) + if data then + assert(client:write(data)) + else + assert(client:read_stop()) + client:close() + server:close() + end + end, 2))) + end))) + + local address = server:getsockname() + p{server=server,address=address} + + local socket = assert(uv.new_tcp()) + assert(socket:connect("127.0.0.1", address.port, expect(function () + assert(socket:read_start(expect(function (err, data) + p("client read", {err=err,data=data}) + assert(not err, err) + assert(socket:read_stop()) + socket:close() + end))) + local req = assert(socket:write("Hello", function (err) + p("client onwrite", socket, err) + assert(not err, err) + end)) + p{socket=socket,req=req} + end))) + end) + + test("tcp invalid ip address", function (print, p, expect, uv) + local ip = '127.0.0.100005' + local server = uv.new_tcp() + local status, err = pcall(function() uv.tcp_bind(server, ip, 1000) end) + assert(not status) + p(err) + assert(err:find(ip)) + uv.close(server) + end) +end) diff --git a/3rdparty/luv/tests/test-thread.lua b/3rdparty/luv/tests/test-thread.lua new file mode 100644 index 00000000000..838b51e4fff --- /dev/null +++ b/3rdparty/luv/tests/test-thread.lua @@ -0,0 +1,47 @@ +return require('lib/tap')(function (test) + + test("test thread create", function(print, p, expect, uv) + local delay = 1000 + local before = os.time() + local thread = uv.new_thread(function(delay) + require('luv').sleep(delay) + end,delay) + uv.thread_join(thread) + local elapsed = (os.time() - before) * 1000 + p({ + delay = delay, + elapsed = elapsed + }) + assert(elapsed >= delay, "elapsed should be at least delay ") + end) + + test("test thread create with arguments", function(print, p, expect, uv) + local before = os.time() + local args = {500, 'string', nil, false, 5, "helloworld"} + local unpack = unpack or table.unpack + uv.new_thread(function(num,s,null,bool,five,hw) + assert(type(num) == "number") + assert(type(s) == "string") + assert(null == nil) + assert(bool == false) + assert(five == 5) + assert(hw == 'helloworld') + require('luv').sleep(1000) + end, unpack(args)):join() + local elapsed = (os.time() - before) * 1000 + assert(elapsed >= 1000, "elapsed should be at least delay ") + end) + + test("test thread sleep msecs in main thread", function(print, p, expect, uv) + local delay = 1000 + local before = os.time() + uv.sleep(delay) + local elapsed = (os.time() - before) * 1000 + p({ + delay = delay, + elapsed = elapsed + }) + assert(elapsed >= delay, "elapsed should be at least delay ") + end) + +end) diff --git a/3rdparty/luv/tests/test-timer.lua b/3rdparty/luv/tests/test-timer.lua new file mode 100644 index 00000000000..f9eb9d89c5f --- /dev/null +++ b/3rdparty/luv/tests/test-timer.lua @@ -0,0 +1,87 @@ +return require('lib/tap')(function (test) + + -- This tests using timers for a simple timeout. + -- It also tests the handle close callback and + test("simple timeout", function (print, p, expect, uv) + local timer = uv.new_timer() + local function onclose() + p("closed", timer) + end + local function ontimeout() + p("timeout", timer) + uv.close(timer, expect(onclose)) + end + uv.timer_start(timer, 10, 0, expect(ontimeout)) + end) + + -- This is like the previous test, but using repeat. + test("simple interval", function (print, p, expect, uv) + local timer = uv.new_timer() + local count = 3 + local onclose = expect(function () + p("closed", timer) + end) + local function oninterval() + p("interval", timer) + count = count - 1 + if count == 0 then + uv.close(timer, onclose) + end + end + uv.timer_start(timer, 10, 10, oninterval) + end) + + -- Test two concurrent timers + -- There is a small race condition, but there are 100ms of wiggle room. + -- 400ms is halfway between 100+200ms and 100+400ms + test("timeout with interval", function (print, p, expect, uv) + local a = uv.new_timer() + local b = uv.new_timer() + uv.timer_start(a, 400, 0, expect(function () + p("timeout", a) + uv.timer_stop(b) + uv.close(a) + uv.close(b) + end)) + uv.timer_start(b, 100, 200, expect(function () + p("interval", b) + end, 2)) + end) + + -- This advanced test uses the rest of the uv_timer_t functions + -- to create an interval that shrinks over time. + test("shrinking interval", function (print, p, expect, uv) + local timer = uv.new_timer() + uv.timer_start(timer, 10, 0, expect(function () + local r = uv.timer_get_repeat(timer) + p("interval", timer, r) + if r == 0 then + uv.timer_set_repeat(timer, 8) + uv.timer_again(timer) + elseif r == 2 then + uv.timer_stop(timer) + uv.close(timer) + else + uv.timer_set_repeat(timer, r / 2) + end + end, 4)) + end) + + test("shrinking interval using methods", function (print, p, expect, uv) + local timer = uv.new_timer() + timer:start(10, 0, expect(function () + local r = timer:get_repeat() + p("interval", timer, r) + if r == 0 then + timer:set_repeat(8) + timer:again() + elseif r == 2 then + timer:stop() + timer:close() + else + timer:set_repeat(r / 2) + end + end, 4)) + end) + +end) diff --git a/3rdparty/luv/tests/test-work.lua b/3rdparty/luv/tests/test-work.lua new file mode 100644 index 00000000000..3a98b15e6bc --- /dev/null +++ b/3rdparty/luv/tests/test-work.lua @@ -0,0 +1,48 @@ +return require('lib/tap')(function (test) + test("test threadpool", function(print,p,expect,_uv) + p('Please be patient, the test cost a lots of time') + local count = 1000 --for memleaks dected + local step = 0 + local ctx + ctx = _uv.new_work( + function(n,s) --work,in threadpool + local uv = require('luv') + local t = uv.thread_self() + uv.sleep(100) + return n,n*n, tostring(uv.thread_self()),s + end, + function(n,r,id, s) + assert(n*n==r) + if step < count then + _uv.queue_work(ctx,n,s) + step = step + 1 + if (step % 100==0) then + p(string.format('run %d%%', math.floor(step*100/count))) + end + end + end --after work, in loop thread + ) + local ls = string.rep('-',4096) + + _uv.queue_work(ctx,2,ls) + _uv.queue_work(ctx,4,ls) + _uv.queue_work(ctx,6,ls) + _uv.queue_work(ctx,-2,ls) + _uv.queue_work(ctx,-11,ls) + _uv.queue_work(ctx,2,ls) + _uv.queue_work(ctx,4,ls) + _uv.queue_work(ctx,6,ls) + _uv.queue_work(ctx,-2,ls) + _uv.queue_work(ctx,-11,ls) + _uv.queue_work(ctx,2,ls) + _uv.queue_work(ctx,4,ls) + _uv.queue_work(ctx,6,ls) + _uv.queue_work(ctx,-2,ls) + _uv.queue_work(ctx,-11,ls) + _uv.queue_work(ctx,2,ls) + _uv.queue_work(ctx,4,ls) + _uv.queue_work(ctx,6,ls) + _uv.queue_work(ctx,-2,ls) + _uv.queue_work(ctx,-11,ls) + end) +end) diff --git a/scripts/genie.lua b/scripts/genie.lua index 34705beefa5..a51c3cbaa5d 100644 --- a/scripts/genie.lua +++ b/scripts/genie.lua @@ -671,9 +671,10 @@ end --DEFS += -DUSE_SYSTEM_JPEGLIB --endif - --To support casting in Lua 5.3 defines { - "LUA_COMPAT_APIINTCASTS", + "LUA_COMPAT_ALL", + "LUA_COMPAT_5_1", + "LUA_COMPAT_5_2", } if _ACTION == "gmake" then diff --git a/scripts/src/3rdparty.lua b/scripts/src/3rdparty.lua index 16b86dcbe21..ef46f1cab24 100644 --- a/scripts/src/3rdparty.lua +++ b/scripts/src/3rdparty.lua @@ -398,6 +398,8 @@ end configuration { } defines { "LUA_COMPAT_ALL", + "LUA_COMPAT_5_1", + "LUA_COMPAT_5_2", } if not (_OPTIONS["targetos"]=="windows") and not (_OPTIONS["targetos"]=="asmjs") then defines { @@ -458,20 +460,19 @@ links { end -------------------------------------------------- --- sqlite3 lua library objects +-- small lua library objects -------------------------------------------------- -project "lsqlite3" +project "lualibs" uuid "1d84edab-94cf-48fb-83ee-b75bc697660e" kind "StaticLib" - -- options { - -- "ForceCPP", - -- } - configuration { "vs*" } buildoptions { "/wd4244", -- warning C4244: 'argument' : conversion from 'xxx' to 'xxx', possible loss of data + "/wd4055", -- warning C4055: 'type cast': from data pointer 'void *' to function pointer 'xxx' + "/wd4152", -- warning C4152: nonstandard extension, function/data pointer conversion in expression + "/wd4130", -- warning C4130: '==': logical operation on address of string constant } configuration { } @@ -487,9 +488,69 @@ project "lsqlite3" MAME_DIR .. "3rdparty/lua/src", } end + if _OPTIONS["with-bundled-zlib"] then + includedirs { + MAME_DIR .. "3rdparty/zlib", + } + end files { MAME_DIR .. "3rdparty/lsqlite3/lsqlite3.c", + MAME_DIR .. "3rdparty/lua-zlib/lua_zlib.c", + MAME_DIR .. "3rdparty/luafilesystem/src/lfs.c", + } + +-------------------------------------------------- +-- luv lua library objects +-------------------------------------------------- + +project "luv" + uuid "d98ec5ca-da2a-4a50-88a2-52061ca53871" + kind "StaticLib" + + if _OPTIONS["targetos"]=="windows" then + defines { + "_WIN32_WINNT=0x0600", + } + end + configuration { "vs*" } + buildoptions { + "/wd4244", -- warning C4244: 'argument' : conversion from 'xxx' to 'xxx', possible loss of data + } + + configuration { "gmake" } + buildoptions_c { + "-Wno-unused-function", + "-Wno-strict-prototypes", + "-Wno-unused-variable", + "-Wno-maybe-uninitialized", + "-Wno-undef", + } + + configuration { "vs2015" } + buildoptions { + "/wd4701", -- warning C4701: potentially uninitialized local variable 'xxx' used + "/wd4703", -- warning C4703: potentially uninitialized local pointer variable 'xxx' used + } + + configuration { } + defines { + "LUA_COMPAT_ALL", + } + + includedirs { + MAME_DIR .. "3rdparty/lua/src", + MAME_DIR .. "3rdparty/libuv/include", + } + if _OPTIONS["with-bundled-lua"] then + includedirs { + MAME_DIR .. "3rdparty/luv/deps/lua/src", + } + end + + files { + MAME_DIR .. "3rdparty/luv/src/luv.c", + MAME_DIR .. "3rdparty/luv/src/luv.h", } -------------------------------------------------- diff --git a/scripts/src/main.lua b/scripts/src/main.lua index 2397a489e00..9d0d9a9d9e1 100644 --- a/scripts/src/main.lua +++ b/scripts/src/main.lua @@ -128,7 +128,8 @@ end "jpeg", "7z", "lua", - "lsqlite3", + "lualibs", + "luv", "uv", "http-parser", } diff --git a/src/emu/luaengine.cpp b/src/emu/luaengine.cpp index c4136cd744a..dbf3d383093 100644 --- a/src/emu/luaengine.cpp +++ b/src/emu/luaengine.cpp @@ -18,6 +18,7 @@ #include "ui/ui.h" #include "luaengine.h" #include +#include "libuv/include/uv.h" //************************************************************************** // LUA ENGINE @@ -46,6 +47,10 @@ lua_engine* lua_engine::luaThis = nullptr; extern "C" { int luaopen_lsqlite3(lua_State *L); + int luaopen_zlib(lua_State *L); + int luaopen_luv(lua_State *L); + int luaopen_lfs(lua_State *L); + uv_loop_t* luv_loop(lua_State* L); } static void lstop(lua_State *L, lua_Debug *ar) @@ -886,8 +891,24 @@ lua_engine::lua_engine() lua_gc(m_lua_state, LUA_GCSTOP, 0); /* stop collector during initialization */ luaL_openlibs(m_lua_state); /* open libraries */ - luaopen_lsqlite3(m_lua_state); + // Get package.preload so we can store builtins in it. + lua_getglobal(m_lua_state, "package"); + lua_getfield(m_lua_state, -1, "preload"); + lua_remove(m_lua_state, -2); // Remove package + // Store uv module definition at preload.uv + lua_pushcfunction(m_lua_state, luaopen_luv); + lua_setfield(m_lua_state, -2, "luv"); + + lua_pushcfunction(m_lua_state, luaopen_zlib); + lua_setfield(m_lua_state, -2, "zlib"); + + lua_pushcfunction(m_lua_state, luaopen_lsqlite3); + lua_setfield(m_lua_state, -2, "lsqlite3"); + + lua_pushcfunction(m_lua_state, luaopen_lfs); + lua_setfield(m_lua_state, -2, "lfs"); + luaopen_ioport(m_lua_state); lua_gc(m_lua_state, LUA_GCRESTART, 0); @@ -1050,33 +1071,37 @@ void lua_engine::periodic_check() { std::lock_guard lock(g_mutex); if (msg.ready == 1) { - lua_settop(m_lua_state, 0); - int status = luaL_loadbuffer(m_lua_state, msg.text.c_str(), msg.text.length(), "=stdin"); - if (incomplete(status)==0) /* cannot try to add lines? */ - { - if (status == LUA_OK) status = docall(0, LUA_MULTRET); - report(status); - if (status == LUA_OK && lua_gettop(m_lua_state) > 0) /* any result to print? */ + lua_settop(m_lua_state, 0); + int status = luaL_loadbuffer(m_lua_state, msg.text.c_str(), msg.text.length(), "=stdin"); + if (incomplete(status)==0) /* cannot try to add lines? */ { - luaL_checkstack(m_lua_state, LUA_MINSTACK, "too many results to print"); - lua_getglobal(m_lua_state, "print"); - lua_insert(m_lua_state, 1); - if (lua_pcall(m_lua_state, lua_gettop(m_lua_state) - 1, 0, 0) != LUA_OK) - lua_writestringerror("%s\n", lua_pushfstring(m_lua_state, - "error calling " LUA_QL("print") " (%s)", - lua_tostring(m_lua_state, -1))); + if (status == LUA_OK) status = docall(0, LUA_MULTRET); + report(status); + if (status == LUA_OK && lua_gettop(m_lua_state) > 0) /* any result to print? */ + { + luaL_checkstack(m_lua_state, LUA_MINSTACK, "too many results to print"); + lua_getglobal(m_lua_state, "print"); + lua_insert(m_lua_state, 1); + if (lua_pcall(m_lua_state, lua_gettop(m_lua_state) - 1, 0, 0) != LUA_OK) + lua_writestringerror("%s\n", lua_pushfstring(m_lua_state, + "error calling " LUA_QL("print") " (%s)", + lua_tostring(m_lua_state, -1))); + } } + else + { + status = -1; + } + msg.status = status; + msg.response = msg.text; + msg.text = ""; + msg.ready = 0; + msg.done = 1; } - else - { - status = -1; - } - msg.status = status; - msg.response = msg.text; - msg.text = ""; - msg.ready = 0; - msg.done = 1; - } + auto loop = luv_loop(m_lua_state); + if (loop!=nullptr) + uv_run(loop, UV_RUN_NOWAIT); + } //-------------------------------------------------