├── .gitignore ├── .luacheckrc ├── .travis.yml ├── LICENSE ├── NEWS ├── README.md ├── examples └── pipes.lua ├── spawn-scm-0.rockspec ├── spawn ├── init.lua ├── posix.c └── wait.lua ├── spec └── init_spec.lua └── vendor └── compat-5.3 ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── c-api ├── compat-5.3.c └── compat-5.3.h ├── compat53 ├── init.lua └── module.lua ├── lprefix.h ├── lstrlib.c ├── ltablib.c ├── lutf8lib.c ├── rockspecs ├── compat53-0.1-1.rockspec ├── compat53-0.2-1.rockspec ├── compat53-0.3-1.rockspec ├── compat53-0.4-1.rockspec ├── compat53-0.5-1.rockspec └── compat53-scm-0.rockspec └── tests ├── test.lua └── testmod.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | -------------------------------------------------------------------------------- /.luacheckrc: -------------------------------------------------------------------------------- 1 | std = "min" 2 | files["spec"] = { 3 | std = "+busted"; 4 | } 5 | exclude_files = { 6 | "vendor"; 7 | } 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | sudo: false 4 | 5 | env: 6 | matrix: 7 | - LUA="lua 5.1" 8 | - LUA="lua 5.2" 9 | - LUA="lua 5.3" 10 | - LUA="luajit @" 11 | - LUA="luajit 2.0" 12 | - LUA="luajit 2.1" 13 | 14 | branches: 15 | only: 16 | - master 17 | 18 | before_install: 19 | - pip install hererocks 20 | - hererocks ~/hererocks -r^ --$LUA 21 | - export PATH=$PATH:~/hererocks/bin 22 | - eval `luarocks path --bin` 23 | - luarocks install luacheck 24 | - luarocks install busted 25 | 26 | install: 27 | - luarocks install --only-deps --server=http://luarocks.org/manifests/daurnimator spawn-scm-0.rockspec 28 | 29 | script: 30 | - luacheck . 31 | - luarocks make CFLAGS="-O2 -fPIC -Wall -Wextra -Werror" 32 | - busted 33 | 34 | notifications: 35 | email: 36 | on_success: change 37 | on_failure: always 38 | 39 | cache: 40 | directories: 41 | - $HOME/.cache/hererocks 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2018 Daurnimator 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 0.1 - 2018-08-10 2 | 3 | - Initial release 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A lua library to spawn programs 2 | 3 | ## Status 4 | 5 | [![Build Status](https://travis-ci.org/daurnimator/lua-spawn.svg)](https://travis-ci.org/daurnimator/lua-spawn) 6 | 7 | 8 | ## Features 9 | 10 | - High level functions for common cases 11 | - Bindings to the full `posix_spawn` family of functions 12 | - Compatible with Lua 5.1, 5.2, 5.3 and [LuaJIT](http://luajit.org/) 13 | 14 | Currently only works on POSIXy systems, but the high level module should be portable to Windows; someone just needs to put the work in. 15 | 16 | 17 | ## Installation 18 | 19 | It's recommended to install lua-spawn by using [luarocks](https://luarocks.org/). 20 | This will automatically install run-time lua dependencies for you. 21 | 22 | $ luarocks install spawn 23 | 24 | 25 | ## Rationale 26 | 27 | Spawning a new child program from a lua script is surprisingly hard. 28 | 29 | Existing solutions: 30 | 31 | - [`os.execute`](http://www.lua.org/manual/5.3/manual.html#pdf-os.execute) doesn't allow interaction with any file descriptors 32 | - [`io.popen`](http://www.lua.org/manual/5.3/manual.html#pdf-io.popen) only allows interaction with *one of* `stdin` or `stdout` 33 | - `fork` + `exec` isn't portable to non-MMU or non-unix architectures 34 | 35 | This project uses the [`posix_spawn`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html) family of functions. 36 | -------------------------------------------------------------------------------- /examples/pipes.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | --[[ 3 | This example shows off using lunix to create pipes for the child process 4 | ]] 5 | local posix_spawn = require "spawn.posix" 6 | local unix = require "unix" 7 | 8 | local read, write, pid do 9 | -- file_actions is an ordered list of operations to do before the child process starts 10 | -- you can add operations to it such as `open()`, `dup2()` and `close()` 11 | local file_actions = assert(posix_spawn.new_file_actions()) 12 | -- Create two pipes, one for stdin, one shared by stdout and stderr 13 | -- the first fd returned by pipe() can only be read from 14 | -- the second fd returned by pipe() can only be written to 15 | -- "e" means to enable O_CLOEXEC (this way the other ends of the pipes are closed in the child) 16 | local child_stdin, child_stdout 17 | child_stdin, write = assert(unix.fpipe("e")) 18 | read, child_stdout = assert(unix.fpipe("e")) 19 | -- Tell posix_spawn to dup `child_stdin` to fd 0 in the child 20 | assert(file_actions:adddup2(unix.fileno(child_stdin), 0)) 21 | -- Tell posix_spawn to dup `child_stdout` to fd 1 in the child 22 | assert(file_actions:adddup2(unix.fileno(child_stdout), 1)) 23 | -- Tell posix_spawn to dup fd 1 (which is child_stdout already) to fd 2 (stderr) 24 | assert(file_actions:adddup2(1, 2)) 25 | -- Start the child program: cat 26 | pid = assert(posix_spawn.spawnp("cat", file_actions, nil, {"cat"}, nil)) 27 | -- Close files now owned by the child 28 | child_stdin:close() 29 | child_stdout:close() 30 | end 31 | -- Lets write a string to the child 32 | assert(write:write("foo")) 33 | assert(write:flush()) 34 | -- The child is 'cat': we should be able to read "foo" back 35 | print(read:read(3)) 36 | -- Close the child's stdin. For 'cat' this should result in the program exiting 37 | write:close() 38 | -- Wait for child to exit and print the exit status 39 | print(unix.waitpid(pid)) 40 | -------------------------------------------------------------------------------- /spawn-scm-0.rockspec: -------------------------------------------------------------------------------- 1 | package = "spawn" 2 | version = "scm-0" 3 | source = { 4 | url = "git://github.com/daurnimator/lua-spawn.git"; 5 | } 6 | description = { 7 | summary = "A lua library to spawn programs"; 8 | homepage = "https://github.com/daurnimator/lua-spawn"; 9 | license = "MIT"; 10 | } 11 | supported_platforms = { 12 | "unix"; 13 | } 14 | dependencies = { 15 | "lua >= 5.1, < 5.4"; 16 | "lunix"; 17 | } 18 | build = { 19 | type = "builtin"; 20 | modules = { 21 | ["spawn.init"] = "spawn/init.lua"; 22 | ["spawn.posix"] = { 23 | defines = { 24 | "_POSIX_C_SOURCE=200809L"; 25 | "_GNU_SOURCE"; 26 | }; 27 | incdirs = { "vendor/compat-5.3/c-api/" }; 28 | sources = { 29 | "spawn/posix.c"; 30 | }; 31 | }; 32 | ["spawn.wait"] = "spawn/wait.lua"; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /spawn/init.lua: -------------------------------------------------------------------------------- 1 | local posix = require "spawn.posix" 2 | local wait = require "spawn.wait" 3 | 4 | local function start(program, ...) 5 | return posix.spawnp(program, nil, nil, { program, ... }, nil) 6 | end 7 | 8 | local function run(...) 9 | local pid, err, errno = start(...) 10 | if pid == nil then 11 | return nil, err, errno 12 | end 13 | return wait.waitpid(pid) 14 | end 15 | 16 | local function system(arg) 17 | return run("/bin/sh", "-c", arg) 18 | end 19 | 20 | return { 21 | _VERSION = nil; 22 | start = start; 23 | run = run; 24 | system = system; 25 | } 26 | -------------------------------------------------------------------------------- /spawn/posix.c: -------------------------------------------------------------------------------- 1 | #include /* O_* */ 2 | #include /* sigset_t */ 3 | #include 4 | #include /* strerror */ 5 | #include /* pid_t */ 6 | #include /* _POSIX_PRIORITY_SCHEDULING */ 7 | 8 | #include 9 | #include 10 | #include "compat-5.3.h" 11 | 12 | #ifdef __APPLE__ 13 | #include 14 | #define environ (*_NSGetEnviron()) 15 | #else 16 | extern char** environ; 17 | #endif 18 | 19 | static const char** l_posix_checkarraystrings(lua_State *L, int arg) { 20 | const char **ret; 21 | lua_Integer n, i; 22 | int t; 23 | int abs_arg = lua_absindex(L, arg); 24 | luaL_checktype(L, abs_arg, LUA_TTABLE); 25 | n = lua_rawlen(L, abs_arg); 26 | ret = lua_newuserdata(L, (n+1)*sizeof(char*)); 27 | for (i=0; i /dev/null")}) 11 | end) 12 | it("emulates system() by running a shell", function() 13 | assert.same({true, "exit", 0}, {spawn.system("true")}) 14 | assert.same({nil, "exit", 2}, {spawn.system("exit 2")}) 15 | end) 16 | it("returns exit signal correctly", function() 17 | -- 15 is SIGTERM 18 | assert.same({nil, "signal", 15}, {spawn.system("kill $$")}) 19 | -- 9 is SIGKILL 20 | assert.same({nil, "signal", 9}, {spawn.system("kill -9 $$")}) 21 | end) 22 | end) 23 | -------------------------------------------------------------------------------- /vendor/compat-5.3/.gitignore: -------------------------------------------------------------------------------- 1 | # generated files 2 | *.so 3 | *.dll 4 | *.o 5 | *.obj 6 | HISTO 7 | 8 | # vim temporaries 9 | .*.swp 10 | 11 | -------------------------------------------------------------------------------- /vendor/compat-5.3/.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: gcc 3 | 4 | sudo: false 5 | 6 | env: 7 | - LUA="lua=5.1" 8 | - LUA="lua=5.1" EXTERNAL=true 9 | - LUA="lua=5.1" COMPILER="g++" 10 | - LUA="lua=5.1" EXTERNAL=true COMPILER="g++" 11 | - LUA="luajit=@v2.1 --compat=none" 12 | - LUA="luajit=@v2.1 --compat=none" EXTERNAL=true 13 | - LUA="luajit=@v2.1 --compat=all" 14 | - LUA="luajit=@v2.1 --compat=all" EXTERNAL=true 15 | - LUA="lua=5.2" 16 | - LUA="lua=5.2" EXTERNAL=true 17 | - LUA="lua=5.2" COMPILER="g++" 18 | - LUA="lua=5.2" EXTERNAL=true COMPILER="g++" 19 | 20 | branches: 21 | only: 22 | - master 23 | 24 | git: 25 | depth: 3 26 | 27 | notifications: 28 | email: false 29 | 30 | before_install: 31 | - pip install --user hererocks 32 | - hererocks old --$LUA 33 | - test -e old/bin/lua || (cd old/bin && ln -s luajit* lua) 34 | - hererocks new --lua=5.3 35 | 36 | install: 37 | - export CC="${COMPILER:-gcc}" DEF="" SRC="" CFLAGS="-Wall -Wextra -Ic-api -O2 -fPIC" 38 | - if [ "x${EXTERNAL:-}" = xtrue ]; then DEF="-DCOMPAT53_PREFIX=compat53" SRC="c-api/compat-5.3.c"; fi 39 | - ${CC} ${CFLAGS} -Iold/include ${DEF} -shared -o old/testmod.so tests/testmod.c ${SRC} 40 | - ${CC} ${CFLAGS} -Inew/include ${DEF} -shared -o new/testmod.so tests/testmod.c ${SRC} 41 | - gcc ${CFLAGS} -Iold/include ${DEF} -shared -o old/compat53.so ltablib.c lutf8lib.c lstrlib.c ${SRC} 42 | 43 | script: 44 | - (cd old && bin/lua ../tests/test.lua) > old.txt 45 | - (cd new && bin/lua ../tests/test.lua) > new.txt 46 | - diff old.txt new.txt || true 47 | 48 | -------------------------------------------------------------------------------- /vendor/compat-5.3/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Kepler Project. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /vendor/compat-5.3/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/keplerproject/lua-compat-5.3.svg?branch=master)](https://travis-ci.org/keplerproject/lua-compat-5.3) 2 | 3 | # lua-compat-5.3 4 | 5 | Lua-5.3-style APIs for Lua 5.2 and 5.1. 6 | 7 | ## What is it 8 | 9 | This is a small module that aims to make it easier to write code 10 | in a Lua-5.3-style that is compatible with Lua 5.1, Lua 5.2, and Lua 11 | 5.3. This does *not* make Lua 5.2 (or even Lua 5.1) entirely 12 | compatible with Lua 5.3, but it brings the API closer to that of Lua 13 | 5.3. 14 | 15 | It includes: 16 | 17 | * _For writing Lua_: The Lua module `compat53`, which can be require'd 18 | from Lua scripts and run in Lua 5.1, 5.2, and 5.3, including a 19 | backport of the `utf8` module, the 5.3 `table` module, and the 20 | string packing functions straight from the Lua 5.3 sources. 21 | * _For writing C_: A C header and file which can be linked to your 22 | Lua module written in C, providing some functions from the C API 23 | of Lua 5.3 that do not exist in Lua 5.2 or 5.1, making it easier to 24 | write C code that compiles with all three versions of liblua. 25 | 26 | ## How to use it 27 | 28 | ### Lua module 29 | 30 | ```lua 31 | require("compat53") 32 | ``` 33 | 34 | `compat53` makes changes to your global environment and does not return 35 | a meaningful return value, so the usual idiom of storing the return of 36 | `require` in a local variable makes no sense. 37 | 38 | When run under Lua 5.3, this module does nothing. 39 | 40 | When run under Lua 5.2 or 5.1, it replaces some of your standard 41 | functions and adds new ones to bring your environment closer to that 42 | of Lua 5.3. It also tries to load the backported `utf8`, `table`, and 43 | string packing modules automatically. If unsuccessful, pure Lua 44 | versions of the new `table` functions are used as a fallback, and 45 | [Roberto's struct library][1] is tried for string packing. 46 | 47 | #### Lua submodules 48 | 49 | ```lua 50 | local _ENV = require("compat53.module") 51 | if setfenv then setfenv(1, _ENV) end 52 | ``` 53 | 54 | The `compat53.module` module does not modify the global environment, 55 | and so it is safe to use in modules without affecting other Lua files. 56 | It is supposed to be set as the current environment (see above), i.e. 57 | cherry picking individual functions from this module is expressly 58 | *not* supported!). Not all features are available when using this 59 | module (e.g. yieldable (x)pcall support, string/file methods, etc.), 60 | so it is recommended to use plain `require("compat53")` whenever 61 | possible. 62 | 63 | ### C code 64 | 65 | There are two ways of adding the C API compatibility functions/macros to 66 | your project: 67 | * If `COMPAT53_PREFIX` is *not* `#define`d, `compat-5.3.h` `#include`s 68 | `compat-5.3.c`, and all functions are made `static`. You don't have to 69 | compile/link/add `compat-5.3.c` yourself. This is useful for one-file 70 | projects. 71 | * If `COMPAT53_PREFIX` is `#define`d, all exported functions are renamed 72 | behind the scenes using this prefix to avoid linker conflicts with other 73 | code using this package. This doesn't change the way you call the 74 | compatibility functions in your code. You have to compile and link 75 | `compat-5.3.c` to your project yourself. You can change the way the 76 | functions are exported using the `COMPAT53_API` macro (e.g. if you need 77 | some `__declspec` magic). While it is technically possible to use 78 | the "lua" prefix (and it looks better in the debugger), this is 79 | discouraged because LuaJIT has started to implement its own Lua 5.2+ 80 | C API functions, and with the "lua" prefix you'd violate the 81 | one-definition rule with recent LuaJIT versions. 82 | 83 | ## What's implemented 84 | 85 | ### Lua 86 | 87 | * the `utf8` module backported from the Lua 5.3 sources 88 | * `string.pack`, `string.packsize`, and `string.unpack` from the Lua 89 | 5.3 sources or from the `struct` module. (`struct` is not 100% 90 | compatible to Lua 5.3's string packing!) (See [here][4]) 91 | * `math.maxinteger` and `math.mininteger`, `math.tointeger`, `math.type`, 92 | and `math.ult` (see [here][5]) 93 | * `assert` accepts non-string error messages 94 | * `ipairs` respects `__index` metamethod 95 | * `table.move` 96 | * `table` library respects metamethods 97 | 98 | For Lua 5.1 additionally: 99 | * `load` and `loadfile` accept `mode` and `env` parameters 100 | * `table.pack` and `table.unpack` 101 | * string patterns may contain embedded zeros (but see [here][6]) 102 | * `string.rep` accepts `sep` argument 103 | * `string.format` calls `tostring` on arguments for `%s` 104 | * `math.log` accepts base argument 105 | * `xpcall` takes additional arguments 106 | * `pcall` and `xpcall` can execute functions that yield (see 107 | [here][22] for a possible problem with `coroutine.running`) 108 | * `pairs` respects `__pairs` metamethod (see [here][7]) 109 | * `rawlen` (but `#` still doesn't respect `__len` for tables) 110 | * `package.searchers` as alias for `package.loaders` 111 | * `package.searchpath` (see [here][8]) 112 | * `coroutine` functions dealing with the main coroutine (see 113 | [here][22] for a possible problem with `coroutine.running`) 114 | * `coroutine.create` accepts functions written in C 115 | * return code of `os.execute` (see [here][9]) 116 | * `io.write` and `file:write` return file handle 117 | * `io.lines` and `file:lines` accept format arguments (like `io.read`) 118 | (see [here][10] and [here][11]) 119 | * `debug.setmetatable` returns object 120 | * `debug.getuservalue` (see [here][12]) 121 | * `debug.setuservalue` (see [here][13]) 122 | 123 | ### C 124 | 125 | * `lua_KContext` (see [here][14]) 126 | * `lua_KFunction` (see [here][14]) 127 | * `lua_dump` (extra `strip` parameter, ignored, see [here][15]) 128 | * `lua_getfield` (return value) 129 | * `lua_geti` and `lua_seti` 130 | * `lua_getglobal` (return value) 131 | * `lua_getmetafield` (return value) 132 | * `lua_gettable` (return value) 133 | * `lua_getuservalue` (limited compatibility, see [here][16]) 134 | * `lua_setuservalue` (limited compatibility, see [here][17]) 135 | * `lua_isinteger` 136 | * `lua_numbertointeger` 137 | * `lua_callk` and `lua_pcallk` (limited compatibility, see [here][14]) 138 | * `lua_resume` 139 | * `lua_rawget` and `lua_rawgeti` (return values) 140 | * `lua_rawgetp` and `lua_rawsetp` 141 | * `luaL_requiref` (now checks `package.loaded` first) 142 | * `lua_rotate` 143 | * `lua_stringtonumber` (see [here][18]) 144 | 145 | For Lua 5.1 additionally: 146 | * `LUA_OK` 147 | * `LUA_ERRGCMM` 148 | * `LUA_OP*` macros for `lua_arith` and `lua_compare` 149 | * `LUA_FILEHANDLE` 150 | * `lua_Unsigned` 151 | * `luaL_Stream` (limited compatibility, see [here][19]) 152 | * `lua_absindex` 153 | * `lua_arith` (see [here][20]) 154 | * `lua_compare` 155 | * `lua_len`, `lua_rawlen`, and `luaL_len` 156 | * `lua_load` (mode argument) 157 | * `lua_pushstring`, `lua_pushlstring` (return value) 158 | * `lua_copy` 159 | * `lua_pushglobaltable` 160 | * `luaL_testudata` 161 | * `luaL_setfuncs`, `luaL_newlibtable`, and `luaL_newlib` 162 | * `luaL_setmetatable` 163 | * `luaL_getsubtable` 164 | * `luaL_traceback` 165 | * `luaL_execresult` 166 | * `luaL_fileresult` 167 | * `luaL_loadbufferx` 168 | * `luaL_loadfilex` 169 | * `luaL_checkversion` (with empty body, only to avoid compile errors, 170 | see [here][21]) 171 | * `luaL_tolstring` 172 | * `luaL_buffinitsize`, `luaL_prepbuffsize`, and `luaL_pushresultsize` 173 | (see [here][22]) 174 | * `lua_pushunsigned`, `lua_tounsignedx`, `lua_tounsigned`, 175 | `luaL_checkunsigned`, `luaL_optunsigned`, if 176 | `LUA_COMPAT_APIINTCASTS` is defined. 177 | 178 | ## What's not implemented 179 | 180 | * bit operators 181 | * integer division operator 182 | * utf8 escape sequences 183 | * 64 bit integers 184 | * `coroutine.isyieldable` 185 | * Lua 5.1: `_ENV`, `goto`, labels, ephemeron tables, etc. See 186 | [`lua-compat-5.2`][2] for a detailed list. 187 | * the following C API functions/macros: 188 | * `lua_isyieldable` 189 | * `lua_getextraspace` 190 | * `lua_arith` (new operators missing) 191 | * `lua_push(v)fstring` (new formats missing) 192 | * `lua_upvalueid` (5.1) 193 | * `lua_upvaluejoin` (5.1) 194 | * `lua_version` (5.1) 195 | * `lua_yieldk` (5.1) 196 | 197 | ## See also 198 | 199 | * For Lua-5.2-style APIs under Lua 5.1, see [lua-compat-5.2][2], 200 | which also is the basis for most of the code in this project. 201 | * For Lua-5.1-style APIs under Lua 5.0, see [Compat-5.1][3] 202 | 203 | ## Credits 204 | 205 | This package contains code written by: 206 | 207 | * [The Lua Team](http://www.lua.org) 208 | * Philipp Janda ([@siffiejoe](http://github.com/siffiejoe)) 209 | * Tomás Guisasola Gorham ([@tomasguisasola](http://github.com/tomasguisasola)) 210 | * Hisham Muhammad ([@hishamhm](http://github.com/hishamhm)) 211 | * Renato Maia ([@renatomaia](http://github.com/renatomaia)) 212 | * [@ThePhD](http://github.com/ThePhD) 213 | * [@Daurnimator](http://github.com/Daurnimator) 214 | 215 | 216 | [1]: http://www.inf.puc-rio.br/~roberto/struct/ 217 | [2]: http://github.com/keplerproject/lua-compat-5.2/ 218 | [3]: http://keplerproject.org/compat/ 219 | [4]: https://github.com/keplerproject/lua-compat-5.3/wiki/string_packing 220 | [5]: https://github.com/keplerproject/lua-compat-5.3/wiki/math.type 221 | [6]: https://github.com/keplerproject/lua-compat-5.3/wiki/pattern_matching 222 | [7]: https://github.com/keplerproject/lua-compat-5.3/wiki/pairs 223 | [8]: https://github.com/keplerproject/lua-compat-5.3/wiki/package.searchpath 224 | [9]: https://github.com/keplerproject/lua-compat-5.3/wiki/os.execute 225 | [10]: https://github.com/keplerproject/lua-compat-5.3/wiki/io.lines 226 | [11]: https://github.com/keplerproject/lua-compat-5.3/wiki/file.lines 227 | [12]: https://github.com/keplerproject/lua-compat-5.3/wiki/debug.getuservalue 228 | [13]: https://github.com/keplerproject/lua-compat-5.3/wiki/debug.setuservalue 229 | [14]: https://github.com/keplerproject/lua-compat-5.3/wiki/yieldable_c_functions 230 | [15]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_dump 231 | [16]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_getuservalue 232 | [17]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_setuservalue 233 | [18]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_stringtonumber 234 | [19]: https://github.com/keplerproject/lua-compat-5.3/wiki/luaL_Stream 235 | [20]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_arith 236 | [21]: https://github.com/keplerproject/lua-compat-5.3/wiki/luaL_checkversion 237 | [22]: https://github.com/keplerproject/lua-compat-5.3/wiki/luaL_Buffer 238 | [23]: https://github.com/keplerproject/lua-compat-5.3/wiki/coroutine.running 239 | 240 | -------------------------------------------------------------------------------- /vendor/compat-5.3/c-api/compat-5.3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "compat-5.3.h" 8 | 9 | /* don't compile it again if it already is included via compat53.h */ 10 | #ifndef COMPAT53_C_ 11 | #define COMPAT53_C_ 12 | 13 | 14 | 15 | /* definitions for Lua 5.1 only */ 16 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 17 | 18 | #ifndef COMPAT53_FOPEN_NO_LOCK 19 | # if defined(_MSC_VER) 20 | # define COMPAT53_FOPEN_NO_LOCK 1 21 | # else /* otherwise */ 22 | # define COMPAT53_FOPEN_NO_LOCK 0 23 | # endif /* VC++ only so far */ 24 | #endif /* No-lock fopen_s usage if possible */ 25 | 26 | #if defined(_MSC_VER) && COMPAT53_FOPEN_NO_LOCK 27 | # include 28 | #endif /* VC++ _fsopen for share-allowed file read */ 29 | 30 | #ifndef COMPAT53_HAVE_STRERROR_R 31 | # if defined(__GLIBC__) || defined(_POSIX_VERSION) || defined(__APPLE__) || \ 32 | (!defined (__MINGW32__) && defined(__GNUC__) && (__GNUC__ < 6)) 33 | # define COMPAT53_HAVE_STRERROR_R 1 34 | # else /* none of the defines matched: define to 0 */ 35 | # define COMPAT53_HAVE_STRERROR_R 0 36 | # endif /* have strerror_r of some form */ 37 | #endif /* strerror_r */ 38 | 39 | #ifndef COMPAT53_HAVE_STRERROR_S 40 | # if defined(_MSC_VER) || (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && \ 41 | defined(__STDC_LIB_EXT1__) && __STDC_LIB_EXT1__) 42 | # define COMPAT53_HAVE_STRERROR_S 1 43 | # else /* not VC++ or C11 */ 44 | # define COMPAT53_HAVE_STRERROR_S 0 45 | # endif /* strerror_s from VC++ or C11 */ 46 | #endif /* strerror_s */ 47 | 48 | #ifndef COMPAT53_LUA_FILE_BUFFER_SIZE 49 | # define COMPAT53_LUA_FILE_BUFFER_SIZE 4096 50 | #endif /* Lua File Buffer Size */ 51 | 52 | 53 | static char* compat53_strerror (int en, char* buff, size_t sz) { 54 | #if COMPAT53_HAVE_STRERROR_R 55 | /* use strerror_r here, because it's available on these specific platforms */ 56 | if (sz > 0) { 57 | buff[0] = '\0'; 58 | /* we don't care whether the GNU version or the XSI version is used: */ 59 | if (strerror_r(en, buff, sz)) { 60 | /* Yes, we really DO want to ignore the return value! 61 | * GCC makes that extra hard, not even a (void) cast will do. */ 62 | } 63 | if (buff[0] == '\0') { 64 | /* Buffer is unchanged, so we probably have called GNU strerror_r which 65 | * returned a static constant string. Chances are that strerror will 66 | * return the same static constant string and therefore be thread-safe. */ 67 | return strerror(en); 68 | } 69 | } 70 | return buff; /* sz is 0 *or* strerror_r wrote into the buffer */ 71 | #elif COMPAT53_HAVE_STRERROR_S 72 | /* for MSVC and other C11 implementations, use strerror_s since it's 73 | * provided by default by the libraries */ 74 | strerror_s(buff, sz, en); 75 | return buff; 76 | #else 77 | /* fallback, but strerror is not guaranteed to be threadsafe due to modifying 78 | * errno itself and some impls not locking a static buffer for it ... but most 79 | * known systems have threadsafe errno: this might only change if the locale 80 | * is changed out from under someone while this function is being called */ 81 | (void)buff; 82 | (void)sz; 83 | return strerror(en); 84 | #endif 85 | } 86 | 87 | 88 | COMPAT53_API int lua_absindex (lua_State *L, int i) { 89 | if (i < 0 && i > LUA_REGISTRYINDEX) 90 | i += lua_gettop(L) + 1; 91 | return i; 92 | } 93 | 94 | 95 | static void compat53_call_lua (lua_State *L, char const code[], size_t len, 96 | int nargs, int nret) { 97 | lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); 98 | if (lua_type(L, -1) != LUA_TFUNCTION) { 99 | lua_pop(L, 1); 100 | if (luaL_loadbuffer(L, code, len, "=none")) 101 | lua_error(L); 102 | lua_pushvalue(L, -1); 103 | lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); 104 | } 105 | lua_insert(L, -nargs-1); 106 | lua_call(L, nargs, nret); 107 | } 108 | 109 | 110 | static const char compat53_arith_code[] = 111 | "local op,a,b=...\n" 112 | "if op==0 then return a+b\n" 113 | "elseif op==1 then return a-b\n" 114 | "elseif op==2 then return a*b\n" 115 | "elseif op==3 then return a/b\n" 116 | "elseif op==4 then return a%b\n" 117 | "elseif op==5 then return a^b\n" 118 | "elseif op==6 then return -a\n" 119 | "end\n"; 120 | 121 | COMPAT53_API void lua_arith (lua_State *L, int op) { 122 | if (op < LUA_OPADD || op > LUA_OPUNM) 123 | luaL_error(L, "invalid 'op' argument for lua_arith"); 124 | luaL_checkstack(L, 5, "not enough stack slots"); 125 | if (op == LUA_OPUNM) 126 | lua_pushvalue(L, -1); 127 | lua_pushnumber(L, op); 128 | lua_insert(L, -3); 129 | compat53_call_lua(L, compat53_arith_code, 130 | sizeof(compat53_arith_code)-1, 3, 1); 131 | } 132 | 133 | 134 | static const char compat53_compare_code[] = 135 | "local a,b=...\n" 136 | "return a<=b\n"; 137 | 138 | COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op) { 139 | int result = 0; 140 | switch (op) { 141 | case LUA_OPEQ: 142 | return lua_equal(L, idx1, idx2); 143 | case LUA_OPLT: 144 | return lua_lessthan(L, idx1, idx2); 145 | case LUA_OPLE: 146 | luaL_checkstack(L, 5, "not enough stack slots"); 147 | idx1 = lua_absindex(L, idx1); 148 | idx2 = lua_absindex(L, idx2); 149 | lua_pushvalue(L, idx1); 150 | lua_pushvalue(L, idx2); 151 | compat53_call_lua(L, compat53_compare_code, 152 | sizeof(compat53_compare_code)-1, 2, 1); 153 | result = lua_toboolean(L, -1); 154 | lua_pop(L, 1); 155 | return result; 156 | default: 157 | luaL_error(L, "invalid 'op' argument for lua_compare"); 158 | } 159 | return 0; 160 | } 161 | 162 | 163 | COMPAT53_API void lua_copy (lua_State *L, int from, int to) { 164 | int abs_to = lua_absindex(L, to); 165 | luaL_checkstack(L, 1, "not enough stack slots"); 166 | lua_pushvalue(L, from); 167 | lua_replace(L, abs_to); 168 | } 169 | 170 | 171 | COMPAT53_API void lua_len (lua_State *L, int i) { 172 | switch (lua_type(L, i)) { 173 | case LUA_TSTRING: 174 | lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); 175 | break; 176 | case LUA_TTABLE: 177 | if (!luaL_callmeta(L, i, "__len")) 178 | lua_pushnumber(L, (lua_Number)lua_objlen(L, i)); 179 | break; 180 | case LUA_TUSERDATA: 181 | if (luaL_callmeta(L, i, "__len")) 182 | break; 183 | /* FALLTHROUGH */ 184 | default: 185 | luaL_error(L, "attempt to get length of a %s value", 186 | lua_typename(L, lua_type(L, i))); 187 | } 188 | } 189 | 190 | 191 | COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p) { 192 | int abs_i = lua_absindex(L, i); 193 | lua_pushlightuserdata(L, (void*)p); 194 | lua_rawget(L, abs_i); 195 | return lua_type(L, -1); 196 | } 197 | 198 | COMPAT53_API void lua_rawsetp (lua_State *L, int i, const void *p) { 199 | int abs_i = lua_absindex(L, i); 200 | luaL_checkstack(L, 1, "not enough stack slots"); 201 | lua_pushlightuserdata(L, (void*)p); 202 | lua_insert(L, -2); 203 | lua_rawset(L, abs_i); 204 | } 205 | 206 | 207 | COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) { 208 | lua_Number n = lua_tonumber(L, i); 209 | if (isnum != NULL) { 210 | *isnum = (n != 0 || lua_isnumber(L, i)); 211 | } 212 | return n; 213 | } 214 | 215 | 216 | COMPAT53_API void luaL_checkversion (lua_State *L) { 217 | (void)L; 218 | } 219 | 220 | 221 | COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg) { 222 | if (!lua_checkstack(L, sp+LUA_MINSTACK)) { 223 | if (msg != NULL) 224 | luaL_error(L, "stack overflow (%s)", msg); 225 | else { 226 | lua_pushliteral(L, "stack overflow"); 227 | lua_error(L); 228 | } 229 | } 230 | } 231 | 232 | 233 | COMPAT53_API int luaL_getsubtable (lua_State *L, int i, const char *name) { 234 | int abs_i = lua_absindex(L, i); 235 | luaL_checkstack(L, 3, "not enough stack slots"); 236 | lua_pushstring(L, name); 237 | lua_gettable(L, abs_i); 238 | if (lua_istable(L, -1)) 239 | return 1; 240 | lua_pop(L, 1); 241 | lua_newtable(L); 242 | lua_pushstring(L, name); 243 | lua_pushvalue(L, -2); 244 | lua_settable(L, abs_i); 245 | return 0; 246 | } 247 | 248 | 249 | COMPAT53_API lua_Integer luaL_len (lua_State *L, int i) { 250 | lua_Integer res = 0; 251 | int isnum = 0; 252 | luaL_checkstack(L, 1, "not enough stack slots"); 253 | lua_len(L, i); 254 | res = lua_tointegerx(L, -1, &isnum); 255 | lua_pop(L, 1); 256 | if (!isnum) 257 | luaL_error(L, "object length is not an integer"); 258 | return res; 259 | } 260 | 261 | 262 | COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { 263 | luaL_checkstack(L, nup+1, "too many upvalues"); 264 | for (; l->name != NULL; l++) { /* fill the table with given functions */ 265 | int i; 266 | lua_pushstring(L, l->name); 267 | for (i = 0; i < nup; i++) /* copy upvalues to the top */ 268 | lua_pushvalue(L, -(nup + 1)); 269 | lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ 270 | lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ 271 | } 272 | lua_pop(L, nup); /* remove upvalues */ 273 | } 274 | 275 | 276 | COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname) { 277 | luaL_checkstack(L, 1, "not enough stack slots"); 278 | luaL_getmetatable(L, tname); 279 | lua_setmetatable(L, -2); 280 | } 281 | 282 | 283 | COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname) { 284 | void *p = lua_touserdata(L, i); 285 | luaL_checkstack(L, 2, "not enough stack slots"); 286 | if (p == NULL || !lua_getmetatable(L, i)) 287 | return NULL; 288 | else { 289 | int res = 0; 290 | luaL_getmetatable(L, tname); 291 | res = lua_rawequal(L, -1, -2); 292 | lua_pop(L, 2); 293 | if (!res) 294 | p = NULL; 295 | } 296 | return p; 297 | } 298 | 299 | 300 | static int compat53_countlevels (lua_State *L) { 301 | lua_Debug ar; 302 | int li = 1, le = 1; 303 | /* find an upper bound */ 304 | while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } 305 | /* do a binary search */ 306 | while (li < le) { 307 | int m = (li + le)/2; 308 | if (lua_getstack(L, m, &ar)) li = m + 1; 309 | else le = m; 310 | } 311 | return le - 1; 312 | } 313 | 314 | static int compat53_findfield (lua_State *L, int objidx, int level) { 315 | if (level == 0 || !lua_istable(L, -1)) 316 | return 0; /* not found */ 317 | lua_pushnil(L); /* start 'next' loop */ 318 | while (lua_next(L, -2)) { /* for each pair in table */ 319 | if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ 320 | if (lua_rawequal(L, objidx, -1)) { /* found object? */ 321 | lua_pop(L, 1); /* remove value (but keep name) */ 322 | return 1; 323 | } 324 | else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */ 325 | lua_remove(L, -2); /* remove table (but keep name) */ 326 | lua_pushliteral(L, "."); 327 | lua_insert(L, -2); /* place '.' between the two names */ 328 | lua_concat(L, 3); 329 | return 1; 330 | } 331 | } 332 | lua_pop(L, 1); /* remove value */ 333 | } 334 | return 0; /* not found */ 335 | } 336 | 337 | static int compat53_pushglobalfuncname (lua_State *L, lua_Debug *ar) { 338 | int top = lua_gettop(L); 339 | lua_getinfo(L, "f", ar); /* push function */ 340 | lua_pushvalue(L, LUA_GLOBALSINDEX); 341 | if (compat53_findfield(L, top + 1, 2)) { 342 | lua_copy(L, -1, top + 1); /* move name to proper place */ 343 | lua_pop(L, 2); /* remove pushed values */ 344 | return 1; 345 | } 346 | else { 347 | lua_settop(L, top); /* remove function and global table */ 348 | return 0; 349 | } 350 | } 351 | 352 | static void compat53_pushfuncname (lua_State *L, lua_Debug *ar) { 353 | if (*ar->namewhat != '\0') /* is there a name? */ 354 | lua_pushfstring(L, "function " LUA_QS, ar->name); 355 | else if (*ar->what == 'm') /* main? */ 356 | lua_pushliteral(L, "main chunk"); 357 | else if (*ar->what == 'C') { 358 | if (compat53_pushglobalfuncname(L, ar)) { 359 | lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); 360 | lua_remove(L, -2); /* remove name */ 361 | } 362 | else 363 | lua_pushliteral(L, "?"); 364 | } 365 | else 366 | lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); 367 | } 368 | 369 | #define COMPAT53_LEVELS1 12 /* size of the first part of the stack */ 370 | #define COMPAT53_LEVELS2 10 /* size of the second part of the stack */ 371 | 372 | COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, 373 | const char *msg, int level) { 374 | lua_Debug ar; 375 | int top = lua_gettop(L); 376 | int numlevels = compat53_countlevels(L1); 377 | int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0; 378 | if (msg) lua_pushfstring(L, "%s\n", msg); 379 | lua_pushliteral(L, "stack traceback:"); 380 | while (lua_getstack(L1, level++, &ar)) { 381 | if (level == mark) { /* too many levels? */ 382 | lua_pushliteral(L, "\n\t..."); /* add a '...' */ 383 | level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */ 384 | } 385 | else { 386 | lua_getinfo(L1, "Slnt", &ar); 387 | lua_pushfstring(L, "\n\t%s:", ar.short_src); 388 | if (ar.currentline > 0) 389 | lua_pushfstring(L, "%d:", ar.currentline); 390 | lua_pushliteral(L, " in "); 391 | compat53_pushfuncname(L, &ar); 392 | lua_concat(L, lua_gettop(L) - top); 393 | } 394 | } 395 | lua_concat(L, lua_gettop(L) - top); 396 | } 397 | 398 | 399 | COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { 400 | const char *serr = NULL; 401 | int en = errno; /* calls to Lua API may change this value */ 402 | char buf[512] = { 0 }; 403 | if (stat) { 404 | lua_pushboolean(L, 1); 405 | return 1; 406 | } 407 | else { 408 | lua_pushnil(L); 409 | serr = compat53_strerror(en, buf, sizeof(buf)); 410 | if (fname) 411 | lua_pushfstring(L, "%s: %s", fname, serr); 412 | else 413 | lua_pushstring(L, serr); 414 | lua_pushnumber(L, (lua_Number)en); 415 | return 3; 416 | } 417 | } 418 | 419 | 420 | static int compat53_checkmode (lua_State *L, const char *mode, const char *modename, int err) { 421 | if (mode && strchr(mode, modename[0]) == NULL) { 422 | lua_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", modename, mode); 423 | return err; 424 | } 425 | return LUA_OK; 426 | } 427 | 428 | 429 | typedef struct { 430 | lua_Reader reader; 431 | void *ud; 432 | int has_peeked_data; 433 | const char *peeked_data; 434 | size_t peeked_data_size; 435 | } compat53_reader_data; 436 | 437 | 438 | static const char *compat53_reader (lua_State *L, void *ud, size_t *size) { 439 | compat53_reader_data *data = (compat53_reader_data *)ud; 440 | if (data->has_peeked_data) { 441 | data->has_peeked_data = 0; 442 | *size = data->peeked_data_size; 443 | return data->peeked_data; 444 | } else 445 | return data->reader(L, data->ud, size); 446 | } 447 | 448 | 449 | COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *source, const char *mode) { 450 | int status = LUA_OK; 451 | compat53_reader_data compat53_data = { reader, data, 1, 0, 0 }; 452 | compat53_data.peeked_data = reader(L, data, &(compat53_data.peeked_data_size)); 453 | if (compat53_data.peeked_data && compat53_data.peeked_data_size && 454 | compat53_data.peeked_data[0] == LUA_SIGNATURE[0]) /* binary file? */ 455 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); 456 | else 457 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); 458 | if (status != LUA_OK) 459 | return status; 460 | /* we need to call the original 5.1 version of lua_load! */ 461 | #undef lua_load 462 | return lua_load(L, compat53_reader, &compat53_data, source); 463 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) 464 | } 465 | 466 | 467 | typedef struct { 468 | int n; /* number of pre-read characters */ 469 | FILE *f; /* file being read */ 470 | char buff[COMPAT53_LUA_FILE_BUFFER_SIZE]; /* area for reading file */ 471 | } compat53_LoadF; 472 | 473 | 474 | static const char *compat53_getF (lua_State *L, void *ud, size_t *size) { 475 | compat53_LoadF *lf = (compat53_LoadF *)ud; 476 | (void)L; /* not used */ 477 | if (lf->n > 0) { /* are there pre-read characters to be read? */ 478 | *size = lf->n; /* return them (chars already in buffer) */ 479 | lf->n = 0; /* no more pre-read characters */ 480 | } 481 | else { /* read a block from file */ 482 | /* 'fread' can return > 0 *and* set the EOF flag. If next call to 483 | 'compat53_getF' called 'fread', it might still wait for user input. 484 | The next check avoids this problem. */ 485 | if (feof(lf->f)) return NULL; 486 | *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ 487 | } 488 | return lf->buff; 489 | } 490 | 491 | 492 | static int compat53_errfile (lua_State *L, const char *what, int fnameindex) { 493 | char buf[512] = {0}; 494 | const char *serr = compat53_strerror(errno, buf, sizeof(buf)); 495 | const char *filename = lua_tostring(L, fnameindex) + 1; 496 | lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); 497 | lua_remove(L, fnameindex); 498 | return LUA_ERRFILE; 499 | } 500 | 501 | 502 | static int compat53_skipBOM (compat53_LoadF *lf) { 503 | const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ 504 | int c; 505 | lf->n = 0; 506 | do { 507 | c = getc(lf->f); 508 | if (c == EOF || c != *(const unsigned char *)p++) return c; 509 | lf->buff[lf->n++] = (char)c; /* to be read by the parser */ 510 | } while (*p != '\0'); 511 | lf->n = 0; /* prefix matched; discard it */ 512 | return getc(lf->f); /* return next character */ 513 | } 514 | 515 | 516 | /* 517 | ** reads the first character of file 'f' and skips an optional BOM mark 518 | ** in its beginning plus its first line if it starts with '#'. Returns 519 | ** true if it skipped the first line. In any case, '*cp' has the 520 | ** first "valid" character of the file (after the optional BOM and 521 | ** a first-line comment). 522 | */ 523 | static int compat53_skipcomment (compat53_LoadF *lf, int *cp) { 524 | int c = *cp = compat53_skipBOM(lf); 525 | if (c == '#') { /* first line is a comment (Unix exec. file)? */ 526 | do { /* skip first line */ 527 | c = getc(lf->f); 528 | } while (c != EOF && c != '\n'); 529 | *cp = getc(lf->f); /* skip end-of-line, if present */ 530 | return 1; /* there was a comment */ 531 | } 532 | else return 0; /* no comment */ 533 | } 534 | 535 | 536 | COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode) { 537 | compat53_LoadF lf; 538 | int status, readstatus; 539 | int c; 540 | int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ 541 | if (filename == NULL) { 542 | lua_pushliteral(L, "=stdin"); 543 | lf.f = stdin; 544 | } 545 | else { 546 | lua_pushfstring(L, "@%s", filename); 547 | #if defined(_MSC_VER) 548 | /* This code is here to stop a deprecation error that stops builds 549 | * if a certain macro is defined. While normally not caring would 550 | * be best, some header-only libraries and builds can't afford to 551 | * dictate this to the user. A quick check shows that fopen_s this 552 | * goes back to VS 2005, and _fsopen goes back to VS 2003 .NET, 553 | * possibly even before that so we don't need to do any version 554 | * number checks, since this has been there since forever. */ 555 | 556 | /* TO USER: if you want the behavior of typical fopen_s/fopen, 557 | * which does lock the file on VC++, define the macro used below to 0 */ 558 | #if COMPAT53_FOPEN_NO_LOCK 559 | lf.f = _fsopen(filename, "r", _SH_DENYNO); /* do not lock the file in any way */ 560 | if (lf.f == NULL) 561 | return compat53_errfile(L, "open", fnameindex); 562 | #else /* use default locking version */ 563 | if (fopen_s(&lf.f, filename, "r") != 0) 564 | return compat53_errfile(L, "open", fnameindex); 565 | #endif /* Locking vs. No-locking fopen variants */ 566 | #else 567 | lf.f = fopen(filename, "r"); /* default stdlib doesn't forcefully lock files here */ 568 | if (lf.f == NULL) return compat53_errfile(L, "open", fnameindex); 569 | #endif 570 | } 571 | if (compat53_skipcomment(&lf, &c)) /* read initial portion */ 572 | lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ 573 | if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ 574 | #if defined(_MSC_VER) 575 | if (freopen_s(&lf.f, filename, "rb", lf.f) != 0) 576 | return compat53_errfile(L, "reopen", fnameindex); 577 | #else 578 | lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ 579 | if (lf.f == NULL) return compat53_errfile(L, "reopen", fnameindex); 580 | #endif 581 | compat53_skipcomment(&lf, &c); /* re-read initial portion */ 582 | } 583 | if (c != EOF) 584 | lf.buff[lf.n++] = (char)c; /* 'c' is the first character of the stream */ 585 | status = lua_load(L, &compat53_getF, &lf, lua_tostring(L, -1), mode); 586 | readstatus = ferror(lf.f); 587 | if (filename) fclose(lf.f); /* close file (even in case of errors) */ 588 | if (readstatus) { 589 | lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ 590 | return compat53_errfile(L, "read", fnameindex); 591 | } 592 | lua_remove(L, fnameindex); 593 | return status; 594 | } 595 | 596 | 597 | COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode) { 598 | int status = LUA_OK; 599 | if (sz > 0 && buff[0] == LUA_SIGNATURE[0]) { 600 | status = compat53_checkmode(L, mode, "binary", LUA_ERRSYNTAX); 601 | } 602 | else { 603 | status = compat53_checkmode(L, mode, "text", LUA_ERRSYNTAX); 604 | } 605 | if (status != LUA_OK) 606 | return status; 607 | return luaL_loadbuffer(L, buff, sz, name); 608 | } 609 | 610 | 611 | #if !defined(l_inspectstat) && \ 612 | (defined(unix) || defined(__unix) || defined(__unix__) || \ 613 | defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \ 614 | (defined(__APPLE__) && defined(__MACH__))) 615 | /* some form of unix; check feature macros in unistd.h for details */ 616 | # include 617 | /* check posix version; the relevant include files and macros probably 618 | * were available before 2001, but I'm not sure */ 619 | # if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L 620 | # include 621 | # define l_inspectstat(stat,what) \ 622 | if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ 623 | else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } 624 | # endif 625 | #endif 626 | 627 | /* provide default (no-op) version */ 628 | #if !defined(l_inspectstat) 629 | # define l_inspectstat(stat,what) ((void)0) 630 | #endif 631 | 632 | 633 | COMPAT53_API int luaL_execresult (lua_State *L, int stat) { 634 | const char *what = "exit"; 635 | if (stat == -1) 636 | return luaL_fileresult(L, 0, NULL); 637 | else { 638 | l_inspectstat(stat, what); 639 | if (*what == 'e' && stat == 0) 640 | lua_pushboolean(L, 1); 641 | else 642 | lua_pushnil(L); 643 | lua_pushstring(L, what); 644 | lua_pushinteger(L, stat); 645 | return 3; 646 | } 647 | } 648 | 649 | 650 | COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B) { 651 | /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ 652 | B->b.p = NULL; 653 | B->b.L = NULL; 654 | B->b.lvl = 0; 655 | /* reuse the buffer from the 5.1-style luaL_Buffer though! */ 656 | B->ptr = B->b.buffer; 657 | B->capacity = LUAL_BUFFERSIZE; 658 | B->nelems = 0; 659 | B->L2 = L; 660 | } 661 | 662 | 663 | COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s) { 664 | if (B->capacity - B->nelems < s) { /* needs to grow */ 665 | char* newptr = NULL; 666 | size_t newcap = B->capacity * 2; 667 | if (newcap - B->nelems < s) 668 | newcap = B->nelems + s; 669 | if (newcap < B->capacity) /* overflow */ 670 | luaL_error(B->L2, "buffer too large"); 671 | newptr = (char*)lua_newuserdata(B->L2, newcap); 672 | memcpy(newptr, B->ptr, B->nelems); 673 | if (B->ptr != B->b.buffer) 674 | lua_replace(B->L2, -2); /* remove old buffer */ 675 | B->ptr = newptr; 676 | B->capacity = newcap; 677 | } 678 | return B->ptr+B->nelems; 679 | } 680 | 681 | 682 | COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l) { 683 | memcpy(luaL_prepbuffsize(B, l), s, l); 684 | luaL_addsize(B, l); 685 | } 686 | 687 | 688 | COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B) { 689 | size_t len = 0; 690 | const char *s = lua_tolstring(B->L2, -1, &len); 691 | if (!s) 692 | luaL_error(B->L2, "cannot convert value to string"); 693 | if (B->ptr != B->b.buffer) 694 | lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ 695 | luaL_addlstring(B, s, len); 696 | lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); 697 | } 698 | 699 | 700 | void luaL_pushresult (luaL_Buffer_53 *B) { 701 | lua_pushlstring(B->L2, B->ptr, B->nelems); 702 | if (B->ptr != B->b.buffer) 703 | lua_replace(B->L2, -2); /* remove userdata buffer */ 704 | } 705 | 706 | 707 | #endif /* Lua 5.1 */ 708 | 709 | 710 | 711 | /* definitions for Lua 5.1 and Lua 5.2 */ 712 | #if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502 713 | 714 | 715 | COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) { 716 | index = lua_absindex(L, index); 717 | lua_pushinteger(L, i); 718 | lua_gettable(L, index); 719 | return lua_type(L, -1); 720 | } 721 | 722 | 723 | COMPAT53_API int lua_isinteger (lua_State *L, int index) { 724 | if (lua_type(L, index) == LUA_TNUMBER) { 725 | lua_Number n = lua_tonumber(L, index); 726 | lua_Integer i = lua_tointeger(L, index); 727 | if (i == n) 728 | return 1; 729 | } 730 | return 0; 731 | } 732 | 733 | 734 | COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) { 735 | int ok = 0; 736 | lua_Number n = lua_tonumberx(L, i, &ok); 737 | if (ok) { 738 | if (n == (lua_Integer)n) { 739 | if (isnum) 740 | *isnum = 1; 741 | return (lua_Integer)n; 742 | } 743 | } 744 | if (isnum) 745 | *isnum = 0; 746 | return 0; 747 | } 748 | 749 | 750 | static void compat53_reverse (lua_State *L, int a, int b) { 751 | for (; a < b; ++a, --b) { 752 | lua_pushvalue(L, a); 753 | lua_pushvalue(L, b); 754 | lua_replace(L, a); 755 | lua_replace(L, b); 756 | } 757 | } 758 | 759 | 760 | COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) { 761 | int n_elems = 0; 762 | idx = lua_absindex(L, idx); 763 | n_elems = lua_gettop(L)-idx+1; 764 | if (n < 0) 765 | n += n_elems; 766 | if ( n > 0 && n < n_elems) { 767 | luaL_checkstack(L, 2, "not enough stack slots available"); 768 | n = n_elems - n; 769 | compat53_reverse(L, idx, idx+n-1); 770 | compat53_reverse(L, idx+n, idx+n_elems-1); 771 | compat53_reverse(L, idx, idx+n_elems-1); 772 | } 773 | } 774 | 775 | 776 | COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i) { 777 | luaL_checkstack(L, 1, "not enough stack slots available"); 778 | index = lua_absindex(L, index); 779 | lua_pushinteger(L, i); 780 | lua_insert(L, -2); 781 | lua_settable(L, index); 782 | } 783 | 784 | 785 | #if !defined(lua_str2number) 786 | # define lua_str2number(s, p) strtod((s), (p)) 787 | #endif 788 | 789 | COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s) { 790 | char* endptr; 791 | lua_Number n = lua_str2number(s, &endptr); 792 | if (endptr != s) { 793 | while (*endptr != '\0' && isspace((unsigned char)*endptr)) 794 | ++endptr; 795 | if (*endptr == '\0') { 796 | lua_pushnumber(L, n); 797 | return endptr - s + 1; 798 | } 799 | } 800 | return 0; 801 | } 802 | 803 | 804 | COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { 805 | if (!luaL_callmeta(L, idx, "__tostring")) { 806 | int t = lua_type(L, idx), tt = 0; 807 | char const* name = NULL; 808 | switch (t) { 809 | case LUA_TNIL: 810 | lua_pushliteral(L, "nil"); 811 | break; 812 | case LUA_TSTRING: 813 | case LUA_TNUMBER: 814 | lua_pushvalue(L, idx); 815 | break; 816 | case LUA_TBOOLEAN: 817 | if (lua_toboolean(L, idx)) 818 | lua_pushliteral(L, "true"); 819 | else 820 | lua_pushliteral(L, "false"); 821 | break; 822 | default: 823 | tt = luaL_getmetafield(L, idx, "__name"); 824 | name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t); 825 | lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx)); 826 | if (tt != LUA_TNIL) 827 | lua_replace(L, -2); 828 | break; 829 | } 830 | } else { 831 | if (!lua_isstring(L, -1)) 832 | luaL_error(L, "'__tostring' must return a string"); 833 | } 834 | return lua_tolstring(L, -1, len); 835 | } 836 | 837 | 838 | COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, 839 | lua_CFunction openf, int glb) { 840 | luaL_checkstack(L, 3, "not enough stack slots available"); 841 | luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); 842 | if (lua_getfield(L, -1, modname) == LUA_TNIL) { 843 | lua_pop(L, 1); 844 | lua_pushcfunction(L, openf); 845 | lua_pushstring(L, modname); 846 | lua_call(L, 1, 1); 847 | lua_pushvalue(L, -1); 848 | lua_setfield(L, -3, modname); 849 | } 850 | if (glb) { 851 | lua_pushvalue(L, -1); 852 | lua_setglobal(L, modname); 853 | } 854 | lua_replace(L, -2); 855 | } 856 | 857 | 858 | #endif /* Lua 5.1 and 5.2 */ 859 | 860 | 861 | #endif /* COMPAT53_C_ */ 862 | 863 | 864 | /********************************************************************* 865 | * This file contains parts of Lua 5.2's and Lua 5.3's source code: 866 | * 867 | * Copyright (C) 1994-2014 Lua.org, PUC-Rio. 868 | * 869 | * Permission is hereby granted, free of charge, to any person obtaining 870 | * a copy of this software and associated documentation files (the 871 | * "Software"), to deal in the Software without restriction, including 872 | * without limitation the rights to use, copy, modify, merge, publish, 873 | * distribute, sublicense, and/or sell copies of the Software, and to 874 | * permit persons to whom the Software is furnished to do so, subject to 875 | * the following conditions: 876 | * 877 | * The above copyright notice and this permission notice shall be 878 | * included in all copies or substantial portions of the Software. 879 | * 880 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 881 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 882 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 883 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 884 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 885 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 886 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 887 | *********************************************************************/ 888 | 889 | -------------------------------------------------------------------------------- /vendor/compat-5.3/c-api/compat-5.3.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPAT53_H_ 2 | #define COMPAT53_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) 8 | extern "C" { 9 | #endif 10 | #include 11 | #include 12 | #include 13 | #if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP) 14 | } 15 | #endif 16 | 17 | 18 | #undef COMPAT53_INCLUDE_SOURCE 19 | #if defined(COMPAT53_PREFIX) 20 | /* - change the symbol names of functions to avoid linker conflicts 21 | * - compat-5.3.c needs to be compiled (and linked) separately 22 | */ 23 | # if !defined(COMPAT53_API) 24 | # define COMPAT53_API extern 25 | # endif 26 | #else /* COMPAT53_PREFIX */ 27 | /* - make all functions static and include the source. 28 | * - compat-5.3.c doesn't need to be compiled (and linked) separately 29 | */ 30 | # define COMPAT53_PREFIX compat53 31 | # undef COMPAT53_API 32 | # if defined(__GNUC__) || defined(__clang__) 33 | # define COMPAT53_API __attribute__((__unused__)) static 34 | # else 35 | # define COMPAT53_API static 36 | # endif 37 | # define COMPAT53_INCLUDE_SOURCE 38 | #endif /* COMPAT53_PREFIX */ 39 | 40 | #define COMPAT53_CONCAT_HELPER(a, b) a##b 41 | #define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b) 42 | 43 | 44 | 45 | /* declarations for Lua 5.1 */ 46 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 47 | 48 | /* XXX not implemented: 49 | * lua_arith (new operators) 50 | * lua_upvalueid 51 | * lua_upvaluejoin 52 | * lua_version 53 | * lua_yieldk 54 | */ 55 | 56 | #ifndef LUA_OK 57 | # define LUA_OK 0 58 | #endif 59 | #ifndef LUA_OPADD 60 | # define LUA_OPADD 0 61 | #endif 62 | #ifndef LUA_OPSUB 63 | # define LUA_OPSUB 1 64 | #endif 65 | #ifndef LUA_OPMUL 66 | # define LUA_OPMUL 2 67 | #endif 68 | #ifndef LUA_OPDIV 69 | # define LUA_OPDIV 3 70 | #endif 71 | #ifndef LUA_OPMOD 72 | # define LUA_OPMOD 4 73 | #endif 74 | #ifndef LUA_OPPOW 75 | # define LUA_OPPOW 5 76 | #endif 77 | #ifndef LUA_OPUNM 78 | # define LUA_OPUNM 6 79 | #endif 80 | #ifndef LUA_OPEQ 81 | # define LUA_OPEQ 0 82 | #endif 83 | #ifndef LUA_OPLT 84 | # define LUA_OPLT 1 85 | #endif 86 | #ifndef LUA_OPLE 87 | # define LUA_OPLE 2 88 | #endif 89 | 90 | /* LuaJIT/Lua 5.1 does not have the updated 91 | * error codes for thread status/function returns (but some patched versions do) 92 | * define it only if it's not found 93 | */ 94 | #if !defined(LUA_ERRGCMM) 95 | /* Use + 2 because in some versions of Lua (Lua 5.1) 96 | * LUA_ERRFILE is defined as (LUA_ERRERR+1) 97 | * so we need to avoid it (LuaJIT might have something at this 98 | * integer value too) 99 | */ 100 | # define LUA_ERRGCMM (LUA_ERRERR + 2) 101 | #endif /* LUA_ERRGCMM define */ 102 | 103 | typedef size_t lua_Unsigned; 104 | 105 | typedef struct luaL_Buffer_53 { 106 | luaL_Buffer b; /* make incorrect code crash! */ 107 | char *ptr; 108 | size_t nelems; 109 | size_t capacity; 110 | lua_State *L2; 111 | } luaL_Buffer_53; 112 | #define luaL_Buffer luaL_Buffer_53 113 | 114 | /* In PUC-Rio 5.1, userdata is a simple FILE* 115 | * In LuaJIT, it's a struct where the first member is a FILE* 116 | * We can't support the `closef` member 117 | */ 118 | typedef struct luaL_Stream { 119 | FILE *f; 120 | } luaL_Stream; 121 | 122 | #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) 123 | COMPAT53_API int lua_absindex (lua_State *L, int i); 124 | 125 | #define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith) 126 | COMPAT53_API void lua_arith (lua_State *L, int op); 127 | 128 | #define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare) 129 | COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op); 130 | 131 | #define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy) 132 | COMPAT53_API void lua_copy (lua_State *L, int from, int to); 133 | 134 | #define lua_getuservalue(L, i) \ 135 | (lua_getfenv((L), (i)), lua_type((L), -1)) 136 | #define lua_setuservalue(L, i) \ 137 | (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i))) 138 | 139 | #define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len) 140 | COMPAT53_API void lua_len (lua_State *L, int i); 141 | 142 | #define lua_pushstring(L, s) \ 143 | (lua_pushstring((L), (s)), lua_tostring((L), -1)) 144 | 145 | #define lua_pushlstring(L, s, len) \ 146 | ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1)) 147 | 148 | #ifndef luaL_newlibtable 149 | # define luaL_newlibtable(L, l) \ 150 | (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1)) 151 | #endif 152 | #ifndef luaL_newlib 153 | # define luaL_newlib(L, l) \ 154 | (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l))) 155 | #endif 156 | 157 | #define lua_pushglobaltable(L) \ 158 | lua_pushvalue((L), LUA_GLOBALSINDEX) 159 | 160 | #define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp) 161 | COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p); 162 | 163 | #define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp) 164 | COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p); 165 | 166 | #define lua_rawlen(L, i) lua_objlen((L), (i)) 167 | 168 | #define lua_tointeger(L, i) lua_tointegerx((L), (i), NULL) 169 | 170 | #define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx) 171 | COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum); 172 | 173 | #define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion) 174 | COMPAT53_API void luaL_checkversion (lua_State *L); 175 | 176 | #define lua_load COMPAT53_CONCAT(COMPAT53_PREFIX, _load_53) 177 | COMPAT53_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char* source, const char* mode); 178 | 179 | #define luaL_loadfilex COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadfilex) 180 | COMPAT53_API int luaL_loadfilex (lua_State *L, const char *filename, const char *mode); 181 | 182 | #define luaL_loadbufferx COMPAT53_CONCAT(COMPAT53_PREFIX, L_loadbufferx) 183 | COMPAT53_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); 184 | 185 | #define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53) 186 | COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg); 187 | 188 | #define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable) 189 | COMPAT53_API int luaL_getsubtable (lua_State* L, int i, const char *name); 190 | 191 | #define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len) 192 | COMPAT53_API lua_Integer luaL_len (lua_State *L, int i); 193 | 194 | #define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs) 195 | COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup); 196 | 197 | #define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable) 198 | COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname); 199 | 200 | #define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata) 201 | COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname); 202 | 203 | #define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback) 204 | COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level); 205 | 206 | #define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult) 207 | COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname); 208 | 209 | #define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult) 210 | COMPAT53_API int luaL_execresult (lua_State *L, int stat); 211 | 212 | #define lua_callk(L, na, nr, ctx, cont) \ 213 | ((void)(ctx), (void)(cont), lua_call((L), (na), (nr))) 214 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ 215 | ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err))) 216 | 217 | #define lua_resume(L, from, nargs) \ 218 | ((void)(from), lua_resume((L), (nargs))) 219 | 220 | #define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53) 221 | COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B); 222 | 223 | #define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53) 224 | COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s); 225 | 226 | #define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53) 227 | COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l); 228 | 229 | #define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53) 230 | COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B); 231 | 232 | #define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53) 233 | COMPAT53_API void luaL_pushresult (luaL_Buffer_53 *B); 234 | 235 | #undef luaL_buffinitsize 236 | #define luaL_buffinitsize(L, B, s) \ 237 | (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s))) 238 | 239 | #undef luaL_prepbuffer 240 | #define luaL_prepbuffer(B) \ 241 | luaL_prepbuffsize((B), LUAL_BUFFERSIZE) 242 | 243 | #undef luaL_addchar 244 | #define luaL_addchar(B, c) \ 245 | ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \ 246 | ((B)->ptr[(B)->nelems++] = (c))) 247 | 248 | #undef luaL_addsize 249 | #define luaL_addsize(B, s) \ 250 | ((B)->nelems += (s)) 251 | 252 | #undef luaL_addstring 253 | #define luaL_addstring(B, s) \ 254 | luaL_addlstring((B), (s), strlen((s))) 255 | 256 | #undef luaL_pushresultsize 257 | #define luaL_pushresultsize(B, s) \ 258 | (luaL_addsize((B), (s)), luaL_pushresult((B))) 259 | 260 | #if defined(LUA_COMPAT_APIINTCASTS) 261 | #define lua_pushunsigned(L, n) \ 262 | lua_pushinteger((L), (lua_Integer)(n)) 263 | #define lua_tounsignedx(L, i, is) \ 264 | ((lua_Unsigned)lua_tointegerx((L), (i), (is))) 265 | #define lua_tounsigned(L, i) \ 266 | lua_tounsignedx((L), (i), NULL) 267 | #define luaL_checkunsigned(L, a) \ 268 | ((lua_Unsigned)luaL_checkinteger((L), (a))) 269 | #define luaL_optunsigned(L, a, d) \ 270 | ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d))) 271 | #endif 272 | 273 | #endif /* Lua 5.1 only */ 274 | 275 | 276 | 277 | /* declarations for Lua 5.1 and 5.2 */ 278 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502 279 | 280 | typedef int lua_KContext; 281 | 282 | typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx); 283 | 284 | #define lua_dump(L, w, d, s) \ 285 | ((void)(s), lua_dump((L), (w), (d))) 286 | 287 | #define lua_getfield(L, i, k) \ 288 | (lua_getfield((L), (i), (k)), lua_type((L), -1)) 289 | 290 | #define lua_gettable(L, i) \ 291 | (lua_gettable((L), (i)), lua_type((L), -1)) 292 | 293 | #define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti) 294 | COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i); 295 | 296 | #define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger) 297 | COMPAT53_API int lua_isinteger (lua_State *L, int index); 298 | 299 | #define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx_53) 300 | COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum); 301 | 302 | #define lua_numbertointeger(n, p) \ 303 | ((*(p) = (lua_Integer)(n)), 1) 304 | 305 | #define lua_rawget(L, i) \ 306 | (lua_rawget((L), (i)), lua_type((L), -1)) 307 | 308 | #define lua_rawgeti(L, i, n) \ 309 | (lua_rawgeti((L), (i), (n)), lua_type((L), -1)) 310 | 311 | #define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate) 312 | COMPAT53_API void lua_rotate (lua_State *L, int idx, int n); 313 | 314 | #define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti) 315 | COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i); 316 | 317 | #define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber) 318 | COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s); 319 | 320 | #define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring) 321 | COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len); 322 | 323 | #define luaL_getmetafield(L, o, e) \ 324 | (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL) 325 | 326 | #define luaL_newmetatable(L, tn) \ 327 | (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0) 328 | 329 | #define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53) 330 | COMPAT53_API void luaL_requiref (lua_State *L, const char *modname, 331 | lua_CFunction openf, int glb ); 332 | 333 | #endif /* Lua 5.1 and Lua 5.2 */ 334 | 335 | 336 | 337 | /* declarations for Lua 5.2 */ 338 | #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502 339 | 340 | /* XXX not implemented: 341 | * lua_isyieldable 342 | * lua_getextraspace 343 | * lua_arith (new operators) 344 | * lua_pushfstring (new formats) 345 | */ 346 | 347 | #define lua_getglobal(L, n) \ 348 | (lua_getglobal((L), (n)), lua_type((L), -1)) 349 | 350 | #define lua_getuservalue(L, i) \ 351 | (lua_getuservalue((L), (i)), lua_type((L), -1)) 352 | 353 | #define lua_pushlstring(L, s, len) \ 354 | (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))) 355 | 356 | #define lua_rawgetp(L, i, p) \ 357 | (lua_rawgetp((L), (i), (p)), lua_type((L), -1)) 358 | 359 | #define LUA_KFUNCTION(_name) \ 360 | static int (_name)(lua_State *L, int status, lua_KContext ctx); \ 361 | static int (_name ## _52)(lua_State *L) { \ 362 | lua_KContext ctx; \ 363 | int status = lua_getctx(L, &ctx); \ 364 | return (_name)(L, status, ctx); \ 365 | } \ 366 | static int (_name)(lua_State *L, int status, lua_KContext ctx) 367 | 368 | #define lua_pcallk(L, na, nr, err, ctx, cont) \ 369 | lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52) 370 | 371 | #define lua_callk(L, na, nr, ctx, cont) \ 372 | lua_callk((L), (na), (nr), (ctx), cont ## _52) 373 | 374 | #define lua_yieldk(L, nr, ctx, cont) \ 375 | lua_yieldk((L), (nr), (ctx), cont ## _52) 376 | 377 | #ifdef lua_call 378 | # undef lua_call 379 | # define lua_call(L, na, nr) \ 380 | (lua_callk)((L), (na), (nr), 0, NULL) 381 | #endif 382 | 383 | #ifdef lua_pcall 384 | # undef lua_pcall 385 | # define lua_pcall(L, na, nr, err) \ 386 | (lua_pcallk)((L), (na), (nr), (err), 0, NULL) 387 | #endif 388 | 389 | #ifdef lua_yield 390 | # undef lua_yield 391 | # define lua_yield(L, nr) \ 392 | (lua_yieldk)((L), (nr), 0, NULL) 393 | #endif 394 | 395 | #endif /* Lua 5.2 only */ 396 | 397 | 398 | 399 | /* other Lua versions */ 400 | #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 503 401 | 402 | # error "unsupported Lua version (i.e. not Lua 5.1, 5.2, or 5.3)" 403 | 404 | #endif /* other Lua versions except 5.1, 5.2, and 5.3 */ 405 | 406 | 407 | 408 | /* helper macro for defining continuation functions (for every version 409 | * *except* Lua 5.2) */ 410 | #ifndef LUA_KFUNCTION 411 | #define LUA_KFUNCTION(_name) \ 412 | static int (_name)(lua_State *L, int status, lua_KContext ctx) 413 | #endif 414 | 415 | 416 | #if defined(COMPAT53_INCLUDE_SOURCE) 417 | # include "compat-5.3.c" 418 | #endif 419 | 420 | 421 | #endif /* COMPAT53_H_ */ 422 | 423 | -------------------------------------------------------------------------------- /vendor/compat-5.3/compat53/init.lua: -------------------------------------------------------------------------------- 1 | local lua_version = _VERSION:sub(-3) 2 | 3 | 4 | if lua_version < "5.3" then 5 | 6 | local _G, pairs, require, select, type = 7 | _G, pairs, require, select, type 8 | local debug, io = debug, io 9 | local unpack = lua_version == "5.1" and unpack or table.unpack 10 | 11 | local M = require("compat53.module") 12 | 13 | -- select the most powerful getmetatable function available 14 | local gmt = type(debug) == "table" and debug.getmetatable or 15 | getmetatable or function() return false end 16 | -- metatable for file objects from Lua's standard io library 17 | local file_meta = gmt(io.stdout) 18 | 19 | 20 | -- make '*' optional for file:read and file:lines 21 | if type(file_meta) == "table" and type(file_meta.__index) == "table" then 22 | 23 | local function addasterisk(fmt) 24 | if type(fmt) == "string" and fmt:sub(1, 1) ~= "*" then 25 | return "*"..fmt 26 | else 27 | return fmt 28 | end 29 | end 30 | 31 | local file_lines = file_meta.__index.lines 32 | file_meta.__index.lines = function(self, ...) 33 | local n = select('#', ...) 34 | for i = 1, n do 35 | local a = select(i, ...) 36 | local b = addasterisk(a) 37 | -- as an optimization we only allocate a table for the 38 | -- modified format arguments when we have a '*' somewhere 39 | if a ~= b then 40 | local args = { ... } 41 | args[i] = b 42 | for j = i+1, n do 43 | args[j] = addasterisk(args[j]) 44 | end 45 | return file_lines(self, unpack(args, 1, n)) 46 | end 47 | end 48 | return file_lines(self, ...) 49 | end 50 | 51 | local file_read = file_meta.__index.read 52 | file_meta.__index.read = function(self, ...) 53 | local n = select('#', ...) 54 | for i = 1, n do 55 | local a = select(i, ...) 56 | local b = addasterisk(a) 57 | -- as an optimization we only allocate a table for the 58 | -- modified format arguments when we have a '*' somewhere 59 | if a ~= b then 60 | local args = { ... } 61 | args[i] = b 62 | for j = i+1, n do 63 | args[j] = addasterisk(args[j]) 64 | end 65 | return file_read(self, unpack(args, 1, n)) 66 | end 67 | end 68 | return file_read(self, ...) 69 | end 70 | 71 | end -- got a valid metatable for file objects 72 | 73 | 74 | -- changes for Lua 5.1 only 75 | if lua_version == "5.1" then 76 | 77 | -- cache globals 78 | local error, pcall, rawset, setmetatable, tostring, xpcall = 79 | error, pcall, rawset, setmetatable, tostring, xpcall 80 | local coroutine, package, string = coroutine, package, string 81 | local coroutine_resume = coroutine.resume 82 | local coroutine_running = coroutine.running 83 | local coroutine_status = coroutine.status 84 | local coroutine_yield = coroutine.yield 85 | local io_type = io.type 86 | 87 | 88 | -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) 89 | local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ" 90 | local is_luajit52 = is_luajit and 91 | #setmetatable({}, { __len = function() return 1 end }) == 1 92 | 93 | 94 | -- make package.searchers available as an alias for package.loaders 95 | local p_index = { searchers = package.loaders } 96 | setmetatable(package, { 97 | __index = p_index, 98 | __newindex = function(p, k, v) 99 | if k == "searchers" then 100 | rawset(p, "loaders", v) 101 | p_index.searchers = v 102 | else 103 | rawset(p, k, v) 104 | end 105 | end 106 | }) 107 | 108 | 109 | if type(file_meta) == "table" and type(file_meta.__index) == "table" then 110 | if not is_luajit then 111 | local function helper(_, var_1, ...) 112 | if var_1 == nil then 113 | if (...) ~= nil then 114 | error((...), 2) 115 | end 116 | end 117 | return var_1, ... 118 | end 119 | 120 | local function lines_iterator(st) 121 | return helper(st, st.f:read(unpack(st, 1, st.n))) 122 | end 123 | 124 | local file_write = file_meta.__index.write 125 | file_meta.__index.write = function(self, ...) 126 | local res, msg, errno = file_write(self, ...) 127 | if res then 128 | return self 129 | else 130 | return nil, msg, errno 131 | end 132 | end 133 | 134 | file_meta.__index.lines = function(self, ...) 135 | if io_type(self) == "closed file" then 136 | error("attempt to use a closed file", 2) 137 | end 138 | local st = { f=self, n=select('#', ...), ... } 139 | for i = 1, st.n do 140 | local t = type(st[i]) 141 | if t == "string" then 142 | local fmt = st[i]:match("^*?([aln])") 143 | if not fmt then 144 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) 145 | end 146 | st[i] = "*"..fmt 147 | elseif t ~= "number" then 148 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) 149 | end 150 | end 151 | return lines_iterator, st 152 | end 153 | end -- not luajit 154 | end -- file_meta valid 155 | 156 | 157 | -- the (x)pcall implementations start a new coroutine internally 158 | -- to allow yielding even in Lua 5.1. to allow for accurate 159 | -- stack traces we keep track of the nested coroutine activations 160 | -- in the weak tables below: 161 | local weak_meta = { __mode = "kv" } 162 | -- maps the internal pcall coroutines to the user coroutine that 163 | -- *should* be running if pcall didn't use coroutines internally 164 | local pcall_mainOf = setmetatable({}, weak_meta) 165 | -- table that maps each running coroutine started by pcall to 166 | -- the coroutine that resumed it (user coroutine *or* pcall 167 | -- coroutine!) 168 | local pcall_previous = setmetatable({}, weak_meta) 169 | -- reverse of `pcall_mainOf`. maps a user coroutine to the 170 | -- currently active pcall coroutine started within it 171 | local pcall_callOf = setmetatable({}, weak_meta) 172 | -- similar to `pcall_mainOf` but is used only while executing 173 | -- the error handler of xpcall (thus no nesting is necessary!) 174 | local xpcall_running = setmetatable({}, weak_meta) 175 | 176 | -- handle debug functions 177 | if type(debug) == "table" then 178 | local debug_getinfo = debug.getinfo 179 | local debug_traceback = debug.traceback 180 | 181 | if not is_luajit then 182 | local function calculate_trace_level(co, level) 183 | if level ~= nil then 184 | for out = 1, 1/0 do 185 | local info = (co==nil) and debug_getinfo(out, "") or debug_getinfo(co, out, "") 186 | if info == nil then 187 | local max = out-1 188 | if level <= max then 189 | return level 190 | end 191 | return nil, level-max 192 | end 193 | end 194 | end 195 | return 1 196 | end 197 | 198 | local stack_pattern = "\nstack traceback:" 199 | local stack_replace = "" 200 | function debug.traceback(co, msg, level) 201 | local lvl 202 | local nilmsg 203 | if type(co) ~= "thread" then 204 | co, msg, level = coroutine_running(), co, msg 205 | end 206 | if msg == nil then 207 | msg = "" 208 | nilmsg = true 209 | elseif type(msg) ~= "string" then 210 | return msg 211 | end 212 | if co == nil then 213 | msg = debug_traceback(msg, level or 1) 214 | else 215 | local xpco = xpcall_running[co] 216 | if xpco ~= nil then 217 | lvl, level = calculate_trace_level(xpco, level) 218 | if lvl then 219 | msg = debug_traceback(xpco, msg, lvl) 220 | else 221 | msg = msg..stack_pattern 222 | end 223 | lvl, level = calculate_trace_level(co, level) 224 | if lvl then 225 | local trace = debug_traceback(co, "", lvl) 226 | msg = msg..trace:gsub(stack_pattern, stack_replace) 227 | end 228 | else 229 | co = pcall_callOf[co] or co 230 | lvl, level = calculate_trace_level(co, level) 231 | if lvl then 232 | msg = debug_traceback(co, msg, lvl) 233 | else 234 | msg = msg..stack_pattern 235 | end 236 | end 237 | co = pcall_previous[co] 238 | while co ~= nil do 239 | lvl, level = calculate_trace_level(co, level) 240 | if lvl then 241 | local trace = debug_traceback(co, "", lvl) 242 | msg = msg..trace:gsub(stack_pattern, stack_replace) 243 | end 244 | co = pcall_previous[co] 245 | end 246 | end 247 | if nilmsg then 248 | msg = msg:gsub("^\n", "") 249 | end 250 | msg = msg:gsub("\n\t%(tail call%): %?", "\000") 251 | msg = msg:gsub("\n\t%.%.%.\n", "\001\n") 252 | msg = msg:gsub("\n\t%.%.%.$", "\001") 253 | msg = msg:gsub("(%z+)\001(%z+)", function(some, other) 254 | return "\n\t(..."..#some+#other.."+ tail call(s)...)" 255 | end) 256 | msg = msg:gsub("\001(%z+)", function(zeros) 257 | return "\n\t(..."..#zeros.."+ tail call(s)...)" 258 | end) 259 | msg = msg:gsub("(%z+)\001", function(zeros) 260 | return "\n\t(..."..#zeros.."+ tail call(s)...)" 261 | end) 262 | msg = msg:gsub("%z+", function(zeros) 263 | return "\n\t(..."..#zeros.." tail call(s)...)" 264 | end) 265 | msg = msg:gsub("\001", function() 266 | return "\n\t..." 267 | end) 268 | return msg 269 | end 270 | end -- is not luajit 271 | end -- debug table available 272 | 273 | 274 | if not is_luajit52 then 275 | local coroutine_running52 = M.coroutine.running 276 | function M.coroutine.running() 277 | local co, ismain = coroutine_running52() 278 | if ismain then 279 | return co, true 280 | else 281 | return pcall_mainOf[co] or co, false 282 | end 283 | end 284 | end 285 | 286 | if not is_luajit then 287 | local function pcall_results(current, call, success, ...) 288 | if coroutine_status(call) == "suspended" then 289 | return pcall_results(current, call, coroutine_resume(call, coroutine_yield(...))) 290 | end 291 | if pcall_previous then 292 | pcall_previous[call] = nil 293 | local main = pcall_mainOf[call] 294 | if main == current then current = nil end 295 | pcall_callOf[main] = current 296 | end 297 | pcall_mainOf[call] = nil 298 | return success, ... 299 | end 300 | 301 | local function pcall_exec(current, call, ...) 302 | local main = pcall_mainOf[current] or current 303 | pcall_mainOf[call] = main 304 | if pcall_previous then 305 | pcall_previous[call] = current 306 | pcall_callOf[main] = call 307 | end 308 | return pcall_results(current, call, coroutine_resume(call, ...)) 309 | end 310 | 311 | local coroutine_create52 = M.coroutine.create 312 | 313 | local function pcall_coroutine(func) 314 | if type(func) ~= "function" then 315 | local callable = func 316 | func = function (...) return callable(...) end 317 | end 318 | return coroutine_create52(func) 319 | end 320 | 321 | function M.pcall(func, ...) 322 | local current = coroutine_running() 323 | if not current then return pcall(func, ...) end 324 | return pcall_exec(current, pcall_coroutine(func), ...) 325 | end 326 | 327 | local function xpcall_catch(current, call, msgh, success, ...) 328 | if not success then 329 | xpcall_running[current] = call 330 | local ok, result = pcall(msgh, ...) 331 | xpcall_running[current] = nil 332 | if not ok then 333 | return false, "error in error handling ("..tostring(result)..")" 334 | end 335 | return false, result 336 | end 337 | return true, ... 338 | end 339 | 340 | function M.xpcall(f, msgh, ...) 341 | local current = coroutine_running() 342 | if not current then 343 | local args, n = { ... }, select('#', ...) 344 | return xpcall(function() return f(unpack(args, 1, n)) end, msgh) 345 | end 346 | local call = pcall_coroutine(f) 347 | return xpcall_catch(current, call, msgh, pcall_exec(current, call, ...)) 348 | end 349 | end -- not luajit 350 | 351 | end -- lua 5.1 352 | 353 | 354 | -- handle exporting to global scope 355 | local function extend_table(from, to) 356 | if from ~= to then 357 | for k,v in pairs(from) do 358 | if type(v) == "table" and 359 | type(to[k]) == "table" and 360 | v ~= to[k] then 361 | extend_table(v, to[k]) 362 | else 363 | to[k] = v 364 | end 365 | end 366 | end 367 | end 368 | 369 | extend_table(M, _G) 370 | 371 | end -- lua < 5.3 372 | 373 | -- vi: set expandtab softtabstop=3 shiftwidth=3 : 374 | -------------------------------------------------------------------------------- /vendor/compat-5.3/compat53/module.lua: -------------------------------------------------------------------------------- 1 | local _G, _VERSION = _G, _VERSION 2 | local lua_version = _VERSION:sub(-3) 3 | 4 | 5 | local M = _G 6 | 7 | if lua_version < "5.3" then 8 | 9 | -- cache globals in upvalues 10 | local error, ipairs, pairs, pcall, require, select, setmetatable, type = 11 | error, ipairs, pairs, pcall, require, select, setmetatable, type 12 | local debug, io, math, package, string, table = 13 | debug, io, math, package, string, table 14 | local io_lines = io.lines 15 | local io_read = io.read 16 | local unpack = lua_version == "5.1" and unpack or table.unpack 17 | 18 | -- create module table 19 | M = {} 20 | local M_meta = { 21 | __index = _G, 22 | -- __newindex is set at the end 23 | } 24 | setmetatable(M, M_meta) 25 | 26 | -- create subtables 27 | M.io = setmetatable({}, { __index = io }) 28 | M.math = setmetatable({}, { __index = math }) 29 | M.string = setmetatable({}, { __index = string }) 30 | M.table = setmetatable({}, { __index = table }) 31 | M.utf8 = {} 32 | 33 | 34 | -- select the most powerful getmetatable function available 35 | local gmt = type(debug) == "table" and debug.getmetatable or 36 | getmetatable or function() return false end 37 | 38 | -- type checking functions 39 | local checkinteger -- forward declararation 40 | 41 | local function argcheck(cond, i, f, extra) 42 | if not cond then 43 | error("bad argument #"..i.." to '"..f.."' ("..extra..")", 0) 44 | end 45 | end 46 | 47 | 48 | -- load utf8 library 49 | local utf8_ok, utf8lib = pcall(require, "compat53.utf8") 50 | if utf8_ok then 51 | if lua_version == "5.1" then 52 | utf8lib.charpattern = "[%z\1-\127\194-\244][\128-\191]*" 53 | end 54 | for k,v in pairs(utf8lib) do 55 | M.utf8[k] = v 56 | end 57 | package.loaded["utf8"] = M.utf8 58 | end 59 | 60 | 61 | -- load table library 62 | local table_ok, tablib = pcall(require, "compat53.table") 63 | if table_ok then 64 | for k,v in pairs(tablib) do 65 | M.table[k] = v 66 | end 67 | end 68 | 69 | 70 | -- load string packing functions 71 | local str_ok, strlib = pcall(require, "compat53.string") 72 | if str_ok then 73 | for k,v in pairs(strlib) do 74 | M.string[k] = v 75 | end 76 | end 77 | 78 | 79 | -- try Roberto's struct module for string packing/unpacking if 80 | -- compat53.string is unavailable 81 | if not str_ok then 82 | local struct_ok, struct = pcall(require, "struct") 83 | if struct_ok then 84 | M.string.pack = struct.pack 85 | M.string.packsize = struct.size 86 | M.string.unpack = struct.unpack 87 | end 88 | end 89 | 90 | 91 | -- update math library 92 | do 93 | local maxint, minint = 1 94 | 95 | while maxint+1 > maxint and 2*maxint > maxint do 96 | maxint = maxint * 2 97 | end 98 | if 2*maxint <= maxint then 99 | maxint = 2*maxint-1 100 | minint = -maxint-1 101 | else 102 | maxint = maxint 103 | minint = -maxint 104 | end 105 | M.math.maxinteger = maxint 106 | M.math.mininteger = minint 107 | 108 | function M.math.tointeger(n) 109 | if type(n) == "number" and n <= maxint and n >= minint and n % 1 == 0 then 110 | return n 111 | end 112 | return nil 113 | end 114 | 115 | function M.math.type(n) 116 | if type(n) == "number" then 117 | if n <= maxint and n >= minint and n % 1 == 0 then 118 | return "integer" 119 | else 120 | return "float" 121 | end 122 | else 123 | return nil 124 | end 125 | end 126 | 127 | function checkinteger(x, i, f) 128 | local t = type(x) 129 | if t ~= "number" then 130 | error("bad argument #"..i.." to '"..f.. 131 | "' (number expected, got "..t..")", 0) 132 | elseif x > maxint or x < minint or x % 1 ~= 0 then 133 | error("bad argument #"..i.." to '"..f.. 134 | "' (number has no integer representation)", 0) 135 | else 136 | return x 137 | end 138 | end 139 | 140 | function M.math.ult(m, n) 141 | m = checkinteger(m, "1", "math.ult") 142 | n = checkinteger(n, "2", "math.ult") 143 | if m >= 0 and n < 0 then 144 | return true 145 | elseif m < 0 and n >= 0 then 146 | return false 147 | else 148 | return m < n 149 | end 150 | end 151 | end 152 | 153 | 154 | -- assert should allow non-string error objects 155 | function M.assert(cond, ...) 156 | if cond then 157 | return cond, ... 158 | elseif select('#', ...) > 0 then 159 | error((...), 0) 160 | else 161 | error("assertion failed!", 0) 162 | end 163 | end 164 | 165 | 166 | -- ipairs should respect __index metamethod 167 | do 168 | local function ipairs_iterator(st, var) 169 | var = var + 1 170 | local val = st[var] 171 | if val ~= nil then 172 | return var, st[var] 173 | end 174 | end 175 | function M.ipairs(t) 176 | if gmt(t) ~= nil then -- t has metatable 177 | return ipairs_iterator, t, 0 178 | else 179 | return ipairs(t) 180 | end 181 | end 182 | end 183 | 184 | 185 | -- make '*' optional for io.read and io.lines 186 | do 187 | local function addasterisk(fmt) 188 | if type(fmt) == "string" and fmt:sub(1, 1) ~= "*" then 189 | return "*"..fmt 190 | else 191 | return fmt 192 | end 193 | end 194 | 195 | function M.io.read(...) 196 | local n = select('#', ...) 197 | for i = 1, n do 198 | local a = select(i, ...) 199 | local b = addasterisk(a) 200 | -- as an optimization we only allocate a table for the 201 | -- modified format arguments when we have a '*' somewhere. 202 | if a ~= b then 203 | local args = { ... } 204 | args[i] = b 205 | for j = i+1, n do 206 | args[j] = addasterisk(args[j]) 207 | end 208 | return io_read(unpack(args, 1, n)) 209 | end 210 | end 211 | return io_read(...) 212 | end 213 | 214 | -- PUC-Rio Lua 5.1 uses a different implementation for io.lines! 215 | function M.io.lines(...) 216 | local n = select('#', ...) 217 | for i = 2, n do 218 | local a = select(i, ...) 219 | local b = addasterisk(a) 220 | -- as an optimization we only allocate a table for the 221 | -- modified format arguments when we have a '*' somewhere. 222 | if a ~= b then 223 | local args = { ... } 224 | args[i] = b 225 | for j = i+1, n do 226 | args[j] = addasterisk(args[j]) 227 | end 228 | return io_lines(unpack(args, 1, n)) 229 | end 230 | end 231 | return io_lines(...) 232 | end 233 | end 234 | 235 | 236 | -- update table library (if C module not available) 237 | if not table_ok then 238 | local table_concat = table.concat 239 | local table_insert = table.insert 240 | local table_remove = table.remove 241 | local table_sort = table.sort 242 | 243 | function M.table.concat(list, sep, i, j) 244 | local mt = gmt(list) 245 | if type(mt) == "table" and type(mt.__len) == "function" then 246 | local src = list 247 | list, i, j = {}, i or 1, j or mt.__len(src) 248 | for k = i, j do 249 | list[k] = src[k] 250 | end 251 | end 252 | return table_concat(list, sep, i, j) 253 | end 254 | 255 | function M.table.insert(list, ...) 256 | local mt = gmt(list) 257 | local has_mt = type(mt) == "table" 258 | local has_len = has_mt and type(mt.__len) == "function" 259 | if has_mt and (has_len or mt.__index or mt.__newindex) then 260 | local e = (has_len and mt.__len(list) or #list)+1 261 | local nargs, pos, value = select('#', ...), ... 262 | if nargs == 1 then 263 | pos, value = e, pos 264 | elseif nargs == 2 then 265 | pos = checkinteger(pos, "2", "table.insert") 266 | argcheck(1 <= pos and pos <= e, "2", "table.insert", 267 | "position out of bounds" ) 268 | else 269 | error("wrong number of arguments to 'insert'", 0) 270 | end 271 | for i = e-1, pos, -1 do 272 | list[i+1] = list[i] 273 | end 274 | list[pos] = value 275 | else 276 | return table_insert(list, ...) 277 | end 278 | end 279 | 280 | function M.table.move(a1, f, e, t, a2) 281 | a2 = a2 or a1 282 | f = checkinteger(f, "2", "table.move") 283 | argcheck(f > 0, "2", "table.move", 284 | "initial position must be positive") 285 | e = checkinteger(e, "3", "table.move") 286 | t = checkinteger(t, "4", "table.move") 287 | if e >= f then 288 | local m, n, d = 0, e-f, 1 289 | if t > f then m, n, d = n, m, -1 end 290 | for i = m, n, d do 291 | a2[t+i] = a1[f+i] 292 | end 293 | end 294 | return a2 295 | end 296 | 297 | function M.table.remove(list, pos) 298 | local mt = gmt(list) 299 | local has_mt = type(mt) == "table" 300 | local has_len = has_mt and type(mt.__len) == "function" 301 | if has_mt and (has_len or mt.__index or mt.__newindex) then 302 | local e = (has_len and mt.__len(list) or #list) 303 | pos = pos ~= nil and checkinteger(pos, "2", "table.remove") or e 304 | if pos ~= e then 305 | argcheck(1 <= pos and pos <= e+1, "2", "table.remove", 306 | "position out of bounds" ) 307 | end 308 | local result = list[pos] 309 | while pos < e do 310 | list[pos] = list[pos+1] 311 | pos = pos + 1 312 | end 313 | list[pos] = nil 314 | return result 315 | else 316 | return table_remove(list, pos) 317 | end 318 | end 319 | 320 | do 321 | local function pivot(list, cmp, a, b) 322 | local m = b - a 323 | if m > 2 then 324 | local c = a + (m-m%2)/2 325 | local x, y, z = list[a], list[b], list[c] 326 | if not cmp(x, y) then 327 | x, y, a, b = y, x, b, a 328 | end 329 | if not cmp(y, z) then 330 | y, b = z, c 331 | end 332 | if not cmp(x, y) then 333 | y, b = x, a 334 | end 335 | return b, y 336 | else 337 | return b, list[b] 338 | end 339 | end 340 | 341 | local function lt_cmp(a, b) 342 | return a < b 343 | end 344 | 345 | local function qsort(list, cmp, b, e) 346 | if b < e then 347 | local i, j, k, val = b, e, pivot(list, cmp, b, e) 348 | while i < j do 349 | while i < j and cmp(list[i], val) do 350 | i = i + 1 351 | end 352 | while i < j and not cmp(list[j], val) do 353 | j = j - 1 354 | end 355 | if i < j then 356 | list[i], list[j] = list[j], list[i] 357 | if i == k then k = j end -- update pivot position 358 | i, j = i+1, j-1 359 | end 360 | end 361 | if i ~= k and not cmp(list[i], val) then 362 | list[i], list[k] = val, list[i] 363 | k = i -- update pivot position 364 | end 365 | qsort(list, cmp, b, i == k and i-1 or i) 366 | return qsort(list, cmp, i+1, e) 367 | end 368 | end 369 | 370 | function M.table.sort(list, cmp) 371 | local mt = gmt(list) 372 | local has_mt = type(mt) == "table" 373 | local has_len = has_mt and type(mt.__len) == "function" 374 | if has_len then 375 | cmp = cmp or lt_cmp 376 | local len = mt.__len(list) 377 | return qsort(list, cmp, 1, len) 378 | else 379 | return table_sort(list, cmp) 380 | end 381 | end 382 | end 383 | 384 | local function unpack_helper(list, i, j, ...) 385 | if j < i then 386 | return ... 387 | else 388 | return unpack_helper(list, i, j-1, list[j], ...) 389 | end 390 | end 391 | function M.table.unpack(list, i, j) 392 | local mt = gmt(list) 393 | local has_mt = type(mt) == "table" 394 | local has_len = has_mt and type(mt.__len) == "function" 395 | if has_mt and (has_len or mt.__index) then 396 | i, j = i or 1, j or (has_len and mt.__len(list)) or #list 397 | return unpack_helper(list, i, j) 398 | else 399 | return unpack(list, i, j) 400 | end 401 | end 402 | end -- update table library 403 | 404 | 405 | -- bring Lua 5.1 (and LuaJIT) up to speed with Lua 5.2 406 | if lua_version == "5.1" then 407 | -- detect LuaJIT (including LUAJIT_ENABLE_LUA52COMPAT compilation flag) 408 | local is_luajit = (string.dump(function() end) or ""):sub(1, 3) == "\027LJ" 409 | local is_luajit52 = is_luajit and 410 | #setmetatable({}, { __len = function() return 1 end }) == 1 411 | 412 | -- cache globals in upvalues 413 | local load, loadfile, loadstring, setfenv, xpcall = 414 | load, loadfile, loadstring, setfenv, xpcall 415 | local coroutine, os = coroutine, os 416 | local coroutine_create = coroutine.create 417 | local coroutine_resume = coroutine.resume 418 | local coroutine_running = coroutine.running 419 | local coroutine_status = coroutine.status 420 | local coroutine_yield = coroutine.yield 421 | local io_input = io.input 422 | local io_open = io.open 423 | local io_output = io.output 424 | local io_write = io.write 425 | local math_log = math.log 426 | local os_execute = os.execute 427 | local string_find = string.find 428 | local string_format = string.format 429 | local string_gmatch = string.gmatch 430 | local string_gsub = string.gsub 431 | local string_match = string.match 432 | local string_rep = string.rep 433 | local table_concat = table.concat 434 | 435 | -- create subtables 436 | M.coroutine = setmetatable({}, { __index = coroutine }) 437 | M.os = setmetatable({}, { __index = os }) 438 | M.package = setmetatable({}, { __index = package }) 439 | 440 | -- handle debug functions 441 | if type(debug) == "table" then 442 | local debug_setfenv = debug.setfenv 443 | local debug_getfenv = debug.getfenv 444 | local debug_setmetatable = debug.setmetatable 445 | 446 | M.debug = setmetatable({}, { __index = debug }) 447 | 448 | if not is_luajit52 then 449 | function M.debug.setuservalue(obj, value) 450 | if type(obj) ~= "userdata" then 451 | error("bad argument #1 to 'setuservalue' (userdata expected, got ".. 452 | type(obj)..")", 2) 453 | end 454 | if value == nil then value = _G end 455 | if type(value) ~= "table" then 456 | error("bad argument #2 to 'setuservalue' (table expected, got ".. 457 | type(value)..")", 2) 458 | end 459 | return debug_setfenv(obj, value) 460 | end 461 | 462 | function M.debug.getuservalue(obj) 463 | if type(obj) ~= "userdata" then 464 | return nil 465 | else 466 | local v = debug_getfenv(obj) 467 | if v == _G or v == package then 468 | return nil 469 | end 470 | return v 471 | end 472 | end 473 | 474 | function M.debug.setmetatable(value, tab) 475 | debug_setmetatable(value, tab) 476 | return value 477 | end 478 | end -- not luajit with compat52 enabled 479 | end -- debug table available 480 | 481 | 482 | if not is_luajit52 then 483 | function M.pairs(t) 484 | local mt = gmt(t) 485 | if type(mt) == "table" and type(mt.__pairs) == "function" then 486 | return mt.__pairs(t) 487 | else 488 | return pairs(t) 489 | end 490 | end 491 | end 492 | 493 | 494 | if not is_luajit then 495 | local function check_mode(mode, prefix) 496 | local has = { text = false, binary = false } 497 | for i = 1,#mode do 498 | local c = mode:sub(i, i) 499 | if c == "t" then has.text = true end 500 | if c == "b" then has.binary = true end 501 | end 502 | local t = prefix:sub(1, 1) == "\27" and "binary" or "text" 503 | if not has[t] then 504 | return "attempt to load a "..t.." chunk (mode is '"..mode.."')" 505 | end 506 | end 507 | 508 | function M.load(ld, source, mode, env) 509 | mode = mode or "bt" 510 | local chunk, msg 511 | if type( ld ) == "string" then 512 | if mode ~= "bt" then 513 | local merr = check_mode(mode, ld) 514 | if merr then return nil, merr end 515 | end 516 | chunk, msg = loadstring(ld, source) 517 | else 518 | local ld_type = type(ld) 519 | if ld_type ~= "function" then 520 | error("bad argument #1 to 'load' (function expected, got ".. 521 | ld_type..")", 2) 522 | end 523 | if mode ~= "bt" then 524 | local checked, merr = false, nil 525 | local function checked_ld() 526 | if checked then 527 | return ld() 528 | else 529 | checked = true 530 | local v = ld() 531 | merr = check_mode(mode, v or "") 532 | if merr then return nil end 533 | return v 534 | end 535 | end 536 | chunk, msg = load(checked_ld, source) 537 | if merr then return nil, merr end 538 | else 539 | chunk, msg = load(ld, source) 540 | end 541 | end 542 | if not chunk then 543 | return chunk, msg 544 | end 545 | if env ~= nil then 546 | setfenv(chunk, env) 547 | end 548 | return chunk 549 | end 550 | 551 | M.loadstring = M.load 552 | 553 | function M.loadfile(file, mode, env) 554 | mode = mode or "bt" 555 | if mode ~= "bt" then 556 | local f = io_open(file, "rb") 557 | if f then 558 | local prefix = f:read(1) 559 | f:close() 560 | if prefix then 561 | local merr = check_mode(mode, prefix) 562 | if merr then return nil, merr end 563 | end 564 | end 565 | end 566 | local chunk, msg = loadfile(file) 567 | if not chunk then 568 | return chunk, msg 569 | end 570 | if env ~= nil then 571 | setfenv(chunk, env) 572 | end 573 | return chunk 574 | end 575 | end -- not luajit 576 | 577 | 578 | if not is_luajit52 then 579 | function M.rawlen(v) 580 | local t = type(v) 581 | if t ~= "string" and t ~= "table" then 582 | error("bad argument #1 to 'rawlen' (table or string expected)", 2) 583 | end 584 | return #v 585 | end 586 | end 587 | 588 | 589 | if not is_luajit then 590 | function M.xpcall(f, msgh, ...) 591 | local args, n = { ... }, select('#', ...) 592 | return xpcall(function() return f(unpack(args, 1, n)) end, msgh) 593 | end 594 | end 595 | 596 | 597 | if not is_luajit52 then 598 | function M.os.execute(cmd) 599 | local code = os_execute(cmd) 600 | -- Lua 5.1 does not report exit by signal. 601 | if code == 0 then 602 | return true, "exit", code 603 | else 604 | if package.config:sub(1, 1) == '/' then 605 | code = code/256 -- only correct on Linux! 606 | end 607 | return nil, "exit", code 608 | end 609 | end 610 | end 611 | 612 | 613 | if not table_ok and not is_luajit52 then 614 | M.table.pack = function(...) 615 | return { n = select('#', ...), ... } 616 | end 617 | end 618 | 619 | 620 | local main_coroutine = coroutine_create(function() end) 621 | 622 | function M.coroutine.create(func) 623 | local success, result = pcall(coroutine_create, func) 624 | if not success then 625 | if type(func) ~= "function" then 626 | error("bad argument #1 (function expected)", 0) 627 | end 628 | result = coroutine_create(function(...) return func(...) end) 629 | end 630 | return result 631 | end 632 | 633 | if not is_luajit52 then 634 | function M.coroutine.running() 635 | local co = coroutine_running() 636 | if co then 637 | return co, false 638 | else 639 | return main_coroutine, true 640 | end 641 | end 642 | end 643 | 644 | function M.coroutine.yield(...) 645 | local co, flag = coroutine_running() 646 | if co and not flag then 647 | return coroutine_yield(...) 648 | else 649 | error("attempt to yield from outside a coroutine", 0) 650 | end 651 | end 652 | 653 | if not is_luajit then 654 | function M.coroutine.resume(co, ...) 655 | if co == main_coroutine then 656 | return false, "cannot resume non-suspended coroutine" 657 | else 658 | return coroutine_resume(co, ...) 659 | end 660 | end 661 | 662 | function M.coroutine.status(co) 663 | local notmain = coroutine_running() 664 | if co == main_coroutine then 665 | return notmain and "normal" or "running" 666 | else 667 | return coroutine_status(co) 668 | end 669 | end 670 | end -- not luajit 671 | 672 | 673 | if not is_luajit then 674 | M.math.log = function(x, base) 675 | if base ~= nil then 676 | return math_log(x)/math_log(base) 677 | else 678 | return math_log(x) 679 | end 680 | end 681 | end 682 | 683 | 684 | if not is_luajit then 685 | function M.package.searchpath(name, path, sep, rep) 686 | sep = (sep or "."):gsub("(%p)", "%%%1") 687 | rep = (rep or package.config:sub(1, 1)):gsub("(%%)", "%%%1") 688 | local pname = name:gsub(sep, rep):gsub("(%%)", "%%%1") 689 | local msg = {} 690 | for subpath in path:gmatch("[^;]+") do 691 | local fpath = subpath:gsub("%?", pname) 692 | local f = io_open(fpath, "r") 693 | if f then 694 | f:close() 695 | return fpath 696 | end 697 | msg[#msg+1] = "\n\tno file '" .. fpath .. "'" 698 | end 699 | return nil, table_concat(msg) 700 | end 701 | end 702 | 703 | 704 | local function fix_pattern(pattern) 705 | return (string_gsub(pattern, "%z", "%%z")) 706 | end 707 | 708 | function M.string.find(s, pattern, ...) 709 | return string_find(s, fix_pattern(pattern), ...) 710 | end 711 | 712 | function M.string.gmatch(s, pattern) 713 | return string_gmatch(s, fix_pattern(pattern)) 714 | end 715 | 716 | function M.string.gsub(s, pattern, ...) 717 | return string_gsub(s, fix_pattern(pattern), ...) 718 | end 719 | 720 | function M.string.match(s, pattern, ...) 721 | return string_match(s, fix_pattern(pattern), ...) 722 | end 723 | 724 | if not is_luajit then 725 | function M.string.rep(s, n, sep) 726 | if sep ~= nil and sep ~= "" and n >= 2 then 727 | return s .. string_rep(sep..s, n-1) 728 | else 729 | return string_rep(s, n) 730 | end 731 | end 732 | end 733 | 734 | if not is_luajit then 735 | do 736 | local addqt = { 737 | ["\n"] = "\\\n", 738 | ["\\"] = "\\\\", 739 | ["\""] = "\\\"" 740 | } 741 | 742 | local function addquoted(c, d) 743 | return (addqt[c] or string_format(d~="" and "\\%03d" or "\\%d", c:byte()))..d 744 | end 745 | 746 | function M.string.format(fmt, ...) 747 | local args, n = { ... }, select('#', ...) 748 | local i = 0 749 | local function adjust_fmt(lead, mods, kind) 750 | if #lead % 2 == 0 then 751 | i = i + 1 752 | if kind == "s" then 753 | args[i] = _G.tostring(args[i]) 754 | elseif kind == "q" then 755 | args[i] = '"'..string_gsub(args[i], "([%z%c\\\"\n])(%d?)", addquoted)..'"' 756 | return lead.."%"..mods.."s" 757 | end 758 | end 759 | end 760 | fmt = string_gsub(fmt, "(%%*)%%([%d%.%-%+%# ]*)(%a)", adjust_fmt) 761 | return string_format(fmt, unpack(args, 1, n)) 762 | end 763 | end 764 | end 765 | 766 | 767 | function M.io.write(...) 768 | local res, msg, errno = io_write(...) 769 | if res then 770 | return io_output() 771 | else 772 | return nil, msg, errno 773 | end 774 | end 775 | 776 | if not is_luajit then 777 | local function helper(st, var_1, ...) 778 | if var_1 == nil then 779 | if st.doclose then st.f:close() end 780 | if (...) ~= nil then 781 | error((...), 2) 782 | end 783 | end 784 | return var_1, ... 785 | end 786 | 787 | local function lines_iterator(st) 788 | return helper(st, st.f:read(unpack(st, 1, st.n))) 789 | end 790 | 791 | function M.io.lines(fname, ...) 792 | local doclose, file, msg 793 | if fname ~= nil then 794 | doclose, file, msg = true, io_open(fname, "r") 795 | if not file then error(msg, 2) end 796 | else 797 | doclose, file = false, io_input() 798 | end 799 | local st = { f=file, doclose=doclose, n=select('#', ...), ... } 800 | for i = 1, st.n do 801 | local t = type(st[i]) 802 | if t == "string" then 803 | local fmt = st[i]:match("^%*?([aln])") 804 | if not fmt then 805 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) 806 | end 807 | st[i] = "*"..fmt 808 | elseif t ~= "number" then 809 | error("bad argument #"..(i+1).." to 'for iterator' (invalid format)", 2) 810 | end 811 | end 812 | return lines_iterator, st 813 | end 814 | end -- not luajit 815 | 816 | end -- lua 5.1 817 | 818 | -- further write should be forwarded to _G 819 | M_meta.__newindex = _G 820 | 821 | end -- lua < 5.3 822 | 823 | 824 | -- return module table 825 | return M 826 | 827 | -- vi: set expandtab softtabstop=3 shiftwidth=3 : 828 | -------------------------------------------------------------------------------- /vendor/compat-5.3/lprefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lprefix.h,v 1.2 2014/12/29 16:54:13 roberto Exp $ 3 | ** Definitions for Lua code that must come before any other header file 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #ifndef lprefix_h 8 | #define lprefix_h 9 | 10 | 11 | /* 12 | ** Allows POSIX/XSI stuff 13 | */ 14 | #if !defined(LUA_USE_C89) /* { */ 15 | 16 | #if !defined(_XOPEN_SOURCE) 17 | #define _XOPEN_SOURCE 600 18 | #elif _XOPEN_SOURCE == 0 19 | #undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ 20 | #endif 21 | 22 | /* 23 | ** Allows manipulation of large files in gcc and some other compilers 24 | */ 25 | #if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) 26 | #define _LARGEFILE_SOURCE 1 27 | #define _FILE_OFFSET_BITS 64 28 | #endif 29 | 30 | #endif /* } */ 31 | 32 | 33 | /* 34 | ** Windows stuff 35 | */ 36 | #if defined(_WIN32) /* { */ 37 | 38 | #if !defined(_CRT_SECURE_NO_WARNINGS) 39 | #define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ 40 | #endif 41 | 42 | #endif /* } */ 43 | 44 | 45 | /* COMPAT53 adaptation */ 46 | #include "c-api/compat-5.3.h" 47 | 48 | #undef LUAMOD_API 49 | #define LUAMOD_API extern 50 | 51 | 52 | #ifdef lutf8lib_c 53 | # define luaopen_utf8 luaopen_compat53_utf8 54 | /* we don't support the %U format string of lua_pushfstring! 55 | * code below adapted from the Lua 5.3 sources: 56 | */ 57 | static const char *compat53_utf8_escape (lua_State* L, long x) { 58 | if (x < 0x80) { /* ASCII */ 59 | char c = (char)x; 60 | lua_pushlstring(L, &c, 1); 61 | } else { 62 | char buff[8] = { 0 }; 63 | unsigned int mfb = 0x3f; 64 | int n = 1; 65 | do { 66 | buff[8 - (n++)] = (char)(0x80|(x & 0x3f)); 67 | x >>= 6; 68 | mfb >>= 1; 69 | } while (x > mfb); 70 | buff[8-n] = (char)((~mfb << 1) | x); 71 | lua_pushlstring(L, buff+8-n, n); 72 | } 73 | return lua_tostring(L, -1); 74 | } 75 | # define lua_pushfstring(L, fmt, l) \ 76 | compat53_utf8_escape(L, l) 77 | #endif 78 | 79 | 80 | #ifdef ltablib_c 81 | # define luaopen_table luaopen_compat53_table 82 | # ifndef LUA_MAXINTEGER 83 | /* conservative estimate: */ 84 | # define LUA_MAXINTEGER INT_MAX 85 | # endif 86 | #endif /* ltablib_c */ 87 | 88 | 89 | #ifdef lstrlib_c 90 | #include 91 | #include 92 | /* move the string library open function out of the way (we only take 93 | * the string packing functions)! 94 | */ 95 | # define luaopen_string luaopen_string_XXX 96 | /* used in string.format implementation, which we don't use: */ 97 | # ifndef LUA_INTEGER_FRMLEN 98 | # define LUA_INTEGER_FRMLEN "" 99 | # define LUA_NUMBER_FRMLEN "" 100 | # endif 101 | # ifndef LUA_MININTEGER 102 | # define LUA_MININTEGER 0 103 | # endif 104 | # ifndef LUA_INTEGER_FMT 105 | # define LUA_INTEGER_FMT "%d" 106 | # endif 107 | # ifndef LUAI_UACINT 108 | # define LUAI_UACINT lua_Integer 109 | # endif 110 | /* different Lua 5.3 versions have conflicting variants of this macro 111 | * in luaconf.h, there's a fallback implementation in lstrlib.c, and 112 | * the macro isn't used for string (un)packing anyway! 113 | * */ 114 | # undef lua_number2strx 115 | # if LUA_VERSION_NUM < 503 116 | /* lstrlib assumes that lua_Integer and lua_Unsigned have the same 117 | * size, so we use the unsigned equivalent of ptrdiff_t! */ 118 | # define lua_Unsigned size_t 119 | # endif 120 | # ifndef l_mathlim 121 | # ifdef LUA_NUMBER_DOUBLE 122 | # define l_mathlim(n) (DBL_##n) 123 | # else 124 | # define l_mathlim(n) (FLT_##n) 125 | # endif 126 | # endif 127 | # ifndef l_mathop 128 | # ifdef LUA_NUMBER_DOUBLE 129 | # define l_mathop(op) op 130 | # else 131 | # define l_mathop(op) op##f 132 | # endif 133 | # endif 134 | # ifndef lua_getlocaledecpoint 135 | # define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) 136 | # endif 137 | # ifndef l_sprintf 138 | # if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 139 | # define l_sprintf(s,sz,f,i) (snprintf(s, sz, f, i)) 140 | # else 141 | # define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s, f, i)) 142 | # endif 143 | # endif 144 | 145 | static int str_pack (lua_State *L); 146 | static int str_packsize (lua_State *L); 147 | static int str_unpack (lua_State *L); 148 | LUAMOD_API int luaopen_compat53_string (lua_State *L) { 149 | luaL_Reg const funcs[] = { 150 | { "pack", str_pack }, 151 | { "packsize", str_packsize }, 152 | { "unpack", str_unpack }, 153 | { NULL, NULL } 154 | }; 155 | luaL_newlib(L, funcs); 156 | return 1; 157 | } 158 | /* fake CLANG feature detection on other compilers */ 159 | # ifndef __has_attribute 160 | # define __has_attribute(x) 0 161 | # endif 162 | /* make luaopen_string(_XXX) static, so it (and all other referenced 163 | * string functions) won't be included in the resulting dll 164 | * (hopefully). 165 | */ 166 | # undef LUAMOD_API 167 | # if defined(__GNUC__) || __has_attribute(__unused__) 168 | # define LUAMOD_API __attribute__((__unused__)) static 169 | # else 170 | # define LUAMOD_API static 171 | # endif 172 | #endif /* lstrlib.c */ 173 | 174 | #endif 175 | 176 | -------------------------------------------------------------------------------- /vendor/compat-5.3/ltablib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: ltablib.c,v 1.93 2016/02/25 19:41:54 roberto Exp $ 3 | ** Library for Table Manipulation 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define ltablib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include "lua.h" 18 | 19 | #include "lauxlib.h" 20 | #include "lualib.h" 21 | 22 | 23 | /* 24 | ** Operations that an object must define to mimic a table 25 | ** (some functions only need some of them) 26 | */ 27 | #define TAB_R 1 /* read */ 28 | #define TAB_W 2 /* write */ 29 | #define TAB_L 4 /* length */ 30 | #define TAB_RW (TAB_R | TAB_W) /* read/write */ 31 | 32 | 33 | #define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n)) 34 | 35 | 36 | static int checkfield (lua_State *L, const char *key, int n) { 37 | lua_pushstring(L, key); 38 | return (lua_rawget(L, -n) != LUA_TNIL); 39 | } 40 | 41 | 42 | /* 43 | ** Check that 'arg' either is a table or can behave like one (that is, 44 | ** has a metatable with the required metamethods) 45 | */ 46 | static void checktab (lua_State *L, int arg, int what) { 47 | if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ 48 | int n = 1; /* number of elements to pop */ 49 | if (lua_getmetatable(L, arg) && /* must have metatable */ 50 | (!(what & TAB_R) || checkfield(L, "__index", ++n)) && 51 | (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && 52 | (!(what & TAB_L) || checkfield(L, "__len", ++n))) { 53 | lua_pop(L, n); /* pop metatable and tested metamethods */ 54 | } 55 | else 56 | luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ 57 | } 58 | } 59 | 60 | 61 | #if defined(LUA_COMPAT_MAXN) 62 | static int maxn (lua_State *L) { 63 | lua_Number max = 0; 64 | luaL_checktype(L, 1, LUA_TTABLE); 65 | lua_pushnil(L); /* first key */ 66 | while (lua_next(L, 1)) { 67 | lua_pop(L, 1); /* remove value */ 68 | if (lua_type(L, -1) == LUA_TNUMBER) { 69 | lua_Number v = lua_tonumber(L, -1); 70 | if (v > max) max = v; 71 | } 72 | } 73 | lua_pushnumber(L, max); 74 | return 1; 75 | } 76 | #endif 77 | 78 | 79 | static int tinsert (lua_State *L) { 80 | lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ 81 | lua_Integer pos; /* where to insert new element */ 82 | switch (lua_gettop(L)) { 83 | case 2: { /* called with only 2 arguments */ 84 | pos = e; /* insert new element at the end */ 85 | break; 86 | } 87 | case 3: { 88 | lua_Integer i; 89 | pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ 90 | luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); 91 | for (i = e; i > pos; i--) { /* move up elements */ 92 | lua_geti(L, 1, i - 1); 93 | lua_seti(L, 1, i); /* t[i] = t[i - 1] */ 94 | } 95 | break; 96 | } 97 | default: { 98 | return luaL_error(L, "wrong number of arguments to 'insert'"); 99 | } 100 | } 101 | lua_seti(L, 1, pos); /* t[pos] = v */ 102 | return 0; 103 | } 104 | 105 | 106 | static int tremove (lua_State *L) { 107 | lua_Integer size = aux_getn(L, 1, TAB_RW); 108 | lua_Integer pos = luaL_optinteger(L, 2, size); 109 | if (pos != size) /* validate 'pos' if given */ 110 | luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); 111 | lua_geti(L, 1, pos); /* result = t[pos] */ 112 | for ( ; pos < size; pos++) { 113 | lua_geti(L, 1, pos + 1); 114 | lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ 115 | } 116 | lua_pushnil(L); 117 | lua_seti(L, 1, pos); /* t[pos] = nil */ 118 | return 1; 119 | } 120 | 121 | 122 | /* 123 | ** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever 124 | ** possible, copy in increasing order, which is better for rehashing. 125 | ** "possible" means destination after original range, or smaller 126 | ** than origin, or copying to another table. 127 | */ 128 | static int tmove (lua_State *L) { 129 | lua_Integer f = luaL_checkinteger(L, 2); 130 | lua_Integer e = luaL_checkinteger(L, 3); 131 | lua_Integer t = luaL_checkinteger(L, 4); 132 | int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ 133 | checktab(L, 1, TAB_R); 134 | checktab(L, tt, TAB_W); 135 | if (e >= f) { /* otherwise, nothing to move */ 136 | lua_Integer n, i; 137 | luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, 138 | "too many elements to move"); 139 | n = e - f + 1; /* number of elements to move */ 140 | luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, 141 | "destination wrap around"); 142 | if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) { 143 | for (i = 0; i < n; i++) { 144 | lua_geti(L, 1, f + i); 145 | lua_seti(L, tt, t + i); 146 | } 147 | } 148 | else { 149 | for (i = n - 1; i >= 0; i--) { 150 | lua_geti(L, 1, f + i); 151 | lua_seti(L, tt, t + i); 152 | } 153 | } 154 | } 155 | lua_pushvalue(L, tt); /* return destination table */ 156 | return 1; 157 | } 158 | 159 | 160 | static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { 161 | lua_geti(L, 1, i); 162 | if (!lua_isstring(L, -1)) 163 | luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", 164 | luaL_typename(L, -1), i); 165 | luaL_addvalue(b); 166 | } 167 | 168 | 169 | static int tconcat (lua_State *L) { 170 | luaL_Buffer b; 171 | lua_Integer last = aux_getn(L, 1, TAB_R); 172 | size_t lsep; 173 | const char *sep = luaL_optlstring(L, 2, "", &lsep); 174 | lua_Integer i = luaL_optinteger(L, 3, 1); 175 | last = luaL_optinteger(L, 4, last); 176 | luaL_buffinit(L, &b); 177 | for (; i < last; i++) { 178 | addfield(L, &b, i); 179 | luaL_addlstring(&b, sep, lsep); 180 | } 181 | if (i == last) /* add last value (if interval was not empty) */ 182 | addfield(L, &b, i); 183 | luaL_pushresult(&b); 184 | return 1; 185 | } 186 | 187 | 188 | /* 189 | ** {====================================================== 190 | ** Pack/unpack 191 | ** ======================================================= 192 | */ 193 | 194 | static int pack (lua_State *L) { 195 | int i; 196 | int n = lua_gettop(L); /* number of elements to pack */ 197 | lua_createtable(L, n, 1); /* create result table */ 198 | lua_insert(L, 1); /* put it at index 1 */ 199 | for (i = n; i >= 1; i--) /* assign elements */ 200 | lua_seti(L, 1, i); 201 | lua_pushinteger(L, n); 202 | lua_setfield(L, 1, "n"); /* t.n = number of elements */ 203 | return 1; /* return table */ 204 | } 205 | 206 | 207 | static int unpack (lua_State *L) { 208 | lua_Unsigned n; 209 | lua_Integer i = luaL_optinteger(L, 2, 1); 210 | lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); 211 | if (i > e) return 0; /* empty range */ 212 | n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ 213 | if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) 214 | return luaL_error(L, "too many results to unpack"); 215 | for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ 216 | lua_geti(L, 1, i); 217 | } 218 | lua_geti(L, 1, e); /* push last element */ 219 | return (int)n; 220 | } 221 | 222 | /* }====================================================== */ 223 | 224 | 225 | 226 | /* 227 | ** {====================================================== 228 | ** Quicksort 229 | ** (based on 'Algorithms in MODULA-3', Robert Sedgewick; 230 | ** Addison-Wesley, 1993.) 231 | ** ======================================================= 232 | */ 233 | 234 | 235 | /* type for array indices */ 236 | typedef unsigned int IdxT; 237 | 238 | 239 | /* 240 | ** Produce a "random" 'unsigned int' to randomize pivot choice. This 241 | ** macro is used only when 'sort' detects a big imbalance in the result 242 | ** of a partition. (If you don't want/need this "randomness", ~0 is a 243 | ** good choice.) 244 | */ 245 | #if !defined(l_randomizePivot) /* { */ 246 | 247 | #include 248 | 249 | /* size of 'e' measured in number of 'unsigned int's */ 250 | #define sof(e) (sizeof(e) / sizeof(unsigned int)) 251 | 252 | /* 253 | ** Use 'time' and 'clock' as sources of "randomness". Because we don't 254 | ** know the types 'clock_t' and 'time_t', we cannot cast them to 255 | ** anything without risking overflows. A safe way to use their values 256 | ** is to copy them to an array of a known type and use the array values. 257 | */ 258 | static unsigned int l_randomizePivot (void) { 259 | clock_t c = clock(); 260 | time_t t = time(NULL); 261 | unsigned int buff[sof(c) + sof(t)]; 262 | unsigned int i, rnd = 0; 263 | memcpy(buff, &c, sof(c) * sizeof(unsigned int)); 264 | memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); 265 | for (i = 0; i < sof(buff); i++) 266 | rnd += buff[i]; 267 | return rnd; 268 | } 269 | 270 | #endif /* } */ 271 | 272 | 273 | /* arrays larger than 'RANLIMIT' may use randomized pivots */ 274 | #define RANLIMIT 100u 275 | 276 | 277 | static void set2 (lua_State *L, IdxT i, IdxT j) { 278 | lua_seti(L, 1, i); 279 | lua_seti(L, 1, j); 280 | } 281 | 282 | 283 | /* 284 | ** Return true iff value at stack index 'a' is less than the value at 285 | ** index 'b' (according to the order of the sort). 286 | */ 287 | static int sort_comp (lua_State *L, int a, int b) { 288 | if (lua_isnil(L, 2)) /* no function? */ 289 | return lua_compare(L, a, b, LUA_OPLT); /* a < b */ 290 | else { /* function */ 291 | int res; 292 | lua_pushvalue(L, 2); /* push function */ 293 | lua_pushvalue(L, a-1); /* -1 to compensate function */ 294 | lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ 295 | lua_call(L, 2, 1); /* call function */ 296 | res = lua_toboolean(L, -1); /* get result */ 297 | lua_pop(L, 1); /* pop result */ 298 | return res; 299 | } 300 | } 301 | 302 | 303 | /* 304 | ** Does the partition: Pivot P is at the top of the stack. 305 | ** precondition: a[lo] <= P == a[up-1] <= a[up], 306 | ** so it only needs to do the partition from lo + 1 to up - 2. 307 | ** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] 308 | ** returns 'i'. 309 | */ 310 | static IdxT partition (lua_State *L, IdxT lo, IdxT up) { 311 | IdxT i = lo; /* will be incremented before first use */ 312 | IdxT j = up - 1; /* will be decremented before first use */ 313 | /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ 314 | for (;;) { 315 | /* next loop: repeat ++i while a[i] < P */ 316 | while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { 317 | if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */ 318 | luaL_error(L, "invalid order function for sorting"); 319 | lua_pop(L, 1); /* remove a[i] */ 320 | } 321 | /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ 322 | /* next loop: repeat --j while P < a[j] */ 323 | while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { 324 | if (j < i) /* j < i but a[j] > P ?? */ 325 | luaL_error(L, "invalid order function for sorting"); 326 | lua_pop(L, 1); /* remove a[j] */ 327 | } 328 | /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ 329 | if (j < i) { /* no elements out of place? */ 330 | /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ 331 | lua_pop(L, 1); /* pop a[j] */ 332 | /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ 333 | set2(L, up - 1, i); 334 | return i; 335 | } 336 | /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ 337 | set2(L, i, j); 338 | } 339 | } 340 | 341 | 342 | /* 343 | ** Choose an element in the middle (2nd-3th quarters) of [lo,up] 344 | ** "randomized" by 'rnd' 345 | */ 346 | static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { 347 | IdxT r4 = (up - lo) / 4; /* range/4 */ 348 | IdxT p = rnd % (r4 * 2) + (lo + r4); 349 | lua_assert(lo + r4 <= p && p <= up - r4); 350 | return p; 351 | } 352 | 353 | 354 | /* 355 | ** QuickSort algorithm (recursive function) 356 | */ 357 | static void auxsort (lua_State *L, IdxT lo, IdxT up, 358 | unsigned int rnd) { 359 | while (lo < up) { /* loop for tail recursion */ 360 | IdxT p; /* Pivot index */ 361 | IdxT n; /* to be used later */ 362 | /* sort elements 'lo', 'p', and 'up' */ 363 | lua_geti(L, 1, lo); 364 | lua_geti(L, 1, up); 365 | if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ 366 | set2(L, lo, up); /* swap a[lo] - a[up] */ 367 | else 368 | lua_pop(L, 2); /* remove both values */ 369 | if (up - lo == 1) /* only 2 elements? */ 370 | return; /* already sorted */ 371 | if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ 372 | p = (lo + up)/2; /* middle element is a good pivot */ 373 | else /* for larger intervals, it is worth a random pivot */ 374 | p = choosePivot(lo, up, rnd); 375 | lua_geti(L, 1, p); 376 | lua_geti(L, 1, lo); 377 | if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ 378 | set2(L, p, lo); /* swap a[p] - a[lo] */ 379 | else { 380 | lua_pop(L, 1); /* remove a[lo] */ 381 | lua_geti(L, 1, up); 382 | if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ 383 | set2(L, p, up); /* swap a[up] - a[p] */ 384 | else 385 | lua_pop(L, 2); 386 | } 387 | if (up - lo == 2) /* only 3 elements? */ 388 | return; /* already sorted */ 389 | lua_geti(L, 1, p); /* get middle element (Pivot) */ 390 | lua_pushvalue(L, -1); /* push Pivot */ 391 | lua_geti(L, 1, up - 1); /* push a[up - 1] */ 392 | set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ 393 | p = partition(L, lo, up); 394 | /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ 395 | if (p - lo < up - p) { /* lower interval is smaller? */ 396 | auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ 397 | n = p - lo; /* size of smaller interval */ 398 | lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ 399 | } 400 | else { 401 | auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ 402 | n = up - p; /* size of smaller interval */ 403 | up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ 404 | } 405 | if ((up - lo) / 128 > n) /* partition too imbalanced? */ 406 | rnd = l_randomizePivot(); /* try a new randomization */ 407 | } /* tail call auxsort(L, lo, up, rnd) */ 408 | } 409 | 410 | 411 | static int sort (lua_State *L) { 412 | lua_Integer n = aux_getn(L, 1, TAB_RW); 413 | if (n > 1) { /* non-trivial interval? */ 414 | luaL_argcheck(L, n < INT_MAX, 1, "array too big"); 415 | if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ 416 | luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ 417 | lua_settop(L, 2); /* make sure there are two arguments */ 418 | auxsort(L, 1, (IdxT)n, 0); 419 | } 420 | return 0; 421 | } 422 | 423 | /* }====================================================== */ 424 | 425 | 426 | static const luaL_Reg tab_funcs[] = { 427 | {"concat", tconcat}, 428 | #if defined(LUA_COMPAT_MAXN) 429 | {"maxn", maxn}, 430 | #endif 431 | {"insert", tinsert}, 432 | {"pack", pack}, 433 | {"unpack", unpack}, 434 | {"remove", tremove}, 435 | {"move", tmove}, 436 | {"sort", sort}, 437 | {NULL, NULL} 438 | }; 439 | 440 | 441 | LUAMOD_API int luaopen_table (lua_State *L) { 442 | luaL_newlib(L, tab_funcs); 443 | #if defined(LUA_COMPAT_UNPACK) 444 | /* _G.unpack = table.unpack */ 445 | lua_getfield(L, -1, "unpack"); 446 | lua_setglobal(L, "unpack"); 447 | #endif 448 | return 1; 449 | } 450 | 451 | -------------------------------------------------------------------------------- /vendor/compat-5.3/lutf8lib.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lutf8lib.c,v 1.16 2016/12/22 13:08:50 roberto Exp $ 3 | ** Standard library for UTF-8 manipulation 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | #define lutf8lib_c 8 | #define LUA_LIB 9 | 10 | #include "lprefix.h" 11 | 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "lua.h" 19 | 20 | #include "lauxlib.h" 21 | #include "lualib.h" 22 | 23 | #define MAXUNICODE 0x10FFFF 24 | 25 | #define iscont(p) ((*(p) & 0xC0) == 0x80) 26 | 27 | 28 | /* from strlib */ 29 | /* translate a relative string position: negative means back from end */ 30 | static lua_Integer u_posrelat (lua_Integer pos, size_t len) { 31 | if (pos >= 0) return pos; 32 | else if (0u - (size_t)pos > len) return 0; 33 | else return (lua_Integer)len + pos + 1; 34 | } 35 | 36 | 37 | /* 38 | ** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. 39 | */ 40 | static const char *utf8_decode (const char *o, int *val) { 41 | static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; 42 | const unsigned char *s = (const unsigned char *)o; 43 | unsigned int c = s[0]; 44 | unsigned int res = 0; /* final result */ 45 | if (c < 0x80) /* ascii? */ 46 | res = c; 47 | else { 48 | int count = 0; /* to count number of continuation bytes */ 49 | while (c & 0x40) { /* still have continuation bytes? */ 50 | int cc = s[++count]; /* read next byte */ 51 | if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ 52 | return NULL; /* invalid byte sequence */ 53 | res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ 54 | c <<= 1; /* to test next bit */ 55 | } 56 | res |= ((c & 0x7F) << (count * 5)); /* add first byte */ 57 | if (count > 3 || res > MAXUNICODE || res <= limits[count]) 58 | return NULL; /* invalid byte sequence */ 59 | s += count; /* skip continuation bytes read */ 60 | } 61 | if (val) *val = res; 62 | return (const char *)s + 1; /* +1 to include first byte */ 63 | } 64 | 65 | 66 | /* 67 | ** utf8len(s [, i [, j]]) --> number of characters that start in the 68 | ** range [i,j], or nil + current position if 's' is not well formed in 69 | ** that interval 70 | */ 71 | static int utflen (lua_State *L) { 72 | int n = 0; 73 | size_t len; 74 | const char *s = luaL_checklstring(L, 1, &len); 75 | lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); 76 | lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); 77 | luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, 78 | "initial position out of string"); 79 | luaL_argcheck(L, --posj < (lua_Integer)len, 3, 80 | "final position out of string"); 81 | while (posi <= posj) { 82 | const char *s1 = utf8_decode(s + posi, NULL); 83 | if (s1 == NULL) { /* conversion error? */ 84 | lua_pushnil(L); /* return nil ... */ 85 | lua_pushinteger(L, posi + 1); /* ... and current position */ 86 | return 2; 87 | } 88 | posi = s1 - s; 89 | n++; 90 | } 91 | lua_pushinteger(L, n); 92 | return 1; 93 | } 94 | 95 | 96 | /* 97 | ** codepoint(s, [i, [j]]) -> returns codepoints for all characters 98 | ** that start in the range [i,j] 99 | */ 100 | static int codepoint (lua_State *L) { 101 | size_t len; 102 | const char *s = luaL_checklstring(L, 1, &len); 103 | lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); 104 | lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); 105 | int n; 106 | const char *se; 107 | luaL_argcheck(L, posi >= 1, 2, "out of range"); 108 | luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); 109 | if (posi > pose) return 0; /* empty interval; return no values */ 110 | if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ 111 | return luaL_error(L, "string slice too long"); 112 | n = (int)(pose - posi) + 1; 113 | luaL_checkstack(L, n, "string slice too long"); 114 | n = 0; 115 | se = s + pose; 116 | for (s += posi - 1; s < se;) { 117 | int code; 118 | s = utf8_decode(s, &code); 119 | if (s == NULL) 120 | return luaL_error(L, "invalid UTF-8 code"); 121 | lua_pushinteger(L, code); 122 | n++; 123 | } 124 | return n; 125 | } 126 | 127 | 128 | static void pushutfchar (lua_State *L, int arg) { 129 | lua_Integer code = luaL_checkinteger(L, arg); 130 | luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); 131 | lua_pushfstring(L, "%U", (long)code); 132 | } 133 | 134 | 135 | /* 136 | ** utfchar(n1, n2, ...) -> char(n1)..char(n2)... 137 | */ 138 | static int utfchar (lua_State *L) { 139 | int n = lua_gettop(L); /* number of arguments */ 140 | if (n == 1) /* optimize common case of single char */ 141 | pushutfchar(L, 1); 142 | else { 143 | int i; 144 | luaL_Buffer b; 145 | luaL_buffinit(L, &b); 146 | for (i = 1; i <= n; i++) { 147 | pushutfchar(L, i); 148 | luaL_addvalue(&b); 149 | } 150 | luaL_pushresult(&b); 151 | } 152 | return 1; 153 | } 154 | 155 | 156 | /* 157 | ** offset(s, n, [i]) -> index where n-th character counting from 158 | ** position 'i' starts; 0 means character at 'i'. 159 | */ 160 | static int byteoffset (lua_State *L) { 161 | size_t len; 162 | const char *s = luaL_checklstring(L, 1, &len); 163 | lua_Integer n = luaL_checkinteger(L, 2); 164 | lua_Integer posi = (n >= 0) ? 1 : len + 1; 165 | posi = u_posrelat(luaL_optinteger(L, 3, posi), len); 166 | luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, 167 | "position out of range"); 168 | if (n == 0) { 169 | /* find beginning of current byte sequence */ 170 | while (posi > 0 && iscont(s + posi)) posi--; 171 | } 172 | else { 173 | if (iscont(s + posi)) 174 | luaL_error(L, "initial position is a continuation byte"); 175 | if (n < 0) { 176 | while (n < 0 && posi > 0) { /* move back */ 177 | do { /* find beginning of previous character */ 178 | posi--; 179 | } while (posi > 0 && iscont(s + posi)); 180 | n++; 181 | } 182 | } 183 | else { 184 | n--; /* do not move for 1st character */ 185 | while (n > 0 && posi < (lua_Integer)len) { 186 | do { /* find beginning of next character */ 187 | posi++; 188 | } while (iscont(s + posi)); /* (cannot pass final '\0') */ 189 | n--; 190 | } 191 | } 192 | } 193 | if (n == 0) /* did it find given character? */ 194 | lua_pushinteger(L, posi + 1); 195 | else /* no such character */ 196 | lua_pushnil(L); 197 | return 1; 198 | } 199 | 200 | 201 | static int iter_aux (lua_State *L) { 202 | size_t len; 203 | const char *s = luaL_checklstring(L, 1, &len); 204 | lua_Integer n = lua_tointeger(L, 2) - 1; 205 | if (n < 0) /* first iteration? */ 206 | n = 0; /* start from here */ 207 | else if (n < (lua_Integer)len) { 208 | n++; /* skip current byte */ 209 | while (iscont(s + n)) n++; /* and its continuations */ 210 | } 211 | if (n >= (lua_Integer)len) 212 | return 0; /* no more codepoints */ 213 | else { 214 | int code; 215 | const char *next = utf8_decode(s + n, &code); 216 | if (next == NULL || iscont(next)) 217 | return luaL_error(L, "invalid UTF-8 code"); 218 | lua_pushinteger(L, n + 1); 219 | lua_pushinteger(L, code); 220 | return 2; 221 | } 222 | } 223 | 224 | 225 | static int iter_codes (lua_State *L) { 226 | luaL_checkstring(L, 1); 227 | lua_pushcfunction(L, iter_aux); 228 | lua_pushvalue(L, 1); 229 | lua_pushinteger(L, 0); 230 | return 3; 231 | } 232 | 233 | 234 | /* pattern to match a single UTF-8 character */ 235 | #define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" 236 | 237 | 238 | static const luaL_Reg funcs[] = { 239 | {"offset", byteoffset}, 240 | {"codepoint", codepoint}, 241 | {"char", utfchar}, 242 | {"len", utflen}, 243 | {"codes", iter_codes}, 244 | /* placeholders */ 245 | {"charpattern", NULL}, 246 | {NULL, NULL} 247 | }; 248 | 249 | 250 | LUAMOD_API int luaopen_utf8 (lua_State *L) { 251 | luaL_newlib(L, funcs); 252 | lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); 253 | lua_setfield(L, -2, "charpattern"); 254 | return 1; 255 | } 256 | 257 | -------------------------------------------------------------------------------- /vendor/compat-5.3/rockspecs/compat53-0.1-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "compat53" 2 | version = "0.1-1" 3 | source = { 4 | url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.1.zip", 5 | dir = "lua-compat-5.3-0.1", 6 | } 7 | description = { 8 | summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1", 9 | detailed = [[ 10 | This is a small module that aims to make it easier to write Lua 11 | code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1. 12 | It does *not* make Lua 5.2 (or even 5.1) entirely compatible 13 | with Lua 5.3, but it brings the API closer to that of Lua 5.3. 14 | ]], 15 | homepage = "https://github.com/keplerproject/lua-compat-5.3", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1, < 5.4", 20 | --"struct" -- make Roberto's struct module optional 21 | } 22 | build = { 23 | type = "builtin", 24 | modules = { 25 | ["compat53"] = "compat53.lua", 26 | ["compat53.utf8"] = "lutf8lib.c", 27 | ["compat53.table"] = "ltablib.c", 28 | ["compat53.string"] = "lstrlib.c", 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /vendor/compat-5.3/rockspecs/compat53-0.2-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "compat53" 2 | version = "0.2-1" 3 | source = { 4 | url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.2.zip", 5 | dir = "lua-compat-5.3-0.2", 6 | } 7 | description = { 8 | summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1", 9 | detailed = [[ 10 | This is a small module that aims to make it easier to write Lua 11 | code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1. 12 | It does *not* make Lua 5.2 (or even 5.1) entirely compatible 13 | with Lua 5.3, but it brings the API closer to that of Lua 5.3. 14 | ]], 15 | homepage = "https://github.com/keplerproject/lua-compat-5.3", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1, < 5.4", 20 | --"struct" -- make Roberto's struct module optional 21 | } 22 | build = { 23 | type = "builtin", 24 | modules = { 25 | ["compat53.init"] = "compat53/init.lua", 26 | ["compat53.module"] = "compat53/module.lua", 27 | ["compat53.utf8"] = "lutf8lib.c", 28 | ["compat53.table"] = "ltablib.c", 29 | ["compat53.string"] = "lstrlib.c", 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /vendor/compat-5.3/rockspecs/compat53-0.3-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "compat53" 2 | version = "0.3-1" 3 | source = { 4 | url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.3.zip", 5 | dir = "lua-compat-5.3-0.3", 6 | } 7 | description = { 8 | summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1", 9 | detailed = [[ 10 | This is a small module that aims to make it easier to write Lua 11 | code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1. 12 | It does *not* make Lua 5.2 (or even 5.1) entirely compatible 13 | with Lua 5.3, but it brings the API closer to that of Lua 5.3. 14 | ]], 15 | homepage = "https://github.com/keplerproject/lua-compat-5.3", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1, < 5.4", 20 | --"struct" -- make Roberto's struct module optional 21 | } 22 | build = { 23 | type = "builtin", 24 | modules = { 25 | ["compat53.init"] = "compat53/init.lua", 26 | ["compat53.module"] = "compat53/module.lua", 27 | ["compat53.utf8"] = "lutf8lib.c", 28 | ["compat53.table"] = "ltablib.c", 29 | ["compat53.string"] = "lstrlib.c", 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /vendor/compat-5.3/rockspecs/compat53-0.4-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "compat53" 2 | version = "0.4-1" 3 | source = { 4 | url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.4.zip", 5 | dir = "lua-compat-5.3-0.4", 6 | } 7 | description = { 8 | summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1", 9 | detailed = [[ 10 | This is a small module that aims to make it easier to write Lua 11 | code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1. 12 | It does *not* make Lua 5.2 (or even 5.1) entirely compatible 13 | with Lua 5.3, but it brings the API closer to that of Lua 5.3. 14 | ]], 15 | homepage = "https://github.com/keplerproject/lua-compat-5.3", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1, < 5.4", 20 | --"struct" -- make Roberto's struct module optional 21 | } 22 | build = { 23 | type = "builtin", 24 | modules = { 25 | ["compat53.init"] = "compat53/init.lua", 26 | ["compat53.module"] = "compat53/module.lua", 27 | ["compat53.utf8"] = "lutf8lib.c", 28 | ["compat53.table"] = "ltablib.c", 29 | ["compat53.string"] = "lstrlib.c", 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /vendor/compat-5.3/rockspecs/compat53-0.5-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "compat53" 2 | version = "0.5-1" 3 | source = { 4 | url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.5.zip", 5 | dir = "lua-compat-5.3-0.5", 6 | } 7 | description = { 8 | summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1", 9 | detailed = [[ 10 | This is a small module that aims to make it easier to write Lua 11 | code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1. 12 | It does *not* make Lua 5.2 (or even 5.1) entirely compatible 13 | with Lua 5.3, but it brings the API closer to that of Lua 5.3. 14 | ]], 15 | homepage = "https://github.com/keplerproject/lua-compat-5.3", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1, < 5.4", 20 | --"struct" -- make Roberto's struct module optional 21 | } 22 | build = { 23 | type = "builtin", 24 | modules = { 25 | ["compat53.init"] = "compat53/init.lua", 26 | ["compat53.module"] = "compat53/module.lua", 27 | ["compat53.utf8"] = "lutf8lib.c", 28 | ["compat53.table"] = "ltablib.c", 29 | ["compat53.string"] = "lstrlib.c", 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /vendor/compat-5.3/rockspecs/compat53-scm-0.rockspec: -------------------------------------------------------------------------------- 1 | package = "compat53" 2 | version = "scm-0" 3 | source = { 4 | url = "https://github.com/keplerproject/lua-compat-5.3/archive/master.zip", 5 | dir = "lua-compat-5.3-master", 6 | } 7 | description = { 8 | summary = "Compatibility module providing Lua-5.3-style APIs for Lua 5.2 and 5.1", 9 | detailed = [[ 10 | This is a small module that aims to make it easier to write Lua 11 | code in a Lua-5.3-style that runs on Lua 5.3, 5.2, and 5.1. 12 | It does *not* make Lua 5.2 (or even 5.1) entirely compatible 13 | with Lua 5.3, but it brings the API closer to that of Lua 5.3. 14 | ]], 15 | homepage = "https://github.com/keplerproject/lua-compat-5.3", 16 | license = "MIT" 17 | } 18 | dependencies = { 19 | "lua >= 5.1, < 5.4", 20 | --"struct" -- make Roberto's struct module optional 21 | } 22 | build = { 23 | type = "builtin", 24 | modules = { 25 | ["compat53.init"] = "compat53/init.lua", 26 | ["compat53.module"] = "compat53/module.lua", 27 | ["compat53.utf8"] = "lutf8lib.c", 28 | ["compat53.table"] = "ltablib.c", 29 | ["compat53.string"] = "lstrlib.c", 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /vendor/compat-5.3/tests/test.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local F, tproxy, writefile, noprint, ___ 4 | do 5 | local type, unpack = type, table.unpack or unpack 6 | local assert, io = assert, io 7 | function F(...) 8 | local args, n = { ... }, select('#', ...) 9 | for i = 1, n do 10 | local t = type(args[i]) 11 | if t ~= "string" and t ~= "number" and t ~= "boolean" then 12 | args[i] = t 13 | end 14 | end 15 | return unpack(args, 1, n) 16 | end 17 | function tproxy(t) 18 | return setmetatable({}, { 19 | __index = t, 20 | __newindex = t, 21 | __len = function() return #t end, 22 | }), t 23 | end 24 | function writefile(name, contents, bin) 25 | local f = assert(io.open(name, bin and "wb" or "w")) 26 | f:write(contents) 27 | f:close() 28 | end 29 | function noprint() end 30 | local sep = ("="):rep(70) 31 | function ___() 32 | print(sep) 33 | end 34 | end 35 | 36 | local V = _VERSION:gsub("^.*(%d+)%.(%d+)$", "%1%2") 37 | if jit then V = "jit" end 38 | 39 | local mode = "global" 40 | if arg[1] == "module" then 41 | mode = "module" 42 | end 43 | local self = arg[0] 44 | 45 | package.path = "../?.lua;../?/init.lua" 46 | package.cpath = "./?-"..V..".so;./?-"..V..".dll;./?.so;./?.dll" 47 | if mode == "module" then 48 | print("testing Lua API using `compat53.module` ...") 49 | _ENV = require("compat53.module") 50 | if setfenv then setfenv(1, _ENV) end 51 | else 52 | print("testing Lua API using `compat53` ...") 53 | require("compat53") 54 | end 55 | 56 | 57 | ___'' 58 | do 59 | print("assert", F(pcall(assert, false))) 60 | print("assert", F(pcall(assert, false, nil))) 61 | print("assert", F(pcall(assert, false, "error msg"))) 62 | print("assert", F(pcall(assert, nil, {}))) 63 | print("assert", F(pcall(assert, 1, 2, 3))) 64 | end 65 | 66 | 67 | ___'' 68 | do 69 | local t = setmetatable({}, { __index = { 1, false, "three" } }) 70 | for i,v in ipairs(t) do 71 | print("ipairs", i, v) 72 | end 73 | end 74 | 75 | 76 | ___'' 77 | do 78 | local p, t = tproxy{ "a", "b", "c" } 79 | print("table.concat", table.concat(p)) 80 | print("table.concat", table.concat(p, ",", 2)) 81 | print("table.concat", table.concat(p, ".", 1, 2)) 82 | print("table.concat", table.concat(t)) 83 | print("table.concat", table.concat(t, ",", 2)) 84 | print("table.concat", table.concat(t, ".", 1, 2)) 85 | end 86 | 87 | 88 | ___'' 89 | do 90 | local p, t = tproxy{ "a", "b", "c" } 91 | table.insert(p, "d") 92 | print("table.insert", next(p), t[4]) 93 | table.insert(p, 1, "z") 94 | print("table.insert", next(p), t[1], t[2]) 95 | table.insert(p, 2, "y") 96 | print("table.insert", next(p), t[1], t[2], p[3]) 97 | t = { "a", "b", "c" } 98 | table.insert(t, "d") 99 | print("table.insert", t[1], t[2], t[3], t[4]) 100 | table.insert(t, 1, "z") 101 | print("table.insert", t[1], t[2], t[3], t[4], t[5]) 102 | table.insert(t, 2, "y") 103 | print("table.insert", t[1], t[2], t[3], t[4], t[5]) 104 | end 105 | 106 | 107 | ___'' 108 | do 109 | local ps, s = tproxy{ "a", "b", "c", "d" } 110 | local pd, d = tproxy{ "A", "B", "C", "D" } 111 | table.move(ps, 1, 4, 1, pd) 112 | print("table.move", next(pd), d[1], d[2], d[3], d[4]) 113 | pd, d = tproxy{ "A", "B", "C", "D" } 114 | table.move(ps, 2, 4, 1, pd) 115 | print("table.move", next(pd), d[1], d[2], d[3], d[4]) 116 | pd, d = tproxy{ "A", "B", "C", "D" } 117 | table.move(ps, 2, 3, 4, pd) 118 | print("table.move", next(pd), d[1], d[2], d[3], d[4], d[5]) 119 | table.move(ps, 2, 4, 1) 120 | print("table.move", next(ps), s[1], s[2], s[3], s[4]) 121 | ps, s = tproxy{ "a", "b", "c", "d" } 122 | table.move(ps, 2, 3, 4) 123 | print("table.move", next(ps), s[1], s[2], s[3], s[4], s[5]) 124 | s = { "a", "b", "c", "d" } 125 | d = { "A", "B", "C", "D" } 126 | table.move(s, 1, 4, 1, d) 127 | print("table.move", d[1], d[2], d[3], d[4]) 128 | d = { "A", "B", "C", "D" } 129 | table.move(s, 2, 4, 1, d) 130 | print("table.move", d[1], d[2], d[3], d[4]) 131 | d = { "A", "B", "C", "D" } 132 | table.move(s, 2, 3, 4, d) 133 | print("table.move", d[1], d[2], d[3], d[4], d[5]) 134 | table.move(s, 2, 4, 1) 135 | print("table.move", s[1], s[2], s[3], s[4]) 136 | s = { "a", "b", "c", "d" } 137 | table.move(s, 2, 3, 4) 138 | print("table.move", s[1], s[2], s[3], s[4], s[5]) 139 | end 140 | 141 | 142 | ___'' 143 | do 144 | local p, t = tproxy{ "a", "b", "c", "d", "e" } 145 | print("table.remove", table.remove(p)) 146 | print("table.remove", next(p), t[1], t[2], t[3], t[4], t[5]) 147 | print("table.remove", table.remove(p, 1)) 148 | print("table.remove", next(p), t[1], t[2], t[3], t[4]) 149 | print("table.remove", table.remove(p, 2)) 150 | print("table.remove", next(p), t[1], t[2], t[3]) 151 | print("table.remove", table.remove(p, 3)) 152 | print("table.remove", next(p), t[1], t[2], t[3]) 153 | p, t = tproxy{} 154 | print("table.remove", table.remove(p)) 155 | print("table.remove", next(p), next(t)) 156 | t = { "a", "b", "c", "d", "e" } 157 | print("table.remove", table.remove(t)) 158 | print("table.remove", t[1], t[2], t[3], t[4], t[5]) 159 | print("table.remove", table.remove(t, 1)) 160 | print("table.remove", t[1], t[2], t[3], t[4]) 161 | print("table.remove", table.remove(t, 2)) 162 | print("table.remove", t[1], t[2], t[3]) 163 | print("table.remove", table.remove(t, 3)) 164 | print("table.remove", t[1], t[2], t[3]) 165 | t = {} 166 | print("table.remove", table.remove(t)) 167 | print("table.remove", next(t)) 168 | end 169 | 170 | ___'' 171 | do 172 | local p, t = tproxy{ 3, 1, 5, 2, 8, 5, 2, 9, 7, 4 } 173 | table.sort(p) 174 | print("table.sort", next(p)) 175 | for i,v in ipairs(t) do 176 | print("table.sort", i, v) 177 | end 178 | table.sort(p) 179 | print("table.sort", next(p)) 180 | for i,v in ipairs(t) do 181 | print("table.sort", i, v) 182 | end 183 | p, t = tproxy{ 9, 8, 7, 6, 5, 4, 3, 2, 1 } 184 | table.sort(p) 185 | print("table.sort", next(p)) 186 | for i,v in ipairs(t) do 187 | print("table.sort", i, v) 188 | end 189 | table.sort(p, function(a, b) return a > b end) 190 | print("table.sort", next(p)) 191 | for i,v in ipairs(t) do 192 | print("table.sort", i, v) 193 | end 194 | p, t = tproxy{ 1, 1, 1, 1, 1 } 195 | print("table.sort", next(p)) 196 | for i,v in ipairs(t) do 197 | print("table.sort", i, v) 198 | end 199 | t = { 3, 1, 5, 2, 8, 5, 2, 9, 7, 4 } 200 | table.sort(t) 201 | for i,v in ipairs(t) do 202 | print("table.sort", i, v) 203 | end 204 | table.sort(t, function(a, b) return a > b end) 205 | for i,v in ipairs(t) do 206 | print("table.sort", i, v) 207 | end 208 | end 209 | 210 | 211 | ___'' 212 | do 213 | local p, t = tproxy{ "a", "b", "c" } 214 | print("table.unpack", table.unpack(p)) 215 | print("table.unpack", table.unpack(p, 2)) 216 | print("table.unpack", table.unpack(p, 1, 2)) 217 | print("table.unpack", table.unpack(t)) 218 | print("table.unpack", table.unpack(t, 2)) 219 | print("table.unpack", table.unpack(t, 1, 2)) 220 | end 221 | 222 | 223 | ___'' 224 | print("math.maxinteger", math.maxinteger+1 > math.maxinteger) 225 | print("math.mininteger", math.mininteger-1 < math.mininteger) 226 | 227 | 228 | ___'' 229 | print("math.tointeger", math.tointeger(0)) 230 | print("math.tointeger", math.tointeger(math.pi)) 231 | print("math.tointeger", math.tointeger("hello")) 232 | print("math.tointeger", math.tointeger(math.maxinteger+2.0)) 233 | print("math.tointeger", math.tointeger(math.mininteger*2.0)) 234 | 235 | 236 | ___'' 237 | print("math.type", math.type(0)) 238 | print("math.type", math.type(math.pi)) 239 | print("math.type", math.type("hello")) 240 | 241 | 242 | ___'' 243 | print("math.ult", math.ult(1, 2), math.ult(2, 1)) 244 | print("math.ult", math.ult(-1, 2), math.ult(2, -1)) 245 | print("math.ult", math.ult(-1, -2), math.ult(-2, -1)) 246 | print("math.ult", pcall(math.ult, "x", 2)) 247 | print("math.ult", pcall(math.ult, 1, 2.1)) 248 | ___'' 249 | 250 | 251 | if utf8.len then 252 | local unpack = table.unpack or unpack 253 | local function utf8rt(s) 254 | local t = { utf8.codepoint(s, 1, #s) } 255 | local ps, cs = {}, {} 256 | for p,c in utf8.codes(s) do 257 | ps[#ps+1], cs[#cs+1] = p, c 258 | end 259 | print("utf8.codes", unpack(ps)) 260 | print("utf8.codes", unpack(cs)) 261 | print("utf8.codepoint", unpack(t)) 262 | print("utf8.len", utf8.len(s), #t, #s) 263 | print("utf8.char", utf8.char(unpack(t))) 264 | end 265 | utf8rt("äöüßÄÖÜ") 266 | utf8rt("abcdefg") 267 | ___'' 268 | local s = "äöüßÄÖÜ" 269 | print("utf8.offset", utf8.offset(s, 1, 1)) 270 | print("utf8.offset", utf8.offset(s, 2, 1)) 271 | print("utf8.offset", utf8.offset(s, 3, 1)) 272 | print("utf8.offset", pcall(utf8.offset, s, 3, 2)) 273 | print("utf8.offset", utf8.offset(s, 3, 3)) 274 | print("utf8.offset", utf8.offset(s, -1, 7)) 275 | print("utf8.offset", utf8.offset(s, -2, 7)) 276 | print("utf8.offset", utf8.offset(s, -3, 7)) 277 | print("utf8.offset", utf8.offset(s, -1)) 278 | ___'' 279 | else 280 | print("XXX: utf8 module not available") 281 | end 282 | 283 | 284 | if string.pack then 285 | local format = "bBhHlLjJdc3z" 286 | local s = string.pack(format, -128, 255, -32768, 65535, -2147483648, 4294967295, -32768, 65536, 1.25, "abc", "defgh") 287 | print("string.unpack", string.unpack(format, s)) 288 | ___'' 289 | else 290 | print("XXX: string packing not available") 291 | end 292 | 293 | 294 | print("testing Lua API for Lua 5.1 ...") 295 | 296 | ___'' 297 | print("debug.getuservalue()", F(debug.getuservalue(false))) 298 | print("debug.setuservalue()", pcall(function() 299 | debug.setuservalue(false, {}) 300 | end)) 301 | print("debug.setmetatable()", F(debug.setmetatable({}, {}))) 302 | 303 | 304 | ___'' 305 | do 306 | local t = setmetatable({}, { 307 | __pairs = function() return pairs({ a = "a" }) end, 308 | }) 309 | for k,v in pairs(t) do 310 | print("pairs()", k, v) 311 | end 312 | end 313 | 314 | 315 | ___'' 316 | do 317 | local code = "print('hello world')\n" 318 | local badcode = "print('blub\n" 319 | print("load()", pcall(function() load(true) end)) 320 | print("load()", F(load(badcode))) 321 | print("load()", F(load(code))) 322 | print("load()", F(load(code, "[L]"))) 323 | print("load()", F(load(code, "[L]", "b"))) 324 | print("load()", F(load(code, "[L]", "t"))) 325 | print("load()", F(load(code, "[L]", "bt"))) 326 | local f = load(code, "[L]", "bt", {}) 327 | print("load()", pcall(f)) 328 | f = load(code, "[L]", "bt", { print = noprint }) 329 | print("load()", pcall(f)) 330 | local bytecode = string.dump(f) 331 | print("load()", F(load(bytecode))) 332 | print("load()", F(load(bytecode, "[L]"))) 333 | print("load()", F(load(bytecode, "[L]", "b"))) 334 | print("load()", F(load(bytecode, "[L]", "t"))) 335 | print("load()", F(load(bytecode, "[L]", "bt"))) 336 | f = load(bytecode, "[L]", "bt", {}) 337 | print("load()", pcall(f)) 338 | f = load(bytecode, "[L]", "bt", { print = noprint }) 339 | print("load()", pcall(f)) 340 | local function make_loader(code) 341 | local mid = math.floor( #code/2 ) 342 | local array = { code:sub(1, mid), code:sub(mid+1) } 343 | local i = 0 344 | return function() 345 | i = i + 1 346 | return array[i] 347 | end 348 | end 349 | print("load()", F(load(make_loader(badcode)))) 350 | print("load()", F(load(make_loader(code)))) 351 | print("load()", F(load(make_loader(code), "[L]"))) 352 | print("load()", F(load(make_loader(code), "[L]", "b"))) 353 | print("load()", F(load(make_loader(code), "[L]", "t"))) 354 | print("load()", F(load(make_loader(code), "[L]", "bt"))) 355 | f = load(make_loader(code), "[L]", "bt", {}) 356 | print("load()", pcall(f)) 357 | f = load(make_loader(code), "[L]", "bt", { print = noprint }) 358 | print("load()", pcall(f)) 359 | print("load()", F(load(make_loader(bytecode)))) 360 | print("load()", F(load(make_loader(bytecode), "[L]"))) 361 | print("load()", F(load(make_loader(bytecode), "[L]", "b"))) 362 | print("load()", F(load(make_loader(bytecode), "[L]", "t"))) 363 | print("load()", F(load(make_loader(bytecode), "[L]", "bt"))) 364 | f = load(make_loader(bytecode), "[L]", "bt", {}) 365 | print("load()", pcall(f)) 366 | f = load(make_loader(bytecode), "[L]", "bt", { print = noprint }) 367 | print("load()", pcall(f)) 368 | writefile("good.lua", code) 369 | writefile("bad.lua", badcode) 370 | writefile("good.luac", bytecode, true) 371 | print("loadfile()", F(loadfile("bad.lua"))) 372 | print("loadfile()", F(loadfile("good.lua"))) 373 | print("loadfile()", F(loadfile("good.lua", "b"))) 374 | print("loadfile()", F(loadfile("good.lua", "t"))) 375 | print("loadfile()", F(loadfile("good.lua", "bt"))) 376 | f = loadfile("good.lua", "bt", {}) 377 | print("loadfile()", pcall(f)) 378 | f = loadfile("good.lua", "bt", { print = noprint }) 379 | print("loadfile()", pcall(f)) 380 | print("loadfile()", F(loadfile("good.luac"))) 381 | print("loadfile()", F(loadfile("good.luac", "b"))) 382 | print("loadfile()", F(loadfile("good.luac", "t"))) 383 | print("loadfile()", F(loadfile("good.luac", "bt"))) 384 | f = loadfile("good.luac", "bt", {}) 385 | print("loadfile()", pcall(f)) 386 | f = loadfile("good.luac", "bt", { print = noprint }) 387 | print("loadfile()", pcall(f)) 388 | os.remove("good.lua") 389 | os.remove("bad.lua") 390 | os.remove("good.luac") 391 | end 392 | 393 | 394 | ___'' 395 | do 396 | local function func(throw) 397 | if throw then 398 | error("argh") 399 | else 400 | return 1, 2, 3 401 | end 402 | end 403 | local function tb(err) return "|"..err.."|" end 404 | print("xpcall()", xpcall(func, debug.traceback, false)) 405 | print("xpcall()", xpcall(func, debug.traceback, true)) 406 | print("xpcall()", xpcall(func, tb, true)) 407 | if mode ~= "module" then 408 | local function func2(cb) 409 | print("xpcall()", xpcall(cb, debug.traceback, "str")) 410 | end 411 | local function func3(cb) 412 | print("pcall()", pcall(cb, "str")) 413 | end 414 | local function cb(arg) 415 | coroutine.yield(2) 416 | return arg 417 | end 418 | local c = coroutine.wrap(func2) 419 | print("xpcall()", c(cb)) 420 | print("xpcall()", c()) 421 | local c = coroutine.wrap(func3) 422 | print("pcall()", c(cb)) 423 | print("pcall()", c()) 424 | end 425 | end 426 | 427 | 428 | ___'' 429 | do 430 | local t = setmetatable({ 1 }, { __len = function() return 5 end }) 431 | print("rawlen()", rawlen(t), rawlen("123")) 432 | end 433 | 434 | 435 | ___'' 436 | print("os.execute()", os.execute("exit 1")) 437 | io.flush() 438 | print("os.execute()", os.execute("echo 'hello world!'")) 439 | io.flush() 440 | print("os.execute()", os.execute("no_such_file")) 441 | 442 | 443 | ___'' 444 | do 445 | local t = table.pack("a", nil, "b", nil) 446 | print("table.(un)pack()", t.n, table.unpack(t, 1, t.n)) 447 | end 448 | 449 | 450 | ___'' 451 | do 452 | print("coroutine.running()", F(coroutine.wrap(function() 453 | return coroutine.running() 454 | end)())) 455 | print("coroutine.running()", F(coroutine.running())) 456 | local main_co, co1, co2 = coroutine.running() 457 | -- coroutine.yield 458 | if mode ~= "module" then 459 | print("coroutine.yield()", pcall(function() 460 | coroutine.yield(1, 2, 3) 461 | end)) 462 | end 463 | print("coroutine.yield()", coroutine.wrap(function() 464 | coroutine.yield(1, 2, 3) 465 | end)()) 466 | print("coroutine.resume()", coroutine.resume(main_co, 1, 2, 3)) 467 | co1 = coroutine.create(function(a, b, c) 468 | print("coroutine.resume()", a, b, c) 469 | return a, b, c 470 | end) 471 | print("coroutine.resume()", coroutine.resume(co1, 1, 2, 3)) 472 | co1 = coroutine.create(function() 473 | print("coroutine.status()", "[co1] main is", coroutine.status(main_co)) 474 | print("coroutine.status()", "[co1] co2 is", coroutine.status(co2)) 475 | end) 476 | co2 = coroutine.create(function() 477 | print("coroutine.status()", "[co2] main is", coroutine.status(main_co)) 478 | print("coroutine.status()", "[co2] co2 is", coroutine.status(co2)) 479 | coroutine.yield() 480 | coroutine.resume(co1) 481 | end) 482 | print("coroutine.status()", coroutine.status(main_co)) 483 | print("coroutine.status()", coroutine.status(co2)) 484 | coroutine.resume(co2) 485 | print("coroutine.status()", F(coroutine.status(co2))) 486 | coroutine.resume(co2) 487 | print("coroutine.status()", F(coroutine.status(co2))) 488 | end 489 | 490 | 491 | ___'' 492 | print("math.log()", math.log(1000)) 493 | print("math.log()", math.log(1000, 10)) 494 | 495 | 496 | ___'' 497 | do 498 | local path, prefix = "./?.lua;?/init.lua;../?.lua", "package.searchpath()" 499 | print(prefix, package.searchpath("no.such.module", path)) 500 | print(prefix, package.searchpath("no.such.module", "")) 501 | print(prefix, package.searchpath("compat53", path)) 502 | print(prefix, package.searchpath("no:such:module", path, ":", "|")) 503 | end 504 | 505 | 506 | ___'' 507 | if mode ~= "module" then 508 | local function mod_func() return {} end 509 | local function my_searcher(name) 510 | if name == "my.module" then 511 | print("package.searchers", "my.module found") 512 | return mod_func 513 | end 514 | end 515 | local function my_searcher2(name) 516 | if name == "my.module" then 517 | print("package.searchers", "my.module found 2") 518 | return mod_func 519 | end 520 | end 521 | table.insert(package.searchers, my_searcher) 522 | require("my.module") 523 | package.loaded["my.module"] = nil 524 | local new_s = { my_searcher2 } 525 | for i,f in ipairs(package.searchers) do 526 | new_s[i+1] = f 527 | end 528 | package.searchers = new_s 529 | require("my.module") 530 | end 531 | 532 | 533 | ___'' 534 | do 535 | print("string.find()", string.find("abc\0abc\0abc", "[^a\0]+")) 536 | print("string.find()", string.find("abc\0abc\0abc", "%w+\0", 5)) 537 | for x in string.gmatch("abc\0def\0ghi", "[^\0]+") do 538 | print("string.gmatch()", x) 539 | end 540 | for x in string.gmatch("abc\0def\0ghi", "%w*\0") do 541 | print("string.gmatch()", #x) 542 | end 543 | print("string.gsub()", string.gsub("abc\0def\0ghi", "[\0]", "X")) 544 | print("string.gsub()", string.gsub("abc\0def\0ghi", "%w*\0", "X")) 545 | print("string.gsub()", string.gsub("abc\0def\0ghi", "%A", "X")) 546 | print("string.match()", string.match("abc\0abc\0abc", "([^\0a]+)")) 547 | print("string.match()", #string.match("abc\0abc\0abc", ".*\0")) 548 | print("string.rep()", string.rep("a", 0)) 549 | print("string.rep()", string.rep("b", 1)) 550 | print("string.rep()", string.rep("c", 4)) 551 | print("string.rep()", string.rep("a", 0, "|")) 552 | print("string.rep()", string.rep("b", 1, "|")) 553 | print("string.rep()", string.rep("c", 4, "|")) 554 | local _tostring = tostring 555 | function tostring(v) 556 | if type(v) == "number" then 557 | return "(".._tostring(v)..")" 558 | else 559 | return _tostring(v) 560 | end 561 | end 562 | print("string.format()", string.format("%q", "\"\\\0000\0010\002\r\n0\t0\"")) 563 | print("string.format()", string.format("%12.3fx%%sxx%.6s", 3.1, {})) 564 | print("string.format()", string.format("%-3f %%%s %%s", 3.1, true)) 565 | print("string.format()", string.format("% 3.2g %%d %%%s", 3.1, nil)) 566 | print("string.format()", string.format("%+3d %%d %%%%%10.6s", 3, io.stdout)) 567 | print("string.format()", pcall(function() 568 | print("string.format()", string.format("%d %%s", {})) 569 | end)) 570 | tostring = _tostring 571 | end 572 | 573 | 574 | ___'' 575 | do 576 | print("io.write()", io.type(io.write("hello world\n"))) 577 | local f = assert(io.tmpfile()) 578 | print("file:write()", io.type(f:write("hello world\n"))) 579 | f:close() 580 | end 581 | 582 | 583 | ___'' 584 | do 585 | writefile("data.txt", "123 18.8 hello world\ni'm here\n") 586 | io.input("data.txt") 587 | print("io.read()", io.read("*n", "*number", "*l", "*a")) 588 | io.input("data.txt") 589 | print("io.read()", io.read("n", "number", "l", "a")) 590 | io.input(io.stdin) 591 | if mode ~= "module" then 592 | local f = assert(io.open("data.txt", "r")) 593 | print("file:read()", f:read("*n", "*number", "*l", "*a")) 594 | f:close() 595 | f = assert(io.open("data.txt", "r")) 596 | print("file:read()", f:read("n", "number", "l", "a")) 597 | f:close() 598 | end 599 | os.remove("data.txt") 600 | end 601 | 602 | 603 | ___'' 604 | do 605 | writefile("data.txt", "123 18.8 hello world\ni'm here\n") 606 | for a,b in io.lines(self, 2, "*l") do 607 | print("io.lines()", a, b) 608 | break 609 | end 610 | for l in io.lines(self) do 611 | print("io.lines()", l) 612 | break 613 | end 614 | for n1,n2,rest in io.lines("data.txt", "*n", "n", "*a") do 615 | print("io.lines()", n1, n2, rest) 616 | end 617 | for l in io.lines("data.txt") do 618 | print("io.lines()", l) 619 | end 620 | print("io.lines()", pcall(function() 621 | for l in io.lines("data.txt", "*x") do print(l) end 622 | end)) 623 | print("io.lines()", pcall(function() 624 | for l in io.lines("no_such_file.txt") do print(l) end 625 | end)) 626 | if mode ~= "module" then 627 | local f = assert(io.open(self, "r")) 628 | for a,b in f:lines(2, "*l") do 629 | print("file:lines()", a, b) 630 | break 631 | end 632 | f:close() 633 | f = assert(io.open("data.txt", "r")) 634 | for n1,n2,rest in f:lines("*n", "n", "*a") do 635 | print("file:lines()", n1, n2, rest) 636 | end 637 | f:close() 638 | f = assert(io.open("data.txt", "r")) 639 | for l in f:lines() do 640 | print("file:lines()", l) 641 | end 642 | f:close() 643 | print("file:lines()", pcall(function() 644 | for l in f:lines() do print(l) end 645 | end)) 646 | print("file:lines()", pcall(function() 647 | local f = assert(io.open("data.txt", "r")) 648 | for l in f:lines("*l", "*x") do print(l) end 649 | f:close() 650 | end)) 651 | end 652 | os.remove("data.txt") 653 | end 654 | ___'' 655 | 656 | 657 | print("testing C API ...") 658 | local mod = require("testmod") 659 | ___'' 660 | print("isinteger", mod.isinteger(1)) 661 | print("isinteger", mod.isinteger(0)) 662 | print("isinteger", mod.isinteger(1234567)) 663 | print("isinteger", mod.isinteger(12.3)) 664 | print("isinteger", mod.isinteger(math.huge)) 665 | print("isinteger", mod.isinteger(math.sqrt(-1))) 666 | 667 | 668 | ___'' 669 | print("rotate", mod.rotate(1, 1, 2, 3, 4, 5, 6)) 670 | print("rotate", mod.rotate(-1, 1, 2, 3, 4, 5, 6)) 671 | print("rotate", mod.rotate(4, 1, 2, 3, 4, 5, 6)) 672 | print("rotate", mod.rotate(-4, 1, 2, 3, 4, 5, 6)) 673 | 674 | 675 | ___'' 676 | print("strtonum", mod.strtonum("+123")) 677 | print("strtonum", mod.strtonum(" 123 ")) 678 | print("strtonum", mod.strtonum("-1.23")) 679 | print("strtonum", mod.strtonum(" 123 abc")) 680 | print("strtonum", mod.strtonum("jkl")) 681 | 682 | 683 | ___'' 684 | local a, b, c = mod.requiref() 685 | print("requiref", type(a), type(b), type(c), 686 | a.boolean, b.boolean, c.boolean, 687 | type(requiref1), type(requiref2), type(requiref3)) 688 | 689 | ___'' 690 | local proxy, backend = {}, {} 691 | setmetatable(proxy, { __index = backend, __newindex = backend }) 692 | print("geti/seti", rawget(proxy, 1), rawget(backend, 1)) 693 | print("geti/seti", mod.getseti(proxy, 1)) 694 | print("geti/seti", rawget(proxy, 1), rawget(backend, 1)) 695 | print("geti/seti", mod.getseti(proxy, 1)) 696 | print("geti/seti", rawget(proxy, 1), rawget(backend, 1)) 697 | 698 | -- tests for Lua 5.1 699 | ___'' 700 | print("tonumber", mod.tonumber(12)) 701 | print("tonumber", mod.tonumber("12")) 702 | print("tonumber", mod.tonumber("0")) 703 | print("tonumber", mod.tonumber(false)) 704 | print("tonumber", mod.tonumber("error")) 705 | 706 | ___'' 707 | print("tointeger", mod.tointeger(12)) 708 | print("tointeger", mod.tointeger(-12)) 709 | print("tointeger", mod.tointeger(12.1)) 710 | print("tointeger", mod.tointeger(12.9)) 711 | print("tointeger", mod.tointeger(-12.1)) 712 | print("tointeger", mod.tointeger(-12.9)) 713 | print("tointeger", mod.tointeger("12")) 714 | print("tointeger", mod.tointeger("0")) 715 | print("tointeger", mod.tointeger(math.pi)) 716 | print("tointeger", mod.tointeger(false)) 717 | print("tointeger", mod.tointeger("error")) 718 | 719 | ___'' 720 | print("len", mod.len("123")) 721 | print("len", mod.len({ 1, 2, 3})) 722 | print("len", pcall(mod.len, true)) 723 | local ud, meta = mod.newproxy() 724 | meta.__len = function() return 5 end 725 | print("len", mod.len(ud)) 726 | meta.__len = function() return true end 727 | print("len", pcall(mod.len, ud)) 728 | 729 | ___'' 730 | print("copy", mod.copy(true, "string", {}, 1)) 731 | 732 | ___'' 733 | print("rawgetp/rawsetp", mod.rawxetp()) 734 | print("rawgetp/rawsetp", mod.rawxetp("I'm back")) 735 | 736 | ___'' 737 | print("globals", F(mod.globals()), mod.globals() == _G) 738 | 739 | ___'' 740 | local t = {} 741 | print("getsubtable", F(mod.subtable(t))) 742 | local x, msg = mod.subtable(t) 743 | print("getsubtable", F(x, msg, x == t.xxx)) 744 | 745 | ___'' 746 | print("udata", F(mod.udata())) 747 | print("udata", mod.udata("nosuchtype")) 748 | 749 | ___'' 750 | print("uservalue", F(mod.uservalue())) 751 | 752 | ___'' 753 | print("upvalues", mod.getupvalues()) 754 | 755 | ___'' 756 | print("absindex", mod.absindex("hi", true)) 757 | 758 | ___'' 759 | print("arith", mod.arith(2, 1)) 760 | print("arith", mod.arith(3, 5)) 761 | 762 | ___'' 763 | print("compare", mod.compare(1, 1)) 764 | print("compare", mod.compare(2, 1)) 765 | print("compare", mod.compare(1, 2)) 766 | 767 | ___'' 768 | print("tolstring", mod.tolstring("string")) 769 | local t = setmetatable({}, { 770 | __tostring = function(v) return "mytable" end 771 | }) 772 | print("tolstring", mod.tolstring(t)) 773 | local t = setmetatable({}, { 774 | __tostring = function(v) return nil end 775 | }) 776 | print("tolstring", pcall(mod.tolstring, t)) 777 | local ud, meta = mod.newproxy() 778 | meta.__name = "XXX" 779 | print("tolstring", mod.tolstring(ud):gsub(":.*$", ": yyy")) 780 | 781 | ___'' 782 | print("pushstring", mod.pushstring()) 783 | 784 | ___'' 785 | print("Buffer", mod.buffer()) 786 | 787 | ___'' 788 | print("execresult", mod.exec("exit 0")) 789 | print("execresult", mod.exec("exit 1")) 790 | print("execresult", mod.exec("exit 25")) 791 | 792 | ___'' 793 | do 794 | local bin = string.dump(function() end) 795 | local modes = { "t", "b", "bt" } 796 | local codes = { 797 | "", "return true", bin, "invalidsource", "\27invalidbinary" 798 | } 799 | for _,m in ipairs(modes) do 800 | for i,c in ipairs(codes) do 801 | print("loadbufferx", m, i, F(mod.loadstring(c, m))) 802 | end 803 | end 804 | 805 | ___'' 806 | local bom = "\239\187\191" 807 | local shebang = "#!/usr/bin/env lua\n" 808 | codes[#codes+1] = bom .. shebang .. "return true" 809 | codes[#codes+1] = bom .. shebang .. bin 810 | codes[#codes+1] = bom .. shebang .. "invalidsource" 811 | codes[#codes+1] = bom .. shebang .. "\027invalidbinary" 812 | for _,m in ipairs(modes) do 813 | for i,c in ipairs(codes) do 814 | print("loadfilex", m, i, F(mod.loadfile(c, m))) 815 | end 816 | end 817 | end 818 | ___'' 819 | 820 | -------------------------------------------------------------------------------- /vendor/compat-5.3/tests/testmod.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "compat-5.3.h" 4 | 5 | 6 | static int test_isinteger (lua_State *L) { 7 | lua_pushboolean(L, lua_isinteger(L, 1)); 8 | return 1; 9 | } 10 | 11 | 12 | static int test_rotate (lua_State *L) { 13 | int r = (int)luaL_checkinteger(L, 1); 14 | int n = lua_gettop(L)-1; 15 | luaL_argcheck(L, (r < 0 ? -r : r) <= n, 1, "not enough arguments"); 16 | lua_rotate(L, 2, r); 17 | return n; 18 | } 19 | 20 | 21 | static int test_str2num (lua_State *L) { 22 | const char *s = luaL_checkstring(L, 1); 23 | size_t len = lua_stringtonumber(L, s); 24 | if (len == 0) 25 | lua_pushnumber(L, 0); 26 | lua_pushinteger(L, (lua_Integer)len); 27 | return 2; 28 | } 29 | 30 | 31 | static int my_mod (lua_State *L ) { 32 | lua_newtable(L); 33 | lua_pushboolean(L, 1); 34 | lua_setfield(L, -2, "boolean"); 35 | return 1; 36 | } 37 | 38 | static int test_requiref (lua_State *L) { 39 | lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 40 | lua_newtable(L); 41 | lua_pushboolean(L, 0); 42 | lua_setfield(L, -2, "boolean"); 43 | lua_setfield(L, -2, "requiref3"); 44 | lua_pop(L, 1); 45 | luaL_requiref(L, "requiref1", my_mod, 0); 46 | luaL_requiref(L, "requiref2", my_mod, 1); 47 | luaL_requiref(L, "requiref3", my_mod, 1); 48 | return 3; 49 | } 50 | 51 | static int test_getseti (lua_State *L) { 52 | lua_Integer k = luaL_checkinteger(L, 2); 53 | lua_Integer n = 0; 54 | if (lua_geti(L, 1, k) == LUA_TNUMBER) { 55 | n = lua_tointeger(L, -1); 56 | } else { 57 | lua_pop(L, 1); 58 | lua_pushinteger(L, n); 59 | } 60 | lua_pushinteger(L, n+1); 61 | lua_seti(L, 1, k); 62 | return 1; 63 | } 64 | 65 | 66 | /* additional tests for Lua5.1 */ 67 | #define NUP 3 68 | 69 | static int test_newproxy (lua_State *L) { 70 | lua_settop(L, 0); 71 | lua_newuserdata(L, 0); 72 | lua_newtable(L); 73 | lua_pushvalue(L, -1); 74 | lua_pushboolean(L, 1); 75 | lua_setfield(L, -2, "__gc"); 76 | lua_setmetatable(L, -3); 77 | return 2; 78 | } 79 | 80 | static int test_absindex (lua_State *L) { 81 | int i = 1; 82 | for (i = 1; i <= NUP; ++i) 83 | lua_pushvalue(L, lua_absindex(L, lua_upvalueindex(i))); 84 | lua_pushvalue(L, lua_absindex(L, LUA_REGISTRYINDEX)); 85 | lua_pushstring(L, lua_typename(L, lua_type(L, lua_absindex(L, -1)))); 86 | lua_replace(L, lua_absindex(L, -2)); 87 | lua_pushvalue(L, lua_absindex(L, -2)); 88 | lua_pushvalue(L, lua_absindex(L, -4)); 89 | lua_pushvalue(L, lua_absindex(L, -6)); 90 | i += 3; 91 | lua_pushvalue(L, lua_absindex(L, 1)); 92 | lua_pushvalue(L, lua_absindex(L, 2)); 93 | lua_pushvalue(L, lua_absindex(L, 3)); 94 | i += 3; 95 | return i; 96 | } 97 | 98 | static int test_arith (lua_State *L) { 99 | lua_settop(L, 2); 100 | lua_pushvalue(L, 1); 101 | lua_pushvalue(L, 2); 102 | lua_arith(L, LUA_OPADD); 103 | lua_pushvalue(L, 1); 104 | lua_pushvalue(L, 2); 105 | lua_arith(L, LUA_OPSUB); 106 | lua_pushvalue(L, 1); 107 | lua_pushvalue(L, 2); 108 | lua_arith(L, LUA_OPMUL); 109 | lua_pushvalue(L, 1); 110 | lua_pushvalue(L, 2); 111 | lua_arith(L, LUA_OPDIV); 112 | lua_pushvalue(L, 1); 113 | lua_pushvalue(L, 2); 114 | lua_arith(L, LUA_OPMOD); 115 | lua_pushvalue(L, 1); 116 | lua_pushvalue(L, 2); 117 | lua_arith(L, LUA_OPPOW); 118 | lua_pushvalue(L, 1); 119 | lua_arith(L, LUA_OPUNM); 120 | return lua_gettop(L)-2; 121 | } 122 | 123 | static int test_compare (lua_State *L) { 124 | luaL_checknumber(L, 1); 125 | luaL_checknumber(L, 2); 126 | lua_settop(L, 2); 127 | lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPEQ)); 128 | lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLT)); 129 | lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLE)); 130 | return 3; 131 | } 132 | 133 | static int test_globals (lua_State *L) { 134 | lua_pushglobaltable(L); 135 | return 1; 136 | } 137 | 138 | static int test_tonumber (lua_State *L) { 139 | int isnum = 0; 140 | lua_Number n = lua_tonumberx(L, 1, &isnum); 141 | if (!isnum) 142 | lua_pushnil(L); 143 | else 144 | lua_pushnumber(L, n); 145 | return 1; 146 | } 147 | 148 | static int test_tointeger (lua_State *L) { 149 | int isnum = 0; 150 | lua_Integer n = lua_tointegerx(L, 1, &isnum); 151 | if (!isnum) 152 | lua_pushnil(L); 153 | else 154 | lua_pushinteger(L, n); 155 | lua_pushinteger(L, lua_tointeger(L, 1)); 156 | return 2; 157 | } 158 | 159 | static int test_len (lua_State *L) { 160 | luaL_checkany(L, 1); 161 | lua_len(L, 1); 162 | lua_pushinteger(L, luaL_len(L, 1)); 163 | return 2; 164 | } 165 | 166 | static int test_copy (lua_State *L) { 167 | int args = lua_gettop(L); 168 | if (args >= 2) { 169 | int i = 0; 170 | for (i = args-1; i > 0; --i) 171 | lua_copy(L, args, i); 172 | } 173 | return args; 174 | } 175 | 176 | /* need an address */ 177 | static char const dummy = 0; 178 | 179 | static int test_rawxetp (lua_State *L) { 180 | if (lua_gettop(L) > 0) 181 | lua_pushvalue(L, 1); 182 | else 183 | lua_pushliteral(L, "hello again"); 184 | lua_rawsetp(L, LUA_REGISTRYINDEX, &dummy); 185 | lua_settop(L, 0); 186 | lua_rawgetp(L, LUA_REGISTRYINDEX, &dummy); 187 | return 1; 188 | } 189 | 190 | static int test_udata (lua_State *L) { 191 | const char *tname = luaL_optstring(L, 1, "utype1"); 192 | void *u1 = lua_newuserdata(L, 1); 193 | int u1pos = lua_gettop(L); 194 | void *u2 = lua_newuserdata(L, 1); 195 | int u2pos = lua_gettop(L); 196 | luaL_newmetatable(L, "utype1"); 197 | luaL_newmetatable(L, "utype2"); 198 | lua_pop(L, 2); 199 | luaL_setmetatable(L, "utype2"); 200 | lua_pushvalue(L, u1pos); 201 | luaL_setmetatable(L, "utype1"); 202 | lua_pop(L, 1); 203 | (void)u1; 204 | (void)u2; 205 | lua_pushlightuserdata(L, luaL_testudata(L, u1pos, tname)); 206 | lua_pushlightuserdata(L, luaL_testudata(L, u2pos, tname)); 207 | luaL_getmetatable(L, "utype1"); 208 | lua_getfield(L, -1, "__name"); 209 | lua_replace(L, -2); 210 | return 3; 211 | } 212 | 213 | static int test_subtable (lua_State *L) { 214 | luaL_checktype(L, 1, LUA_TTABLE); 215 | lua_settop(L, 1); 216 | if (luaL_getsubtable(L, 1, "xxx")) { 217 | lua_pushliteral(L, "oldtable"); 218 | } else { 219 | lua_pushliteral(L, "newtable"); 220 | } 221 | return 2; 222 | } 223 | 224 | static int test_uservalue (lua_State *L) { 225 | void *udata = lua_newuserdata(L, 1); 226 | int ui = lua_gettop(L); 227 | lua_newtable(L); 228 | lua_setuservalue(L, ui); 229 | lua_pushinteger(L, lua_getuservalue(L, ui)); 230 | (void)udata; 231 | return 2; 232 | } 233 | 234 | static int test_upvalues (lua_State *L) { 235 | int i = 1; 236 | for (i = 1; i <= NUP; ++i) 237 | lua_pushvalue(L, lua_upvalueindex(i)); 238 | return NUP; 239 | } 240 | 241 | static int test_tolstring (lua_State *L) { 242 | size_t len = 0; 243 | luaL_tolstring(L, 1, &len); 244 | lua_pushinteger(L, (int)len); 245 | return 2; 246 | } 247 | 248 | static int test_pushstring (lua_State *L) { 249 | lua_pushstring(L, lua_pushliteral(L, "abc")); 250 | lua_pushstring(L, lua_pushlstring(L, "abc", 2)); 251 | lua_pushstring(L, lua_pushlstring(L, NULL, 0)); 252 | lua_pushstring(L, lua_pushstring(L, "abc")); 253 | lua_pushboolean(L, NULL == lua_pushstring(L, NULL)); 254 | return 10; 255 | } 256 | 257 | static int test_buffer (lua_State *L) { 258 | luaL_Buffer b; 259 | char *p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE+1); 260 | p[0] = 'a'; 261 | p[1] = 'b'; 262 | luaL_addsize(&b, 2); 263 | luaL_addstring(&b, "c"); 264 | lua_pushliteral(L, "d"); 265 | luaL_addvalue(&b); 266 | luaL_addchar(&b, 'e'); 267 | luaL_pushresult(&b); 268 | return 1; 269 | } 270 | 271 | static int test_exec (lua_State *L) { 272 | const char *cmd = luaL_checkstring(L, 1); 273 | return luaL_execresult(L, system(cmd)); 274 | } 275 | 276 | static int test_loadstring (lua_State *L) { 277 | size_t len = 0; 278 | char const* s = luaL_checklstring(L, 1, &len); 279 | char const* mode = luaL_optstring(L, 2, "bt"); 280 | lua_pushinteger(L, luaL_loadbufferx(L, s, len, s, mode)); 281 | return 2; 282 | } 283 | 284 | static int test_loadfile (lua_State *L) { 285 | char filename[L_tmpnam+1] = { 0 }; 286 | size_t len = 0; 287 | char const* s = luaL_checklstring(L, 1, &len); 288 | char const* mode = luaL_optstring(L, 2, "bt"); 289 | if (tmpnam(filename)) { 290 | FILE* f = fopen(filename, "wb"); 291 | if (f) { 292 | fwrite(s, 1, len, f); 293 | fclose(f); 294 | lua_pushinteger(L, luaL_loadfilex(L, filename, mode)); 295 | remove(filename); 296 | return 2; 297 | } else 298 | remove(filename); 299 | } 300 | return 0; 301 | } 302 | 303 | 304 | static const luaL_Reg funcs[] = { 305 | { "isinteger", test_isinteger }, 306 | { "rotate", test_rotate }, 307 | { "strtonum", test_str2num }, 308 | { "requiref", test_requiref }, 309 | { "getseti", test_getseti }, 310 | { "newproxy", test_newproxy }, 311 | { "arith", test_arith }, 312 | { "compare", test_compare }, 313 | { "tonumber", test_tonumber }, 314 | { "tointeger", test_tointeger }, 315 | { "len", test_len }, 316 | { "copy", test_copy }, 317 | { "rawxetp", test_rawxetp }, 318 | { "subtable", test_subtable }, 319 | { "udata", test_udata }, 320 | { "uservalue", test_uservalue }, 321 | { "globals", test_globals }, 322 | { "tolstring", test_tolstring }, 323 | { "pushstring", test_pushstring }, 324 | { "buffer", test_buffer }, 325 | { "exec", test_exec }, 326 | { "loadstring", test_loadstring }, 327 | { "loadfile", test_loadfile }, 328 | { NULL, NULL } 329 | }; 330 | 331 | static const luaL_Reg more_funcs[] = { 332 | { "getupvalues", test_upvalues }, 333 | { "absindex", test_absindex }, 334 | { NULL, NULL } 335 | }; 336 | 337 | 338 | #ifdef __cplusplus 339 | extern "C" { 340 | #endif 341 | int luaopen_testmod (lua_State *L) { 342 | int i = 1; 343 | luaL_newlib(L, funcs); 344 | for (i = 1; i <= NUP; ++i) 345 | lua_pushnumber(L, i); 346 | luaL_setfuncs(L, more_funcs, NUP); 347 | return 1; 348 | } 349 | #ifdef __cplusplus 350 | } 351 | #endif 352 | 353 | --------------------------------------------------------------------------------