1/*
2 * This is the bit32 library from lua 5.2.0, backported to
3 * lua 5.1.4.
4 *
5 * version 5.2.0-backport4
6 *
7 * This backport was assembled by Sean Bolton (sean at smbolton
8 * dot com) almost entirely from the above mentioned Lua distributions,
9 * which are:
10 *
11 * Copyright (C) 1994-2011 Lua.org, PUC-Rio. All rights reserved.
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
28 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
29 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
30 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 */
32
33#define LUA_LIB
34
35extern "C" {
36#if defined(_MSC_VER) || defined(ANDROID)
37#include <luajit/lua.h>
38#include <luajit/lualib.h>
39#include <luajit/lauxlib.h>
40#else
41#include <lua.h>
42#include <lualib.h>
43#include <lauxlib.h>
44#endif
45}
46
47/* ----- adapted from lua-5.2.0 luaconf.h: ----- */
48
49/*
50@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned.
51** It must have at least 32 bits.
52*/
53#ifndef LUAI_INT32
54#define LUAI_INT32 int
55#endif
56#define LUA_UNSIGNED unsigned LUAI_INT32
57
58#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
59
60/* On a Microsoft compiler on a Pentium, use assembler to avoid clashes
61 with a DirectX idiosyncrasy */
62#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */
63
64#define MS_ASMTRICK
65
66#else /* }{ */
67/* the next definition uses a trick that should work on any machine
68 using IEEE754 with a 32-bit integer type */
69
70#define LUA_IEEE754TRICK
71
72/*
73@@ LUA_IEEEENDIAN is the endianness of doubles in your machine
74** (0 for little endian, 1 for big endian); if not defined, Lua will
75** check it dynamically.
76*/
77/* check for known architectures */
78#if defined(__i386__) || defined(__i386) || defined(__X86__) || \
79 defined (__x86_64)
80#define LUA_IEEEENDIAN 0
81#elif defined(__POWERPC__) || defined(__ppc__)
82#define LUA_IEEEENDIAN 1
83#endif
84
85#endif /* } */
86
87#endif /* } */
88
89/* ----- from lua-5.2.0 lua.h: ----- */
90
91/* unsigned integer type */
92typedef LUA_UNSIGNED lua_Unsigned;
93
94/* ----- adapted from lua-5.2.0 llimits.h: ----- */
95
96/* lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned.
97** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number.
98*/
99
100#if defined(MS_ASMTRICK) /* { */
101/* trick with Microsoft assembler for X86 */
102
103#define lua_number2unsigned(i,n) \
104 {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;}
105
106#elif defined(LUA_IEEE754TRICK) /* }{ */
107/* the next trick should work on any machine using IEEE754 with
108 a 32-bit integer type */
109
110union luai_Cast2 { double l_d; LUAI_INT32 l_p[2]; };
111
112#if !defined(LUA_IEEEENDIAN) /* { */
113#define LUAI_EXTRAIEEE \
114 static const union luai_Cast2 ieeeendian = {-(33.0 + 6755399441055744.0)};
115#define LUA_IEEEENDIAN (ieeeendian.l_p[1] == 33)
116#else
117#define LUAI_EXTRAIEEE /* empty */
118#endif /* } */
119
120#define lua_number2int32(i,n,t) \
121 { LUAI_EXTRAIEEE \
122 volatile union luai_Cast2 u; u.l_d = (n) + 6755399441055744.0; \
123 (i) = (t)u.l_p[LUA_IEEEENDIAN]; }
124
125#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned)
126
127#endif /* } */
128
129#if !defined(lua_number2unsigned) /* { */
130/* the following definition assures proper modulo behavior */
131#if defined(LUA_NUMBER_DOUBLE)
132#include <math.h>
133#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1)
134#define lua_number2unsigned(i,n) \
135 ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED))
136#else
137#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n))
138#endif
139#endif /* } */
140
141/* on several machines, coercion from unsigned to double is slow,
142 so it may be worth to avoid */
143#define lua_unsigned2number(u) \
144 (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u))
145
146/* ----- adapted from lua-5.2.0 lapi.c: ----- */
147
148static void lua_pushunsigned (lua_State *L, lua_Unsigned u) {
149 lua_Number n;
150 n = lua_unsigned2number(u);
151 lua_pushnumber(L, n);
152}
153
154/* ----- adapted from lua-5.2.0-work3 lbitlib.c getuintarg(): ----- */
155
156static lua_Unsigned luaL_checkunsigned (lua_State *L, int arg) {
157 lua_Unsigned r;
158 lua_Number x = lua_tonumber(L, arg);
159 if (x == 0) luaL_checktype(L, arg, LUA_TNUMBER);
160 lua_number2unsigned(r, x);
161 return r;
162}
163
164/* ----- Lua 5.2 luaL_newlib() compatibility: ----- */
165
166#define LUAMOD_API LUALIB_API
167#define LUA_BIT32LIBNAME "bit32"
168#define luaL_newlib(x, y) luaL_register(x, LUA_BIT32LIBNAME, y)
169
170/* ----- avoid a 'symbol redefined' warning below ----- */
171
172#undef LUA_LIB
173
174/* ----- here follows the unmodified lbitlib.c from Lua 5.2.0 ----- */
175
176/*
177** $Id: lbitlib.c,v 1.16 2011/06/20 16:35:23 roberto Exp $
178** Standard library for bitwise operations
179** See Copyright Notice in lua.h
180*/
181
182#define lbitlib_c
183#define LUA_LIB
184
185
186/* number of bits to consider in a number */
187#if !defined(LUA_NBITS)
188#define LUA_NBITS 32
189#endif
190
191
192#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1))
193
194/* macro to trim extra bits */
195#define trim(x) ((x) & ALLONES)
196
197
198/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */
199#define mask(n) (~((ALLONES << 1) << ((n) - 1)))
200
201
202typedef lua_Unsigned b_uint;
203
204
205
206static b_uint andaux (lua_State *L) {
207 int i, n = lua_gettop(L);
208 b_uint r = ~(b_uint)0;
209 for (i = 1; i <= n; i++)
210 r &= luaL_checkunsigned(L, i);
211 return trim(r);
212}
213
214
215static int b_and (lua_State *L) {
216 b_uint r = andaux(L);
217 lua_pushunsigned(L, r);
218 return 1;
219}
220
221
222static int b_test (lua_State *L) {
223 b_uint r = andaux(L);
224 lua_pushboolean(L, r != 0);
225 return 1;
226}
227
228
229static int b_or (lua_State *L) {
230 int i, n = lua_gettop(L);
231 b_uint r = 0;
232 for (i = 1; i <= n; i++)
233 r |= luaL_checkunsigned(L, i);
234 lua_pushunsigned(L, trim(r));
235 return 1;
236}
237
238
239static int b_xor (lua_State *L) {
240 int i, n = lua_gettop(L);
241 b_uint r = 0;
242 for (i = 1; i <= n; i++)
243 r ^= luaL_checkunsigned(L, i);
244 lua_pushunsigned(L, trim(r));
245 return 1;
246}
247
248
249static int b_not (lua_State *L) {
250 b_uint r = ~luaL_checkunsigned(L, 1);
251 lua_pushunsigned(L, trim(r));
252 return 1;
253}
254
255
256static int b_shift (lua_State *L, b_uint r, int i) {
257 if (i < 0) { /* shift right? */
258 i = -i;
259 r = trim(r);
260 if (i >= LUA_NBITS) r = 0;
261 else r >>= i;
262 }
263 else { /* shift left */
264 if (i >= LUA_NBITS) r = 0;
265 else r <<= i;
266 r = trim(r);
267 }
268 lua_pushunsigned(L, r);
269 return 1;
270}
271
272
273static int b_lshift (lua_State *L) {
274 return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2));
275}
276
277
278static int b_rshift (lua_State *L) {
279 return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2));
280}
281
282
283static int b_arshift (lua_State *L) {
284 b_uint r = luaL_checkunsigned(L, 1);
285 int i = luaL_checkint(L, 2);
286 if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1))))
287 return b_shift(L, r, -i);
288 else { /* arithmetic shift for 'negative' number */
289 if (i >= LUA_NBITS) r = ALLONES;
290 else
291 r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */
292 lua_pushunsigned(L, r);
293 return 1;
294 }
295}
296
297
298static int b_rot (lua_State *L, int i) {
299 b_uint r = luaL_checkunsigned(L, 1);
300 i &= (LUA_NBITS - 1); /* i = i % NBITS */
301 r = trim(r);
302 r = (r << i) | (r >> (LUA_NBITS - i));
303 lua_pushunsigned(L, trim(r));
304 return 1;
305}
306
307
308static int b_lrot (lua_State *L) {
309 return b_rot(L, luaL_checkint(L, 2));
310}
311
312
313static int b_rrot (lua_State *L) {
314 return b_rot(L, -luaL_checkint(L, 2));
315}
316
317
318/*
319** get field and width arguments for field-manipulation functions,
320** checking whether they are valid
321*/
322static int fieldargs (lua_State *L, int farg, int *width) {
323 int f = luaL_checkint(L, farg);
324 int w = luaL_optint(L, farg + 1, 1);
325 luaL_argcheck(L, 0 <= f, farg, "field cannot be negative");
326 luaL_argcheck(L, 0 < w, farg + 1, "width must be positive");
327 if (f + w > LUA_NBITS)
328 luaL_error(L, "trying to access non-existent bits");
329 *width = w;
330 return f;
331}
332
333
334static int b_extract (lua_State *L) {
335 int w;
336 b_uint r = luaL_checkunsigned(L, 1);
337 int f = fieldargs(L, 2, &w);
338 r = (r >> f) & mask(w);
339 lua_pushunsigned(L, r);
340 return 1;
341}
342
343
344static int b_replace (lua_State *L) {
345 int w;
346 b_uint r = luaL_checkunsigned(L, 1);
347 b_uint v = luaL_checkunsigned(L, 2);
348 int f = fieldargs(L, 3, &w);
349 int m = mask(w);
350 v &= m; /* erase bits outside given width */
351 r = (r & ~(m << f)) | (v << f);
352 lua_pushunsigned(L, r);
353 return 1;
354}
355
356
357static const luaL_Reg bitlib[] = {
358 {"arshift", b_arshift},
359 {"band", b_and},
360 {"bnot", b_not},
361 {"bor", b_or},
362 {"bxor", b_xor},
363 {"btest", b_test},
364 {"extract", b_extract},
365 {"lrotate", b_lrot},
366 {"lshift", b_lshift},
367 {"replace", b_replace},
368 {"rrotate", b_rrot},
369 {"rshift", b_rshift},
370 {NULL, NULL}
371};
372
373int luaopen_bit32 (lua_State *L) {
374 luaL_newlib(L, bitlib);
375 return 1;
376}
377
378#undef trim
379
380