etc/protocols - sync with NetBSD-8
[minix.git] / external / mit / lua / dist / src / lbitlib.c
blob37b50b9adfb93dc3643bbdcd1c1f5115f1364c88
1 /*
2 ** $Id: lbitlib.c,v 1.2 2015/02/02 14:03:05 lneto Exp $
3 ** Standard library for bitwise operations
4 ** See Copyright Notice in lua.h
5 */
7 #define lbitlib_c
8 #define LUA_LIB
10 #include "lprefix.h"
13 #include "lua.h"
15 #include "lauxlib.h"
16 #include "lualib.h"
19 #if defined(LUA_COMPAT_BITLIB) /* { */
22 /* number of bits to consider in a number */
23 #if !defined(LUA_NBITS)
24 #define LUA_NBITS 32
25 #endif
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.)
33 #define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
36 /* macro to trim extra bits */
37 #define trim(x) ((x) & ALLONES)
40 /* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
41 #define mask(n) (~((ALLONES << 1) << ((n) - 1)))
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);
54 static int b_and (lua_State *L) {
55 lua_Unsigned r = andaux(L);
56 lua_pushunsigned(L, r);
57 return 1;
61 static int b_test (lua_State *L) {
62 lua_Unsigned r = andaux(L);
63 lua_pushboolean(L, r != 0);
64 return 1;
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;
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;
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;
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;
102 else { /* shift left */
103 if (i >= LUA_NBITS) r = 0;
104 else r <<= i;
105 r = trim(r);
107 lua_pushunsigned(L, r);
108 return 1;
112 static int b_lshift (lua_State *L) {
113 return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkinteger(L, 2));
117 static int b_rshift (lua_State *L) {
118 return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkinteger(L, 2));
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;
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;
148 static int b_lrot (lua_State *L) {
149 return b_rot(L, luaL_checkinteger(L, 2));
153 static int b_rrot (lua_State *L) {
154 return b_rot(L, -luaL_checkinteger(L, 2));
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.)
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;
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;
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;
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}
217 LUAMOD_API int luaopen_bit32 (lua_State *L) {
218 luaL_newlib(L, bitlib);
219 return 1;
223 #else /* }{ */
226 LUAMOD_API int luaopen_bit32 (lua_State *L) {
227 return luaL_error(L, "library 'bit32' has been deprecated");
230 #endif /* } */