summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaurnimator <quae@daurnimator.com>2017-08-30 13:55:59 +1000
committerdaurnimator <quae@daurnimator.com>2017-08-30 13:56:07 +1000
commitb8e3766294b6bf11d70a8a202e633b2569675e77 (patch)
treec1f29081daf4a1dc3965ee260d88e2aeae9aa902
parentb92fca3b68e551d2583754c80196d524890e5ee4 (diff)
parent7333333568b13db56136e2354c55556adc7714ed (diff)
downloadluaossl-b8e3766294b6bf11d70a8a202e633b2569675e77.tar.gz
luaossl-b8e3766294b6bf11d70a8a202e633b2569675e77.tar.bz2
luaossl-b8e3766294b6bf11d70a8a202e633b2569675e77.zip
Merge commit '7333333568b13db56136e2354c55556adc7714ed' as 'vendor/compat53'
-rw-r--r--vendor/compat53/.gitignore10
-rw-r--r--vendor/compat53/LICENSE20
-rw-r--r--vendor/compat53/README.md229
-rw-r--r--vendor/compat53/c-api/compat-5.3.c617
-rw-r--r--vendor/compat53/c-api/compat-5.3.h388
-rw-r--r--vendor/compat53/compat53/init.lua373
-rw-r--r--vendor/compat53/compat53/module.lua827
-rw-r--r--vendor/compat53/lprefix.h175
-rw-r--r--vendor/compat53/lstrlib.c1584
-rw-r--r--vendor/compat53/ltablib.c450
-rw-r--r--vendor/compat53/lutf8lib.c256
-rw-r--r--vendor/compat53/rockspecs/compat53-0.1-1.rockspec31
-rw-r--r--vendor/compat53/rockspecs/compat53-0.2-1.rockspec32
-rw-r--r--vendor/compat53/rockspecs/compat53-0.3-1.rockspec32
-rw-r--r--vendor/compat53/rockspecs/compat53-0.4-1.rockspec32
-rw-r--r--vendor/compat53/rockspecs/compat53-0.5-1.rockspec32
-rw-r--r--vendor/compat53/rockspecs/compat53-scm-0.rockspec32
-rwxr-xr-xvendor/compat53/tests/test.lua789
-rw-r--r--vendor/compat53/tests/testmod.c318
19 files changed, 6227 insertions, 0 deletions
diff --git a/vendor/compat53/.gitignore b/vendor/compat53/.gitignore
new file mode 100644
index 0000000..67c1b76
--- /dev/null
+++ b/vendor/compat53/.gitignore
@@ -0,0 +1,10 @@
1# generated files
2*.so
3*.dll
4*.o
5*.obj
6HISTO
7
8# vim temporaries
9.*.swp
10
diff --git a/vendor/compat53/LICENSE b/vendor/compat53/LICENSE
new file mode 100644
index 0000000..511db15
--- /dev/null
+++ b/vendor/compat53/LICENSE
@@ -0,0 +1,20 @@
1The MIT License (MIT)
2
3Copyright (c) 2015 Kepler Project.
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in
7the Software without restriction, including without limitation the rights to
8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9the Software, and to permit persons to whom the Software is furnished to do so,
10subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/compat53/README.md b/vendor/compat53/README.md
new file mode 100644
index 0000000..08614a1
--- /dev/null
+++ b/vendor/compat53/README.md
@@ -0,0 +1,229 @@
1# lua-compat-5.3
2
3Lua-5.3-style APIs for Lua 5.2 and 5.1.
4
5## What is it
6
7This is a small module that aims to make it easier to write code
8in a Lua-5.3-style that is compatible with Lua 5.1, Lua 5.2, and Lua
95.3. This does *not* make Lua 5.2 (or even Lua 5.1) entirely
10compatible with Lua 5.3, but it brings the API closer to that of Lua
115.3.
12
13It includes:
14
15* _For writing Lua_: The Lua module `compat53`, which can be require'd
16 from Lua scripts and run in Lua 5.1, 5.2, and 5.3, including a
17 backport of the `utf8` module, the 5.3 `table` module, and the
18 string packing functions straight from the Lua 5.3 sources.
19* _For writing C_: A C header and file which can be linked to your
20 Lua module written in C, providing some functions from the C API
21 of Lua 5.3 that do not exist in Lua 5.2 or 5.1, making it easier to
22 write C code that compiles with all three versions of liblua.
23
24## How to use it
25
26### Lua module
27
28```lua
29require("compat53")
30```
31
32`compat53` makes changes to your global environment and does not return
33a meaningful return value, so the usual idiom of storing the return of
34`require` in a local variable makes no sense.
35
36When run under Lua 5.3, this module does nothing.
37
38When run under Lua 5.2 or 5.1, it replaces some of your standard
39functions and adds new ones to bring your environment closer to that
40of Lua 5.3. It also tries to load the backported `utf8`, `table`, and
41string packing modules automatically. If unsuccessful, pure Lua
42versions of the new `table` functions are used as a fallback, and
43[Roberto's struct library][1] is tried for string packing.
44
45#### Lua submodules
46
47```lua
48local _ENV = require("compat53.module")
49if setfenv then setfenv(1, _ENV) end
50```
51
52The `compat53.module` module does not modify the global environment,
53and so it is safe to use in modules without affecting other Lua files.
54It is supposed to be set as the current environment (see above), i.e.
55cherry picking individual functions from this module is expressly
56*not* supported!). Not all features are available when using this
57module (e.g. yieldable (x)pcall support, string/file methods, etc.),
58so it is recommended to use plain `require("compat53")` whenever
59possible.
60
61### C code
62
63There are two ways of adding the C API compatibility functions/macros to
64your project:
65* If `COMPAT53_PREFIX` is *not* `#define`d, `compat-5.3.h` `#include`s
66 `compat-5.3.c`, and all functions are made `static`. You don't have to
67 compile/link/add `compat-5.3.c` yourself. This is useful for one-file
68 projects.
69* If `COMPAT53_PREFIX` is `#define`d, all exported functions are renamed
70 behind the scenes using this prefix to avoid linker conflicts with other
71 code using this package. This doesn't change the way you call the
72 compatibility functions in your code. You have to compile and link
73 `compat-5.3.c` to your project yourself. You can change the way the
74 functions are exported using the `COMPAT53_API` macro (e.g. if you need
75 some `__declspec` magic). While it is technically possible to use
76 the "lua" prefix (and it looks better in the debugger), this is
77 discouraged because LuaJIT has started to implement its own Lua 5.2+
78 C API functions, and with the "lua" prefix you'd violate the
79 one-definition rule with recent LuaJIT versions.
80
81## What's implemented
82
83### Lua
84
85* the `utf8` module backported from the Lua 5.3 sources
86* `string.pack`, `string.packsize`, and `string.unpack` from the Lua
87 5.3 sources or from the `struct` module. (`struct` is not 100%
88 compatible to Lua 5.3's string packing!) (See [here][4])
89* `math.maxinteger` and `math.mininteger`, `math.tointeger`, `math.type`,
90 and `math.ult` (see [here][5])
91* `assert` accepts non-string error messages
92* `ipairs` respects `__index` metamethod
93* `table.move`
94* `table` library respects metamethods
95
96For Lua 5.1 additionally:
97* `load` and `loadfile` accept `mode` and `env` parameters
98* `table.pack` and `table.unpack`
99* string patterns may contain embedded zeros (but see [here][6])
100* `string.rep` accepts `sep` argument
101* `string.format` calls `tostring` on arguments for `%s`
102* `math.log` accepts base argument
103* `xpcall` takes additional arguments
104* `pcall` and `xpcall` can execute functions that yield (see
105 [here][22] for a possible problem with `coroutine.running`)
106* `pairs` respects `__pairs` metamethod (see [here][7])
107* `rawlen` (but `#` still doesn't respect `__len` for tables)
108* `package.searchers` as alias for `package.loaders`
109* `package.searchpath` (see [here][8])
110* `coroutine` functions dealing with the main coroutine (see
111 [here][22] for a possible problem with `coroutine.running`)
112* `coroutine.create` accepts functions written in C
113* return code of `os.execute` (see [here][9])
114* `io.write` and `file:write` return file handle
115* `io.lines` and `file:lines` accept format arguments (like `io.read`)
116 (see [here][10] and [here][11])
117* `debug.setmetatable` returns object
118* `debug.getuservalue` (see [here][12])
119* `debug.setuservalue` (see [here][13])
120
121### C
122
123* `lua_KContext` (see [here][14])
124* `lua_KFunction` (see [here][14])
125* `lua_dump` (extra `strip` parameter, ignored, see [here][15])
126* `lua_getfield` (return value)
127* `lua_geti` and `lua_seti`
128* `lua_getglobal` (return value)
129* `lua_getmetafield` (return value)
130* `lua_gettable` (return value)
131* `lua_getuservalue` (limited compatibility, see [here][16])
132* `lua_setuservalue` (limited compatibility, see [here][17])
133* `lua_isinteger`
134* `lua_numbertointeger`
135* `lua_callk` and `lua_pcallk` (limited compatibility, see [here][14])
136* `lua_rawget` and `lua_rawgeti` (return values)
137* `lua_rawgetp` and `lua_rawsetp`
138* `luaL_requiref` (now checks `package.loaded` first)
139* `lua_rotate`
140* `lua_stringtonumber` (see [here][18])
141
142For Lua 5.1 additionally:
143* `LUA_OK`
144* `LUA_OP*` macros for `lua_arith` and `lua_compare`
145* `lua_Unsigned`
146* `lua_absindex`
147* `lua_arith` (see [here][19])
148* `lua_compare`
149* `lua_len`, `lua_rawlen`, and `luaL_len`
150* `lua_pushstring`, `lua_pushlstring` (return value)
151* `lua_copy`
152* `lua_pushglobaltable`
153* `luaL_testudata`
154* `luaL_setfuncs`, `luaL_newlibtable`, and `luaL_newlib`
155* `luaL_setmetatable`
156* `luaL_getsubtable`
157* `luaL_traceback`
158* `luaL_execresult`
159* `luaL_fileresult`
160* `luaL_checkversion` (with empty body, only to avoid compile errors,
161 see [here][20])
162* `luaL_tolstring`
163* `luaL_buffinitsize`, `luaL_prepbuffsize`, and `luaL_pushresultsize`
164 (see [here][21])
165* `lua_pushunsigned`, `lua_tounsignedx`, `lua_tounsigned`,
166 `luaL_checkunsigned`, `luaL_optunsigned`, if
167 `LUA_COMPAT_APIINTCASTS` is defined.
168
169## What's not implemented
170
171* bit operators
172* integer division operator
173* utf8 escape sequences
174* 64 bit integers
175* `coroutine.isyieldable`
176* Lua 5.1: `_ENV`, `goto`, labels, ephemeron tables, etc. See
177 [`lua-compat-5.2`][2] for a detailed list.
178* the following C API functions/macros:
179 * `lua_isyieldable`
180 * `lua_getextraspace`
181 * `lua_arith` (new operators missing)
182 * `lua_push(v)fstring` (new formats missing)
183 * `lua_upvalueid` (5.1)
184 * `lua_upvaluejoin` (5.1)
185 * `lua_version` (5.1)
186 * `lua_yieldk` (5.1)
187 * `luaL_loadbufferx` (5.1)
188 * `luaL_loadfilex` (5.1)
189
190## See also
191
192* For Lua-5.2-style APIs under Lua 5.1, see [lua-compat-5.2][2],
193 which also is the basis for most of the code in this project.
194* For Lua-5.1-style APIs under Lua 5.0, see [Compat-5.1][3]
195
196## Credits
197
198This package contains code written by:
199
200* [The Lua Team](http://www.lua.org)
201* Philipp Janda ([@siffiejoe](http://github.com/siffiejoe))
202* Tomás Guisasola Gorham ([@tomasguisasola](http://github.com/tomasguisasola))
203* Hisham Muhammad ([@hishamhm](http://github.com/hishamhm))
204* Renato Maia ([@renatomaia](http://github.com/renatomaia))
205
206
207 [1]: http://www.inf.puc-rio.br/~roberto/struct/
208 [2]: http://github.com/keplerproject/lua-compat-5.2/
209 [3]: http://keplerproject.org/compat/
210 [4]: https://github.com/keplerproject/lua-compat-5.3/wiki/string_packing
211 [5]: https://github.com/keplerproject/lua-compat-5.3/wiki/math.type
212 [6]: https://github.com/keplerproject/lua-compat-5.3/wiki/pattern_matching
213 [7]: https://github.com/keplerproject/lua-compat-5.3/wiki/pairs
214 [8]: https://github.com/keplerproject/lua-compat-5.3/wiki/package.searchpath
215 [9]: https://github.com/keplerproject/lua-compat-5.3/wiki/os.execute
216 [10]: https://github.com/keplerproject/lua-compat-5.3/wiki/io.lines
217 [11]: https://github.com/keplerproject/lua-compat-5.3/wiki/file.lines
218 [12]: https://github.com/keplerproject/lua-compat-5.3/wiki/debug.getuservalue
219 [13]: https://github.com/keplerproject/lua-compat-5.3/wiki/debug.setuservalue
220 [14]: https://github.com/keplerproject/lua-compat-5.3/wiki/yieldable_c_functions
221 [15]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_dump
222 [16]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_getuservalue
223 [17]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_setuservalue
224 [18]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_stringtonumber
225 [19]: https://github.com/keplerproject/lua-compat-5.3/wiki/lua_arith
226 [20]: https://github.com/keplerproject/lua-compat-5.3/wiki/luaL_checkversion
227 [21]: https://github.com/keplerproject/lua-compat-5.3/wiki/luaL_Buffer
228 [22]: https://github.com/keplerproject/lua-compat-5.3/wiki/coroutine.running
229
diff --git a/vendor/compat53/c-api/compat-5.3.c b/vendor/compat53/c-api/compat-5.3.c
new file mode 100644
index 0000000..883efb8
--- /dev/null
+++ b/vendor/compat53/c-api/compat-5.3.c
@@ -0,0 +1,617 @@
1#include <stddef.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <errno.h>
6#include "compat-5.3.h"
7
8/* don't compile it again if it already is included via compat53.h */
9#ifndef COMPAT53_C_
10#define COMPAT53_C_
11
12
13
14/* definitions for Lua 5.1 only */
15#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
16
17
18COMPAT53_API int lua_absindex (lua_State *L, int i) {
19 if (i < 0 && i > LUA_REGISTRYINDEX)
20 i += lua_gettop(L) + 1;
21 return i;
22}
23
24
25static void compat53_call_lua (lua_State *L, char const code[], size_t len,
26 int nargs, int nret) {
27 lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code);
28 if (lua_type(L, -1) != LUA_TFUNCTION) {
29 lua_pop(L, 1);
30 if (luaL_loadbuffer(L, code, len, "=none"))
31 lua_error(L);
32 lua_pushvalue(L, -1);
33 lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code);
34 }
35 lua_insert(L, -nargs-1);
36 lua_call(L, nargs, nret);
37}
38
39
40static const char compat53_arith_code[] =
41 "local op,a,b=...\n"
42 "if op==0 then return a+b\n"
43 "elseif op==1 then return a-b\n"
44 "elseif op==2 then return a*b\n"
45 "elseif op==3 then return a/b\n"
46 "elseif op==4 then return a%b\n"
47 "elseif op==5 then return a^b\n"
48 "elseif op==6 then return -a\n"
49 "end\n";
50
51COMPAT53_API void lua_arith (lua_State *L, int op) {
52 if (op < LUA_OPADD || op > LUA_OPUNM)
53 luaL_error(L, "invalid 'op' argument for lua_arith");
54 luaL_checkstack(L, 5, "not enough stack slots");
55 if (op == LUA_OPUNM)
56 lua_pushvalue(L, -1);
57 lua_pushnumber(L, op);
58 lua_insert(L, -3);
59 compat53_call_lua(L, compat53_arith_code,
60 sizeof(compat53_arith_code)-1, 3, 1);
61}
62
63
64static const char compat53_compare_code[] =
65 "local a,b=...\n"
66 "return a<=b\n";
67
68COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op) {
69 int result = 0;
70 switch (op) {
71 case LUA_OPEQ:
72 return lua_equal(L, idx1, idx2);
73 case LUA_OPLT:
74 return lua_lessthan(L, idx1, idx2);
75 case LUA_OPLE:
76 luaL_checkstack(L, 5, "not enough stack slots");
77 idx1 = lua_absindex(L, idx1);
78 idx2 = lua_absindex(L, idx2);
79 lua_pushvalue(L, idx1);
80 lua_pushvalue(L, idx2);
81 compat53_call_lua(L, compat53_compare_code,
82 sizeof(compat53_compare_code)-1, 2, 1);
83 result = lua_toboolean(L, -1);
84 lua_pop(L, 1);
85 return result;
86 default:
87 luaL_error(L, "invalid 'op' argument for lua_compare");
88 }
89 return 0;
90}
91
92
93COMPAT53_API void lua_copy (lua_State *L, int from, int to) {
94 int abs_to = lua_absindex(L, to);
95 luaL_checkstack(L, 1, "not enough stack slots");
96 lua_pushvalue(L, from);
97 lua_replace(L, abs_to);
98}
99
100
101COMPAT53_API void lua_len (lua_State *L, int i) {
102 switch (lua_type(L, i)) {
103 case LUA_TSTRING:
104 lua_pushnumber(L, (lua_Integer)lua_objlen(L, i));
105 break;
106 case LUA_TTABLE:
107 if (!luaL_callmeta(L, i, "__len"))
108 lua_pushnumber(L, (lua_Integer)lua_objlen(L, i));
109 break;
110 case LUA_TUSERDATA:
111 if (luaL_callmeta(L, i, "__len"))
112 break;
113 /* maybe fall through */
114 default:
115 luaL_error(L, "attempt to get length of a %s value",
116 lua_typename(L, lua_type(L, i)));
117 }
118}
119
120
121COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p) {
122 int abs_i = lua_absindex(L, i);
123 lua_pushlightuserdata(L, (void*)p);
124 lua_rawget(L, abs_i);
125 return lua_type(L, -1);
126}
127
128COMPAT53_API void lua_rawsetp (lua_State *L, int i, const void *p) {
129 int abs_i = lua_absindex(L, i);
130 luaL_checkstack(L, 1, "not enough stack slots");
131 lua_pushlightuserdata(L, (void*)p);
132 lua_insert(L, -2);
133 lua_rawset(L, abs_i);
134}
135
136
137COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) {
138 lua_Integer n = lua_tointeger(L, i);
139 if (isnum != NULL) {
140 *isnum = (n != 0 || lua_isnumber(L, i));
141 }
142 return n;
143}
144
145
146COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) {
147 lua_Number n = lua_tonumber(L, i);
148 if (isnum != NULL) {
149 *isnum = (n != 0 || lua_isnumber(L, i));
150 }
151 return n;
152}
153
154
155COMPAT53_API void luaL_checkversion (lua_State *L) {
156 (void)L;
157}
158
159
160COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg) {
161 if (!lua_checkstack(L, sp+LUA_MINSTACK)) {
162 if (msg != NULL)
163 luaL_error(L, "stack overflow (%s)", msg);
164 else {
165 lua_pushliteral(L, "stack overflow");
166 lua_error(L);
167 }
168 }
169}
170
171
172COMPAT53_API int luaL_getsubtable (lua_State *L, int i, const char *name) {
173 int abs_i = lua_absindex(L, i);
174 luaL_checkstack(L, 3, "not enough stack slots");
175 lua_pushstring(L, name);
176 lua_gettable(L, abs_i);
177 if (lua_istable(L, -1))
178 return 1;
179 lua_pop(L, 1);
180 lua_newtable(L);
181 lua_pushstring(L, name);
182 lua_pushvalue(L, -2);
183 lua_settable(L, abs_i);
184 return 0;
185}
186
187
188COMPAT53_API lua_Integer luaL_len (lua_State *L, int i) {
189 lua_Integer res = 0;
190 int isnum = 0;
191 luaL_checkstack(L, 1, "not enough stack slots");
192 lua_len(L, i);
193 res = lua_tointegerx(L, -1, &isnum);
194 lua_pop(L, 1);
195 if (!isnum)
196 luaL_error(L, "object length is not an integer");
197 return res;
198}
199
200
201COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
202 luaL_checkstack(L, nup+1, "too many upvalues");
203 for (; l->name != NULL; l++) { /* fill the table with given functions */
204 int i;
205 lua_pushstring(L, l->name);
206 for (i = 0; i < nup; i++) /* copy upvalues to the top */
207 lua_pushvalue(L, -(nup + 1));
208 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
209 lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */
210 }
211 lua_pop(L, nup); /* remove upvalues */
212}
213
214
215COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname) {
216 luaL_checkstack(L, 1, "not enough stack slots");
217 luaL_getmetatable(L, tname);
218 lua_setmetatable(L, -2);
219}
220
221
222COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname) {
223 void *p = lua_touserdata(L, i);
224 luaL_checkstack(L, 2, "not enough stack slots");
225 if (p == NULL || !lua_getmetatable(L, i))
226 return NULL;
227 else {
228 int res = 0;
229 luaL_getmetatable(L, tname);
230 res = lua_rawequal(L, -1, -2);
231 lua_pop(L, 2);
232 if (!res)
233 p = NULL;
234 }
235 return p;
236}
237
238
239static int compat53_countlevels (lua_State *L) {
240 lua_Debug ar;
241 int li = 1, le = 1;
242 /* find an upper bound */
243 while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
244 /* do a binary search */
245 while (li < le) {
246 int m = (li + le)/2;
247 if (lua_getstack(L, m, &ar)) li = m + 1;
248 else le = m;
249 }
250 return le - 1;
251}
252
253static int compat53_findfield (lua_State *L, int objidx, int level) {
254 if (level == 0 || !lua_istable(L, -1))
255 return 0; /* not found */
256 lua_pushnil(L); /* start 'next' loop */
257 while (lua_next(L, -2)) { /* for each pair in table */
258 if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */
259 if (lua_rawequal(L, objidx, -1)) { /* found object? */
260 lua_pop(L, 1); /* remove value (but keep name) */
261 return 1;
262 }
263 else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */
264 lua_remove(L, -2); /* remove table (but keep name) */
265 lua_pushliteral(L, ".");
266 lua_insert(L, -2); /* place '.' between the two names */
267 lua_concat(L, 3);
268 return 1;
269 }
270 }
271 lua_pop(L, 1); /* remove value */
272 }
273 return 0; /* not found */
274}
275
276static int compat53_pushglobalfuncname (lua_State *L, lua_Debug *ar) {
277 int top = lua_gettop(L);
278 lua_getinfo(L, "f", ar); /* push function */
279 lua_pushvalue(L, LUA_GLOBALSINDEX);
280 if (compat53_findfield(L, top + 1, 2)) {
281 lua_copy(L, -1, top + 1); /* move name to proper place */
282 lua_pop(L, 2); /* remove pushed values */
283 return 1;
284 }
285 else {
286 lua_settop(L, top); /* remove function and global table */
287 return 0;
288 }
289}
290
291static void compat53_pushfuncname (lua_State *L, lua_Debug *ar) {
292 if (*ar->namewhat != '\0') /* is there a name? */
293 lua_pushfstring(L, "function " LUA_QS, ar->name);
294 else if (*ar->what == 'm') /* main? */
295 lua_pushliteral(L, "main chunk");
296 else if (*ar->what == 'C') {
297 if (compat53_pushglobalfuncname(L, ar)) {
298 lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
299 lua_remove(L, -2); /* remove name */
300 }
301 else
302 lua_pushliteral(L, "?");
303 }
304 else
305 lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
306}
307
308#define COMPAT53_LEVELS1 12 /* size of the first part of the stack */
309#define COMPAT53_LEVELS2 10 /* size of the second part of the stack */
310
311COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1,
312 const char *msg, int level) {
313 lua_Debug ar;
314 int top = lua_gettop(L);
315 int numlevels = compat53_countlevels(L1);
316 int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0;
317 if (msg) lua_pushfstring(L, "%s\n", msg);
318 lua_pushliteral(L, "stack traceback:");
319 while (lua_getstack(L1, level++, &ar)) {
320 if (level == mark) { /* too many levels? */
321 lua_pushliteral(L, "\n\t..."); /* add a '...' */
322 level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */
323 }
324 else {
325 lua_getinfo(L1, "Slnt", &ar);
326 lua_pushfstring(L, "\n\t%s:", ar.short_src);
327 if (ar.currentline > 0)
328 lua_pushfstring(L, "%d:", ar.currentline);
329 lua_pushliteral(L, " in ");
330 compat53_pushfuncname(L, &ar);
331 lua_concat(L, lua_gettop(L) - top);
332 }
333 }
334 lua_concat(L, lua_gettop(L) - top);
335}
336
337
338COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
339 int en = errno; /* calls to Lua API may change this value */
340 if (stat) {
341 lua_pushboolean(L, 1);
342 return 1;
343 }
344 else {
345 lua_pushnil(L);
346 if (fname)
347 lua_pushfstring(L, "%s: %s", fname, strerror(en));
348 else
349 lua_pushstring(L, strerror(en));
350 lua_pushnumber(L, (lua_Number)en);
351 return 3;
352 }
353}
354
355
356#if !defined(l_inspectstat) && \
357 (defined(unix) || defined(__unix) || defined(__unix__) || \
358 defined(__TOS_AIX__) || defined(_SYSTYPE_BSD) || \
359 (defined(__APPLE__) && defined(__MACH__)))
360/* some form of unix; check feature macros in unistd.h for details */
361# include <unistd.h>
362/* check posix version; the relevant include files and macros probably
363 * were available before 2001, but I'm not sure */
364# if defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L
365# include <sys/wait.h>
366# define l_inspectstat(stat,what) \
367 if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \
368 else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; }
369# endif
370#endif
371
372/* provide default (no-op) version */
373#if !defined(l_inspectstat)
374# define l_inspectstat(stat,what) ((void)0)
375#endif
376
377
378COMPAT53_API int luaL_execresult (lua_State *L, int stat) {
379 const char *what = "exit";
380 if (stat == -1)
381 return luaL_fileresult(L, 0, NULL);
382 else {
383 l_inspectstat(stat, what);
384 if (*what == 'e' && stat == 0)
385 lua_pushboolean(L, 1);
386 else
387 lua_pushnil(L);
388 lua_pushstring(L, what);
389 lua_pushinteger(L, stat);
390 return 3;
391 }
392}
393
394
395COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B) {
396 /* make it crash if used via pointer to a 5.1-style luaL_Buffer */
397 B->b.p = NULL;
398 B->b.L = NULL;
399 B->b.lvl = 0;
400 /* reuse the buffer from the 5.1-style luaL_Buffer though! */
401 B->ptr = B->b.buffer;
402 B->capacity = LUAL_BUFFERSIZE;
403 B->nelems = 0;
404 B->L2 = L;
405}
406
407
408COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s) {
409 if (B->capacity - B->nelems < s) { /* needs to grow */
410 char* newptr = NULL;
411 size_t newcap = B->capacity * 2;
412 if (newcap - B->nelems < s)
413 newcap = B->nelems + s;
414 if (newcap < B->capacity) /* overflow */
415 luaL_error(B->L2, "buffer too large");
416 newptr = (char*)lua_newuserdata(B->L2, newcap);
417 memcpy(newptr, B->ptr, B->nelems);
418 if (B->ptr != B->b.buffer)
419 lua_replace(B->L2, -2); /* remove old buffer */
420 B->ptr = newptr;
421 B->capacity = newcap;
422 }
423 return B->ptr+B->nelems;
424}
425
426
427COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l) {
428 memcpy(luaL_prepbuffsize(B, l), s, l);
429 luaL_addsize(B, l);
430}
431
432
433COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B) {
434 size_t len = 0;
435 const char *s = lua_tolstring(B->L2, -1, &len);
436 if (!s)
437 luaL_error(B->L2, "cannot convert value to string");
438 if (B->ptr != B->b.buffer)
439 lua_insert(B->L2, -2); /* userdata buffer must be at stack top */
440 luaL_addlstring(B, s, len);
441 lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1);
442}
443
444
445void luaL_pushresult (luaL_Buffer_53 *B) {
446 lua_pushlstring(B->L2, B->ptr, B->nelems);
447 if (B->ptr != B->b.buffer)
448 lua_replace(B->L2, -2); /* remove userdata buffer */
449}
450
451
452#endif /* Lua 5.1 */
453
454
455
456/* definitions for Lua 5.1 and Lua 5.2 */
457#if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502
458
459
460COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) {
461 index = lua_absindex(L, index);
462 lua_pushinteger(L, i);
463 lua_gettable(L, index);
464 return lua_type(L, -1);
465}
466
467
468COMPAT53_API int lua_isinteger (lua_State *L, int index) {
469 if (lua_type(L, index) == LUA_TNUMBER) {
470 lua_Number n = lua_tonumber(L, index);
471 lua_Integer i = lua_tointeger(L, index);
472 if (i == n)
473 return 1;
474 }
475 return 0;
476}
477
478
479static void compat53_reverse (lua_State *L, int a, int b) {
480 for (; a < b; ++a, --b) {
481 lua_pushvalue(L, a);
482 lua_pushvalue(L, b);
483 lua_replace(L, a);
484 lua_replace(L, b);
485 }
486}
487
488
489COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) {
490 int n_elems = 0;
491 idx = lua_absindex(L, idx);
492 n_elems = lua_gettop(L)-idx+1;
493 if (n < 0)
494 n += n_elems;
495 if ( n > 0 && n < n_elems) {
496 luaL_checkstack(L, 2, "not enough stack slots available");
497 n = n_elems - n;
498 compat53_reverse(L, idx, idx+n-1);
499 compat53_reverse(L, idx+n, idx+n_elems-1);
500 compat53_reverse(L, idx, idx+n_elems-1);
501 }
502}
503
504
505COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i) {
506 luaL_checkstack(L, 1, "not enough stack slots available");
507 index = lua_absindex(L, index);
508 lua_pushinteger(L, i);
509 lua_insert(L, -2);
510 lua_settable(L, index);
511}
512
513
514#if !defined(lua_str2number)
515# define lua_str2number(s, p) strtod((s), (p))
516#endif
517
518COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s) {
519 char* endptr;
520 lua_Number n = lua_str2number(s, &endptr);
521 if (endptr != s) {
522 while (*endptr != '\0' && isspace((unsigned char)*endptr))
523 ++endptr;
524 if (*endptr == '\0') {
525 lua_pushnumber(L, n);
526 return endptr - s + 1;
527 }
528 }
529 return 0;
530}
531
532
533COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
534 if (!luaL_callmeta(L, idx, "__tostring")) {
535 int t = lua_type(L, idx), tt = 0;
536 char const* name = NULL;
537 switch (t) {
538 case LUA_TNIL:
539 lua_pushliteral(L, "nil");
540 break;
541 case LUA_TSTRING:
542 case LUA_TNUMBER:
543 lua_pushvalue(L, idx);
544 break;
545 case LUA_TBOOLEAN:
546 if (lua_toboolean(L, idx))
547 lua_pushliteral(L, "true");
548 else
549 lua_pushliteral(L, "false");
550 break;
551 default:
552 tt = luaL_getmetafield(L, idx, "__name");
553 name = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : lua_typename(L, t);
554 lua_pushfstring(L, "%s: %p", name, lua_topointer(L, idx));
555 if (tt != LUA_TNIL)
556 lua_replace(L, -2);
557 break;
558 }
559 } else {
560 if (!lua_isstring(L, -1))
561 luaL_error(L, "'__tostring' must return a string");
562 }
563 return lua_tolstring(L, -1, len);
564}
565
566
567COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
568 lua_CFunction openf, int glb) {
569 luaL_checkstack(L, 3, "not enough stack slots available");
570 luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
571 if (lua_getfield(L, -1, modname) == LUA_TNIL) {
572 lua_pop(L, 1);
573 lua_pushcfunction(L, openf);
574 lua_pushstring(L, modname);
575 lua_call(L, 1, 1);
576 lua_pushvalue(L, -1);
577 lua_setfield(L, -3, modname);
578 }
579 if (glb) {
580 lua_pushvalue(L, -1);
581 lua_setglobal(L, modname);
582 }
583 lua_replace(L, -2);
584}
585
586
587#endif /* Lua 5.1 and 5.2 */
588
589
590#endif /* COMPAT53_C_ */
591
592
593/*********************************************************************
594* This file contains parts of Lua 5.2's and Lua 5.3's source code:
595*
596* Copyright (C) 1994-2014 Lua.org, PUC-Rio.
597*
598* Permission is hereby granted, free of charge, to any person obtaining
599* a copy of this software and associated documentation files (the
600* "Software"), to deal in the Software without restriction, including
601* without limitation the rights to use, copy, modify, merge, publish,
602* distribute, sublicense, and/or sell copies of the Software, and to
603* permit persons to whom the Software is furnished to do so, subject to
604* the following conditions:
605*
606* The above copyright notice and this permission notice shall be
607* included in all copies or substantial portions of the Software.
608*
609* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
610* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
611* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
612* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
613* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
614* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
615* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
616*********************************************************************/
617
diff --git a/vendor/compat53/c-api/compat-5.3.h b/vendor/compat53/c-api/compat-5.3.h
new file mode 100644
index 0000000..bee77a1
--- /dev/null
+++ b/vendor/compat53/c-api/compat-5.3.h
@@ -0,0 +1,388 @@
1#ifndef COMPAT53_H_
2#define COMPAT53_H_
3
4#include <stddef.h>
5#include <limits.h>
6#include <string.h>
7#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
8extern "C" {
9#endif
10#include <lua.h>
11#include <lauxlib.h>
12#if defined(__cplusplus) && !defined(COMPAT53_LUA_CPP)
13}
14#endif
15
16
17#if defined(COMPAT53_PREFIX)
18/* - change the symbol names of functions to avoid linker conflicts
19 * - compat-5.3.c needs to be compiled (and linked) separately
20 */
21# if !defined(COMPAT53_API)
22# define COMPAT53_API extern
23# endif
24# undef COMPAT53_INCLUDE_SOURCE
25#else /* COMPAT53_PREFIX */
26/* - make all functions static and include the source.
27 * - compat-5.3.c doesn't need to be compiled (and linked) separately
28 */
29# define COMPAT53_PREFIX compat53
30# undef COMPAT53_API
31# if defined(__GNUC__) || defined(__clang__)
32# define COMPAT53_API __attribute__((__unused__)) static
33# else
34# define COMPAT53_API static
35# endif
36# define COMPAT53_INCLUDE_SOURCE
37#endif /* COMPAT53_PREFIX */
38
39#define COMPAT53_CONCAT_HELPER(a, b) a##b
40#define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b)
41
42
43
44/* declarations for Lua 5.1 */
45#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
46
47/* XXX not implemented:
48 * lua_arith (new operators)
49 * lua_upvalueid
50 * lua_upvaluejoin
51 * lua_version
52 * lua_yieldk
53 * luaL_loadbufferx
54 * luaL_loadfilex
55 */
56
57#ifndef LUA_OK
58# define LUA_OK 0
59#endif
60#ifndef LUA_OPADD
61# define LUA_OPADD 0
62#endif
63#ifndef LUA_OPSUB
64# define LUA_OPSUB 1
65#endif
66#ifndef LUA_OPMUL
67# define LUA_OPMUL 2
68#endif
69#ifndef LUA_OPDIV
70# define LUA_OPDIV 3
71#endif
72#ifndef LUA_OPMOD
73# define LUA_OPMOD 4
74#endif
75#ifndef LUA_OPPOW
76# define LUA_OPPOW 5
77#endif
78#ifndef LUA_OPUNM
79# define LUA_OPUNM 6
80#endif
81#ifndef LUA_OPEQ
82# define LUA_OPEQ 0
83#endif
84#ifndef LUA_OPLT
85# define LUA_OPLT 1
86#endif
87#ifndef LUA_OPLE
88# define LUA_OPLE 2
89#endif
90
91typedef size_t lua_Unsigned;
92
93typedef struct luaL_Buffer_53 {
94 luaL_Buffer b; /* make incorrect code crash! */
95 char *ptr;
96 size_t nelems;
97 size_t capacity;
98 lua_State *L2;
99} luaL_Buffer_53;
100#define luaL_Buffer luaL_Buffer_53
101
102#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
103COMPAT53_API int lua_absindex (lua_State *L, int i);
104
105#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith)
106COMPAT53_API void lua_arith (lua_State *L, int op);
107
108#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare)
109COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op);
110
111#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy)
112COMPAT53_API void lua_copy (lua_State *L, int from, int to);
113
114#define lua_getuservalue(L, i) \
115 (lua_getfenv((L), (i)), lua_type((L), -1))
116#define lua_setuservalue(L, i) \
117 (luaL_checktype((L), -1, LUA_TTABLE), lua_setfenv((L), (i)))
118
119#define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len)
120COMPAT53_API void lua_len (lua_State *L, int i);
121
122#define lua_pushstring(L, s) \
123 (lua_pushstring((L), (s)), lua_tostring((L), -1))
124
125#define lua_pushlstring(L, s, len) \
126 ((((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len))), lua_tostring((L), -1))
127
128#ifndef luaL_newlibtable
129# define luaL_newlibtable(L, l) \
130 (lua_createtable((L), 0, sizeof((l))/sizeof(*(l))-1))
131#endif
132#ifndef luaL_newlib
133# define luaL_newlib(L, l) \
134 (luaL_newlibtable((L), (l)), luaL_register((L), NULL, (l)))
135#endif
136
137#define lua_pushglobaltable(L) \
138 lua_pushvalue((L), LUA_GLOBALSINDEX)
139
140#define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp)
141COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p);
142
143#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp)
144COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p);
145
146#define lua_rawlen(L, i) lua_objlen((L), (i))
147
148#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx)
149COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum);
150
151#define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx)
152COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum);
153
154#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
155COMPAT53_API void luaL_checkversion (lua_State *L);
156
157#define luaL_checkstack COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkstack_53)
158COMPAT53_API void luaL_checkstack (lua_State *L, int sp, const char *msg);
159
160#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable)
161COMPAT53_API int luaL_getsubtable (lua_State* L, int i, const char *name);
162
163#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len)
164COMPAT53_API lua_Integer luaL_len (lua_State *L, int i);
165
166#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs)
167COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
168
169#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable)
170COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname);
171
172#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata)
173COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname);
174
175#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback)
176COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level);
177
178#define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult)
179COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname);
180
181#define luaL_execresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_execresult)
182COMPAT53_API int luaL_execresult (lua_State *L, int stat);
183
184#define lua_callk(L, na, nr, ctx, cont) \
185 ((void)(ctx), (void)(cont), lua_call((L), (na), (nr)))
186#define lua_pcallk(L, na, nr, err, ctx, cont) \
187 ((void)(ctx), (void)(cont), lua_pcall((L), (na), (nr), (err)))
188
189#define luaL_buffinit COMPAT53_CONCAT(COMPAT53_PREFIX, _buffinit_53)
190COMPAT53_API void luaL_buffinit (lua_State *L, luaL_Buffer_53 *B);
191
192#define luaL_prepbuffsize COMPAT53_CONCAT(COMPAT53_PREFIX, _prepbufsize_53)
193COMPAT53_API char *luaL_prepbuffsize (luaL_Buffer_53 *B, size_t s);
194
195#define luaL_addlstring COMPAT53_CONCAT(COMPAT53_PREFIX, _addlstring_53)
196COMPAT53_API void luaL_addlstring (luaL_Buffer_53 *B, const char *s, size_t l);
197
198#define luaL_addvalue COMPAT53_CONCAT(COMPAT53_PREFIX, _addvalue_53)
199COMPAT53_API void luaL_addvalue (luaL_Buffer_53 *B);
200
201#define luaL_pushresult COMPAT53_CONCAT(COMPAT53_PREFIX, _pushresult_53)
202COMPAT53_API void luaL_pushresult (luaL_Buffer_53 *B);
203
204#undef luaL_buffinitsize
205#define luaL_buffinitsize(L, B, s) \
206 (luaL_buffinit((L), (B)), luaL_prepbuffsize((B), (s)))
207
208#undef luaL_prepbuffer
209#define luaL_prepbuffer(B) \
210 luaL_prepbuffsize((B), LUAL_BUFFERSIZE)
211
212#undef luaL_addchar
213#define luaL_addchar(B, c) \
214 ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize((B), 1)), \
215 ((B)->ptr[(B)->nelems++] = (c)))
216
217#undef luaL_addsize
218#define luaL_addsize(B, s) \
219 ((B)->nelems += (s))
220
221#undef luaL_addstring
222#define luaL_addstring(B, s) \
223 luaL_addlstring((B), (s), strlen((s)))
224
225#undef luaL_pushresultsize
226#define luaL_pushresultsize(B, s) \
227 (luaL_addsize((B), (s)), luaL_pushresult((B)))
228
229#if defined(LUA_COMPAT_APIINTCASTS)
230#define lua_pushunsigned(L, n) \
231 lua_pushinteger((L), (lua_Integer)(n))
232#define lua_tounsignedx(L, i, is) \
233 ((lua_Unsigned)lua_tointegerx((L), (i), (is)))
234#define lua_tounsigned(L, i) \
235 lua_tounsignedx((L), (i), NULL)
236#define luaL_checkunsigned(L, a) \
237 ((lua_Unsigned)luaL_checkinteger((L), (a)))
238#define luaL_optunsigned(L, a, d) \
239 ((lua_Unsigned)luaL_optinteger((L), (a), (lua_Integer)(d)))
240#endif
241
242#endif /* Lua 5.1 only */
243
244
245
246/* declarations for Lua 5.1 and 5.2 */
247#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
248
249typedef int lua_KContext;
250
251typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx);
252
253#define lua_dump(L, w, d, s) \
254 ((void)(s), lua_dump((L), (w), (d)))
255
256#define lua_getfield(L, i, k) \
257 (lua_getfield((L), (i), (k)), lua_type((L), -1))
258
259#define lua_gettable(L, i) \
260 (lua_gettable((L), (i)), lua_type((L), -1))
261
262#define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti)
263COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i);
264
265#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger)
266COMPAT53_API int lua_isinteger (lua_State *L, int index);
267
268#define lua_numbertointeger(n, p) \
269 ((*(p) = (lua_Integer)(n)), 1)
270
271#define lua_rawget(L, i) \
272 (lua_rawget((L), (i)), lua_type((L), -1))
273
274#define lua_rawgeti(L, i, n) \
275 (lua_rawgeti((L), (i), (n)), lua_type((L), -1))
276
277#define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate)
278COMPAT53_API void lua_rotate (lua_State *L, int idx, int n);
279
280#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti)
281COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i);
282
283#define lua_stringtonumber COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber)
284COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s);
285
286#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring)
287COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len);
288
289#define luaL_getmetafield(L, o, e) \
290 (luaL_getmetafield((L), (o), (e)) ? lua_type((L), -1) : LUA_TNIL)
291
292#define luaL_newmetatable(L, tn) \
293 (luaL_newmetatable((L), (tn)) ? (lua_pushstring((L), (tn)), lua_setfield((L), -2, "__name"), 1) : 0)
294
295#define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_53)
296COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
297 lua_CFunction openf, int glb );
298
299#endif /* Lua 5.1 and Lua 5.2 */
300
301
302
303/* declarations for Lua 5.2 */
304#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502
305
306/* XXX not implemented:
307 * lua_isyieldable
308 * lua_getextraspace
309 * lua_arith (new operators)
310 * lua_pushfstring (new formats)
311 */
312
313#define lua_getglobal(L, n) \
314 (lua_getglobal((L), (n)), lua_type((L), -1))
315
316#define lua_getuservalue(L, i) \
317 (lua_getuservalue((L), (i)), lua_type((L), -1))
318
319#define lua_pushlstring(L, s, len) \
320 (((len) == 0) ? lua_pushlstring((L), "", 0) : lua_pushlstring((L), (s), (len)))
321
322#define lua_rawgetp(L, i, p) \
323 (lua_rawgetp((L), (i), (p)), lua_type((L), -1))
324
325#define LUA_KFUNCTION(_name) \
326 static int (_name)(lua_State *L, int status, lua_KContext ctx); \
327 static int (_name ## _52)(lua_State *L) { \
328 lua_KContext ctx; \
329 int status = lua_getctx(L, &ctx); \
330 return (_name)(L, status, ctx); \
331 } \
332 static int (_name)(lua_State *L, int status, lua_KContext ctx)
333
334#define lua_pcallk(L, na, nr, err, ctx, cont) \
335 lua_pcallk((L), (na), (nr), (err), (ctx), cont ## _52)
336
337#define lua_callk(L, na, nr, ctx, cont) \
338 lua_callk((L), (na), (nr), (ctx), cont ## _52)
339
340#define lua_yieldk(L, nr, ctx, cont) \
341 lua_yieldk((L), (nr), (ctx), cont ## _52)
342
343#ifdef lua_call
344# undef lua_call
345# define lua_call(L, na, nr) \
346 (lua_callk)((L), (na), (nr), 0, NULL)
347#endif
348
349#ifdef lua_pcall
350# undef lua_pcall
351# define lua_pcall(L, na, nr, err) \
352 (lua_pcallk)((L), (na), (nr), (err), 0, NULL)
353#endif
354
355#ifdef lua_yield
356# undef lua_yield
357# define lua_yield(L, nr) \
358 (lua_yieldk)((L), (nr), 0, NULL)
359#endif
360
361#endif /* Lua 5.2 only */
362
363
364
365/* other Lua versions */
366#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 503
367
368# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, or 5.3)"
369
370#endif /* other Lua versions except 5.1, 5.2, and 5.3 */
371
372
373
374/* helper macro for defining continuation functions (for every version
375 * *except* Lua 5.2) */
376#ifndef LUA_KFUNCTION
377#define LUA_KFUNCTION(_name) \
378 static int (_name)(lua_State *L, int status, lua_KContext ctx)
379#endif
380
381
382#if defined(COMPAT53_INCLUDE_SOURCE)
383# include "compat-5.3.c"
384#endif
385
386
387#endif /* COMPAT53_H_ */
388
diff --git a/vendor/compat53/compat53/init.lua b/vendor/compat53/compat53/init.lua
new file mode 100644
index 0000000..a7f0c80
--- /dev/null
+++ b/vendor/compat53/compat53/init.lua
@@ -0,0 +1,373 @@
1local lua_version = _VERSION:sub(-3)
2
3
4if 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
371end -- lua < 5.3
372
373-- vi: set expandtab softtabstop=3 shiftwidth=3 :
diff --git a/vendor/compat53/compat53/module.lua b/vendor/compat53/compat53/module.lua
new file mode 100644
index 0000000..30be6b5
--- /dev/null
+++ b/vendor/compat53/compat53/module.lua
@@ -0,0 +1,827 @@
1local _G, _VERSION = _G, _VERSION
2local lua_version = _VERSION:sub(-3)
3
4
5local M = _G
6
7if 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
821end -- lua < 5.3
822
823
824-- return module table
825return M
826
827-- vi: set expandtab softtabstop=3 shiftwidth=3 :
diff --git a/vendor/compat53/lprefix.h b/vendor/compat53/lprefix.h
new file mode 100644
index 0000000..0eb149f
--- /dev/null
+++ b/vendor/compat53/lprefix.h
@@ -0,0 +1,175 @@
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 */
57static 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 <locale.h>
91#include <lualib.h>
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
145static int str_pack (lua_State *L);
146static int str_packsize (lua_State *L);
147static int str_unpack (lua_State *L);
148LUAMOD_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
diff --git a/vendor/compat53/lstrlib.c b/vendor/compat53/lstrlib.c
new file mode 100644
index 0000000..c7aa755
--- /dev/null
+++ b/vendor/compat53/lstrlib.c
@@ -0,0 +1,1584 @@
1/*
2** $Id: lstrlib.c,v 1.254 2016/12/22 13:08:50 roberto Exp $
3** Standard library for string operations and pattern-matching
4** See Copyright Notice in lua.h
5*/
6
7#define lstrlib_c
8#define LUA_LIB
9
10#include "lprefix.h"
11
12
13#include <ctype.h>
14#include <float.h>
15#include <limits.h>
16#include <locale.h>
17#include <stddef.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include "lua.h"
23
24#include "lauxlib.h"
25#include "lualib.h"
26
27
28/*
29** maximum number of captures that a pattern can do during
30** pattern-matching. This limit is arbitrary, but must fit in
31** an unsigned char.
32*/
33#if !defined(LUA_MAXCAPTURES)
34#define LUA_MAXCAPTURES 32
35#endif
36
37
38/* macro to 'unsign' a character */
39#define uchar(c) ((unsigned char)(c))
40
41
42/*
43** Some sizes are better limited to fit in 'int', but must also fit in
44** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.)
45*/
46#define MAX_SIZET ((size_t)(~(size_t)0))
47
48#define MAXSIZE \
49 (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX))
50
51
52
53
54static int str_len (lua_State *L) {
55 size_t l;
56 luaL_checklstring(L, 1, &l);
57 lua_pushinteger(L, (lua_Integer)l);
58 return 1;
59}
60
61
62/* translate a relative string position: negative means back from end */
63static lua_Integer posrelat (lua_Integer pos, size_t len) {
64 if (pos >= 0) return pos;
65 else if (0u - (size_t)pos > len) return 0;
66 else return (lua_Integer)len + pos + 1;
67}
68
69
70static int str_sub (lua_State *L) {
71 size_t l;
72 const char *s = luaL_checklstring(L, 1, &l);
73 lua_Integer start = posrelat(luaL_checkinteger(L, 2), l);
74 lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l);
75 if (start < 1) start = 1;
76 if (end > (lua_Integer)l) end = l;
77 if (start <= end)
78 lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1);
79 else lua_pushliteral(L, "");
80 return 1;
81}
82
83
84static int str_reverse (lua_State *L) {
85 size_t l, i;
86 luaL_Buffer b;
87 const char *s = luaL_checklstring(L, 1, &l);
88 char *p = luaL_buffinitsize(L, &b, l);
89 for (i = 0; i < l; i++)
90 p[i] = s[l - i - 1];
91 luaL_pushresultsize(&b, l);
92 return 1;
93}
94
95
96static int str_lower (lua_State *L) {
97 size_t l;
98 size_t i;
99 luaL_Buffer b;
100 const char *s = luaL_checklstring(L, 1, &l);
101 char *p = luaL_buffinitsize(L, &b, l);
102 for (i=0; i<l; i++)
103 p[i] = tolower(uchar(s[i]));
104 luaL_pushresultsize(&b, l);
105 return 1;
106}
107
108
109static int str_upper (lua_State *L) {
110 size_t l;
111 size_t i;
112 luaL_Buffer b;
113 const char *s = luaL_checklstring(L, 1, &l);
114 char *p = luaL_buffinitsize(L, &b, l);
115 for (i=0; i<l; i++)
116 p[i] = toupper(uchar(s[i]));
117 luaL_pushresultsize(&b, l);
118 return 1;
119}
120
121
122static int str_rep (lua_State *L) {
123 size_t l, lsep;
124 const char *s = luaL_checklstring(L, 1, &l);
125 lua_Integer n = luaL_checkinteger(L, 2);
126 const char *sep = luaL_optlstring(L, 3, "", &lsep);
127 if (n <= 0) lua_pushliteral(L, "");
128 else if (l + lsep < l || l + lsep > MAXSIZE / n) /* may overflow? */
129 return luaL_error(L, "resulting string too large");
130 else {
131 size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep;
132 luaL_Buffer b;
133 char *p = luaL_buffinitsize(L, &b, totallen);
134 while (n-- > 1) { /* first n-1 copies (followed by separator) */
135 memcpy(p, s, l * sizeof(char)); p += l;
136 if (lsep > 0) { /* empty 'memcpy' is not that cheap */
137 memcpy(p, sep, lsep * sizeof(char));
138 p += lsep;
139 }
140 }
141 memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */
142 luaL_pushresultsize(&b, totallen);
143 }
144 return 1;
145}
146
147
148static int str_byte (lua_State *L) {
149 size_t l;
150 const char *s = luaL_checklstring(L, 1, &l);
151 lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l);
152 lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l);
153 int n, i;
154 if (posi < 1) posi = 1;
155 if (pose > (lua_Integer)l) pose = l;
156 if (posi > pose) return 0; /* empty interval; return no values */
157 if (pose - posi >= INT_MAX) /* arithmetic overflow? */
158 return luaL_error(L, "string slice too long");
159 n = (int)(pose - posi) + 1;
160 luaL_checkstack(L, n, "string slice too long");
161 for (i=0; i<n; i++)
162 lua_pushinteger(L, uchar(s[posi+i-1]));
163 return n;
164}
165
166
167static int str_char (lua_State *L) {
168 int n = lua_gettop(L); /* number of arguments */
169 int i;
170 luaL_Buffer b;
171 char *p = luaL_buffinitsize(L, &b, n);
172 for (i=1; i<=n; i++) {
173 lua_Integer c = luaL_checkinteger(L, i);
174 luaL_argcheck(L, uchar(c) == c, i, "value out of range");
175 p[i - 1] = uchar(c);
176 }
177 luaL_pushresultsize(&b, n);
178 return 1;
179}
180
181
182static int writer (lua_State *L, const void *b, size_t size, void *B) {
183 (void)L;
184 luaL_addlstring((luaL_Buffer *) B, (const char *)b, size);
185 return 0;
186}
187
188
189static int str_dump (lua_State *L) {
190 luaL_Buffer b;
191 int strip = lua_toboolean(L, 2);
192 luaL_checktype(L, 1, LUA_TFUNCTION);
193 lua_settop(L, 1);
194 luaL_buffinit(L,&b);
195 if (lua_dump(L, writer, &b, strip) != 0)
196 return luaL_error(L, "unable to dump given function");
197 luaL_pushresult(&b);
198 return 1;
199}
200
201
202
203/*
204** {======================================================
205** PATTERN MATCHING
206** =======================================================
207*/
208
209
210#define CAP_UNFINISHED (-1)
211#define CAP_POSITION (-2)
212
213
214typedef struct MatchState {
215 const char *src_init; /* init of source string */
216 const char *src_end; /* end ('\0') of source string */
217 const char *p_end; /* end ('\0') of pattern */
218 lua_State *L;
219 int matchdepth; /* control for recursive depth (to avoid C stack overflow) */
220 unsigned char level; /* total number of captures (finished or unfinished) */
221 struct {
222 const char *init;
223 ptrdiff_t len;
224 } capture[LUA_MAXCAPTURES];
225} MatchState;
226
227
228/* recursive function */
229static const char *match (MatchState *ms, const char *s, const char *p);
230
231
232/* maximum recursion depth for 'match' */
233#if !defined(MAXCCALLS)
234#define MAXCCALLS 200
235#endif
236
237
238#define L_ESC '%'
239#define SPECIALS "^$*+?.([%-"
240
241
242static int check_capture (MatchState *ms, int l) {
243 l -= '1';
244 if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
245 return luaL_error(ms->L, "invalid capture index %%%d", l + 1);
246 return l;
247}
248
249
250static int capture_to_close (MatchState *ms) {
251 int level = ms->level;
252 for (level--; level>=0; level--)
253 if (ms->capture[level].len == CAP_UNFINISHED) return level;
254 return luaL_error(ms->L, "invalid pattern capture");
255}
256
257
258static const char *classend (MatchState *ms, const char *p) {
259 switch (*p++) {
260 case L_ESC: {
261 if (p == ms->p_end)
262 luaL_error(ms->L, "malformed pattern (ends with '%%')");
263 return p+1;
264 }
265 case '[': {
266 if (*p == '^') p++;
267 do { /* look for a ']' */
268 if (p == ms->p_end)
269 luaL_error(ms->L, "malformed pattern (missing ']')");
270 if (*(p++) == L_ESC && p < ms->p_end)
271 p++; /* skip escapes (e.g. '%]') */
272 } while (*p != ']');
273 return p+1;
274 }
275 default: {
276 return p;
277 }
278 }
279}
280
281
282static int match_class (int c, int cl) {
283 int res;
284 switch (tolower(cl)) {
285 case 'a' : res = isalpha(c); break;
286 case 'c' : res = iscntrl(c); break;
287 case 'd' : res = isdigit(c); break;
288 case 'g' : res = isgraph(c); break;
289 case 'l' : res = islower(c); break;
290 case 'p' : res = ispunct(c); break;
291 case 's' : res = isspace(c); break;
292 case 'u' : res = isupper(c); break;
293 case 'w' : res = isalnum(c); break;
294 case 'x' : res = isxdigit(c); break;
295 case 'z' : res = (c == 0); break; /* deprecated option */
296 default: return (cl == c);
297 }
298 return (islower(cl) ? res : !res);
299}
300
301
302static int matchbracketclass (int c, const char *p, const char *ec) {
303 int sig = 1;
304 if (*(p+1) == '^') {
305 sig = 0;
306 p++; /* skip the '^' */
307 }
308 while (++p < ec) {
309 if (*p == L_ESC) {
310 p++;
311 if (match_class(c, uchar(*p)))
312 return sig;
313 }
314 else if ((*(p+1) == '-') && (p+2 < ec)) {
315 p+=2;
316 if (uchar(*(p-2)) <= c && c <= uchar(*p))
317 return sig;
318 }
319 else if (uchar(*p) == c) return sig;
320 }
321 return !sig;
322}
323
324
325static int singlematch (MatchState *ms, const char *s, const char *p,
326 const char *ep) {
327 if (s >= ms->src_end)
328 return 0;
329 else {
330 int c = uchar(*s);
331 switch (*p) {
332 case '.': return 1; /* matches any char */
333 case L_ESC: return match_class(c, uchar(*(p+1)));
334 case '[': return matchbracketclass(c, p, ep-1);
335 default: return (uchar(*p) == c);
336 }
337 }
338}
339
340
341static const char *matchbalance (MatchState *ms, const char *s,
342 const char *p) {
343 if (p >= ms->p_end - 1)
344 luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')");
345 if (*s != *p) return NULL;
346 else {
347 int b = *p;
348 int e = *(p+1);
349 int cont = 1;
350 while (++s < ms->src_end) {
351 if (*s == e) {
352 if (--cont == 0) return s+1;
353 }
354 else if (*s == b) cont++;
355 }
356 }
357 return NULL; /* string ends out of balance */
358}
359
360
361static const char *max_expand (MatchState *ms, const char *s,
362 const char *p, const char *ep) {
363 ptrdiff_t i = 0; /* counts maximum expand for item */
364 while (singlematch(ms, s + i, p, ep))
365 i++;
366 /* keeps trying to match with the maximum repetitions */
367 while (i>=0) {
368 const char *res = match(ms, (s+i), ep+1);
369 if (res) return res;
370 i--; /* else didn't match; reduce 1 repetition to try again */
371 }
372 return NULL;
373}
374
375
376static const char *min_expand (MatchState *ms, const char *s,
377 const char *p, const char *ep) {
378 for (;;) {
379 const char *res = match(ms, s, ep+1);
380 if (res != NULL)
381 return res;
382 else if (singlematch(ms, s, p, ep))
383 s++; /* try with one more repetition */
384 else return NULL;
385 }
386}
387
388
389static const char *start_capture (MatchState *ms, const char *s,
390 const char *p, int what) {
391 const char *res;
392 int level = ms->level;
393 if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
394 ms->capture[level].init = s;
395 ms->capture[level].len = what;
396 ms->level = level+1;
397 if ((res=match(ms, s, p)) == NULL) /* match failed? */
398 ms->level--; /* undo capture */
399 return res;
400}
401
402
403static const char *end_capture (MatchState *ms, const char *s,
404 const char *p) {
405 int l = capture_to_close(ms);
406 const char *res;
407 ms->capture[l].len = s - ms->capture[l].init; /* close capture */
408 if ((res = match(ms, s, p)) == NULL) /* match failed? */
409 ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
410 return res;
411}
412
413
414static const char *match_capture (MatchState *ms, const char *s, int l) {
415 size_t len;
416 l = check_capture(ms, l);
417 len = ms->capture[l].len;
418 if ((size_t)(ms->src_end-s) >= len &&
419 memcmp(ms->capture[l].init, s, len) == 0)
420 return s+len;
421 else return NULL;
422}
423
424
425static const char *match (MatchState *ms, const char *s, const char *p) {
426 if (ms->matchdepth-- == 0)
427 luaL_error(ms->L, "pattern too complex");
428 init: /* using goto's to optimize tail recursion */
429 if (p != ms->p_end) { /* end of pattern? */
430 switch (*p) {
431 case '(': { /* start capture */
432 if (*(p + 1) == ')') /* position capture? */
433 s = start_capture(ms, s, p + 2, CAP_POSITION);
434 else
435 s = start_capture(ms, s, p + 1, CAP_UNFINISHED);
436 break;
437 }
438 case ')': { /* end capture */
439 s = end_capture(ms, s, p + 1);
440 break;
441 }
442 case '$': {
443 if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */
444 goto dflt; /* no; go to default */
445 s = (s == ms->src_end) ? s : NULL; /* check end of string */
446 break;
447 }
448 case L_ESC: { /* escaped sequences not in the format class[*+?-]? */
449 switch (*(p + 1)) {
450 case 'b': { /* balanced string? */
451 s = matchbalance(ms, s, p + 2);
452 if (s != NULL) {
453 p += 4; goto init; /* return match(ms, s, p + 4); */
454 } /* else fail (s == NULL) */
455 break;
456 }
457 case 'f': { /* frontier? */
458 const char *ep; char previous;
459 p += 2;
460 if (*p != '[')
461 luaL_error(ms->L, "missing '[' after '%%f' in pattern");
462 ep = classend(ms, p); /* points to what is next */
463 previous = (s == ms->src_init) ? '\0' : *(s - 1);
464 if (!matchbracketclass(uchar(previous), p, ep - 1) &&
465 matchbracketclass(uchar(*s), p, ep - 1)) {
466 p = ep; goto init; /* return match(ms, s, ep); */
467 }
468 s = NULL; /* match failed */
469 break;
470 }
471 case '0': case '1': case '2': case '3':
472 case '4': case '5': case '6': case '7':
473 case '8': case '9': { /* capture results (%0-%9)? */
474 s = match_capture(ms, s, uchar(*(p + 1)));
475 if (s != NULL) {
476 p += 2; goto init; /* return match(ms, s, p + 2) */
477 }
478 break;
479 }
480 default: goto dflt;
481 }
482 break;
483 }
484 default: dflt: { /* pattern class plus optional suffix */
485 const char *ep = classend(ms, p); /* points to optional suffix */
486 /* does not match at least once? */
487 if (!singlematch(ms, s, p, ep)) {
488 if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */
489 p = ep + 1; goto init; /* return match(ms, s, ep + 1); */
490 }
491 else /* '+' or no suffix */
492 s = NULL; /* fail */
493 }
494 else { /* matched once */
495 switch (*ep) { /* handle optional suffix */
496 case '?': { /* optional */
497 const char *res;
498 if ((res = match(ms, s + 1, ep + 1)) != NULL)
499 s = res;
500 else {
501 p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */
502 }
503 break;
504 }
505 case '+': /* 1 or more repetitions */
506 s++; /* 1 match already done */
507 /* FALLTHROUGH */
508 case '*': /* 0 or more repetitions */
509 s = max_expand(ms, s, p, ep);
510 break;
511 case '-': /* 0 or more repetitions (minimum) */
512 s = min_expand(ms, s, p, ep);
513 break;
514 default: /* no suffix */
515 s++; p = ep; goto init; /* return match(ms, s + 1, ep); */
516 }
517 }
518 break;
519 }
520 }
521 }
522 ms->matchdepth++;
523 return s;
524}
525
526
527
528static const char *lmemfind (const char *s1, size_t l1,
529 const char *s2, size_t l2) {
530 if (l2 == 0) return s1; /* empty strings are everywhere */
531 else if (l2 > l1) return NULL; /* avoids a negative 'l1' */
532 else {
533 const char *init; /* to search for a '*s2' inside 's1' */
534 l2--; /* 1st char will be checked by 'memchr' */
535 l1 = l1-l2; /* 's2' cannot be found after that */
536 while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
537 init++; /* 1st char is already checked */
538 if (memcmp(init, s2+1, l2) == 0)
539 return init-1;
540 else { /* correct 'l1' and 's1' to try again */
541 l1 -= init-s1;
542 s1 = init;
543 }
544 }
545 return NULL; /* not found */
546 }
547}
548
549
550static void push_onecapture (MatchState *ms, int i, const char *s,
551 const char *e) {
552 if (i >= ms->level) {
553 if (i == 0) /* ms->level == 0, too */
554 lua_pushlstring(ms->L, s, e - s); /* add whole match */
555 else
556 luaL_error(ms->L, "invalid capture index %%%d", i + 1);
557 }
558 else {
559 ptrdiff_t l = ms->capture[i].len;
560 if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
561 if (l == CAP_POSITION)
562 lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1);
563 else
564 lua_pushlstring(ms->L, ms->capture[i].init, l);
565 }
566}
567
568
569static int push_captures (MatchState *ms, const char *s, const char *e) {
570 int i;
571 int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
572 luaL_checkstack(ms->L, nlevels, "too many captures");
573 for (i = 0; i < nlevels; i++)
574 push_onecapture(ms, i, s, e);
575 return nlevels; /* number of strings pushed */
576}
577
578
579/* check whether pattern has no special characters */
580static int nospecials (const char *p, size_t l) {
581 size_t upto = 0;
582 do {
583 if (strpbrk(p + upto, SPECIALS))
584 return 0; /* pattern has a special character */
585 upto += strlen(p + upto) + 1; /* may have more after \0 */
586 } while (upto <= l);
587 return 1; /* no special chars found */
588}
589
590
591static void prepstate (MatchState *ms, lua_State *L,
592 const char *s, size_t ls, const char *p, size_t lp) {
593 ms->L = L;
594 ms->matchdepth = MAXCCALLS;
595 ms->src_init = s;
596 ms->src_end = s + ls;
597 ms->p_end = p + lp;
598}
599
600
601static void reprepstate (MatchState *ms) {
602 ms->level = 0;
603 lua_assert(ms->matchdepth == MAXCCALLS);
604}
605
606
607static int str_find_aux (lua_State *L, int find) {
608 size_t ls, lp;
609 const char *s = luaL_checklstring(L, 1, &ls);
610 const char *p = luaL_checklstring(L, 2, &lp);
611 lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls);
612 if (init < 1) init = 1;
613 else if (init > (lua_Integer)ls + 1) { /* start after string's end? */
614 lua_pushnil(L); /* cannot find anything */
615 return 1;
616 }
617 /* explicit request or no special characters? */
618 if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) {
619 /* do a plain search */
620 const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp);
621 if (s2) {
622 lua_pushinteger(L, (s2 - s) + 1);
623 lua_pushinteger(L, (s2 - s) + lp);
624 return 2;
625 }
626 }
627 else {
628 MatchState ms;
629 const char *s1 = s + init - 1;
630 int anchor = (*p == '^');
631 if (anchor) {
632 p++; lp--; /* skip anchor character */
633 }
634 prepstate(&ms, L, s, ls, p, lp);
635 do {
636 const char *res;
637 reprepstate(&ms);
638 if ((res=match(&ms, s1, p)) != NULL) {
639 if (find) {
640 lua_pushinteger(L, (s1 - s) + 1); /* start */
641 lua_pushinteger(L, res - s); /* end */
642 return push_captures(&ms, NULL, 0) + 2;
643 }
644 else
645 return push_captures(&ms, s1, res);
646 }
647 } while (s1++ < ms.src_end && !anchor);
648 }
649 lua_pushnil(L); /* not found */
650 return 1;
651}
652
653
654static int str_find (lua_State *L) {
655 return str_find_aux(L, 1);
656}
657
658
659static int str_match (lua_State *L) {
660 return str_find_aux(L, 0);
661}
662
663
664/* state for 'gmatch' */
665typedef struct GMatchState {
666 const char *src; /* current position */
667 const char *p; /* pattern */
668 const char *lastmatch; /* end of last match */
669 MatchState ms; /* match state */
670} GMatchState;
671
672
673static int gmatch_aux (lua_State *L) {
674 GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
675 const char *src;
676 gm->ms.L = L;
677 for (src = gm->src; src <= gm->ms.src_end; src++) {
678 const char *e;
679 reprepstate(&gm->ms);
680 if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) {
681 gm->src = gm->lastmatch = e;
682 return push_captures(&gm->ms, src, e);
683 }
684 }
685 return 0; /* not found */
686}
687
688
689static int gmatch (lua_State *L) {
690 size_t ls, lp;
691 const char *s = luaL_checklstring(L, 1, &ls);
692 const char *p = luaL_checklstring(L, 2, &lp);
693 GMatchState *gm;
694 lua_settop(L, 2); /* keep them on closure to avoid being collected */
695 gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
696 prepstate(&gm->ms, L, s, ls, p, lp);
697 gm->src = s; gm->p = p; gm->lastmatch = NULL;
698 lua_pushcclosure(L, gmatch_aux, 3);
699 return 1;
700}
701
702
703static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
704 const char *e) {
705 size_t l, i;
706 lua_State *L = ms->L;
707 const char *news = lua_tolstring(L, 3, &l);
708 for (i = 0; i < l; i++) {
709 if (news[i] != L_ESC)
710 luaL_addchar(b, news[i]);
711 else {
712 i++; /* skip ESC */
713 if (!isdigit(uchar(news[i]))) {
714 if (news[i] != L_ESC)
715 luaL_error(L, "invalid use of '%c' in replacement string", L_ESC);
716 luaL_addchar(b, news[i]);
717 }
718 else if (news[i] == '0')
719 luaL_addlstring(b, s, e - s);
720 else {
721 push_onecapture(ms, news[i] - '1', s, e);
722 luaL_tolstring(L, -1, NULL); /* if number, convert it to string */
723 lua_remove(L, -2); /* remove original value */
724 luaL_addvalue(b); /* add capture to accumulated result */
725 }
726 }
727 }
728}
729
730
731static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
732 const char *e, int tr) {
733 lua_State *L = ms->L;
734 switch (tr) {
735 case LUA_TFUNCTION: {
736 int n;
737 lua_pushvalue(L, 3);
738 n = push_captures(ms, s, e);
739 lua_call(L, n, 1);
740 break;
741 }
742 case LUA_TTABLE: {
743 push_onecapture(ms, 0, s, e);
744 lua_gettable(L, 3);
745 break;
746 }
747 default: { /* LUA_TNUMBER or LUA_TSTRING */
748 add_s(ms, b, s, e);
749 return;
750 }
751 }
752 if (!lua_toboolean(L, -1)) { /* nil or false? */
753 lua_pop(L, 1);
754 lua_pushlstring(L, s, e - s); /* keep original text */
755 }
756 else if (!lua_isstring(L, -1))
757 luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
758 luaL_addvalue(b); /* add result to accumulator */
759}
760
761
762static int str_gsub (lua_State *L) {
763 size_t srcl, lp;
764 const char *src = luaL_checklstring(L, 1, &srcl); /* subject */
765 const char *p = luaL_checklstring(L, 2, &lp); /* pattern */
766 const char *lastmatch = NULL; /* end of last match */
767 int tr = lua_type(L, 3); /* replacement type */
768 lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */
769 int anchor = (*p == '^');
770 lua_Integer n = 0; /* replacement count */
771 MatchState ms;
772 luaL_Buffer b;
773 luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
774 tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
775 "string/function/table expected");
776 luaL_buffinit(L, &b);
777 if (anchor) {
778 p++; lp--; /* skip anchor character */
779 }
780 prepstate(&ms, L, src, srcl, p, lp);
781 while (n < max_s) {
782 const char *e;
783 reprepstate(&ms); /* (re)prepare state for new match */
784 if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */
785 n++;
786 add_value(&ms, &b, src, e, tr); /* add replacement to buffer */
787 src = lastmatch = e;
788 }
789 else if (src < ms.src_end) /* otherwise, skip one character */
790 luaL_addchar(&b, *src++);
791 else break; /* end of subject */
792 if (anchor) break;
793 }
794 luaL_addlstring(&b, src, ms.src_end-src);
795 luaL_pushresult(&b);
796 lua_pushinteger(L, n); /* number of substitutions */
797 return 2;
798}
799
800/* }====================================================== */
801
802
803
804/*
805** {======================================================
806** STRING FORMAT
807** =======================================================
808*/
809
810#if !defined(lua_number2strx) /* { */
811
812/*
813** Hexadecimal floating-point formatter
814*/
815
816#include <math.h>
817
818#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char))
819
820
821/*
822** Number of bits that goes into the first digit. It can be any value
823** between 1 and 4; the following definition tries to align the number
824** to nibble boundaries by making what is left after that first digit a
825** multiple of 4.
826*/
827#define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1)
828
829
830/*
831** Add integer part of 'x' to buffer and return new 'x'
832*/
833static lua_Number adddigit (char *buff, int n, lua_Number x) {
834 lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */
835 int d = (int)dd;
836 buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */
837 return x - dd; /* return what is left */
838}
839
840
841static int num2straux (char *buff, int sz, lua_Number x) {
842 /* if 'inf' or 'NaN', format it like '%g' */
843 if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL)
844 return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x);
845 else if (x == 0) { /* can be -0... */
846 /* create "0" or "-0" followed by exponent */
847 return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x);
848 }
849 else {
850 int e;
851 lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */
852 int n = 0; /* character count */
853 if (m < 0) { /* is number negative? */
854 buff[n++] = '-'; /* add signal */
855 m = -m; /* make it positive */
856 }
857 buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */
858 m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */
859 e -= L_NBFD; /* this digit goes before the radix point */
860 if (m > 0) { /* more digits? */
861 buff[n++] = lua_getlocaledecpoint(); /* add radix point */
862 do { /* add as many digits as needed */
863 m = adddigit(buff, n++, m * 16);
864 } while (m > 0);
865 }
866 n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */
867 lua_assert(n < sz);
868 return n;
869 }
870}
871
872
873static int lua_number2strx (lua_State *L, char *buff, int sz,
874 const char *fmt, lua_Number x) {
875 int n = num2straux(buff, sz, x);
876 if (fmt[SIZELENMOD] == 'A') {
877 int i;
878 for (i = 0; i < n; i++)
879 buff[i] = toupper(uchar(buff[i]));
880 }
881 else if (fmt[SIZELENMOD] != 'a')
882 luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented");
883 return n;
884}
885
886#endif /* } */
887
888
889/*
890** Maximum size of each formatted item. This maximum size is produced
891** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.',
892** and '\0') + number of decimal digits to represent maxfloat (which
893** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra
894** expenses", such as locale-dependent stuff)
895*/
896#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP))
897
898
899/* valid flags in a format specification */
900#define FLAGS "-+ #0"
901
902/*
903** maximum size of each format specification (such as "%-099.99d")
904*/
905#define MAX_FORMAT 32
906
907
908static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
909 luaL_addchar(b, '"');
910 while (len--) {
911 if (*s == '"' || *s == '\\' || *s == '\n') {
912 luaL_addchar(b, '\\');
913 luaL_addchar(b, *s);
914 }
915 else if (iscntrl(uchar(*s))) {
916 char buff[10];
917 if (!isdigit(uchar(*(s+1))))
918 l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s));
919 else
920 l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s));
921 luaL_addstring(b, buff);
922 }
923 else
924 luaL_addchar(b, *s);
925 s++;
926 }
927 luaL_addchar(b, '"');
928}
929
930
931/*
932** Ensures the 'buff' string uses a dot as the radix character.
933*/
934static void checkdp (char *buff, int nb) {
935 if (memchr(buff, '.', nb) == NULL) { /* no dot? */
936 char point = lua_getlocaledecpoint(); /* try locale point */
937 char *ppoint = (char *)memchr(buff, point, nb);
938 if (ppoint) *ppoint = '.'; /* change it to a dot */
939 }
940}
941
942
943static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
944 switch (lua_type(L, arg)) {
945 case LUA_TSTRING: {
946 size_t len;
947 const char *s = lua_tolstring(L, arg, &len);
948 addquoted(b, s, len);
949 break;
950 }
951 case LUA_TNUMBER: {
952 char *buff = luaL_prepbuffsize(b, MAX_ITEM);
953 int nb;
954 if (!lua_isinteger(L, arg)) { /* float? */
955 lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */
956 nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n);
957 checkdp(buff, nb); /* ensure it uses a dot */
958 }
959 else { /* integers */
960 lua_Integer n = lua_tointeger(L, arg);
961 const char *format = (n == LUA_MININTEGER) /* corner case? */
962 ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */
963 : LUA_INTEGER_FMT; /* else use default format */
964 nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n);
965 }
966 luaL_addsize(b, nb);
967 break;
968 }
969 case LUA_TNIL: case LUA_TBOOLEAN: {
970 luaL_tolstring(L, arg, NULL);
971 luaL_addvalue(b);
972 break;
973 }
974 default: {
975 luaL_argerror(L, arg, "value has no literal form");
976 }
977 }
978}
979
980
981static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
982 const char *p = strfrmt;
983 while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
984 if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char))
985 luaL_error(L, "invalid format (repeated flags)");
986 if (isdigit(uchar(*p))) p++; /* skip width */
987 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
988 if (*p == '.') {
989 p++;
990 if (isdigit(uchar(*p))) p++; /* skip precision */
991 if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
992 }
993 if (isdigit(uchar(*p)))
994 luaL_error(L, "invalid format (width or precision too long)");
995 *(form++) = '%';
996 memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char));
997 form += (p - strfrmt) + 1;
998 *form = '\0';
999 return p;
1000}
1001
1002
1003/*
1004** add length modifier into formats
1005*/
1006static void addlenmod (char *form, const char *lenmod) {
1007 size_t l = strlen(form);
1008 size_t lm = strlen(lenmod);
1009 char spec = form[l - 1];
1010 strcpy(form + l - 1, lenmod);
1011 form[l + lm - 1] = spec;
1012 form[l + lm] = '\0';
1013}
1014
1015
1016static int str_format (lua_State *L) {
1017 int top = lua_gettop(L);
1018 int arg = 1;
1019 size_t sfl;
1020 const char *strfrmt = luaL_checklstring(L, arg, &sfl);
1021 const char *strfrmt_end = strfrmt+sfl;
1022 luaL_Buffer b;
1023 luaL_buffinit(L, &b);
1024 while (strfrmt < strfrmt_end) {
1025 if (*strfrmt != L_ESC)
1026 luaL_addchar(&b, *strfrmt++);
1027 else if (*++strfrmt == L_ESC)
1028 luaL_addchar(&b, *strfrmt++); /* %% */
1029 else { /* format item */
1030 char form[MAX_FORMAT]; /* to store the format ('%...') */
1031 char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */
1032 int nb = 0; /* number of bytes in added item */
1033 if (++arg > top)
1034 luaL_argerror(L, arg, "no value");
1035 strfrmt = scanformat(L, strfrmt, form);
1036 switch (*strfrmt++) {
1037 case 'c': {
1038 nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg));
1039 break;
1040 }
1041 case 'd': case 'i':
1042 case 'o': case 'u': case 'x': case 'X': {
1043 lua_Integer n = luaL_checkinteger(L, arg);
1044 addlenmod(form, LUA_INTEGER_FRMLEN);
1045 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n);
1046 break;
1047 }
1048 case 'a': case 'A':
1049 addlenmod(form, LUA_NUMBER_FRMLEN);
1050 nb = lua_number2strx(L, buff, MAX_ITEM, form,
1051 luaL_checknumber(L, arg));
1052 break;
1053 case 'e': case 'E': case 'f':
1054 case 'g': case 'G': {
1055 lua_Number n = luaL_checknumber(L, arg);
1056 addlenmod(form, LUA_NUMBER_FRMLEN);
1057 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n);
1058 break;
1059 }
1060 case 'q': {
1061 addliteral(L, &b, arg);
1062 break;
1063 }
1064 case 's': {
1065 size_t l;
1066 const char *s = luaL_tolstring(L, arg, &l);
1067 if (form[2] == '\0') /* no modifiers? */
1068 luaL_addvalue(&b); /* keep entire string */
1069 else {
1070 luaL_argcheck(L, l == strlen(s), arg, "string contains zeros");
1071 if (!strchr(form, '.') && l >= 100) {
1072 /* no precision and string is too long to be formatted */
1073 luaL_addvalue(&b); /* keep entire string */
1074 }
1075 else { /* format the string into 'buff' */
1076 nb = l_sprintf(buff, MAX_ITEM, form, s);
1077 lua_pop(L, 1); /* remove result from 'luaL_tolstring' */
1078 }
1079 }
1080 break;
1081 }
1082 default: { /* also treat cases 'pnLlh' */
1083 return luaL_error(L, "invalid option '%%%c' to 'format'",
1084 *(strfrmt - 1));
1085 }
1086 }
1087 lua_assert(nb < MAX_ITEM);
1088 luaL_addsize(&b, nb);
1089 }
1090 }
1091 luaL_pushresult(&b);
1092 return 1;
1093}
1094
1095/* }====================================================== */
1096
1097
1098/*
1099** {======================================================
1100** PACK/UNPACK
1101** =======================================================
1102*/
1103
1104
1105/* value used for padding */
1106#if !defined(LUAL_PACKPADBYTE)
1107#define LUAL_PACKPADBYTE 0x00
1108#endif
1109
1110/* maximum size for the binary representation of an integer */
1111#define MAXINTSIZE 16
1112
1113/* number of bits in a character */
1114#define NB CHAR_BIT
1115
1116/* mask for one character (NB 1's) */
1117#define MC ((1 << NB) - 1)
1118
1119/* size of a lua_Integer */
1120#define SZINT ((int)sizeof(lua_Integer))
1121
1122
1123/* dummy union to get native endianness */
1124static const union {
1125 int dummy;
1126 char little; /* true iff machine is little endian */
1127} nativeendian = {1};
1128
1129
1130/* dummy structure to get native alignment requirements */
1131struct cD {
1132 char c;
1133 union { double d; void *p; lua_Integer i; lua_Number n; } u;
1134};
1135
1136#define MAXALIGN (offsetof(struct cD, u))
1137
1138
1139/*
1140** Union for serializing floats
1141*/
1142typedef union Ftypes {
1143 float f;
1144 double d;
1145 lua_Number n;
1146 char buff[5 * sizeof(lua_Number)]; /* enough for any float type */
1147} Ftypes;
1148
1149
1150/*
1151** information to pack/unpack stuff
1152*/
1153typedef struct Header {
1154 lua_State *L;
1155 int islittle;
1156 int maxalign;
1157} Header;
1158
1159
1160/*
1161** options for pack/unpack
1162*/
1163typedef enum KOption {
1164 Kint, /* signed integers */
1165 Kuint, /* unsigned integers */
1166 Kfloat, /* floating-point numbers */
1167 Kchar, /* fixed-length strings */
1168 Kstring, /* strings with prefixed length */
1169 Kzstr, /* zero-terminated strings */
1170 Kpadding, /* padding */
1171 Kpaddalign, /* padding for alignment */
1172 Knop /* no-op (configuration or spaces) */
1173} KOption;
1174
1175
1176/*
1177** Read an integer numeral from string 'fmt' or return 'df' if
1178** there is no numeral
1179*/
1180static int digit (int c) { return '0' <= c && c <= '9'; }
1181
1182static int getnum (const char **fmt, int df) {
1183 if (!digit(**fmt)) /* no number? */
1184 return df; /* return default value */
1185 else {
1186 int a = 0;
1187 do {
1188 a = a*10 + (*((*fmt)++) - '0');
1189 } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10);
1190 return a;
1191 }
1192}
1193
1194
1195/*
1196** Read an integer numeral and raises an error if it is larger
1197** than the maximum size for integers.
1198*/
1199static int getnumlimit (Header *h, const char **fmt, int df) {
1200 int sz = getnum(fmt, df);
1201 if (sz > MAXINTSIZE || sz <= 0)
1202 luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
1203 sz, MAXINTSIZE);
1204 return sz;
1205}
1206
1207
1208/*
1209** Initialize Header
1210*/
1211static void initheader (lua_State *L, Header *h) {
1212 h->L = L;
1213 h->islittle = nativeendian.little;
1214 h->maxalign = 1;
1215}
1216
1217
1218/*
1219** Read and classify next option. 'size' is filled with option's size.
1220*/
1221static KOption getoption (Header *h, const char **fmt, int *size) {
1222 int opt = *((*fmt)++);
1223 *size = 0; /* default */
1224 switch (opt) {
1225 case 'b': *size = sizeof(char); return Kint;
1226 case 'B': *size = sizeof(char); return Kuint;
1227 case 'h': *size = sizeof(short); return Kint;
1228 case 'H': *size = sizeof(short); return Kuint;
1229 case 'l': *size = sizeof(long); return Kint;
1230 case 'L': *size = sizeof(long); return Kuint;
1231 case 'j': *size = sizeof(lua_Integer); return Kint;
1232 case 'J': *size = sizeof(lua_Integer); return Kuint;
1233 case 'T': *size = sizeof(size_t); return Kuint;
1234 case 'f': *size = sizeof(float); return Kfloat;
1235 case 'd': *size = sizeof(double); return Kfloat;
1236 case 'n': *size = sizeof(lua_Number); return Kfloat;
1237 case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint;
1238 case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint;
1239 case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring;
1240 case 'c':
1241 *size = getnum(fmt, -1);
1242 if (*size == -1)
1243 luaL_error(h->L, "missing size for format option 'c'");
1244 return Kchar;
1245 case 'z': return Kzstr;
1246 case 'x': *size = 1; return Kpadding;
1247 case 'X': return Kpaddalign;
1248 case ' ': break;
1249 case '<': h->islittle = 1; break;
1250 case '>': h->islittle = 0; break;
1251 case '=': h->islittle = nativeendian.little; break;
1252 case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break;
1253 default: luaL_error(h->L, "invalid format option '%c'", opt);
1254 }
1255 return Knop;
1256}
1257
1258
1259/*
1260** Read, classify, and fill other details about the next option.
1261** 'psize' is filled with option's size, 'notoalign' with its
1262** alignment requirements.
1263** Local variable 'size' gets the size to be aligned. (Kpadal option
1264** always gets its full alignment, other options are limited by
1265** the maximum alignment ('maxalign'). Kchar option needs no alignment
1266** despite its size.
1267*/
1268static KOption getdetails (Header *h, size_t totalsize,
1269 const char **fmt, int *psize, int *ntoalign) {
1270 KOption opt = getoption(h, fmt, psize);
1271 int align = *psize; /* usually, alignment follows size */
1272 if (opt == Kpaddalign) { /* 'X' gets alignment from following option */
1273 if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0)
1274 luaL_argerror(h->L, 1, "invalid next option for option 'X'");
1275 }
1276 if (align <= 1 || opt == Kchar) /* need no alignment? */
1277 *ntoalign = 0;
1278 else {
1279 if (align > h->maxalign) /* enforce maximum alignment */
1280 align = h->maxalign;
1281 if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */
1282 luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
1283 *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
1284 }
1285 return opt;
1286}
1287
1288
1289/*
1290** Pack integer 'n' with 'size' bytes and 'islittle' endianness.
1291** The final 'if' handles the case when 'size' is larger than
1292** the size of a Lua integer, correcting the extra sign-extension
1293** bytes if necessary (by default they would be zeros).
1294*/
1295static void packint (luaL_Buffer *b, lua_Unsigned n,
1296 int islittle, int size, int neg) {
1297 char *buff = luaL_prepbuffsize(b, size);
1298 int i;
1299 buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */
1300 for (i = 1; i < size; i++) {
1301 n >>= NB;
1302 buff[islittle ? i : size - 1 - i] = (char)(n & MC);
1303 }
1304 if (neg && size > SZINT) { /* negative number need sign extension? */
1305 for (i = SZINT; i < size; i++) /* correct extra bytes */
1306 buff[islittle ? i : size - 1 - i] = (char)MC;
1307 }
1308 luaL_addsize(b, size); /* add result to buffer */
1309}
1310
1311
1312/*
1313** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
1314** given 'islittle' is different from native endianness.
1315*/
1316static void copywithendian (volatile char *dest, volatile const char *src,
1317 int size, int islittle) {
1318 if (islittle == nativeendian.little) {
1319 while (size-- != 0)
1320 *(dest++) = *(src++);
1321 }
1322 else {
1323 dest += size - 1;
1324 while (size-- != 0)
1325 *(dest--) = *(src++);
1326 }
1327}
1328
1329
1330static int str_pack (lua_State *L) {
1331 luaL_Buffer b;
1332 Header h;
1333 const char *fmt = luaL_checkstring(L, 1); /* format string */
1334 int arg = 1; /* current argument to pack */
1335 size_t totalsize = 0; /* accumulate total size of result */
1336 initheader(L, &h);
1337 lua_pushnil(L); /* mark to separate arguments from string buffer */
1338 luaL_buffinit(L, &b);
1339 while (*fmt != '\0') {
1340 int size, ntoalign;
1341 KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1342 totalsize += ntoalign + size;
1343 while (ntoalign-- > 0)
1344 luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */
1345 arg++;
1346 switch (opt) {
1347 case Kint: { /* signed integers */
1348 lua_Integer n = luaL_checkinteger(L, arg);
1349 if (size < SZINT) { /* need overflow check? */
1350 lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1);
1351 luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
1352 }
1353 packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0));
1354 break;
1355 }
1356 case Kuint: { /* unsigned integers */
1357 lua_Integer n = luaL_checkinteger(L, arg);
1358 if (size < SZINT) /* need overflow check? */
1359 luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)),
1360 arg, "unsigned overflow");
1361 packint(&b, (lua_Unsigned)n, h.islittle, size, 0);
1362 break;
1363 }
1364 case Kfloat: { /* floating-point options */
1365 volatile Ftypes u;
1366 char *buff = luaL_prepbuffsize(&b, size);
1367 lua_Number n = luaL_checknumber(L, arg); /* get argument */
1368 if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */
1369 else if (size == sizeof(u.d)) u.d = (double)n;
1370 else u.n = n;
1371 /* move 'u' to final result, correcting endianness if needed */
1372 copywithendian(buff, u.buff, size, h.islittle);
1373 luaL_addsize(&b, size);
1374 break;
1375 }
1376 case Kchar: { /* fixed-size string */
1377 size_t len;
1378 const char *s = luaL_checklstring(L, arg, &len);
1379 luaL_argcheck(L, len <= (size_t)size, arg,
1380 "string longer than given size");
1381 luaL_addlstring(&b, s, len); /* add string */
1382 while (len++ < (size_t)size) /* pad extra space */
1383 luaL_addchar(&b, LUAL_PACKPADBYTE);
1384 break;
1385 }
1386 case Kstring: { /* strings with length count */
1387 size_t len;
1388 const char *s = luaL_checklstring(L, arg, &len);
1389 luaL_argcheck(L, size >= (int)sizeof(size_t) ||
1390 len < ((size_t)1 << (size * NB)),
1391 arg, "string length does not fit in given size");
1392 packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */
1393 luaL_addlstring(&b, s, len);
1394 totalsize += len;
1395 break;
1396 }
1397 case Kzstr: { /* zero-terminated string */
1398 size_t len;
1399 const char *s = luaL_checklstring(L, arg, &len);
1400 luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
1401 luaL_addlstring(&b, s, len);
1402 luaL_addchar(&b, '\0'); /* add zero at the end */
1403 totalsize += len + 1;
1404 break;
1405 }
1406 case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */
1407 case Kpaddalign: case Knop:
1408 arg--; /* undo increment */
1409 break;
1410 }
1411 }
1412 luaL_pushresult(&b);
1413 return 1;
1414}
1415
1416
1417static int str_packsize (lua_State *L) {
1418 Header h;
1419 const char *fmt = luaL_checkstring(L, 1); /* format string */
1420 size_t totalsize = 0; /* accumulate total size of result */
1421 initheader(L, &h);
1422 while (*fmt != '\0') {
1423 int size, ntoalign;
1424 KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
1425 size += ntoalign; /* total space used by option */
1426 luaL_argcheck(L, totalsize <= MAXSIZE - size, 1,
1427 "format result too large");
1428 totalsize += size;
1429 switch (opt) {
1430 case Kstring: /* strings with length count */
1431 case Kzstr: /* zero-terminated string */
1432 luaL_argerror(L, 1, "variable-length format");
1433 /* call never return, but to avoid warnings: *//* FALLTHROUGH */
1434 default: break;
1435 }
1436 }
1437 lua_pushinteger(L, (lua_Integer)totalsize);
1438 return 1;
1439}
1440
1441
1442/*
1443** Unpack an integer with 'size' bytes and 'islittle' endianness.
1444** If size is smaller than the size of a Lua integer and integer
1445** is signed, must do sign extension (propagating the sign to the
1446** higher bits); if size is larger than the size of a Lua integer,
1447** it must check the unread bytes to see whether they do not cause an
1448** overflow.
1449*/
1450static lua_Integer unpackint (lua_State *L, const char *str,
1451 int islittle, int size, int issigned) {
1452 lua_Unsigned res = 0;
1453 int i;
1454 int limit = (size <= SZINT) ? size : SZINT;
1455 for (i = limit - 1; i >= 0; i--) {
1456 res <<= NB;
1457 res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i];
1458 }
1459 if (size < SZINT) { /* real size smaller than lua_Integer? */
1460 if (issigned) { /* needs sign extension? */
1461 lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
1462 res = ((res ^ mask) - mask); /* do sign extension */
1463 }
1464 }
1465 else if (size > SZINT) { /* must check unread bytes */
1466 int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC;
1467 for (i = limit; i < size; i++) {
1468 if ((unsigned char)str[islittle ? i : size - 1 - i] != mask)
1469 luaL_error(L, "%d-byte integer does not fit into Lua Integer", size);
1470 }
1471 }
1472 return (lua_Integer)res;
1473}
1474
1475
1476static int str_unpack (lua_State *L) {
1477 Header h;
1478 const char *fmt = luaL_checkstring(L, 1);
1479 size_t ld;
1480 const char *data = luaL_checklstring(L, 2, &ld);
1481 size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1;
1482 int n = 0; /* number of results */
1483 luaL_argcheck(L, pos <= ld, 3, "initial position out of string");
1484 initheader(L, &h);
1485 while (*fmt != '\0') {
1486 int size, ntoalign;
1487 KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
1488 if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld)
1489 luaL_argerror(L, 2, "data string too short");
1490 pos += ntoalign; /* skip alignment */
1491 /* stack space for item + next position */
1492 luaL_checkstack(L, 2, "too many results");
1493 n++;
1494 switch (opt) {
1495 case Kint:
1496 case Kuint: {
1497 lua_Integer res = unpackint(L, data + pos, h.islittle, size,
1498 (opt == Kint));
1499 lua_pushinteger(L, res);
1500 break;
1501 }
1502 case Kfloat: {
1503 volatile Ftypes u;
1504 lua_Number num;
1505 copywithendian(u.buff, data + pos, size, h.islittle);
1506 if (size == sizeof(u.f)) num = (lua_Number)u.f;
1507 else if (size == sizeof(u.d)) num = (lua_Number)u.d;
1508 else num = u.n;
1509 lua_pushnumber(L, num);
1510 break;
1511 }
1512 case Kchar: {
1513 lua_pushlstring(L, data + pos, size);
1514 break;
1515 }
1516 case Kstring: {
1517 size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
1518 luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short");
1519 lua_pushlstring(L, data + pos + size, len);
1520 pos += len; /* skip string */
1521 break;
1522 }
1523 case Kzstr: {
1524 size_t len = (int)strlen(data + pos);
1525 lua_pushlstring(L, data + pos, len);
1526 pos += len + 1; /* skip string plus final '\0' */
1527 break;
1528 }
1529 case Kpaddalign: case Kpadding: case Knop:
1530 n--; /* undo increment */
1531 break;
1532 }
1533 pos += size;
1534 }
1535 lua_pushinteger(L, pos + 1); /* next position */
1536 return n + 1;
1537}
1538
1539/* }====================================================== */
1540
1541
1542static const luaL_Reg strlib[] = {
1543 {"byte", str_byte},
1544 {"char", str_char},
1545 {"dump", str_dump},
1546 {"find", str_find},
1547 {"format", str_format},
1548 {"gmatch", gmatch},
1549 {"gsub", str_gsub},
1550 {"len", str_len},
1551 {"lower", str_lower},
1552 {"match", str_match},
1553 {"rep", str_rep},
1554 {"reverse", str_reverse},
1555 {"sub", str_sub},
1556 {"upper", str_upper},
1557 {"pack", str_pack},
1558 {"packsize", str_packsize},
1559 {"unpack", str_unpack},
1560 {NULL, NULL}
1561};
1562
1563
1564static void createmetatable (lua_State *L) {
1565 lua_createtable(L, 0, 1); /* table to be metatable for strings */
1566 lua_pushliteral(L, ""); /* dummy string */
1567 lua_pushvalue(L, -2); /* copy table */
1568 lua_setmetatable(L, -2); /* set table as metatable for strings */
1569 lua_pop(L, 1); /* pop dummy string */
1570 lua_pushvalue(L, -2); /* get string library */
1571 lua_setfield(L, -2, "__index"); /* metatable.__index = string */
1572 lua_pop(L, 1); /* pop metatable */
1573}
1574
1575
1576/*
1577** Open string library
1578*/
1579LUAMOD_API int luaopen_string (lua_State *L) {
1580 luaL_newlib(L, strlib);
1581 createmetatable(L);
1582 return 1;
1583}
1584
diff --git a/vendor/compat53/ltablib.c b/vendor/compat53/ltablib.c
new file mode 100644
index 0000000..98b2f87
--- /dev/null
+++ b/vendor/compat53/ltablib.c
@@ -0,0 +1,450 @@
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 <limits.h>
14#include <stddef.h>
15#include <string.h>
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
36static 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*/
46static 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)
62static 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
79static 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
106static 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*/
128static 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
160static 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
169static 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
194static 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
207static 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 */
236typedef 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 <time.h>
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*/
258static 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
277static 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*/
287static 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*/
310static 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*/
346static 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*/
357static 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
411static 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
426static 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
441LUAMOD_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
diff --git a/vendor/compat53/lutf8lib.c b/vendor/compat53/lutf8lib.c
new file mode 100644
index 0000000..de9e3dc
--- /dev/null
+++ b/vendor/compat53/lutf8lib.c
@@ -0,0 +1,256 @@
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 <assert.h>
14#include <limits.h>
15#include <stdlib.h>
16#include <string.h>
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 */
30static 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*/
40static 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*/
71static 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*/
100static 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
128static 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*/
138static 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*/
160static 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
201static 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
225static 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
238static 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
250LUAMOD_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
diff --git a/vendor/compat53/rockspecs/compat53-0.1-1.rockspec b/vendor/compat53/rockspecs/compat53-0.1-1.rockspec
new file mode 100644
index 0000000..0ff56b0
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.1-1.rockspec
@@ -0,0 +1,31 @@
1package = "compat53"
2version = "0.1-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.1.zip",
5 dir = "lua-compat-5.3-0.1",
6}
7description = {
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}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
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
diff --git a/vendor/compat53/rockspecs/compat53-0.2-1.rockspec b/vendor/compat53/rockspecs/compat53-0.2-1.rockspec
new file mode 100644
index 0000000..1b3c80e
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.2-1.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "0.2-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.2.zip",
5 dir = "lua-compat-5.3-0.2",
6}
7description = {
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}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
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
diff --git a/vendor/compat53/rockspecs/compat53-0.3-1.rockspec b/vendor/compat53/rockspecs/compat53-0.3-1.rockspec
new file mode 100644
index 0000000..43f53d2
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.3-1.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "0.3-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.3.zip",
5 dir = "lua-compat-5.3-0.3",
6}
7description = {
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}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
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
diff --git a/vendor/compat53/rockspecs/compat53-0.4-1.rockspec b/vendor/compat53/rockspecs/compat53-0.4-1.rockspec
new file mode 100644
index 0000000..9331e19
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.4-1.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "0.4-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.4.zip",
5 dir = "lua-compat-5.3-0.4",
6}
7description = {
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}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
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
diff --git a/vendor/compat53/rockspecs/compat53-0.5-1.rockspec b/vendor/compat53/rockspecs/compat53-0.5-1.rockspec
new file mode 100644
index 0000000..3cceccd
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-0.5-1.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "0.5-1"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/v0.5.zip",
5 dir = "lua-compat-5.3-0.5",
6}
7description = {
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}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
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
diff --git a/vendor/compat53/rockspecs/compat53-scm-0.rockspec b/vendor/compat53/rockspecs/compat53-scm-0.rockspec
new file mode 100644
index 0000000..317e18c
--- /dev/null
+++ b/vendor/compat53/rockspecs/compat53-scm-0.rockspec
@@ -0,0 +1,32 @@
1package = "compat53"
2version = "scm-0"
3source = {
4 url = "https://github.com/keplerproject/lua-compat-5.3/archive/master.zip",
5 dir = "lua-compat-5.3-master",
6}
7description = {
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}
18dependencies = {
19 "lua >= 5.1, < 5.4",
20 --"struct" -- make Roberto's struct module optional
21}
22build = {
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
diff --git a/vendor/compat53/tests/test.lua b/vendor/compat53/tests/test.lua
new file mode 100755
index 0000000..582f55e
--- /dev/null
+++ b/vendor/compat53/tests/test.lua
@@ -0,0 +1,789 @@
1#!/usr/bin/env lua
2
3local F, tproxy, writefile, noprint, ___
4do
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
34end
35
36local V = _VERSION:gsub("^.*(%d+)%.(%d+)$", "%1%2")
37if jit then V = "jit" end
38
39local mode = "global"
40if arg[1] == "module" then
41 mode = "module"
42end
43
44
45package.path = "../?.lua;../?/init.lua"
46package.cpath = "./?-"..V..".so;./?-"..V..".dll;./?.so;./?.dll"
47if mode == "module" then
48 print("testing Lua API using `compat53.module` ...")
49 _ENV = require("compat53.module")
50 if setfenv then setfenv(1, _ENV) end
51else
52 print("testing Lua API using `compat53` ...")
53 require("compat53")
54end
55
56
57___''
58do
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)))
64end
65
66
67___''
68do
69 local t = setmetatable({}, { __index = { 1, false, "three" } })
70 for i,v in ipairs(t) do
71 print("ipairs", i, v)
72 end
73end
74
75
76___''
77do
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))
85end
86
87
88___''
89do
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])
104end
105
106
107___''
108do
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])
139end
140
141
142___''
143do
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))
168end
169
170___''
171do
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
208end
209
210
211___''
212do
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))
220end
221
222
223___''
224print("math.maxinteger", math.maxinteger+1 > math.maxinteger)
225print("math.mininteger", math.mininteger-1 < math.mininteger)
226
227
228___''
229print("math.tointeger", math.tointeger(0))
230print("math.tointeger", math.tointeger(math.pi))
231print("math.tointeger", math.tointeger("hello"))
232print("math.tointeger", math.tointeger(math.maxinteger+2.0))
233print("math.tointeger", math.tointeger(math.mininteger*2.0))
234
235
236___''
237print("math.type", math.type(0))
238print("math.type", math.type(math.pi))
239print("math.type", math.type("hello"))
240
241
242___''
243print("math.ult", math.ult(1, 2), math.ult(2, 1))
244print("math.ult", math.ult(-1, 2), math.ult(2, -1))
245print("math.ult", math.ult(-1, -2), math.ult(-2, -1))
246print("math.ult", pcall(math.ult, "x", 2))
247print("math.ult", pcall(math.ult, 1, 2.1))
248___''
249
250
251if 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 ___''
279else
280 print("XXX: utf8 module not available")
281end
282
283
284if 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 ___''
289else
290 print("XXX: string packing not available")
291end
292
293
294print("testing Lua API for Lua 5.1 ...")
295
296___''
297print("debug.getuservalue()", F(debug.getuservalue(false)))
298print("debug.setuservalue()", pcall(function()
299 debug.setuservalue(false, {})
300end))
301print("debug.setmetatable()", F(debug.setmetatable({}, {})))
302
303
304___''
305do
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
312end
313
314
315___''
316do
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")
391end
392
393
394___''
395do
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
425end
426
427
428___''
429do
430 local t = setmetatable({ 1 }, { __len = function() return 5 end })
431 print("rawlen()", rawlen(t), rawlen("123"))
432end
433
434
435___''
436print("os.execute()", os.execute("exit 1"))
437io.flush()
438print("os.execute()", os.execute("echo 'hello world!'"))
439io.flush()
440print("os.execute()", os.execute("no_such_file"))
441
442
443___''
444do
445 local t = table.pack("a", nil, "b", nil)
446 print("table.(un)pack()", t.n, table.unpack(t, 1, t.n))
447end
448
449
450___''
451do
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)))
488end
489
490
491___''
492print("math.log()", math.log(1000))
493print("math.log()", math.log(1000, 10))
494
495
496___''
497do
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, ":", "|"))
503end
504
505
506___''
507if 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")
530end
531
532
533___''
534do
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
571end
572
573
574___''
575do
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()
580end
581
582
583___''
584do
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")
600end
601
602
603___''
604do
605 writefile("data.txt", "123 18.8 hello world\ni'm here\n")
606 for a,b in io.lines("test.lua", 2, "*l") do
607 print("io.lines()", a, b)
608 break
609 end
610 for l in io.lines("test.lua") 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("test.lua", "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")
653end
654___''
655
656
657print("testing C API ...")
658local mod = require("testmod")
659___''
660print(mod.isinteger(1))
661print(mod.isinteger(0))
662print(mod.isinteger(1234567))
663print(mod.isinteger(12.3))
664print(mod.isinteger(math.huge))
665print(mod.isinteger(math.sqrt(-1)))
666
667
668___''
669print(mod.rotate(1, 1, 2, 3, 4, 5, 6))
670print(mod.rotate(-1, 1, 2, 3, 4, 5, 6))
671print(mod.rotate(4, 1, 2, 3, 4, 5, 6))
672print(mod.rotate(-4, 1, 2, 3, 4, 5, 6))
673
674
675___''
676print(mod.strtonum("+123"))
677print(mod.strtonum(" 123 "))
678print(mod.strtonum("-1.23"))
679print(mod.strtonum(" 123 abc"))
680print(mod.strtonum("jkl"))
681
682
683___''
684local a, b, c = mod.requiref()
685print( type(a), type(b), type(c),
686 a.boolean, b.boolean, c.boolean,
687 type(requiref1), type(requiref2), type(requiref3))
688
689___''
690local proxy, backend = {}, {}
691setmetatable(proxy, { __index = backend, __newindex = backend })
692print(rawget(proxy, 1), rawget(backend, 1))
693print(mod.getseti(proxy, 1))
694print(rawget(proxy, 1), rawget(backend, 1))
695print(mod.getseti(proxy, 1))
696print(rawget(proxy, 1), rawget(backend, 1))
697
698-- tests for Lua 5.1
699___''
700print(mod.tonumber(12))
701print(mod.tonumber("12"))
702print(mod.tonumber("0"))
703print(mod.tonumber(false))
704print(mod.tonumber("error"))
705
706___''
707print(mod.tointeger(12))
708print(mod.tointeger("12"))
709print(mod.tointeger("0"))
710print( "aaa" )
711print(mod.tointeger(math.pi))
712print( "bbb" )
713print(mod.tointeger(false))
714print(mod.tointeger("error"))
715
716___''
717print(mod.len("123"))
718print(mod.len({ 1, 2, 3}))
719print(pcall(mod.len, true))
720local ud, meta = mod.newproxy()
721meta.__len = function() return 5 end
722print(mod.len(ud))
723meta.__len = function() return true end
724print(pcall(mod.len, ud))
725
726___''
727print(mod.copy(true, "string", {}, 1))
728
729___''
730print(mod.rawxetp())
731print(mod.rawxetp("I'm back"))
732
733___''
734print(F(mod.globals()), mod.globals() == _G)
735
736___''
737local t = {}
738print(F(mod.subtable(t)))
739local x, msg = mod.subtable(t)
740print(F(x, msg, x == t.xxx))
741
742___''
743print(F(mod.udata()))
744print(mod.udata("nosuchtype"))
745
746___''
747print(F(mod.uservalue()))
748
749___''
750print(mod.getupvalues())
751
752___''
753print(mod.absindex("hi", true))
754
755___''
756print(mod.arith(2, 1))
757print(mod.arith(3, 5))
758
759___''
760print(mod.compare(1, 1))
761print(mod.compare(2, 1))
762print(mod.compare(1, 2))
763
764___''
765print(mod.tolstring("string"))
766local t = setmetatable({}, {
767 __tostring = function(v) return "mytable" end
768})
769print(mod.tolstring(t))
770local t = setmetatable({}, {
771 __tostring = function(v) return nil end
772})
773print(pcall(mod.tolstring, t))
774local ud, meta = mod.newproxy()
775meta.__name = "XXX"
776print(mod.tolstring(ud):gsub(":.*$", ": yyy"))
777
778___''
779print(mod.pushstring())
780
781___''
782print(mod.buffer())
783
784___''
785print(mod.exec("exit 0"))
786print(mod.exec("exit 1"))
787print(mod.exec("exit 25"))
788___''
789
diff --git a/vendor/compat53/tests/testmod.c b/vendor/compat53/tests/testmod.c
new file mode 100644
index 0000000..868136b
--- /dev/null
+++ b/vendor/compat53/tests/testmod.c
@@ -0,0 +1,318 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <lua.h>
4#include <lauxlib.h>
5#include "compat-5.3.h"
6
7
8static int test_isinteger (lua_State *L) {
9 lua_pushboolean(L, lua_isinteger(L, 1));
10 return 1;
11}
12
13
14static int test_rotate (lua_State *L) {
15 int r = luaL_checkint(L, 1);
16 int n = lua_gettop(L)-1;
17 luaL_argcheck(L, (r < 0 ? -r : r) <= n, 1, "not enough arguments");
18 lua_rotate(L, 2, r);
19 return n;
20}
21
22
23static int test_str2num (lua_State *L) {
24 const char *s = luaL_checkstring(L, 1);
25 size_t len = lua_stringtonumber(L, s);
26 if (len == 0)
27 lua_pushnumber(L, 0);
28 lua_pushinteger(L, (lua_Integer)len);
29 return 2;
30}
31
32
33static int my_mod (lua_State *L ) {
34 lua_newtable(L);
35 lua_pushboolean(L, 1);
36 lua_setfield(L, -2, "boolean");
37 return 1;
38}
39
40static int test_requiref (lua_State *L) {
41 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
42 lua_newtable(L);
43 lua_pushboolean(L, 0);
44 lua_setfield(L, -2, "boolean");
45 lua_setfield(L, -2, "requiref3");
46 lua_pop(L, 1);
47 luaL_requiref(L, "requiref1", my_mod, 0);
48 luaL_requiref(L, "requiref2", my_mod, 1);
49 luaL_requiref(L, "requiref3", my_mod, 1);
50 return 3;
51}
52
53static int test_getseti (lua_State *L) {
54 lua_Integer k = luaL_checkinteger(L, 2);
55 lua_Integer n = 0;
56 if (lua_geti(L, 1, k) == LUA_TNUMBER) {
57 n = lua_tointeger(L, -1);
58 } else {
59 lua_pop(L, 1);
60 lua_pushinteger(L, n);
61 }
62 lua_pushinteger(L, n+1);
63 lua_seti(L, 1, k);
64 return 1;
65}
66
67
68/* additional tests for Lua5.1 */
69#define NUP 3
70
71static int test_newproxy (lua_State *L) {
72 lua_settop(L, 0);
73 lua_newuserdata(L, 0);
74 lua_newtable(L);
75 lua_pushvalue(L, -1);
76 lua_pushboolean(L, 1);
77 lua_setfield(L, -2, "__gc");
78 lua_setmetatable(L, -3);
79 return 2;
80}
81
82static int test_absindex (lua_State *L) {
83 int i = 1;
84 for (i = 1; i <= NUP; ++i)
85 lua_pushvalue(L, lua_absindex(L, lua_upvalueindex(i)));
86 lua_pushvalue(L, lua_absindex(L, LUA_REGISTRYINDEX));
87 lua_pushstring(L, lua_typename(L, lua_type(L, lua_absindex(L, -1))));
88 lua_replace(L, lua_absindex(L, -2));
89 lua_pushvalue(L, lua_absindex(L, -2));
90 lua_pushvalue(L, lua_absindex(L, -4));
91 lua_pushvalue(L, lua_absindex(L, -6));
92 i += 3;
93 lua_pushvalue(L, lua_absindex(L, 1));
94 lua_pushvalue(L, lua_absindex(L, 2));
95 lua_pushvalue(L, lua_absindex(L, 3));
96 i += 3;
97 return i;
98}
99
100static int test_arith (lua_State *L) {
101 lua_settop(L, 2);
102 lua_pushvalue(L, 1);
103 lua_pushvalue(L, 2);
104 lua_arith(L, LUA_OPADD);
105 lua_pushvalue(L, 1);
106 lua_pushvalue(L, 2);
107 lua_arith(L, LUA_OPSUB);
108 lua_pushvalue(L, 1);
109 lua_pushvalue(L, 2);
110 lua_arith(L, LUA_OPMUL);
111 lua_pushvalue(L, 1);
112 lua_pushvalue(L, 2);
113 lua_arith(L, LUA_OPDIV);
114 lua_pushvalue(L, 1);
115 lua_pushvalue(L, 2);
116 lua_arith(L, LUA_OPMOD);
117 lua_pushvalue(L, 1);
118 lua_pushvalue(L, 2);
119 lua_arith(L, LUA_OPPOW);
120 lua_pushvalue(L, 1);
121 lua_arith(L, LUA_OPUNM);
122 return lua_gettop(L)-2;
123}
124
125static int test_compare (lua_State *L) {
126 luaL_checknumber(L, 1);
127 luaL_checknumber(L, 2);
128 lua_settop(L, 2);
129 lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPEQ));
130 lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLT));
131 lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLE));
132 return 3;
133}
134
135static int test_globals (lua_State *L) {
136 lua_pushglobaltable(L);
137 return 1;
138}
139
140static int test_tonumber (lua_State *L) {
141 int isnum = 0;
142 lua_Number n = lua_tonumberx(L, 1, &isnum);
143 if (!isnum)
144 lua_pushnil(L);
145 else
146 lua_pushnumber(L, n);
147 return 1;
148}
149
150static int test_tointeger (lua_State *L) {
151 int isnum = 0;
152 lua_Integer n = lua_tointegerx(L, 1, &isnum);
153 if (!isnum)
154 lua_pushnil(L);
155 else
156 lua_pushinteger(L, n);
157 return 1;
158}
159
160static int test_len (lua_State *L) {
161 luaL_checkany(L, 1);
162 lua_len(L, 1);
163 lua_pushinteger(L, luaL_len(L, 1));
164 return 2;
165}
166
167static int test_copy (lua_State *L) {
168 int args = lua_gettop(L);
169 if (args >= 2) {
170 int i = 0;
171 for (i = args-1; i > 0; --i)
172 lua_copy(L, args, i);
173 }
174 return args;
175}
176
177/* need an address */
178static char const dummy = 0;
179
180static int test_rawxetp (lua_State *L) {
181 if (lua_gettop(L) > 0)
182 lua_pushvalue(L, 1);
183 else
184 lua_pushliteral(L, "hello again");
185 lua_rawsetp(L, LUA_REGISTRYINDEX, &dummy);
186 lua_settop(L, 0);
187 lua_rawgetp(L, LUA_REGISTRYINDEX, &dummy);
188 return 1;
189}
190
191static int test_udata (lua_State *L) {
192 const char *tname = luaL_optstring(L, 1, "utype1");
193 void *u1 = lua_newuserdata(L, 1);
194 int u1pos = lua_gettop(L);
195 void *u2 = lua_newuserdata(L, 1);
196 int u2pos = lua_gettop(L);
197 luaL_newmetatable(L, "utype1");
198 luaL_newmetatable(L, "utype2");
199 lua_pop(L, 2);
200 luaL_setmetatable(L, "utype2");
201 lua_pushvalue(L, u1pos);
202 luaL_setmetatable(L, "utype1");
203 lua_pop(L, 1);
204 (void)u1;
205 (void)u2;
206 lua_pushlightuserdata(L, luaL_testudata(L, u1pos, tname));
207 lua_pushlightuserdata(L, luaL_testudata(L, u2pos, tname));
208 luaL_getmetatable(L, "utype1");
209 lua_getfield(L, -1, "__name");
210 lua_replace(L, -2);
211 return 3;
212}
213
214static int test_subtable (lua_State *L) {
215 luaL_checktype(L, 1, LUA_TTABLE);
216 lua_settop(L, 1);
217 if (luaL_getsubtable(L, 1, "xxx")) {
218 lua_pushliteral(L, "oldtable");
219 } else {
220 lua_pushliteral(L, "newtable");
221 }
222 return 2;
223}
224
225static int test_uservalue (lua_State *L) {
226 void *udata = lua_newuserdata(L, 1);
227 int ui = lua_gettop(L);
228 lua_newtable(L);
229 lua_setuservalue(L, ui);
230 lua_getuservalue(L, ui);
231 (void)udata;
232 return 1;
233}
234
235static int test_upvalues (lua_State *L) {
236 int i = 1;
237 for (i = 1; i <= NUP; ++i)
238 lua_pushvalue(L, lua_upvalueindex(i));
239 return NUP;
240}
241
242static int test_tolstring (lua_State *L) {
243 size_t len = 0;
244 luaL_tolstring(L, 1, &len);
245 lua_pushinteger(L, (int)len);
246 return 2;
247}
248
249static int test_pushstring (lua_State *L) {
250 lua_pushstring(L, lua_pushliteral(L, "abc"));
251 lua_pushstring(L, lua_pushlstring(L, "abc", 2));
252 lua_pushstring(L, lua_pushlstring(L, NULL, 0));
253 lua_pushstring(L, lua_pushstring(L, "abc"));
254 lua_pushboolean(L, NULL == lua_pushstring(L, NULL));
255 return 10;
256}
257
258static int test_buffer (lua_State *L) {
259 luaL_Buffer b;
260 char *p = luaL_buffinitsize(L, &b, LUAL_BUFFERSIZE+1);
261 p[0] = 'a';
262 p[1] = 'b';
263 luaL_addsize(&b, 2);
264 luaL_addstring(&b, "c");
265 lua_pushliteral(L, "d");
266 luaL_addvalue(&b);
267 luaL_addchar(&b, 'e');
268 luaL_pushresult(&b);
269 return 1;
270}
271
272static int test_exec (lua_State *L) {
273 const char *cmd = luaL_checkstring(L, 1);
274 return luaL_execresult(L, system(cmd));
275}
276
277
278static const luaL_Reg funcs[] = {
279 { "isinteger", test_isinteger },
280 { "rotate", test_rotate },
281 { "strtonum", test_str2num },
282 { "requiref", test_requiref },
283 { "getseti", test_getseti },
284 { "newproxy", test_newproxy },
285 { "arith", test_arith },
286 { "compare", test_compare },
287 { "tonumber", test_tonumber },
288 { "tointeger", test_tointeger },
289 { "len", test_len },
290 { "copy", test_copy },
291 { "rawxetp", test_rawxetp },
292 { "subtable", test_subtable },
293 { "udata", test_udata },
294 { "uservalue", test_uservalue },
295 { "globals", test_globals },
296 { "tolstring", test_tolstring },
297 { "pushstring", test_pushstring },
298 { "buffer", test_buffer },
299 { "exec", test_exec },
300 { NULL, NULL }
301};
302
303static const luaL_Reg more_funcs[] = {
304 { "getupvalues", test_upvalues },
305 { "absindex", test_absindex },
306 { NULL, NULL }
307};
308
309
310int luaopen_testmod (lua_State *L) {
311 int i = 1;
312 luaL_newlib(L, funcs);
313 for (i = 1; i <= NUP; ++i)
314 lua_pushnumber(L, i);
315 luaL_setfuncs(L, more_funcs, NUP);
316 return 1;
317}
318