1 /*
2 ** $Id: lbitlib.c,v 1.28 2014/11/02 19:19:04 roberto Exp $
3 ** Standard library for bitwise operations
4 ** See Copyright Notice in lua.h
5 */
6 
7 #define lbitlib_c
8 #define LUA_LIB
9 
10 #include "lprefix.h"
11 
12 
13 #include "lua.h"
14 
15 #include "lauxlib.h"
16 #include "lualib.h"
17 
18 
19 #if defined(LUA_COMPAT_BITLIB)		/* { */
20 
21 
22 /* number of bits to consider in a number */
23 #if !defined(LUA_NBITS)
24 #define LUA_NBITS	32
25 #endif
26 
27 
28 /*
29 ** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must
30 ** be made in two parts to avoid problems when LUA_NBITS is equal to the
31 ** number of bits in a lua_Unsigned.)
32 */
33 #define ALLONES		(~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
34 
35 
36 /* macro to trim extra bits */
37 #define trim(x)		((x) & ALLONES)
38 
39 
40 /* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
41 #define mask(n)		(~((ALLONES << 1) << ((n) - 1)))
42 
43 
44 
andaux(lua_State * L)45 static lua_Unsigned andaux (lua_State *L) {
46   int i, n = lua_gettop(L);
47   lua_Unsigned r = ~(lua_Unsigned)0;
48   for (i = 1; i <= n; i++)
49     r &= luaL_checkunsigned(L, i);
50   return trim(r);
51 }
52 
53 
b_and(lua_State * L)54 static int b_and (lua_State *L) {
55   lua_Unsigned r = andaux(L);
56   lua_pushunsigned(L, r);
57   return 1;
58 }
59 
60 
b_test(lua_State * L)61 static int b_test (lua_State *L) {
62   lua_Unsigned r = andaux(L);
63   lua_pushboolean(L, r != 0);
64   return 1;
65 }
66 
67 
b_or(lua_State * L)68 static int b_or (lua_State *L) {
69   int i, n = lua_gettop(L);
70   lua_Unsigned r = 0;
71   for (i = 1; i <= n; i++)
72     r |= luaL_checkunsigned(L, i);
73   lua_pushunsigned(L, trim(r));
74   return 1;
75 }
76 
77 
b_xor(lua_State * L)78 static int b_xor (lua_State *L) {
79   int i, n = lua_gettop(L);
80   lua_Unsigned r = 0;
81   for (i = 1; i <= n; i++)
82     r ^= luaL_checkunsigned(L, i);
83   lua_pushunsigned(L, trim(r));
84   return 1;
85 }
86 
87 
b_not(lua_State * L)88 static int b_not (lua_State *L) {
89   lua_Unsigned r = ~luaL_checkunsigned(L, 1);
90   lua_pushunsigned(L, trim(r));
91   return 1;
92 }
93 
94 
b_shift(lua_State * L,lua_Unsigned r,lua_Integer i)95 static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) {
96   if (i < 0) {  /* shift right? */
97     i = -i;
98     r = trim(r);
99     if (i >= LUA_NBITS) r = 0;
100     else r >>= i;
101   }
102   else {  /* shift left */
103     if (i >= LUA_NBITS) r = 0;
104     else r <<= i;
105     r = trim(r);
106   }
107   lua_pushunsigned(L, r);
108   return 1;
109 }
110 
111 
b_lshift(lua_State * L)112 static int b_lshift (lua_State *L) {
113   return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkinteger(L, 2));
114 }
115 
116 
b_rshift(lua_State * L)117 static int b_rshift (lua_State *L) {
118   return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkinteger(L, 2));
119 }
120 
121 
b_arshift(lua_State * L)122 static int b_arshift (lua_State *L) {
123   lua_Unsigned r = luaL_checkunsigned(L, 1);
124   lua_Integer i = luaL_checkinteger(L, 2);
125   if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1))))
126     return b_shift(L, r, -i);
127   else {  /* arithmetic shift for 'negative' number */
128     if (i >= LUA_NBITS) r = ALLONES;
129     else
130       r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i));  /* add signal bit */
131     lua_pushunsigned(L, r);
132     return 1;
133   }
134 }
135 
136 
b_rot(lua_State * L,lua_Integer d)137 static int b_rot (lua_State *L, lua_Integer d) {
138   lua_Unsigned r = luaL_checkunsigned(L, 1);
139   int i = d & (LUA_NBITS - 1);  /* i = d % NBITS */
140   r = trim(r);
141   if (i != 0)  /* avoid undefined shift of LUA_NBITS when i == 0 */
142     r = (r << i) | (r >> (LUA_NBITS - i));
143   lua_pushunsigned(L, trim(r));
144   return 1;
145 }
146 
147 
b_lrot(lua_State * L)148 static int b_lrot (lua_State *L) {
149   return b_rot(L, luaL_checkinteger(L, 2));
150 }
151 
152 
b_rrot(lua_State * L)153 static int b_rrot (lua_State *L) {
154   return b_rot(L, -luaL_checkinteger(L, 2));
155 }
156 
157 
158 /*
159 ** get field and width arguments for field-manipulation functions,
160 ** checking whether they are valid.
161 ** ('luaL_error' called without 'return' to avoid later warnings about
162 ** 'width' being used uninitialized.)
163 */
fieldargs(lua_State * L,int farg,int * width)164 static int fieldargs (lua_State *L, int farg, int *width) {
165   lua_Integer f = luaL_checkinteger(L, farg);
166   lua_Integer w = luaL_optinteger(L, farg + 1, 1);
167   luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
168   luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
169   if (f + w > LUA_NBITS)
170     luaL_error(L, "trying to access non-existent bits");
171   *width = (int)w;
172   return (int)f;
173 }
174 
175 
b_extract(lua_State * L)176 static int b_extract (lua_State *L) {
177   int w;
178   lua_Unsigned r = trim(luaL_checkunsigned(L, 1));
179   int f = fieldargs(L, 2, &w);
180   r = (r >> f) & mask(w);
181   lua_pushunsigned(L, r);
182   return 1;
183 }
184 
185 
b_replace(lua_State * L)186 static int b_replace (lua_State *L) {
187   int w;
188   lua_Unsigned r = trim(luaL_checkunsigned(L, 1));
189   lua_Unsigned v = luaL_checkunsigned(L, 2);
190   int f = fieldargs(L, 3, &w);
191   int m = mask(w);
192   v &= m;  /* erase bits outside given width */
193   r = (r & ~(m << f)) | (v << f);
194   lua_pushunsigned(L, r);
195   return 1;
196 }
197 
198 
199 static const luaL_Reg bitlib[] = {
200   {"arshift", b_arshift},
201   {"band", b_and},
202   {"bnot", b_not},
203   {"bor", b_or},
204   {"bxor", b_xor},
205   {"btest", b_test},
206   {"extract", b_extract},
207   {"lrotate", b_lrot},
208   {"lshift", b_lshift},
209   {"replace", b_replace},
210   {"rrotate", b_rrot},
211   {"rshift", b_rshift},
212   {NULL, NULL}
213 };
214 
215 
216 
luaopen_bit32(lua_State * L)217 LUAMOD_API int luaopen_bit32 (lua_State *L) {
218   luaL_newlib(L, bitlib);
219   return 1;
220 }
221 
222 
223 #else					/* }{ */
224 
225 
luaopen_bit32(lua_State * L)226 LUAMOD_API int luaopen_bit32 (lua_State *L) {
227   return luaL_error(L, "library 'bit32' has been deprecated");
228 }
229 
230 #endif					/* } */
231