From 489cd678823e0981ff2e4d2544b84094ed23c587 Mon Sep 17 00:00:00 2001 From: Philipp Janda Date: Tue, 20 Jan 2015 01:02:20 +0100 Subject: add lua_arith and lua_compare for Lua 5.1 --- c-api/compat-5.3.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ c-api/compat-5.3.h | 18 +++++++++-- tests/test.lua | 9 ++++++ tests/testmod.c | 37 ++++++++++++++++++++++ 4 files changed, 152 insertions(+), 2 deletions(-) diff --git a/c-api/compat-5.3.c b/c-api/compat-5.3.c index e45c728..a539aed 100644 --- a/c-api/compat-5.3.c +++ b/c-api/compat-5.3.c @@ -24,6 +24,96 @@ COMPAT53_API int lua_absindex (lua_State *L, int i) { } +static const char compat53_arith_code[] = { + 'l', 'o', 'c', 'a', 'l', ' ', 'o', 'p', ',', 'a', ',', 'b', + '=', '.', '.', '.', '\n', + 'i', 'f', ' ', 'o', 'p', '=', '=', '0', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '+', 'b', '\n', + 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '1', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '-', 'b', '\n', + 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '2', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '*', 'b', '\n', + 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '3', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '/', 'b', '\n', + 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '4', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '%', 'b', '\n', + 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '5', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '^', 'b', '\n', + 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '6', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', '-', 'a', '\n', + 'e', 'n', 'd', '\n', '\0' +}; + +COMPAT53_API void lua_arith (lua_State *L, int op) { + luaL_checkstack(L, 5, "not enough stack slots"); + if (op == LUA_OPUNM) + lua_pushvalue(L, -1); + lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)compat53_arith_code); + if (lua_type(L, -1) != LUA_TFUNCTION) { + lua_pop(L, 1); + if (luaL_loadbuffer(L, compat53_arith_code, + sizeof(compat53_arith_code)-1, "=none")) + lua_error(L); + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)compat53_arith_code); + } + lua_pushnumber(L, op); + lua_pushvalue(L, -4); + lua_pushvalue(L, -4); + lua_call(L, 3, 1); + lua_replace(L, -3); /* replace first operand */ + lua_pop(L, 1); /* pop second */ +} + + +static const char compat53_compare_code[] = { + 'l', 'o', 'c', 'a', 'l', ' ', 'o', 'p', ',', 'a', ',', 'b', + '=', '.', '.', '.', '\n', + 'i', 'f', ' ', 'o', 'p', '=', '=', '0', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '=', '=', 'b', '\n', + 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '1', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '<', 'b', '\n', + 'e', 'l', 's', 'e', 'i', 'f', ' ', 'o', 'p', '=', '=', '2', ' ', + 't', 'h', 'e', 'n', '\n', + 'r', 'e', 't', 'u', 'r', 'n', ' ', 'a', '<', '=', 'b', '\n', + 'e', 'n', 'd', '\n', '\0' +}; + +COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op) { + int result = 0; + luaL_checkstack(L, 4, "not enough stack slots"); + idx1 = lua_absindex(L, idx1); + idx2 = lua_absindex(L, idx2); + lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)compat53_compare_code); + if (lua_type(L, -1) != LUA_TFUNCTION) { + lua_pop(L, 1); + if (luaL_loadbuffer(L, compat53_compare_code, + sizeof(compat53_compare_code)-1, "=none")) + lua_error(L); + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)compat53_compare_code); + } + lua_pushnumber(L, op); + lua_pushvalue(L, idx1); + lua_pushvalue(L, idx2); + lua_call(L, 3, 1); + if(lua_type(L, -1) != LUA_TBOOLEAN) + luaL_error(L, "invalid 'op' argument for lua_compare"); + result = lua_toboolean(L, -1); + lua_pop(L, 1); + return result; +} + + COMPAT53_API void lua_copy (lua_State *L, int from, int to) { int abs_to = lua_absindex(L, to); luaL_checkstack(L, 1, "not enough stack slots"); diff --git a/c-api/compat-5.3.h b/c-api/compat-5.3.h index b288126..3905a10 100644 --- a/c-api/compat-5.3.h +++ b/c-api/compat-5.3.h @@ -40,8 +40,6 @@ #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 /* XXX not implemented: - * lua_arith - * lua_compare * lua_upvalueid * lua_upvaluejoin * lua_version @@ -63,6 +61,16 @@ #endif #define LUA_OK 0 +#define LUA_OPADD 0 +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPDIV 3 +#define LUA_OPMOD 4 +#define LUA_OPPOW 5 +#define LUA_OPUNM 6 +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 typedef struct luaL_Stream { FILE *f; @@ -74,6 +82,12 @@ typedef size_t lua_Unsigned; #define lua_absindex COMPAT53_CONCAT(COMPAT53_PREFIX, _absindex) COMPAT53_API int lua_absindex (lua_State *L, int i); +#define lua_arith COMPAT53_CONCAT(COMPAT53_PREFIX, _arith) +COMPAT53_API void lua_arith (lua_State *L, int op); + +#define lua_compare COMPAT53_CONCAT(COMPAT53_PREFIX, _compare) +COMPAT53_API int lua_compare (lua_State *L, int idx1, int idx2, int op); + #define lua_copy COMPAT53_CONCAT(COMPAT53_PREFIX, _copy) COMPAT53_API void lua_copy (lua_State *L, int from, int to); diff --git a/tests/test.lua b/tests/test.lua index b59fd94..2b53b92 100755 --- a/tests/test.lua +++ b/tests/test.lua @@ -313,6 +313,15 @@ print(mod.getupvalues()) ___'' print(mod.absindex("hi", true)) +___'' +print(mod.arith(2, 1)) +print(mod.arith(3, 5)) + +___'' +print(mod.compare(1, 1)) +print(mod.compare(2, 1)) +print(mod.compare(1, 2)) + ___'' print(mod.tolstring("string")) local t = setmetatable({}, { diff --git a/tests/testmod.c b/tests/testmod.c index a9c8e8d..2c6242b 100644 --- a/tests/testmod.c +++ b/tests/testmod.c @@ -96,6 +96,41 @@ static int test_absindex (lua_State *L) { return i; } +static int test_arith (lua_State *L) { + lua_settop(L, 2); + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_arith(L, LUA_OPADD); + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_arith(L, LUA_OPSUB); + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_arith(L, LUA_OPMUL); + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_arith(L, LUA_OPDIV); + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_arith(L, LUA_OPMOD); + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + lua_arith(L, LUA_OPPOW); + lua_pushvalue(L, 1); + lua_arith(L, LUA_OPUNM); + return lua_gettop(L)-2; +} + +static int test_compare (lua_State *L) { + luaL_checknumber(L, 1); + luaL_checknumber(L, 2); + lua_settop(L, 2); + lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPEQ)); + lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLT)); + lua_pushboolean(L, lua_compare(L, 1, 2, LUA_OPLE)); + return 3; +} + static int test_globals (lua_State *L) { lua_pushglobaltable(L); return 1; @@ -215,6 +250,8 @@ static const luaL_Reg funcs[] = { { "requiref", test_requiref }, { "getseti", test_getseti }, { "newproxy", test_newproxy }, + { "arith", test_arith }, + { "compare", test_compare }, { "tonumber", test_tonumber }, { "tointeger", test_tointeger }, { "len", test_len }, -- cgit v1.2.3-55-g6feb