mudgangster

Tiny, scriptable MUD client
Log | Files | Refs | README

lbitlib.cc (4963B)


      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 
     49 static 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 
     58 static int b_and (lua_State *L) {
     59   lua_Unsigned r = andaux(L);
     60   pushunsigned(L, r);
     61   return 1;
     62 }
     63 
     64 
     65 static int b_test (lua_State *L) {
     66   lua_Unsigned r = andaux(L);
     67   lua_pushboolean(L, r != 0);
     68   return 1;
     69 }
     70 
     71 
     72 static 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 
     82 static 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 
     92 static int b_not (lua_State *L) {
     93   lua_Unsigned r = ~checkunsigned(L, 1);
     94   pushunsigned(L, trim(r));
     95   return 1;
     96 }
     97 
     98 
     99 static 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 
    116 static int b_lshift (lua_State *L) {
    117   return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2));
    118 }
    119 
    120 
    121 static int b_rshift (lua_State *L) {
    122   return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2));
    123 }
    124 
    125 
    126 static 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 
    141 static 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 
    152 static int b_lrot (lua_State *L) {
    153   return b_rot(L, luaL_checkinteger(L, 2));
    154 }
    155 
    156 
    157 static 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 */
    168 static 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 
    180 static 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 
    190 static 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 
    202 static 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 
    220 LUAMOD_API int luaopen_bit32 (lua_State *L) {
    221   luaL_newlib(L, bitlib);
    222   return 1;
    223 }
    224 
    225 
    226 #else					/* }{ */
    227 
    228 
    229 LUAMOD_API int luaopen_bit32 (lua_State *L) {
    230   return luaL_error(L, "library 'bit32' has been deprecated");
    231 }
    232 
    233 #endif					/* } */