2
** $Id: lbitlib.c,v 1.18 2013/03/19 13:19:12 roberto Exp $
3
** Standard library for bitwise operations
4
** See Copyright Notice in lua.h
16
/* number of bits to consider in a number */
17
#if !defined(LUA_NBITS)
22
#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
24
/* macro to trim extra bits */
25
#define trim(x) ((x) & ALLONES)
28
/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
29
#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
32
typedef lua_Unsigned b_uint;
36
static b_uint andaux (lua_State *L) {
37
int i, n = lua_gettop(L);
38
b_uint r = ~(b_uint)0;
39
for (i = 1; i <= n; i++)
40
r &= luaL_checkunsigned(L, i);
45
static int b_and (lua_State *L) {
47
lua_pushunsigned(L, r);
52
static int b_test (lua_State *L) {
54
lua_pushboolean(L, r != 0);
59
static int b_or (lua_State *L) {
60
int i, n = lua_gettop(L);
62
for (i = 1; i <= n; i++)
63
r |= luaL_checkunsigned(L, i);
64
lua_pushunsigned(L, trim(r));
69
static int b_xor (lua_State *L) {
70
int i, n = lua_gettop(L);
72
for (i = 1; i <= n; i++)
73
r ^= luaL_checkunsigned(L, i);
74
lua_pushunsigned(L, trim(r));
79
static int b_not (lua_State *L) {
80
b_uint r = ~luaL_checkunsigned(L, 1);
81
lua_pushunsigned(L, trim(r));
86
static int b_shift (lua_State *L, b_uint r, int i) {
87
if (i < 0) { /* shift right? */
90
if (i >= LUA_NBITS) r = 0;
93
else { /* shift left */
94
if (i >= LUA_NBITS) r = 0;
98
lua_pushunsigned(L, r);
103
static int b_lshift (lua_State *L) {
104
return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2));
108
static int b_rshift (lua_State *L) {
109
return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2));
113
static int b_arshift (lua_State *L) {
114
b_uint r = luaL_checkunsigned(L, 1);
115
int i = luaL_checkint(L, 2);
116
if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1))))
117
return b_shift(L, r, -i);
118
else { /* arithmetic shift for 'negative' number */
119
if (i >= LUA_NBITS) r = ALLONES;
121
r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */
122
lua_pushunsigned(L, r);
128
static int b_rot (lua_State *L, int i) {
129
b_uint r = luaL_checkunsigned(L, 1);
130
i &= (LUA_NBITS - 1); /* i = i % NBITS */
132
r = (r << i) | (r >> (LUA_NBITS - i));
133
lua_pushunsigned(L, trim(r));
138
static int b_lrot (lua_State *L) {
139
return b_rot(L, luaL_checkint(L, 2));
143
static int b_rrot (lua_State *L) {
144
return b_rot(L, -luaL_checkint(L, 2));
149
** get field and width arguments for field-manipulation functions,
150
** checking whether they are valid.
151
** ('luaL_error' called without 'return' to avoid later warnings about
152
** 'width' being used uninitialized.)
154
static int fieldargs (lua_State *L, int farg, int *width) {
155
int f = luaL_checkint(L, farg);
156
int w = luaL_optint(L, farg + 1, 1);
157
luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
158
luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
159
if (f + w > LUA_NBITS)
160
luaL_error(L, "trying to access non-existent bits");
166
static int b_extract (lua_State *L) {
168
b_uint r = luaL_checkunsigned(L, 1);
169
int f = fieldargs(L, 2, &w);
170
r = (r >> f) & mask(w);
171
lua_pushunsigned(L, r);
176
static int b_replace (lua_State *L) {
178
b_uint r = luaL_checkunsigned(L, 1);
179
b_uint v = luaL_checkunsigned(L, 2);
180
int f = fieldargs(L, 3, &w);
182
v &= m; /* erase bits outside given width */
183
r = (r & ~(m << f)) | (v << f);
184
lua_pushunsigned(L, r);
189
static const luaL_Reg bitlib[] = {
190
{"arshift", b_arshift},
196
{"extract", b_extract},
198
{"lshift", b_lshift},
199
{"replace", b_replace},
201
{"rshift", b_rshift},
207
LUAMOD_API int luaopen_bit32 (lua_State *L) {
208
luaL_newlib(L, bitlib);