aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Janda <siffiejoe@gmx.net>2015-01-13 08:27:20 +0100
committerPhilipp Janda <siffiejoe@gmx.net>2015-01-13 08:27:20 +0100
commit901f1bfdbadc7afa5526ca854a12bdfe8fcb88b3 (patch)
tree698870c642950c4287c7ab57c2dcab28b3efb6a6
parent46bbf75fbea482c19c4eb50bf97ef948f611e26a (diff)
downloadlua-compat-5.3-901f1bfdbadc7afa5526ca854a12bdfe8fcb88b3.tar.gz
lua-compat-5.3-901f1bfdbadc7afa5526ca854a12bdfe8fcb88b3.tar.bz2
lua-compat-5.3-901f1bfdbadc7afa5526ca854a12bdfe8fcb88b3.zip
add initial implementation of c-api and license
-rw-r--r--LICENSE20
-rw-r--r--c-api/compat-5.3.c430
-rw-r--r--c-api/compat-5.3.h294
-rwxr-xr-xtests/test.lua109
-rw-r--r--tests/testmod.c246
5 files changed, 1099 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..511db15
--- /dev/null
+++ b/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/c-api/compat-5.3.c b/c-api/compat-5.3.c
new file mode 100644
index 0000000..9edd5f1
--- /dev/null
+++ b/c-api/compat-5.3.c
@@ -0,0 +1,430 @@
1#include <stddef.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ctype.h>
5#include <errno.h>
6#include <lua.h>
7#include <lauxlib.h>
8#include "compat-5.3.h"
9
10/* don't compile it again if it already is included via compat53.h */
11#ifndef COMPAT53_C_
12#define COMPAT53_C_
13
14
15
16/* definitions for Lua 5.1 only */
17#if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM == 501
18
19
20COMPAT53_API int lua_absindex (lua_State *L, int i) {
21 if (i < 0 && i > LUA_REGISTRYINDEX)
22 i += lua_gettop(L) + 1;
23 return i;
24}
25
26
27COMPAT53_API void lua_copy (lua_State *L, int from, int to) {
28 int abs_to = lua_absindex(L, to);
29 luaL_checkstack(L, 1, "not enough stack slots");
30 lua_pushvalue(L, from);
31 lua_replace(L, abs_to);
32}
33
34
35COMPAT53_API void lua_len (lua_State *L, int i) {
36 switch (lua_type(L, i)) {
37 case LUA_TSTRING: /* fall through */
38 case LUA_TTABLE:
39 lua_pushnumber(L, (int)lua_objlen(L, i));
40 break;
41 case LUA_TUSERDATA:
42 if (luaL_callmeta(L, i, "__len"))
43 break;
44 /* maybe fall through */
45 default:
46 luaL_error(L, "attempt to get length of a %s value",
47 lua_typename(L, lua_type(L, i)));
48 }
49}
50
51
52COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p) {
53 int abs_i = lua_absindex(L, i);
54 lua_pushlightuserdata(L, (void*)p);
55 lua_rawget(L, abs_i);
56 return lua_type(L, -1);
57}
58
59COMPAT53_API void lua_rawsetp (lua_State *L, int i, const void *p) {
60 int abs_i = lua_absindex(L, i);
61 luaL_checkstack(L, 1, "not enough stack slots");
62 lua_pushlightuserdata(L, (void*)p);
63 lua_insert(L, -2);
64 lua_rawset(L, abs_i);
65}
66
67
68COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum) {
69 lua_Integer n = lua_tointeger(L, i);
70 if (isnum != NULL) {
71 *isnum = (n != 0 || lua_isnumber(L, i));
72}
73 return n;
74}
75
76
77COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum) {
78 lua_Number n = lua_tonumber(L, i);
79 if (isnum != NULL) {
80 *isnum = (n != 0 || lua_isnumber(L, i));
81 }
82 return n;
83}
84
85
86COMPAT53_API void luaL_checkversion (lua_State *L) {
87 (void)L;
88}
89
90
91COMPAT53_API int luaL_getsubtable (lua_State *L, int i, const char *name) {
92 int abs_i = lua_absindex(L, i);
93 luaL_checkstack(L, 3, "not enough stack slots");
94 lua_pushstring(L, name);
95 lua_gettable(L, abs_i);
96 if (lua_istable(L, -1))
97 return 1;
98 lua_pop(L, 1);
99 lua_newtable(L);
100 lua_pushstring(L, name);
101 lua_pushvalue(L, -2);
102 lua_settable(L, abs_i);
103 return 0;
104}
105
106
107COMPAT53_API int luaL_len (lua_State *L, int i) {
108 int res = 0, isnum = 0;
109 luaL_checkstack(L, 1, "not enough stack slots");
110 lua_len(L, i);
111 res = (int)lua_tointegerx(L, -1, &isnum);
112 lua_pop(L, 1);
113 if (!isnum)
114 luaL_error(L, "object length is not a number");
115 return res;
116}
117
118
119COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
120 luaL_checkstack(L, nup+1, "too many upvalues");
121 for (; l->name != NULL; l++) { /* fill the table with given functions */
122 int i;
123 lua_pushstring(L, l->name);
124 for (i = 0; i < nup; i++) /* copy upvalues to the top */
125 lua_pushvalue(L, -(nup + 1));
126 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
127 lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */
128 }
129 lua_pop(L, nup); /* remove upvalues */
130}
131
132
133COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname) {
134 luaL_checkstack(L, 1, "not enough stack slots");
135 luaL_getmetatable(L, tname);
136 lua_setmetatable(L, -2);
137}
138
139
140COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname) {
141 void *p = lua_touserdata(L, i);
142 luaL_checkstack(L, 2, "not enough stack slots");
143 if (p == NULL || !lua_getmetatable(L, i))
144 return NULL;
145 else {
146 int res = 0;
147 luaL_getmetatable(L, tname);
148 res = lua_rawequal(L, -1, -2);
149 lua_pop(L, 2);
150 if (!res)
151 p = NULL;
152 }
153 return p;
154}
155
156
157COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) {
158 if (!luaL_callmeta(L, idx, "__tostring")) {
159 int t = lua_type(L, idx);
160 switch (t) {
161 case LUA_TNIL:
162 lua_pushliteral(L, "nil");
163 break;
164 case LUA_TSTRING:
165 case LUA_TNUMBER:
166 lua_pushvalue(L, idx);
167 break;
168 case LUA_TBOOLEAN:
169 if (lua_toboolean(L, idx))
170 lua_pushliteral(L, "true");
171 else
172 lua_pushliteral(L, "false");
173 break;
174 default:
175 lua_pushfstring(L, "%s: %p", lua_typename(L, t),
176 lua_topointer(L, idx));
177 break;
178 }
179 }
180 return lua_tolstring(L, -1, len);
181}
182
183
184#if !defined(COMPAT53_IS_LUAJIT)
185static int compat53_countlevels (lua_State *L) {
186 lua_Debug ar;
187 int li = 1, le = 1;
188 /* find an upper bound */
189 while (lua_getstack(L, le, &ar)) { li = le; le *= 2; }
190 /* do a binary search */
191 while (li < le) {
192 int m = (li + le)/2;
193 if (lua_getstack(L, m, &ar)) li = m + 1;
194 else le = m;
195 }
196 return le - 1;
197}
198
199static int compat53_findfield (lua_State *L, int objidx, int level) {
200 if (level == 0 || !lua_istable(L, -1))
201 return 0; /* not found */
202 lua_pushnil(L); /* start 'next' loop */
203 while (lua_next(L, -2)) { /* for each pair in table */
204 if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */
205 if (lua_rawequal(L, objidx, -1)) { /* found object? */
206 lua_pop(L, 1); /* remove value (but keep name) */
207 return 1;
208 }
209 else if (compat53_findfield(L, objidx, level - 1)) { /* try recursively */
210 lua_remove(L, -2); /* remove table (but keep name) */
211 lua_pushliteral(L, ".");
212 lua_insert(L, -2); /* place '.' between the two names */
213 lua_concat(L, 3);
214 return 1;
215 }
216 }
217 lua_pop(L, 1); /* remove value */
218 }
219 return 0; /* not found */
220}
221
222static int compat53_pushglobalfuncname (lua_State *L, lua_Debug *ar) {
223 int top = lua_gettop(L);
224 lua_getinfo(L, "f", ar); /* push function */
225 lua_pushvalue(L, LUA_GLOBALSINDEX);
226 if (compat53_findfield(L, top + 1, 2)) {
227 lua_copy(L, -1, top + 1); /* move name to proper place */
228 lua_pop(L, 2); /* remove pushed values */
229 return 1;
230 }
231 else {
232 lua_settop(L, top); /* remove function and global table */
233 return 0;
234 }
235}
236
237static void compat53_pushfuncname (lua_State *L, lua_Debug *ar) {
238 if (*ar->namewhat != '\0') /* is there a name? */
239 lua_pushfstring(L, "function " LUA_QS, ar->name);
240 else if (*ar->what == 'm') /* main? */
241 lua_pushliteral(L, "main chunk");
242 else if (*ar->what == 'C') {
243 if (compat53_pushglobalfuncname(L, ar)) {
244 lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1));
245 lua_remove(L, -2); /* remove name */
246 }
247 else
248 lua_pushliteral(L, "?");
249 }
250 else
251 lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined);
252}
253
254#define COMPAT53_LEVELS1 12 /* size of the first part of the stack */
255#define COMPAT53_LEVELS2 10 /* size of the second part of the stack */
256
257COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1,
258 const char *msg, int level) {
259 lua_Debug ar;
260 int top = lua_gettop(L);
261 int numlevels = compat53_countlevels(L1);
262 int mark = (numlevels > COMPAT53_LEVELS1 + COMPAT53_LEVELS2) ? COMPAT53_LEVELS1 : 0;
263 if (msg) lua_pushfstring(L, "%s\n", msg);
264 lua_pushliteral(L, "stack traceback:");
265 while (lua_getstack(L1, level++, &ar)) {
266 if (level == mark) { /* too many levels? */
267 lua_pushliteral(L, "\n\t..."); /* add a '...' */
268 level = numlevels - COMPAT53_LEVELS2; /* and skip to last ones */
269 }
270 else {
271 lua_getinfo(L1, "Slnt", &ar);
272 lua_pushfstring(L, "\n\t%s:", ar.short_src);
273 if (ar.currentline > 0)
274 lua_pushfstring(L, "%d:", ar.currentline);
275 lua_pushliteral(L, " in ");
276 compat53_pushfuncname(L, &ar);
277 lua_concat(L, lua_gettop(L) - top);
278 }
279 }
280 lua_concat(L, lua_gettop(L) - top);
281}
282
283
284COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname) {
285 int en = errno; /* calls to Lua API may change this value */
286 if (stat) {
287 lua_pushboolean(L, 1);
288 return 1;
289 }
290 else {
291 lua_pushnil(L);
292 if (fname)
293 lua_pushfstring(L, "%s: %s", fname, strerror(en));
294 else
295 lua_pushstring(L, strerror(en));
296 lua_pushnumber(L, (lua_Number)en);
297 return 3;
298 }
299}
300#endif /* not COMPAT53_IS_LUAJIT */
301
302
303#endif /* Lua 5.1 */
304
305
306
307/* definitions for Lua 5.1 and Lua 5.2 */
308#if defined( LUA_VERSION_NUM ) && LUA_VERSION_NUM <= 502
309
310
311COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i) {
312 index = lua_absindex(L, index);
313 lua_pushinteger(L, i);
314 lua_gettable(L, index);
315 return lua_type(L, -1);
316}
317
318
319COMPAT53_API int lua_isinteger (lua_State *L, int index) {
320 if (lua_type(L, index) == LUA_TNUMBER) {
321 lua_Number n = lua_tonumber(L, index);
322 lua_Integer i = lua_tointeger(L, index);
323 if (i == n)
324 return 1;
325 }
326 return 0;
327}
328
329
330static void compat53_reverse (lua_State *L, int a, int b) {
331 for (; a < b; ++a, --b) {
332 lua_pushvalue(L, a);
333 lua_pushvalue(L, b);
334 lua_replace(L, a);
335 lua_replace(L, b);
336 }
337}
338
339
340COMPAT53_API void lua_rotate (lua_State *L, int idx, int n) {
341 int n_elems = 0;
342 idx = lua_absindex(L, idx);
343 n_elems = lua_gettop(L)-idx+1;
344 if (n < 0)
345 n += n_elems;
346 if ( n > 0 && n < n_elems) {
347 luaL_checkstack(L, 2, "not enough stack slots available");
348 n = n_elems - n;
349 compat53_reverse(L, idx, idx+n-1);
350 compat53_reverse(L, idx+n, idx+n_elems-1);
351 compat53_reverse(L, idx, idx+n_elems-1);
352 }
353}
354
355
356COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i) {
357 luaL_checkstack(L, 1, "not enough stack slots available");
358 index = lua_absindex(L, index);
359 lua_pushinteger(L, i);
360 lua_insert(L, -2);
361 lua_settable(L, index);
362}
363
364
365COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s) {
366 char* endptr;
367 lua_Number n = lua_str2number(s, &endptr);
368 if (endptr != s) {
369 while (*endptr != '\0' && isspace((unsigned char)*endptr))
370 ++endptr;
371 if (*endptr == '\0') {
372 lua_pushnumber(L, n);
373 return endptr - s + 1;
374 }
375 }
376 return 0;
377}
378
379
380COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
381 lua_CFunction openf, int glb) {
382 luaL_checkstack(L, 3, "not enough stack slots available");
383 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
384 if (lua_getfield(L, -1, modname) == LUA_TNIL) {
385 lua_pop(L, 1);
386 lua_pushcfunction(L, openf);
387 lua_pushstring(L, modname);
388 lua_call(L, 1, 1);
389 lua_pushvalue(L, -1);
390 lua_setfield(L, -3, modname);
391 }
392 if (glb) {
393 lua_pushvalue(L, -1);
394 lua_setglobal(L, modname);
395 }
396 lua_replace(L, -2);
397}
398
399
400#endif /* Lua 5.1 and 5.2 */
401
402
403#endif /* COMPAT53_C_ */
404
405
406/*********************************************************************
407* This file contains parts of Lua 5.2's and Lua 5.3's source code:
408*
409* Copyright (C) 1994-2014 Lua.org, PUC-Rio.
410*
411* Permission is hereby granted, free of charge, to any person obtaining
412* a copy of this software and associated documentation files (the
413* "Software"), to deal in the Software without restriction, including
414* without limitation the rights to use, copy, modify, merge, publish,
415* distribute, sublicense, and/or sell copies of the Software, and to
416* permit persons to whom the Software is furnished to do so, subject to
417* the following conditions:
418*
419* The above copyright notice and this permission notice shall be
420* included in all copies or substantial portions of the Software.
421*
422* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
423* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
424* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
425* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
426* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
427* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
428* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
429*********************************************************************/
430
diff --git a/c-api/compat-5.3.h b/c-api/compat-5.3.h
new file mode 100644
index 0000000..b288126
--- /dev/null
+++ b/c-api/compat-5.3.h
@@ -0,0 +1,294 @@
1#ifndef COMPAT53_H_
2#define COMPAT53_H_
3
4#include <stddef.h>
5#include <limits.h>
6#include <lua.h>
7#include <lauxlib.h>
8#include <lualib.h>
9
10
11#if defined(COMPAT53_PREFIX)
12/* - change the symbol names of functions to avoid linker conflicts
13 * - compat-5.3.c needs to be compiled (and linked) separately
14 */
15# if !defined(COMPAT53_API)
16# define COMPAT53_API extern
17# endif
18# undef COMPAT53_INCLUDE_SOURCE
19#else /* COMPAT53_PREFIX */
20/* - make all functions static and include the source.
21 * - don't mess with the symbol names of functions
22 * - compat-5.3.c doesn't need to be compiled (and linked) separately
23 */
24# define COMPAT53_PREFIX lua
25# undef COMPAT53_API
26# if defined(__GNUC__) || defined(__clang__)
27# define COMPAT53_API __attribute__((__unused__)) static
28# else
29# define COMPAT53_API static
30# endif
31# define COMPAT53_INCLUDE_SOURCE
32#endif /* COMPAT53_PREFIX */
33
34#define COMPAT53_CONCAT_HELPER(a, b) a##b
35#define COMPAT53_CONCAT(a, b) COMPAT53_CONCAT_HELPER(a, b)
36
37
38
39/* declarations for Lua 5.1 */
40#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
41
42/* XXX not implemented:
43 * lua_arith
44 * lua_compare
45 * lua_upvalueid
46 * lua_upvaluejoin
47 * lua_version
48 * lua_yieldk
49 * luaL_buffinitsize
50 * luaL_execresult
51 * luaL_loadbufferx
52 * luaL_loadfilex
53 * luaL_prepbuffsize
54 * luaL_pushresultsize
55 */
56
57/* PUC-Rio Lua uses lconfig_h as include guard for luaconf.h,
58 * LuaJIT uses luaconf_h. If you use PUC-Rio's include files
59 * but LuaJIT's library, you will need to define the macro
60 * COMPAT53_IS_LUAJIT yourself! */
61#if !defined(COMPAT53_IS_LUAJIT) && defined(luaconf_h)
62# define COMPAT53_IS_LUAJIT
63#endif
64
65#define LUA_OK 0
66
67typedef struct luaL_Stream {
68 FILE *f;
69 lua_CFunction closef;
70} luaL_Stream;
71
72typedef size_t lua_Unsigned;
73
74#define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex)
75COMPAT53_API int lua_absindex (lua_State *L, int i);
76
77#define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy)
78COMPAT53_API void lua_copy (lua_State *L, int from, int to);
79
80#define lua_getuservalue(L, i) \
81 (lua_getfenv(L, i), lua_type(L, -1))
82#define lua_setuservalue(L, i) \
83 (luaL_checktype(L, -1, LUA_TTABLE), lua_setfenv(L, i))
84
85#define lua_len COMPAT53_CONCAT(COMPAT53_PREFIX, _len)
86COMPAT53_API void lua_len (lua_State *L, int i);
87
88#define luaL_newlibtable(L, l) \
89 (lua_createtable(L, 0, sizeof(l)/sizeof(*(l))-1))
90#define luaL_newlib(L, l) \
91 (luaL_newlibtable(L, l), luaL_register(L, NULL, l))
92
93#define lua_pushglobaltable(L) \
94 lua_pushvalue(L, LUA_GLOBALSINDEX)
95
96#define lua_rawgetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawgetp)
97COMPAT53_API int lua_rawgetp (lua_State *L, int i, const void *p);
98
99#define lua_rawsetp COMPAT53_CONCAT(COMPAT53_PREFIX, _rawsetp)
100COMPAT53_API void lua_rawsetp(lua_State *L, int i, const void *p);
101
102#define lua_rawlen(L, i) lua_objlen(L, i)
103
104#define lua_tointegerx COMPAT53_CONCAT(COMPAT53_PREFIX, _tointegerx)
105COMPAT53_API lua_Integer lua_tointegerx (lua_State *L, int i, int *isnum);
106
107#define lua_tonumberx COMPAT53_CONCAT(COMPAT53_PREFIX, _tonumberx)
108COMPAT53_API lua_Number lua_tonumberx (lua_State *L, int i, int *isnum);
109
110#define luaL_checkversion COMPAT53_CONCAT(COMPAT53_PREFIX, L_checkversion)
111COMPAT53_API void luaL_checkversion (lua_State *L);
112
113#define luaL_getsubtable COMPAT53_CONCAT(COMPAT53_PREFIX, L_getsubtable)
114COMPAT53_API int luaL_getsubtable (lua_State* L, int i, const char *name);
115
116#define luaL_len COMPAT53_CONCAT(COMPAT53_PREFIX, L_len)
117COMPAT53_API int luaL_len (lua_State *L, int i);
118
119#define luaL_setfuncs COMPAT53_CONCAT(COMPAT53_PREFIX, L_setfuncs)
120COMPAT53_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
121
122#define luaL_setmetatable COMPAT53_CONCAT(COMPAT53_PREFIX, L_setmetatable)
123COMPAT53_API void luaL_setmetatable (lua_State *L, const char *tname);
124
125#define luaL_testudata COMPAT53_CONCAT(COMPAT53_PREFIX, L_testudata)
126COMPAT53_API void *luaL_testudata (lua_State *L, int i, const char *tname);
127
128#define luaL_tolstring COMPAT53_CONCAT(COMPAT53_PREFIX, L_tolstring)
129COMPAT53_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len);
130
131#if !defined(COMPAT53_IS_LUAJIT)
132#define luaL_traceback COMPAT53_CONCAT(COMPAT53_PREFIX, L_traceback)
133COMPAT53_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg, int level);
134
135#define luaL_fileresult COMPAT53_CONCAT(COMPAT53_PREFIX, L_fileresult)
136COMPAT53_API int luaL_fileresult (lua_State *L, int stat, const char *fname);
137#endif /* COMPAT53_IS_LUAJIT */
138
139#define lua_callk(L, na, nr, ctx, cont) \
140 ((void)(ctx), (void)(cont), lua_call(L, na, nr))
141#define lua_pcallk(L, na, nr, err, ctx, cont) \
142 ((void)(ctx), (void)(cont), lua_pcall(L, na, nr, err))
143
144#if defined(LUA_COMPAT_APIINTCASTS)
145#define lua_pushunsigned(L, n) \
146 lua_pushinteger(L, (lua_Integer)(n))
147#define lua_tounsignedx(L, i, is) \
148 ((lua_Unsigned)lua_tointegerx(L, i, is))
149#define lua_tounsigned(L, i) \
150 lua_tounsignedx(L, i, NULL)
151#define luaL_checkunsigned(L, a) \
152 ((lua_Unsigned)luaL_checkinteger(L, a))
153#define luaL_optunsigned(L, a, d) \
154 ((lua_Unsigned)luaL_optinteger(L, a, (lua_Integer)(d)))
155#endif
156
157#endif /* Lua 5.1 only */
158
159
160
161/* declarations for Lua 5.1 and 5.2 */
162#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM <= 502
163
164typedef int lua_KContext;
165
166typedef int (*lua_KFunction)(lua_State *L, int status, lua_KContext ctx);
167
168#define lua_dump(L, w, d, s) \
169 ((void)(s), lua_dump(L, w, d))
170
171#define lua_getfield(L, i, k) \
172 (lua_getfield(L, i, k), lua_type(L, -1))
173
174#define lua_gettable(L, i) \
175 (lua_gettable(L, i), lua_type(L, -1))
176
177#define lua_geti COMPAT53_CONCAT(COMPAT53_PREFIX, _geti)
178COMPAT53_API int lua_geti (lua_State *L, int index, lua_Integer i);
179
180#define lua_isinteger COMPAT53_CONCAT(COMPAT53_PREFIX, _isinteger)
181COMPAT53_API int lua_isinteger (lua_State *L, int index);
182
183#define lua_numbertointeger(n, p) \
184 ((*(p) = (lua_Integer)(n)), 1)
185
186#define lua_rawget(L, i) \
187 (lua_rawget(L, i), lua_type(L, -1))
188
189#define lua_rawgeti(L, i, n) \
190 (lua_rawgeti(L, i, n), lua_type(L, -1))
191
192#define lua_rotate COMPAT53_CONCAT(COMPAT53_PREFIX, _rotate)
193COMPAT53_API void lua_rotate (lua_State *L, int idx, int n);
194
195#define lua_seti COMPAT53_CONCAT(COMPAT53_PREFIX, _seti)
196COMPAT53_API void lua_seti (lua_State *L, int index, lua_Integer i);
197
198#define lua_strtonum COMPAT53_CONCAT(COMPAT53_PREFIX, _stringtonumber)
199COMPAT53_API size_t lua_stringtonumber (lua_State *L, const char *s);
200
201#define luaL_getmetafield(L, o, e) \
202 (luaL_getmetafield(L, o, e) ? lua_type(L, -1) : LUA_TNIL)
203
204#define luaL_requiref COMPAT53_CONCAT(COMPAT53_PREFIX, L_requiref_)
205COMPAT53_API void luaL_requiref (lua_State *L, const char *modname,
206 lua_CFunction openf, int glb );
207
208#endif /* Lua 5.1 and Lua 5.2 */
209
210
211
212/* declarations for Lua 5.2 */
213#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 502
214
215/* XXX not implemented:
216 * lua_isyieldable
217 * lua_getextraspace
218 * lua_arith (new operators)
219 * lua_pushfstring (new formats)
220 */
221
222#define lua_getglobal(L, n) \
223 (lua_getglobal(L, n), lua_type(L, -1))
224
225#define lua_getuservalue(L, i) \
226 (lua_getuservalue(L, i), lua_type(L, -1))
227
228#define lua_rawgetp(L, i, p) \
229 (lua_rawgetp(L, i, p), lua_type(L, -1))
230
231#define LUA_KFUNCTION(_name) \
232 static int (_name)(lua_State *L, int status, lua_KContext ctx); \
233 static int (_name ## _52)(lua_State *L) { \
234 luaK_Context ctx; \
235 int status = lua_getctx(L, &ctx); \
236 return (_name)(L, status, ctx); \
237 } \
238 static int (_name)(lua_State *L, int status, lua_KContext ctx)
239
240#define lua_pcallk(L, na, nr, err, ctx, cont) \
241 lua_pcallk(L, na, nr, err, ctx, cont ## _52)
242
243#define lua_callk(L, na, nr, ctx, cont) \
244 lua_callk(L, na, nr, ctx, cont ## _52)
245
246#define lua_yieldk(L, nr, ctx, cont) \
247 lua_yieldk(L, nr, ctx, cont ## _52)
248
249#ifdef lua_call
250# undef lua_call
251# define lua_call(L, na, nr) \
252 (lua_callk)(L, na, nr, 0, NULL)
253#endif
254
255#ifdef lua_pcall
256# undef lua_pcall
257# define lua_pcall(L, na, nr, err) \
258 (lua_pcallk)(L, na, nr, err, 0, NULL)
259#endif
260
261#ifdef lua_yield
262# undef lua_yield
263# define lua_yield(L, nr) \
264 (lua_yieldk)(L, nr, 0, NULL)
265#endif
266
267#endif /* Lua 5.2 only */
268
269
270
271/* other Lua versions */
272#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 503
273
274# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, or 5.3)"
275
276#endif /* other Lua versions except 5.1, 5.2, and 5.3 */
277
278
279
280/* helper macro for defining continuation functions (for every version
281 * *except* Lua 5.2) */
282#ifndef LUA_KFUNCTION
283#define LUA_KFUNCTION(_name) \
284 static int (_name)(lua_State *L, int status, lua_KContext ctx)
285#endif
286
287
288#if defined(COMPAT53_INCLUDE_SOURCE)
289# include "compat-5.3.c"
290#endif
291
292
293#endif /* COMPAT53_H_ */
294
diff --git a/tests/test.lua b/tests/test.lua
new file mode 100755
index 0000000..cc07ee8
--- /dev/null
+++ b/tests/test.lua
@@ -0,0 +1,109 @@
1#!/usr/bin/env lua
2
3local mod = require( "testmod" )
4local F
5do
6 local type, unpack = type, table.unpack or unpack
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
17end
18
19
20print( mod.isinteger( 1 ) )
21print( mod.isinteger( 0 ) )
22print( mod.isinteger( 1234567 ) )
23print( mod.isinteger( 12.3 ) )
24print( mod.isinteger( math.huge ) )
25print( mod.isinteger( math.sqrt( -1 ) ) )
26
27
28print( mod.rotate( 1, 1, 2, 3, 4, 5, 6 ) )
29print( mod.rotate(-1, 1, 2, 3, 4, 5, 6 ) )
30print( mod.rotate( 4, 1, 2, 3, 4, 5, 6 ) )
31print( mod.rotate( -4, 1, 2, 3, 4, 5, 6 ) )
32
33
34print( mod.strtonum( "+123" ) )
35print( mod.strtonum( " 123 " ) )
36print( mod.strtonum( "-1.23" ) )
37print( mod.strtonum( " 123 abc" ) )
38print( mod.strtonum( "jkl" ) )
39
40
41local a, b, c = mod.requiref()
42print( type( a ), type( b ), type( c ),
43 a.boolean, b.boolean, c.boolean,
44 type( requiref1 ), type( requiref2 ), type( requiref3 ) )
45
46local proxy, backend = {}, {}
47setmetatable( proxy, { __index = backend, __newindex = backend } )
48print( rawget( proxy, 1 ), rawget( backend, 1 ) )
49print( mod.getseti( proxy, 1 ) )
50print( rawget( proxy, 1 ), rawget( backend, 1 ) )
51print( mod.getseti( proxy, 1 ) )
52print( rawget( proxy, 1 ), rawget( backend, 1 ) )
53
54-- tests for Lua 5.1
55print(mod.tonumber(12))
56print(mod.tonumber("12"))
57print(mod.tonumber("0"))
58print(mod.tonumber(false))
59print(mod.tonumber("error"))
60
61print(mod.tointeger(12))
62print(mod.tointeger("12"))
63print(mod.tointeger("0"))
64print( "aaa" )
65print(mod.tointeger(math.pi))
66print( "bbb" )
67print(mod.tointeger(false))
68print(mod.tointeger("error"))
69
70print(mod.len("123"))
71print(mod.len({ 1, 2, 3}))
72print(pcall(mod.len, true))
73local ud, meta = mod.newproxy()
74meta.__len = function() return 5 end
75print(mod.len(ud))
76meta.__len = function() return true end
77print(pcall(mod.len, ud))
78
79print(mod.copy(true, "string", {}, 1))
80
81print(mod.rawxetp())
82print(mod.rawxetp("I'm back"))
83
84print(F(mod.globals()), mod.globals() == _G)
85
86local t = {}
87print(F(mod.subtable(t)))
88local x, msg = mod.subtable(t)
89print(F(x, msg, x == t.xxx))
90
91print(F(mod.udata()))
92print(mod.udata("nosuchtype"))
93
94print(F(mod.uservalue()))
95
96print(mod.getupvalues())
97
98print(mod.absindex("hi", true))
99
100print(mod.tolstring("string"))
101local t = setmetatable({}, {
102 __tostring = function(v) return "mytable" end
103})
104print(mod.tolstring( t ) )
105local t = setmetatable({}, {
106 __tostring = function(v) return nil end
107})
108print(pcall(mod.tolstring, t))
109
diff --git a/tests/testmod.c b/tests/testmod.c
new file mode 100644
index 0000000..a9c8e8d
--- /dev/null
+++ b/tests/testmod.c
@@ -0,0 +1,246 @@
1#include <stdio.h>
2#include <lua.h>
3#include <lauxlib.h>
4#include "compat-5.3.h"
5
6
7static int test_isinteger (lua_State *L) {
8 lua_pushboolean(L, lua_isinteger(L, 1));
9 return 1;
10}
11
12
13static int test_rotate (lua_State *L) {
14 int r = luaL_checkint(L, 1);
15 int n = lua_gettop(L)-1;
16 luaL_argcheck(L, (r < 0 ? -r : r) <= n, 1, "not enough arguments");
17 lua_rotate(L, 2, r);
18 return n;
19}
20
21
22static int test_str2num (lua_State *L) {
23 const char *s = luaL_checkstring(L, 1);
24 size_t len = lua_stringtonumber(L, s);
25 if (len == 0)
26 lua_pushnumber(L, 0);
27 lua_pushinteger(L, (lua_Integer)len);
28 return 2;
29}
30
31
32static int my_mod (lua_State *L ) {
33 lua_newtable(L);
34 lua_pushboolean(L, 1);
35 lua_setfield(L, -2, "boolean");
36 return 1;
37}
38
39static int test_requiref (lua_State *L) {
40 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
41 lua_newtable(L);
42 lua_pushboolean(L, 0);
43 lua_setfield(L, -2, "boolean");
44 lua_setfield(L, -2, "requiref3");
45 lua_pop(L, 1);
46 luaL_requiref(L, "requiref1", my_mod, 0);
47 luaL_requiref(L, "requiref2", my_mod, 1);
48 luaL_requiref(L, "requiref3", my_mod, 1);
49 return 3;
50}
51
52static int test_getseti (lua_State *L) {
53 lua_Integer k = luaL_checkinteger(L, 2);
54 lua_Integer n = 0;
55 if (lua_geti(L, 1, k) == LUA_TNUMBER) {
56 n = lua_tointeger(L, -1);
57 } else {
58 lua_pop(L, 1);
59 lua_pushinteger(L, n);
60 }
61 lua_pushinteger(L, n+1);
62 lua_seti(L, 1, k);
63 return 1;
64}
65
66
67/* additional tests for Lua5.1 */
68#define NUP 3
69
70static int test_newproxy (lua_State *L) {
71 lua_settop(L, 0);
72 lua_newuserdata(L, 0);
73 lua_newtable(L);
74 lua_pushvalue(L, -1);
75 lua_pushboolean(L, 1);
76 lua_setfield(L, -2, "__gc");
77 lua_setmetatable(L, -3);
78 return 2;
79}
80
81static int test_absindex (lua_State *L) {
82 int i = 1;
83 for (i = 1; i <= NUP; ++i)
84 lua_pushvalue(L, lua_absindex(L, lua_upvalueindex(i)));
85 lua_pushvalue(L, lua_absindex(L, LUA_REGISTRYINDEX));
86 lua_pushstring(L, lua_typename(L, lua_type(L, lua_absindex(L, -1))));
87 lua_replace(L, lua_absindex(L, -2));
88 lua_pushvalue(L, lua_absindex(L, -2));
89 lua_pushvalue(L, lua_absindex(L, -4));
90 lua_pushvalue(L, lua_absindex(L, -6));
91 i += 3;
92 lua_pushvalue(L, lua_absindex(L, 1));
93 lua_pushvalue(L, lua_absindex(L, 2));
94 lua_pushvalue(L, lua_absindex(L, 3));
95 i += 3;
96 return i;
97}
98
99static int test_globals (lua_State *L) {
100 lua_pushglobaltable(L);
101 return 1;
102}
103
104static int test_tonumber (lua_State *L) {
105 int isnum = 0;
106 lua_Number n = lua_tonumberx(L, 1, &isnum);
107 if (!isnum)
108 lua_pushnil(L);
109 else
110 lua_pushnumber(L, n);
111 return 1;
112}
113
114static int test_tointeger (lua_State *L) {
115 int isnum = 0;
116 lua_Integer n = lua_tointegerx(L, 1, &isnum);
117 if (!isnum)
118 lua_pushnil(L);
119 else
120 lua_pushinteger(L, n);
121 return 1;
122}
123
124static int test_len (lua_State *L) {
125 luaL_checkany(L, 1);
126 lua_len(L, 1);
127 lua_pushinteger(L, luaL_len(L, 1));
128 return 2;
129}
130
131static int test_copy (lua_State *L) {
132 int args = lua_gettop(L);
133 if (args >= 2) {
134 int i = 0;
135 for (i = args-1; i > 0; --i)
136 lua_copy(L, args, i);
137 }
138 return args;
139}
140
141/* need an address */
142static char const dummy = 0;
143
144static int test_rawxetp (lua_State *L) {
145 if (lua_gettop(L) > 0)
146 lua_pushvalue(L, 1);
147 else
148 lua_pushliteral(L, "hello again");
149 lua_rawsetp(L, LUA_REGISTRYINDEX, &dummy);
150 lua_settop(L, 0);
151 lua_rawgetp(L, LUA_REGISTRYINDEX, &dummy);
152 return 1;
153}
154
155static int test_udata (lua_State *L) {
156 const char *tname = luaL_optstring(L, 1, "utype1");
157 void *u1 = lua_newuserdata(L, 1);
158 int u1pos = lua_gettop(L);
159 void *u2 = lua_newuserdata(L, 1);
160 int u2pos = lua_gettop(L);
161 luaL_newmetatable(L, "utype1");
162 luaL_newmetatable(L, "utype2");
163 lua_pop(L, 2);
164 luaL_setmetatable(L, "utype2");
165 lua_pushvalue(L, u1pos);
166 luaL_setmetatable(L, "utype1");
167 lua_pop(L, 1);
168 (void)u1;
169 (void)u2;
170 lua_pushlightuserdata(L, luaL_testudata(L, u1pos, tname));
171 lua_pushlightuserdata(L, luaL_testudata(L, u2pos, tname));
172 return 2;
173}
174
175static int test_subtable (lua_State *L) {
176 luaL_checktype(L, 1, LUA_TTABLE);
177 lua_settop(L, 1);
178 if (luaL_getsubtable(L, 1, "xxx")) {
179 lua_pushliteral(L, "oldtable");
180 } else {
181 lua_pushliteral(L, "newtable");
182 }
183 return 2;
184}
185
186static int test_uservalue (lua_State *L) {
187 void *udata = lua_newuserdata(L, 1);
188 int ui = lua_gettop(L);
189 lua_newtable(L);
190 lua_setuservalue(L, ui);
191 lua_getuservalue(L, ui);
192 (void)udata;
193 return 1;
194}
195
196static int test_upvalues (lua_State *L) {
197 int i = 1;
198 for (i = 1; i <= NUP; ++i)
199 lua_pushvalue(L, lua_upvalueindex(i));
200 return NUP;
201}
202
203static int test_tolstring (lua_State *L) {
204 size_t len = 0;
205 luaL_tolstring(L, 1, &len);
206 lua_pushinteger(L, (int)len);
207 return 2;
208}
209
210
211static const luaL_Reg funcs[] = {
212 { "isinteger", test_isinteger },
213 { "rotate", test_rotate },
214 { "strtonum", test_str2num },
215 { "requiref", test_requiref },
216 { "getseti", test_getseti },
217 { "newproxy", test_newproxy },
218 { "tonumber", test_tonumber },
219 { "tointeger", test_tointeger },
220 { "len", test_len },
221 { "copy", test_copy },
222 { "rawxetp", test_rawxetp },
223 { "subtable", test_subtable },
224 { "udata", test_udata },
225 { "uservalue", test_uservalue },
226 { "globals", test_globals },
227 { "tolstring", test_tolstring },
228 { NULL, NULL }
229};
230
231static const luaL_Reg more_funcs[] = {
232 { "getupvalues", test_upvalues },
233 { "absindex", test_absindex },
234 { NULL, NULL }
235};
236
237
238int luaopen_testmod (lua_State *L) {
239 int i = 1;
240 luaL_newlib(L, funcs);
241 for (i = 1; i <= NUP; ++i)
242 lua_pushnumber(L, i);
243 luaL_setfuncs(L, more_funcs, NUP);
244 return 1;
245}
246