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