summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2009-06-01 22:02:18 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2009-06-01 22:02:18 +0000
commit82eea9ed69886a4eaf41a1124b292635ca60fe9a (patch)
treedb6bb8849b433a8440770015de490327cbfb4195
parentc1d27d105c3333b5df67c97d88885efa2a49bc9a (diff)
downloadrockbox-82eea9ed69886a4eaf41a1124b292635ca60fe9a.tar.gz
rockbox-82eea9ed69886a4eaf41a1124b292635ca60fe9a.tar.bz2
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
-rw-r--r--apps/plugins/lua/SOURCES1
-rw-r--r--apps/plugins/lua/lbitlib.c125
-rw-r--r--apps/plugins/lua/lualib.h2
-rw-r--r--apps/plugins/lua/rocklua.c1
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}
};