]> git.lizzy.rs Git - metalua.git/blob - src/binlibs/bit.c
CRLF fsckup
[metalua.git] / src / binlibs / bit.c
1 /* Bitwise operations library */
2 /* (c) Reuben Thomas 2000-2008 */
3 /* See README for license */
4
5 /* Metalua: no automake/autoconf goo pleaaaze! :) */
6 /* #include "config.h" */
7
8 #include <lua.h>
9 #include <lauxlib.h>
10
11 /* FIXME: Should really use limits of lua_Integer (currently not given
12    by Lua); the code below assumes that lua_Integer is ptrdiff_t, that
13    size_t is the same as unsigned ptrdiff_t, and that lua_Number is
14    floating-point and fits in a double (use of fmod). */
15 #ifdef BUILTIN_CAST
16 #define TOINTEGER(L, n, f)                      \
17   ((void)(f),                                   \
18    luaL_checkinteger((L), (n)))
19 #else
20 #include <stdint.h>
21 #include <math.h>
22
23 #define TOINTEGER(L, n, f)                                              \
24   ((ptrdiff_t)(((f) = fmod(luaL_checknumber((L), (n)), (double)SIZE_MAX)), \
25                (f) > PTRDIFF_MAX ? ((f) -= SIZE_MAX + 1) :              \
26                ((f) < PTRDIFF_MIN ? ((f) += SIZE_MAX + 1) : (f))))
27 #endif
28
29 #define TDYADIC(name, op)                                 \
30   static int bit_ ## name(lua_State *L) {                 \
31     lua_Number f;                                         \
32     lua_Integer w = TOINTEGER(L, 1, f);                   \
33     lua_pushinteger(L, w op TOINTEGER(L, 2, f));          \
34     return 1;                                             \
35   }
36
37 #define MONADIC(name, op)                                 \
38   static int bit_ ## name(lua_State *L) {                 \
39     lua_Number f;                                         \
40     lua_pushinteger(L, op TOINTEGER(L, 1, f));            \
41     return 1;                                             \
42   }
43
44 #define VARIADIC(name, op)                      \
45   static int bit_ ## name(lua_State *L) {       \
46     lua_Number f;                               \
47     int n = lua_gettop(L), i;                   \
48     lua_Integer w = TOINTEGER(L, 1, f);         \
49     for (i = 2; i <= n; i++)                    \
50       w op TOINTEGER(L, i, f);                  \
51     lua_pushinteger(L, w);                      \
52     return 1;                                   \
53   }
54
55 MONADIC(cast,    +)
56 MONADIC(bnot,    ~)
57 VARIADIC(band,   &=)
58 VARIADIC(bor,    |=)
59 VARIADIC(bxor,   ^=)
60 TDYADIC(lshift,  <<)
61 TDYADIC(rshift,  >>)
62 TDYADIC(arshift, >>)
63
64 static const struct luaL_reg bitlib[] = {
65   {"cast",    bit_cast},
66   {"bnot",    bit_bnot},
67   {"band",    bit_band},
68   {"bor",     bit_bor},
69   {"bxor",    bit_bxor},
70   {"lshift",  bit_lshift},
71   {"rshift",  bit_rshift},
72   {"arshift", bit_arshift},
73   {NULL, NULL}
74 };
75
76 LUALIB_API int luaopen_bit (lua_State *L) {
77   luaL_openlib(L, "bit", bitlib, 0);
78   return 1;
79 }