xref: /illumos-gate/usr/src/uts/common/fs/zfs/lua/lbitlib.c (revision e86372a01d2d16a5dd4a64e144ed978ba17fe7dd)
1 /*
2 ** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 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 "lua.h"
11 
12 #include "lauxlib.h"
13 #include "lualib.h"
14 
15 
16 /* number of bits to consider in a number */
17 #if !defined(LUA_NBITS)
18 #define LUA_NBITS	32
19 #endif
20 
21 
22 #define ALLONES		(~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
23 
24 /* macro to trim extra bits */
25 #define trim(x)		((x) & ALLONES)
26 
27 
28 /* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
29 #define mask(n)		(~((ALLONES << 1) << ((n) - 1)))
30 
31 
32 typedef lua_Unsigned b_uint;
33 
34 
35 
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);
41   return trim(r);
42 }
43 
44 
45 static int b_and (lua_State *L) {
46   b_uint r = andaux(L);
47   lua_pushunsigned(L, r);
48   return 1;
49 }
50 
51 
52 static int b_test (lua_State *L) {
53   b_uint r = andaux(L);
54   lua_pushboolean(L, r != 0);
55   return 1;
56 }
57 
58 
59 static int b_or (lua_State *L) {
60   int i, n = lua_gettop(L);
61   b_uint r = 0;
62   for (i = 1; i <= n; i++)
63     r |= luaL_checkunsigned(L, i);
64   lua_pushunsigned(L, trim(r));
65   return 1;
66 }
67 
68 
69 static int b_xor (lua_State *L) {
70   int i, n = lua_gettop(L);
71   b_uint r = 0;
72   for (i = 1; i <= n; i++)
73     r ^= luaL_checkunsigned(L, i);
74   lua_pushunsigned(L, trim(r));
75   return 1;
76 }
77 
78 
79 static int b_not (lua_State *L) {
80   b_uint r = ~luaL_checkunsigned(L, 1);
81   lua_pushunsigned(L, trim(r));
82   return 1;
83 }
84 
85 
86 static int b_shift (lua_State *L, b_uint r, int i) {
87   if (i < 0) {  /* shift right? */
88     i = -i;
89     r = trim(r);
90     if (i >= LUA_NBITS) r = 0;
91     else r >>= i;
92   }
93   else {  /* shift left */
94     if (i >= LUA_NBITS) r = 0;
95     else r <<= i;
96     r = trim(r);
97   }
98   lua_pushunsigned(L, r);
99   return 1;
100 }
101 
102 
103 static int b_lshift (lua_State *L) {
104   return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2));
105 }
106 
107 
108 static int b_rshift (lua_State *L) {
109   return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2));
110 }
111 
112 
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;
120     else
121       r = trim((r >> i) | ~(~(b_uint)0 >> i));  /* add signal bit */
122     lua_pushunsigned(L, r);
123     return 1;
124   }
125 }
126 
127 
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 */
131   r = trim(r);
132   if (i != 0)  /* avoid undefined shift of LUA_NBITS when i == 0 */
133     r = (r << i) | (r >> (LUA_NBITS - i));
134   lua_pushunsigned(L, trim(r));
135   return 1;
136 }
137 
138 
139 static int b_lrot (lua_State *L) {
140   return b_rot(L, luaL_checkint(L, 2));
141 }
142 
143 
144 static int b_rrot (lua_State *L) {
145   return b_rot(L, -luaL_checkint(L, 2));
146 }
147 
148 
149 /*
150 ** get field and width arguments for field-manipulation functions,
151 ** checking whether they are valid.
152 ** ('luaL_error' called without 'return' to avoid later warnings about
153 ** 'width' being used uninitialized.)
154 */
155 static int fieldargs (lua_State *L, int farg, int *width) {
156   int f = luaL_checkint(L, farg);
157   int w = luaL_optint(L, farg + 1, 1);
158   luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
159   luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
160   if (f + w > LUA_NBITS)
161     luaL_error(L, "trying to access non-existent bits");
162   *width = w;
163   return f;
164 }
165 
166 
167 static int b_extract (lua_State *L) {
168   int w;
169   b_uint r = luaL_checkunsigned(L, 1);
170   int f = fieldargs(L, 2, &w);
171   r = (r >> f) & mask(w);
172   lua_pushunsigned(L, r);
173   return 1;
174 }
175 
176 
177 static int b_replace (lua_State *L) {
178   int w;
179   b_uint r = luaL_checkunsigned(L, 1);
180   b_uint v = luaL_checkunsigned(L, 2);
181   int f = fieldargs(L, 3, &w);
182   int m = mask(w);
183   v &= m;  /* erase bits outside given width */
184   r = (r & ~(m << f)) | (v << f);
185   lua_pushunsigned(L, r);
186   return 1;
187 }
188 
189 
190 static const luaL_Reg bitlib[] = {
191   {"arshift", b_arshift},
192   {"band", b_and},
193   {"bnot", b_not},
194   {"bor", b_or},
195   {"bxor", b_xor},
196   {"btest", b_test},
197   {"extract", b_extract},
198   {"lrotate", b_lrot},
199   {"lshift", b_lshift},
200   {"replace", b_replace},
201   {"rrotate", b_rrot},
202   {"rshift", b_rshift},
203   {NULL, NULL}
204 };
205 
206 
207 
208 LUAMOD_API int luaopen_bit32 (lua_State *L) {
209   luaL_newlib(L, bitlib);
210   return 1;
211 }
212 
213