diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2009-06-01 22:02:18 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2009-06-01 22:02:18 +0000 |
commit | 82eea9ed69886a4eaf41a1124b292635ca60fe9a (patch) | |
tree | db6bb8849b433a8440770015de490327cbfb4195 /apps | |
parent | c1d27d105c3333b5df67c97d88885efa2a49bc9a (diff) | |
download | rockbox-82eea9ed69886a4eaf41a1124b292635ca60fe9a.tar.gz rockbox-82eea9ed69886a4eaf41a1124b292635ca60fe9a.zip |
Lua: add bitlib (makes bitwise operators possible)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21164 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/lua/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/lua/lbitlib.c | 125 | ||||
-rw-r--r-- | apps/plugins/lua/lualib.h | 2 | ||||
-rw-r--r-- | apps/plugins/lua/rocklua.c | 1 |
4 files changed, 129 insertions, 0 deletions
diff --git a/apps/plugins/lua/SOURCES b/apps/plugins/lua/SOURCES index 058b991417..b443ce8437 100644 --- a/apps/plugins/lua/SOURCES +++ b/apps/plugins/lua/SOURCES @@ -1,6 +1,7 @@ lauxlib.c lapi.c lbaselib.c +lbitlib.c lcode.c ldebug.c ldo.c diff --git a/apps/plugins/lua/lbitlib.c b/apps/plugins/lua/lbitlib.c new file mode 100644 index 0000000000..f7e4619377 --- /dev/null +++ b/apps/plugins/lua/lbitlib.c @@ -0,0 +1,125 @@ +/* Bitwise operations library */ +/* (c) Reuben Thomas 2000-2008 */ +/* bitlib is copyright Reuben Thomas 2000-2008, and is released under the MIT + license, like Lua (see http://www.lua.org/copyright.html; it's + basically the same as the BSD license). There is no warranty. */ + +#include "config.h" + +#include <lua.h> +#include <lauxlib.h> +#include <limits.h> + + +/* FIXME: Assume lua_Integer is ptrdiff_t */ +#define LUA_INTEGER_MAX INTPTR_MAX +#define LUA_INTEGER_MIN INTPTR_MIN + +/* FIXME: Assume size_t is an unsigned lua_Integer */ +typedef size_t lua_UInteger; +#define LUA_UINTEGER_MAX UINT_MAX + + +/* Bit type size and limits */ + +#define BIT_BITS (CHAR_BIT * sizeof(lua_Integer)) + +/* This code may give warnings if BITLIB_FLOAT_* are too big to fit in + long, but that doesn't matter since in that case they won't be + used. */ +#define BIT_MAX (LUA_INTEGER_MAX) + +#define BIT_MIN (LUA_INTEGER_MIN) + +#define BIT_UMAX (LUA_UINTEGER_MAX) + + +/* Define TOBIT to get a bit value */ +#ifdef BUILTIN_CAST +#define +#define TOBIT(L, n, res) \ + ((void)(res), luaL_checkinteger((L), (n))) +#else + +#define TOBIT(L, n, res) \ + ((lua_Integer)(((res) = luaL_checknumber(L, (n)) % BIT_UMAX), \ + (res) > BIT_MAX ? ((res) -= BIT_UMAX, (res) -= 1) : \ + ((res) < BIT_MIN ? ((res) += BIT_UMAX, (res) += 1) : (res)))) +#endif + + +#define BIT_TRUNCATE(i) \ + ((i) & BIT_UMAX) + + +/* Operations + + The macros MONADIC and VARIADIC only deal with bitwise operations. + + LOGICAL_SHIFT truncates its left-hand operand before shifting so + that any extra bits at the most-significant end are not shifted + into the result. + + ARITHMETIC_SHIFT does not truncate its left-hand operand, so that + the sign bits are not removed and right shift work properly. + */ + +#define MONADIC(name, op) \ + static int bit_ ## name(lua_State *L) { \ + lua_Number f; \ + lua_pushinteger(L, BIT_TRUNCATE(op TOBIT(L, 1, f))); \ + return 1; \ + } + +#define VARIADIC(name, op) \ + static int bit_ ## name(lua_State *L) { \ + lua_Number f; \ + int n = lua_gettop(L), i; \ + lua_Integer w = TOBIT(L, 1, f); \ + for (i = 2; i <= n; i++) \ + w op TOBIT(L, i, f); \ + lua_pushinteger(L, BIT_TRUNCATE(w)); \ + return 1; \ + } + +#define LOGICAL_SHIFT(name, op) \ + static int bit_ ## name(lua_State *L) { \ + lua_Number f; \ + lua_pushinteger(L, BIT_TRUNCATE(BIT_TRUNCATE((lua_UInteger)TOBIT(L, 1, f)) op \ + (unsigned)luaL_checknumber(L, 2))); \ + return 1; \ + } + +#define ARITHMETIC_SHIFT(name, op) \ + static int bit_ ## name(lua_State *L) { \ + lua_Number f; \ + lua_pushinteger(L, BIT_TRUNCATE((lua_Integer)TOBIT(L, 1, f) op \ + (unsigned)luaL_checknumber(L, 2))); \ + return 1; \ + } + +MONADIC(bnot, ~) +VARIADIC(band, &=) +VARIADIC(bor, |=) +VARIADIC(bxor, ^=) +ARITHMETIC_SHIFT(lshift, <<) +LOGICAL_SHIFT(rshift, >>) +ARITHMETIC_SHIFT(arshift, >>) + +static const struct luaL_reg bitlib[] = { + {"bnot", bit_bnot}, + {"band", bit_band}, + {"bor", bit_bor}, + {"bxor", bit_bxor}, + {"lshift", bit_lshift}, + {"rshift", bit_rshift}, + {"arshift", bit_arshift}, + {NULL, NULL} +}; + +LUALIB_API int luaopen_bit (lua_State *L) { + luaL_register(L, "bit", bitlib); + lua_pushnumber(L, BIT_BITS); + lua_setfield(L, -2, "bits"); + return 1; +} diff --git a/apps/plugins/lua/lualib.h b/apps/plugins/lua/lualib.h index 33d4e314c2..d4f69fc4af 100644 --- a/apps/plugins/lua/lualib.h +++ b/apps/plugins/lua/lualib.h @@ -39,6 +39,8 @@ LUALIB_API int (luaopen_debug) (lua_State *L); #define LUA_LOADLIBNAME "package" LUALIB_API int (luaopen_package) (lua_State *L); +#define LUA_BITLIBNAME "bit" +LUALIB_API int (luaopen_bit) (lua_State *L); /* open all previous libraries */ LUALIB_API void (luaL_openlibs) (lua_State *L); diff --git a/apps/plugins/lua/rocklua.c b/apps/plugins/lua/rocklua.c index 1162c026d1..98ffea8123 100644 --- a/apps/plugins/lua/rocklua.c +++ b/apps/plugins/lua/rocklua.c @@ -35,6 +35,7 @@ static const luaL_Reg lualibs[] = { {LUA_STRLIBNAME, luaopen_string}, {LUA_OSLIBNAME, luaopen_os}, {LUA_ROCKLIBNAME, luaopen_rock}, + {LUA_BITLIBNAME, luaopen_bit}, {NULL, NULL} }; |