summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2016-02-14 08:16:35 +0100
committer Miodrag Milanovic <mmicko@gmail.com>2016-02-14 08:16:35 +0100
commit2db49088141b6238e92aecc4c073076a02c73065 (patch)
treedba4ea354a0dec2d986fd49de943e5f30b81f8a1
parent80e8fe80e6354acc7157bd82066e719365642a1b (diff)
Added lua-zlib, lfs and luv support for LUA, exposed all using luaengine (nw)
-rw-r--r--3rdparty/lua-zlib/.gitattributes1
-rw-r--r--3rdparty/lua-zlib/CMakeLists.txt62
-rw-r--r--3rdparty/lua-zlib/Makefile62
-rw-r--r--3rdparty/lua-zlib/README151
-rw-r--r--3rdparty/lua-zlib/amnon_david.gzbin0 -> 65 bytes
-rw-r--r--3rdparty/lua-zlib/cmake/Modules/FindLuaJIT.cmake63
-rw-r--r--3rdparty/lua-zlib/lua_zlib.c401
-rw-r--r--3rdparty/lua-zlib/rockspec35
-rw-r--r--3rdparty/lua-zlib/tap.lua24
-rw-r--r--3rdparty/lua-zlib/test.lua198
-rw-r--r--3rdparty/lua-zlib/tom_macwright.gz4
-rw-r--r--3rdparty/lua-zlib/tom_macwright.outbin0 -> 245 bytes
-rw-r--r--3rdparty/lua-zlib/zlib.def2
-rw-r--r--3rdparty/luafilesystem/.travis.yml33
-rw-r--r--3rdparty/luafilesystem/.travis/platform.sh15
-rw-r--r--3rdparty/luafilesystem/.travis/setup_lua.sh101
-rw-r--r--3rdparty/luafilesystem/LICENSE21
-rw-r--r--3rdparty/luafilesystem/Makefile25
-rw-r--r--3rdparty/luafilesystem/Makefile.win25
-rw-r--r--3rdparty/luafilesystem/README23
-rw-r--r--3rdparty/luafilesystem/config24
-rw-r--r--3rdparty/luafilesystem/config.win19
-rw-r--r--3rdparty/luafilesystem/doc/us/doc.css212
-rw-r--r--3rdparty/luafilesystem/doc/us/examples.html103
-rw-r--r--3rdparty/luafilesystem/doc/us/index.html218
-rw-r--r--3rdparty/luafilesystem/doc/us/license.html122
-rw-r--r--3rdparty/luafilesystem/doc/us/luafilesystem.pngbin0 -> 8535 bytes
-rw-r--r--3rdparty/luafilesystem/doc/us/manual.html280
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.3.0-1.rockspec27
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-1.rockspec27
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.0-2.rockspec43
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1-1.rockspec43
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.1rc1-1.rockspec43
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.4.2-1.rockspec26
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.5.0-1.rockspec27
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.0-1.rockspec27
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.1-1.rockspec27
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.2-1.rockspec27
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-1.6.3-1.rockspec28
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-1.rockspec44
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-2.rockspec26
-rw-r--r--3rdparty/luafilesystem/rockspecs/luafilesystem-cvs-3.rockspec27
-rw-r--r--3rdparty/luafilesystem/src/.gitignore2
-rw-r--r--3rdparty/luafilesystem/src/lfs.c906
-rw-r--r--3rdparty/luafilesystem/src/lfs.def4
-rw-r--r--3rdparty/luafilesystem/src/lfs.h34
-rw-r--r--3rdparty/luafilesystem/tests/test.lua175
-rw-r--r--3rdparty/luafilesystem/vc6/lfs.def5
-rw-r--r--3rdparty/luafilesystem/vc6/luafilesystem.dsw33
-rw-r--r--3rdparty/luafilesystem/vc6/luafilesystem_dll.dsp127
-rw-r--r--3rdparty/luv/.ci/install.bat270
-rw-r--r--3rdparty/luv/.ci/platform.sh15
-rw-r--r--3rdparty/luv/.ci/set_compiler_env.bat40
-rw-r--r--3rdparty/luv/.ci/setenv_lua.sh3
-rw-r--r--3rdparty/luv/.ci/setup_lua.sh122
-rw-r--r--3rdparty/luv/.ci/winmake.bat457
-rw-r--r--3rdparty/luv/.gitignore10
-rw-r--r--3rdparty/luv/.travis.yml36
-rw-r--r--3rdparty/luv/CMakeLists.txt191
-rw-r--r--3rdparty/luv/LICENSE.txt202
-rw-r--r--3rdparty/luv/Makefile61
-rw-r--r--3rdparty/luv/README.md213
-rw-r--r--3rdparty/luv/appveyor.yml42
-rw-r--r--3rdparty/luv/cmake/Modules/FindLibuv.cmake11
-rw-r--r--3rdparty/luv/cmake/Modules/FindLuaJIT.cmake55
-rw-r--r--3rdparty/luv/deps/lua.cmake128
-rw-r--r--3rdparty/luv/deps/lua_one.c97
-rw-r--r--3rdparty/luv/deps/luajit.cmake407
-rw-r--r--3rdparty/luv/deps/uv.cmake224
-rw-r--r--3rdparty/luv/docs.md1309
-rw-r--r--3rdparty/luv/examples/cqueues-main.lua31
-rw-r--r--3rdparty/luv/examples/cqueues-slave.lua55
-rw-r--r--3rdparty/luv/examples/echo-server-client.lua68
-rw-r--r--3rdparty/luv/examples/killing-children.lua24
-rw-r--r--3rdparty/luv/examples/lots-o-dns.lua49
-rw-r--r--3rdparty/luv/examples/repl.lua89
-rw-r--r--3rdparty/luv/examples/talking-to-children.lua47
-rw-r--r--3rdparty/luv/examples/tcp-cluster.lua84
-rw-r--r--3rdparty/luv/examples/timers.lua68
-rw-r--r--3rdparty/luv/examples/uvbook/helloworld.lua5
-rw-r--r--3rdparty/luv/examples/uvbook/idle-basic.lua14
-rw-r--r--3rdparty/luv/examples/uvbook/onchange.lua30
-rw-r--r--3rdparty/luv/examples/uvbook/queue-work.lua19
-rw-r--r--3rdparty/luv/examples/uvbook/tcp-echo-client.lua21
-rw-r--r--3rdparty/luv/examples/uvbook/tcp-echo-server.lua22
-rw-r--r--3rdparty/luv/examples/uvbook/thread-create.lua38
-rw-r--r--3rdparty/luv/examples/uvbook/uvcat.lua37
-rw-r--r--3rdparty/luv/examples/uvbook/uvtee.lua35
-rw-r--r--3rdparty/luv/lib/tap.lua165
-rw-r--r--3rdparty/luv/lib/utils.lua165
-rw-r--r--3rdparty/luv/luv-1.8.0-4.rockspec34
-rw-r--r--3rdparty/luv/msvcbuild.bat13
-rw-r--r--3rdparty/luv/src/async.c63
-rw-r--r--3rdparty/luv/src/check.c59
-rw-r--r--3rdparty/luv/src/constants.c649
-rw-r--r--3rdparty/luv/src/dns.c296
-rw-r--r--3rdparty/luv/src/fs.c614
-rw-r--r--3rdparty/luv/src/fs_event.c97
-rw-r--r--3rdparty/luv/src/fs_poll.c90
-rw-r--r--3rdparty/luv/src/handle.c173
-rw-r--r--3rdparty/luv/src/idle.c59
-rw-r--r--3rdparty/luv/src/lhandle.c116
-rw-r--r--3rdparty/luv/src/lhandle.h67
-rw-r--r--3rdparty/luv/src/loop.c92
-rw-r--r--3rdparty/luv/src/lreq.c71
-rw-r--r--3rdparty/luv/src/lreq.h43
-rw-r--r--3rdparty/luv/src/lthreadpool.h48
-rw-r--r--3rdparty/luv/src/luv.c519
-rw-r--r--3rdparty/luv/src/luv.h109
-rw-r--r--3rdparty/luv/src/misc.c316
-rw-r--r--3rdparty/luv/src/pipe.c114
-rw-r--r--3rdparty/luv/src/poll.c100
-rw-r--r--3rdparty/luv/src/prepare.c59
-rw-r--r--3rdparty/luv/src/process.c266
-rw-r--r--3rdparty/luv/src/req.c52
-rw-r--r--3rdparty/luv/src/schema.c16
-rw-r--r--3rdparty/luv/src/signal.c72
-rw-r--r--3rdparty/luv/src/stream.c263
-rw-r--r--3rdparty/luv/src/tcp.c182
-rw-r--r--3rdparty/luv/src/thread.c353
-rw-r--r--3rdparty/luv/src/timer.c84
-rw-r--r--3rdparty/luv/src/tty.c65
-rw-r--r--3rdparty/luv/src/udp.c260
-rw-r--r--3rdparty/luv/src/util.c56
-rw-r--r--3rdparty/luv/src/util.h26
-rw-r--r--3rdparty/luv/src/work.c224
-rw-r--r--3rdparty/luv/tests/manual-test-cluster.lua213
-rw-r--r--3rdparty/luv/tests/run.lua33
-rw-r--r--3rdparty/luv/tests/test-async.lua32
-rw-r--r--3rdparty/luv/tests/test-conversions.lua6
-rw-r--r--3rdparty/luv/tests/test-dns.lua125
-rw-r--r--3rdparty/luv/tests/test-fs.lua90
-rw-r--r--3rdparty/luv/tests/test-leaks.lua186
-rw-r--r--3rdparty/luv/tests/test-misc.lua85
-rw-r--r--3rdparty/luv/tests/test-prepare-check-idle-async.lua49
-rw-r--r--3rdparty/luv/tests/test-process.lua101
-rw-r--r--3rdparty/luv/tests/test-sigchld-after-lua_close.sh45
-rw-r--r--3rdparty/luv/tests/test-signal.lua40
-rw-r--r--3rdparty/luv/tests/test-tcp.lua114
-rw-r--r--3rdparty/luv/tests/test-thread.lua47
-rw-r--r--3rdparty/luv/tests/test-timer.lua87
-rw-r--r--3rdparty/luv/tests/test-work.lua48
-rw-r--r--scripts/genie.lua5
-rw-r--r--scripts/src/3rdparty.lua73
-rw-r--r--scripts/src/main.lua3
-rw-r--r--src/emu/luaengine.cpp75
146 files changed, 16054 insertions, 34 deletions
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) <platform>"
+ @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 <maherb at brimworks dot com>
+* 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 <platform>
+
+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 00000000000..c56de231d1a
--- /dev/null
+++ b/3rdparty/lua-zlib/amnon_david.gz
Binary files differ
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 <ctype.h>
+#include <lauxlib.h>
+#include <lua.h>
+#include <stdlib.h>
+#include <string.h>
+#include <zlib.h>
+
+/*
+ * ** 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); /* <empty> */
+}
+
+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); /* <empty> */
+}
+
+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ýÎ*f–Igò(ˆèüüN“éL#mÄí[\‚—‡scÉy®Ðê*=&òNŒïƒ:'–…I˜1Yi[ØpŒ£z…U–
+Žóä¼íR?0J§îzãQê­ñÖ%I…wÊ
+÷’áâcÇ©Â)‡øù͢ÃülbÉgФÉ!·¤áˆŒ¨vºŸ¬ò§®®K‚½¾ ”E¶F}šÊ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 00000000000..ca88bcb6c2d
--- /dev/null
+++ b/3rdparty/lua-zlib/tom_macwright.out
Binary files differ
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 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>LuaFileSystem</title>
+ <link rel="stylesheet" href="doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org">
+ <img alt="LuaFileSystem" src="luafilesystem.png"/>
+ </a>
+ </div>
+ <div id="product_name"><big><strong>LuaFileSystem</strong></big></div>
+ <div id="product_description">File System Library for the Lua Programming Language</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaFileSystem</h1>
+ <ul>
+ <li><a href="index.html">Home</a>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact us</a></li>
+ </ul>
+ </li>
+ <li><a href="manual.html">Manual</a>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#building">Building</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><strong>Examples</strong></li>
+ <li><a href="https://github.com/keplerproject/luafilesystem">Project</a>
+ <ul>
+ <li><a href="https://github.com/keplerproject/luafilesystem/issues">Bug Tracker</a></li>
+ <li><a href="https://github.com/keplerproject/luafilesystem">Git</a></li>
+ </ul>
+ </li>
+ <li><a href="license.html">License</a></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h2><a name="example"></a>Examples</h2>
+
+<h3>Directory iterator</h3>
+
+<p>The following example iterates over a directory and recursively lists the
+attributes for each file inside it.</p>
+
+<pre class="example">
+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 (".")
+</pre>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.0!</a></p>
+ <p><small>$Id: examples.html,v 1.8 2007/12/14 15:28:04 carregal Exp $</small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
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 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>LuaFileSystem</title>
+ <link rel="stylesheet" href="doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org">
+ <img alt="LuaFileSystem" src="luafilesystem.png"/>
+ </a>
+ </div>
+ <div id="product_name"><big><strong>LuaFileSystem</strong></big></div>
+ <div id="product_description">File System Library for the Lua Programming Language</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaFileSystem</h1>
+ <ul>
+ <li><strong>Home</strong>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact us</a></li>
+ </ul>
+ </li>
+ <li><a href="manual.html">Manual</a>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#building">Building</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><a href="examples.html">Examples</a></li>
+ <li><a href="https://github.com/keplerproject/luafilesystem">Project</a>
+ <ul>
+ <li><a href="https://github.com/keplerproject/luafilesystem/issues">Bug Tracker</a></li>
+ <li><a href="https://github.com/keplerproject/luafilesystem">Git</a></li>
+ </ul>
+ </li>
+ <li><a href="license.html">License</a></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h2><a name="overview"></a>Overview</h2>
+
+<p>LuaFileSystem is a <a href="http://www.lua.org">Lua</a> library
+developed to complement the set of functions related to file
+systems offered by the standard Lua distribution.</p>
+
+<p>LuaFileSystem offers a portable way to access
+the underlying directory structure and file attributes.</p>
+
+<p>LuaFileSystem is free software and uses the same
+<a href="license.html">license</a> as Lua 5.1.</p>
+
+<h2><a name="status"></a>Status</h2>
+
+<p>Current version is 1.6.3. It works with Lua 5.1, 5.2 and 5.3.</p>
+
+<h2><a name="download"></a>Download</h2>
+
+<p>LuaFileSystem source can be downloaded from its
+<a href="http://github.com/keplerproject/luafilesystem">Github</a>
+page.</p>
+
+<h2><a name="history"></a>History</h2>
+
+<dl class="history">
+ <dt><strong>Version 1.6.3</strong> [15/Jan/2015]</dt>
+ <dd><ul>
+ <li>Lua 5.3 support.</li>
+ <li>Assorted bugfixes.</li>
+ </ul></dd>
+
+ <dt><strong>Version 1.6.2</strong> [??/Oct/2012]</dt>
+ <dd><ul>
+ <li>Full Lua 5.2 compatibility (with Lua 5.1 fallbacks)</li>
+ </ul></dd>
+
+ <dt><strong>Version 1.6.1</strong> [01/Oct/2012]</dt>
+ <dd><ul>
+ <li>fix build for Lua 5.2</li>
+ </ul></dd>
+
+ <dt><strong>Version 1.6.0</strong> [26/Sep/2012]</dt>
+ <dd><ul>
+ <li>getcwd fix for Android</li>
+ <li>support for Lua 5.2</li>
+ <li>add lfs.link</li>
+ <li>other bug fixes</li>
+ </ul></dd>
+
+ <dt><strong>Version 1.5.0</strong> [20/Oct/2009]</dt>
+ <dd><ul>
+ <li>Added explicit next and close methods to second return value of lfs.dir
+(the directory object), for explicit iteration or explicit closing.</li>
+ <li>Added directory locking via lfs.lock_dir function (see the <a href="manual.html">manual</a>).</li>
+ </ul></dd>
+ <dt><strong>Version 1.4.2</strong> [03/Feb/2009]</dt>
+ <dd>
+ <ul>
+ <li>fixed bug [<a href="http://luaforge.net/tracker/?func=detail&amp;group_id=66&amp;aid=13198&amp;atid=356">#13198</a>]
+ lfs.attributes(filename, 'size') overflow on files > 2 Gb again (bug report and patch by KUBO Takehiro).</li>
+ <li>fixed bug [<a href="http://luaforge.net/tracker/?group_id=66&amp;atid=356&amp;func=detail&amp;aid=39794">#39794</a>]
+ Compile error on Solaris 10 (bug report and patch by Aaron B).</li>
+ <li>fixed compilation problems with Borland C.</li>
+ </ul>
+ </dd>
+
+ <dt><strong>Version 1.4.1</strong> [07/May/2008]</dt>
+ <dd>
+ <ul>
+ <li>documentation review</li>
+ <li>fixed Windows compilation issues</li>
+ <li>fixed bug in the Windows tests (patch by Shmuel Zeigerman)</li>
+ <li>fixed bug [<a href="http://luaforge.net/tracker/?func=detail&amp;group_id=66&amp;aid=2185&amp;atid=356">#2185</a>]
+ <code>lfs.attributes(filename, 'size')</code> overflow on files > 2 Gb
+ </li>
+ </ul>
+ </dd>
+
+ <dt><strong>Version 1.4.0</strong> [13/Feb/2008]</dt>
+ <dd>
+ <ul>
+ <li>added function
+ <a href="manual.html#setmode"><code>lfs.setmode</code></a>
+ (works only in Windows systems).</li>
+ <li><a href="manual.html#attributes"><code>lfs.attributes</code></a>
+ raises an error if attribute does not exist</li>
+ </ul>
+ </dd>
+
+ <dt><strong>Version 1.3.0</strong> [26/Oct/2007]</dt>
+ <dd>
+ <ul>
+ <li>added function
+ <a href="manual.html#symlinkattributes"><code>lfs.symlinkattributes</code></a>
+ (works only in non Windows systems).</li>
+ </ul>
+ </dd>
+
+ <dt><strong>Version 1.2.1</strong> [08/May/2007]</dt>
+ <dd>
+ <ul>
+ <li>compatible only with Lua 5.1 (Lua 5.0 support was dropped)</li>
+ </ul>
+ </dd>
+
+ <dt><strong>Version 1.2</strong> [15/Mar/2006]</dt>
+ <dd>
+ <ul>
+ <li>added optional argument to
+ <a href="manual.html#attributes"><code>lfs.attributes</code></a></li>
+ <li>added function
+ <a href="manual.html#rmdir"><code>lfs.rmdir</code></a></li>
+ <li>bug correction on <a href="manual.html#dir"><code>lfs.dir</code></a></li>
+ </ul>
+ </dd>
+
+ <dt><strong>Version 1.1</strong> [30/May/2005]</dt>
+ <dd>
+ <ul>
+ <li>added function <a href="manual.html#touch"><code>lfs.touch</code></a>.</li>
+ </ul>
+ </dd>
+
+ <dt><strong>Version 1.0</strong> [21/Jan/2005]</dt>
+ <dd />
+
+ <dt><strong>Version 1.0 Beta</strong> [10/Nov/2004]</dt>
+ <dd />
+</dl>
+
+<h2><a name="credits"></a>Credits</h2>
+
+<p>LuaFileSystem was designed by Roberto Ierusalimschy,
+Andr&eacute; Carregal and Tom&aacute;s Guisasola as part of the
+<a href="http://www.keplerproject.org">Kepler Project</a>,
+which holds its copyright. LuaFileSystem is currently maintained by F&aacute;bio Mascarenhas.</p>
+
+<h2><a name="contact"></a>Contact us</h2>
+
+<p>For more information please
+<a href="mailto:info-NO-SPAM-THANKS@keplerproject.org">contact us</a>.
+Comments are welcome!</p>
+
+<p>You can also reach other Kepler developers and users on the Kepler Project
+<a href="http://luaforge.net/mail/?group_id=104">mailing list</a>.</p>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.0!</a></p>
+ <p><small>$Id: index.html,v 1.44 2009/02/04 21:21:33 carregal Exp $</small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
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 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>LuaFileSystem</title>
+ <link rel="stylesheet" href="doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org">
+ <img alt="LuaFileSystem" src="luafilesystem.png"/>
+ </a>
+ </div>
+ <div id="product_name"><big><strong>LuaFileSystem</strong></big></div>
+ <div id="product_description">File System Library for the Lua Programming Language</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaFileSystem</h1>
+ <ul>
+ <li><a href="index.html">Home</a>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact us</a></li>
+ </ul>
+ </li>
+ <li><a href="manual.html">Manual</a>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#building">Building</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><a href="examples.html">Examples</a></li>
+ <li><a href="https://github.com/keplerproject/luafilesystem">Project</a>
+ <ul>
+ <li><a href="https://github.com/keplerproject/luafilesystem/issues/">Bug Tracker</a></li>
+ <li><a href="https://github.com/keplerproject/luafilesystem">Git</a></li>
+ </ul>
+ </li>
+ <li><strong>License</strong></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h1>License</h1>
+
+<p>
+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
+<a href="http://www.opensource.org/docs/definition.html">Open Source</a>
+software.
+Its licenses are compatible with
+<a href="http://www.gnu.org/licenses/gpl.html">GPL</a>.
+LuaFileSystem is not in the public domain and the
+<a href="http://www.keplerproject.org">Kepler Project</a>
+keep its copyright.
+The legal details are below.
+</p>
+
+<p>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.</p>
+
+<p>The LuaFileSystem library is designed and implemented by Roberto
+Ierusalimschy, Andr&eacute; Carregal and Tom&aacute;s Guisasola.
+The implementation is not derived from licensed software.</p>
+
+<hr/>
+<p>Copyright &copy; 2003 Kepler Project.</p>
+
+<p>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:</p>
+
+<p>The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.</p>
+
+<p>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.</p>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.0!</a></p>
+ <p><small>$Id: license.html,v 1.13 2008/02/11 22:42:21 carregal Exp $</small></p>
+</div><!-- id="about" -->
+
+</div><!-- id="container" -->
+
+</body>
+</html>
diff --git a/3rdparty/luafilesystem/doc/us/luafilesystem.png b/3rdparty/luafilesystem/doc/us/luafilesystem.png
new file mode 100644
index 00000000000..e1dd8c65b52
--- /dev/null
+++ b/3rdparty/luafilesystem/doc/us/luafilesystem.png
Binary files differ
diff --git a/3rdparty/luafilesystem/doc/us/manual.html b/3rdparty/luafilesystem/doc/us/manual.html
new file mode 100644
index 00000000000..33c1cbea573
--- /dev/null
+++ b/3rdparty/luafilesystem/doc/us/manual.html
@@ -0,0 +1,280 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>LuaFileSystem</title>
+ <link rel="stylesheet" href="doc.css" type="text/css"/>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+</head>
+
+<body>
+
+<div id="container">
+
+<div id="product">
+ <div id="product_logo">
+ <a href="http://www.keplerproject.org"><img alt="LuaFileSystem" src="luafilesystem.png"/></a>
+ </div>
+ <div id="product_name"><big><strong>LuaFileSystem</strong></big></div>
+ <div id="product_description">File System Library for the Lua Programming Language</div>
+</div> <!-- id="product" -->
+
+<div id="main">
+
+<div id="navigation">
+<h1>LuaFileSystem</h1>
+ <ul>
+ <li><a href="index.html">Home</a>
+ <ul>
+ <li><a href="index.html#overview">Overview</a></li>
+ <li><a href="index.html#status">Status</a></li>
+ <li><a href="index.html#download">Download</a></li>
+ <li><a href="index.html#history">History</a></li>
+ <li><a href="index.html#credits">Credits</a></li>
+ <li><a href="index.html#contact">Contact us</a></li>
+ </ul>
+ </li>
+ <li><strong>Manual</strong>
+ <ul>
+ <li><a href="manual.html#introduction">Introduction</a></li>
+ <li><a href="manual.html#building">Building</a></li>
+ <li><a href="manual.html#installation">Installation</a></li>
+ <li><a href="manual.html#reference">Reference</a></li>
+ </ul>
+ </li>
+ <li><a href="examples.html">Examples</a></li>
+ <li><a href="https://github.com/keplerproject/luafilesystem">Project</a>
+ <ul>
+ <li><a href="https://github.com/keplerproject/luafilesystem/issues">Bug Tracker</a></li>
+ <li><a href="https://github.com/keplerproject/luafilesystem">Git</a></li>
+ </ul>
+ </li>
+ <li><a href="license.html">License</a></li>
+ </ul>
+</div> <!-- id="navigation" -->
+
+<div id="content">
+
+<h2><a name="introduction"></a>Introduction</h2>
+
+<p>LuaFileSystem is a <a href="http://www.lua.org">Lua</a> library
+developed to complement the set of functions related to file
+systems offered by the standard Lua distribution.</p>
+
+<p>LuaFileSystem offers a portable way to access
+the underlying directory structure and file attributes.</p>
+
+<h2><a name="building"></a>Building</h2>
+
+<p>
+LuaFileSystem should be built with Lua 5.1 so the language library
+and header files for the target version must be installed properly.
+</p>
+
+<p>
+LuaFileSystem offers a Makefile and a separate configuration file,
+<code>config</code>,
+which should be edited to suit your installation before running
+<code>make</code>.
+The file has some definitions like paths to the external libraries,
+compiler options and the like.
+</p>
+
+<p>On Windows, the C runtime used to compile LuaFileSystem must be the same
+runtime that Lua uses, or some LuaFileSystem functions will not work.</p>
+
+<h2><a name="installation"></a>Installation</h2>
+
+<p>The easiest way to install LuaFileSystem is to use LuaRocks:</p>
+
+<pre class="example">
+luarocks install luafilesystem
+</pre>
+
+<p>If you prefer to install LuaFileSystem manually, the compiled binary should be copied to a directory in your
+<a href="http://www.lua.org/manual/5.1/manual.html#pdf-package.cpath">C path</a>.</p>
+
+<h2><a name="reference"></a>Reference</h2>
+
+<p>
+LuaFileSystem offers the following functions:
+</p>
+
+<dl class="reference">
+ <dt><a name="attributes"></a><strong><code>lfs.attributes (filepath [, aname])</code></strong></dt>
+ <dd>Returns a table with the file attributes corresponding to
+ <code>filepath</code> (or <code>nil</code> 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
+ <code>lfs.attributes(filepath).aname</code>, but the table is not created
+ and only one attribute is retrieved from the O.S.).
+ The attributes are described as follows;
+ attribute <code>mode</code> is a string, all the others are numbers,
+ and the time related attributes use the same time reference of
+ <a href="http://www.lua.org/manual/5.1/manual.html#pdf-os.time"><code>os.time</code></a>:
+ <dl>
+ <dt><strong><code>dev</code></strong></dt>
+ <dd>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</dd>
+
+ <dt><strong><code>ino</code></strong></dt>
+ <dd>on Unix systems, this represents the inode number. On Windows systems this has no meaning</dd>
+
+ <dt><strong><code>mode</code></strong></dt>
+ <dd>string representing the associated protection mode (the values could be
+ <code>file</code>, <code>directory</code>, <code>link</code>, <code>socket</code>,
+ <code>named pipe</code>, <code>char device</code>, <code>block device</code> or
+ <code>other</code>)</dd>
+
+ <dt><strong><code>nlink</code></strong></dt>
+ <dd>number of hard links to the file</dd>
+
+ <dt><strong><code>uid</code></strong></dt>
+ <dd>user-id of owner (Unix only, always 0 on Windows)</dd>
+
+ <dt><strong><code>gid</code></strong></dt>
+ <dd>group-id of owner (Unix only, always 0 on Windows)</dd>
+
+ <dt><strong><code>rdev</code></strong></dt>
+ <dd>on Unix systems, represents the device type, for special file inodes.
+ On Windows systems represents the same as <code>dev</code></dd>
+
+ <dt><strong><code>access</code></strong></dt>
+ <dd>time of last access</dd>
+
+ <dt><strong><code>modification</code></strong></dt>
+ <dd>time of last data modification</dd>
+
+ <dt><strong><code>change</code></strong></dt>
+ <dd>time of last file status change</dd>
+
+ <dt><strong><code>size</code></strong></dt>
+ <dd>file size, in bytes</dd>
+
+ <dt><strong><code>blocks</code></strong></dt>
+ <dd>block allocated for file; (Unix only)</dd>
+
+ <dt><strong><code>blksize</code></strong></dt>
+ <dd>optimal file system I/O blocksize; (Unix only)</dd>
+ </dl>
+ This function uses <code>stat</code> internally thus if the given
+ <code>filepath</code> 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
+ <a href="#symlinkattributes">lfs.symlinkattributes</a>.
+ </dd>
+
+ <dt><a name="chdir"></a><strong><code>lfs.chdir (path)</code></strong></dt>
+ <dd>Changes the current working directory to the given
+ <code>path</code>.<br />
+ Returns <code>true</code> in case of success or <code>nil</code> plus an
+ error string.</dd>
+
+ <dt><a name="chdir"></a><strong><code>lfs.lock_dir(path, [seconds_stale])</code></strong></dt>
+ <dd>Creates a lockfile (called lockfile.lfs) in <code>path</code> 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 <code>INT_MAX</code>, which in practice means the lock will never
+ be stale. To free the the lock call <code>lock:free()</code>. <br/>
+ 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.</dd>
+
+ <dt><a name="getcwd"></a><strong><code>lfs.currentdir ()</code></strong></dt>
+ <dd>Returns a string with the current working directory or <code>nil</code>
+ plus an error string.</dd>
+
+ <dt><a name="dir"></a><strong><code>iter, dir_obj = lfs.dir (path)</code></strong></dt>
+ <dd>
+ Lua iterator over the entries of a given directory.
+ Each time the iterator is called with <code>dir_obj</code> it returns a directory entry's name as a string, or
+ <code>nil</code> if there are no more entries. You can also iterate by calling <code>dir_obj:next()</code>, and
+ explicitly close the directory before the iteration finished with <code>dir_obj:close()</code>.
+ Raises an error if <code>path</code> is not a directory.
+ </dd>
+
+ <dt><a name="lock"></a><strong><code>lfs.lock (filehandle, mode[, start[, length]])</code></strong></dt>
+ <dd>Locks a file or a part of it. This function works on <em>open files</em>; the
+ file handle should be specified as the first argument.
+ The string <code>mode</code> could be either
+ <code>r</code> (for a read/shared lock) or <code>w</code> (for a
+ write/exclusive lock). The optional arguments <code>start</code>
+ and <code>length</code> can be used to specify a starting point and
+ its length; both should be numbers.<br />
+ Returns <code>true</code> if the operation was successful; in
+ case of error, it returns <code>nil</code> plus an error string.
+ </dd>
+
+ <dt><a name="link"></a><strong><code>lfs.link (old, new[, symlink])</code></strong></dt>
+ <dd>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).
+ </dd>
+
+ <dt><a name="mkdir"></a><strong><code>lfs.mkdir (dirname)</code></strong></dt>
+ <dd>Creates a new directory. The argument is the name of the new
+ directory.<br />
+ Returns <code>true</code> if the operation was successful;
+ in case of error, it returns <code>nil</code> plus an error string.
+ </dd>
+
+ <dt><a name="rmdir"></a><strong><code>lfs.rmdir (dirname)</code></strong></dt>
+ <dd>Removes an existing directory. The argument is the name of the directory.<br />
+ Returns <code>true</code> if the operation was successful;
+ in case of error, it returns <code>nil</code> plus an error string.</dd>
+
+ <dt><a name="setmode"></a><strong><code>lfs.setmode (file, mode)</code></strong></dt>
+ <dd>Sets the writing mode for a file. The mode string can be either <code>"binary"</code> or <code>"text"</code>.
+ Returns <code>true</code> followed the previous mode string for the file, or
+ <code>nil</code> 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 <code>binary</code>.
+ </dd>
+
+ <dt><a name="symlinkattributes"></a><strong><code>lfs.symlinkattributes (filepath [, aname])</code></strong></dt>
+ <dd>Identical to <a href="#attributes">lfs.attributes</a> 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
+ <code>lfs.attributes</code>.
+ </dd>
+
+ <dt><a name="touch"></a><strong><code>lfs.touch (filepath [, atime [, mtime]])</code></strong></dt>
+ <dd>Set access and modification times of a file. This function is
+ a bind to <code>utime</code> function. The first argument is the
+ filename, the second argument (<code>atime</code>) is the access time,
+ and the third argument (<code>mtime</code>) is the modification time.
+ Both times are provided in seconds (which should be generated with
+ Lua standard function <code>os.time</code>).
+ If the modification time is omitted, the access time provided is used;
+ if both times are omitted, the current time is used.<br />
+ Returns <code>true</code> if the operation was successful;
+ in case of error, it returns <code>nil</code> plus an error string.
+ </dd>
+
+ <dt><a name="unlock"></a><strong><code>lfs.unlock (filehandle[, start[, length]])</code></strong></dt>
+ <dd>Unlocks a file or a part of it. This function works on
+ <em>open files</em>; the file handle should be specified as the first
+ argument. The optional arguments <code>start</code> and
+ <code>length</code> can be used to specify a starting point and its
+ length; both should be numbers.<br />
+ Returns <code>true</code> if the operation was successful;
+ in case of error, it returns <code>nil</code> plus an error string.
+ </dd>
+</dl>
+
+</div> <!-- id="content" -->
+
+</div> <!-- id="main" -->
+
+<div id="about">
+ <p><a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.0!</a></p>
+ <p><small>$Id: manual.html,v 1.45 2009/06/03 20:53:55 mascarenhas Exp $</small></p>
+</div> <!-- id="about" -->
+
+</div> <!-- id="container" -->
+
+</body>
+</html>
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 <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <windows.h>
+#include <io.h>
+#include <sys/locking.h>
+#ifdef __BORLANDC__
+ #include <utime.h>
+#else
+ #include <sys/utime.h>
+#endif
+#include <fcntl.h>
+#else
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <utime.h>
+#endif
+
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+
+#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 <sys/param.h>
+ #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 <http://git-scm.com>. 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 <eike@sf-mail.de>
+#
+# 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 <ryan at trolocsis.com>
+# 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 <ryan at trolocsis.com>
+# 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 "'<eof>'$" 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 <command> <file1> [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 <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#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 <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+#include "uv.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#if defined(_WIN32)
+# include <fcntl.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# 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 <unistd.h>
+#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 <process.h>
+#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, "<unknown sa family>", INET6_ADDRSTRLEN);
+ strncpy(netmask, "<unknown sa family>", 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 <mutex>
+#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<std::mutex> 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);
+
}
//-------------------------------------------------