[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: PATCH: hex numbers and bit ops
- From: Mike Pall <mikelu-0509@...>
- Date: Sun, 4 Sep 2005 23:52:39 +0200
Hi,
this is a patch relative to Lua 5.1 alpha:
- The lexer now parses hex numbers (e.g. 0x1234 == 4660).
- luaO_str2d has a fallback for non C99 compliant systems
(used by tonumber() and by the lexer).
- String literals allow hex escape sequences (e.g. "\x40" == "@").
- New bit operations:
y = math.bitor(x1, x2)
y = math.bitand(x1 [, x2]) x2 = -1 if omitted (i.e. tobit)
y = math.bitxor(x1 [, x2]) x2 = -1 if omitted (i.e. bitnot)
y... = math.bitfield(x, start [, len] ...)
'start' is the bit position relative to the lsb (bit 0)
It's a right/left shift for a positive/negative 'start'.
It's a pure shift if 'len' is omitted.
Otherwise the result is masked to 'len' valid bits.
Examples:
bitand(120.123) --> 120
bitxor(120) --> -121
bitor(0x5aff, 0xa5f0) --> 0xffff
bitand(0x5aff, 0xa5f0) --> 0x00f0
bitxor(0x5aff, 0xa5f0) --> 0xff0f
bitfield(0x345678, 8) --> 0x3456
bitfield(0x345678, -8) --> 0x34567800
bitfield(0x345678, 8, 8) --> 0x56
bitfield(0x345678, -8, 8) --> 0x7800
bitfield(0x345678, 3, 10) --> 0x2cf
bitfield(0x345678, 0,8, 8,8, 16,8) --> 0x78 0x56 0x34
- Restrictions:
- Non C99 compliant systems only support hex integer syntax
but not hex FP syntax (0xa.1p4).
- The precision of bit operations is limited by the minimum
precision of lua_Number and lua_Integer (ptrdiff_t). The
practical limit is usually at least 32 bits (only 24 bits
when lua_Number is a float). Bit operations work fine with
negative numbers and may produce negative numbers, too.
Bye,
Mike
diff -u lua-5.1-alpha/src/llex.c lua51alpha-hex/src/llex.c
--- lua-5.1-alpha/src/llex.c 2005-05-17 21:49:15 +0200
+++ lua51alpha-hex/src/llex.c 2005-09-04 22:46:44 +0200
@@ -158,9 +158,17 @@
/* LUA_NUMBER */
static void read_numeral (LexState *ls, SemInfo *seminfo) {
+ int hex = 0;
while (isdigit(ls->current)) {
save_and_next(ls);
}
+ if (ls->current == 'x' || ls->current == 'X') {
+ save_and_next(ls); /* read `x' */
+ while (isxdigit(ls->current)) {
+ save_and_next(ls);
+ }
+ hex = 1;
+ }
if (ls->current == '.') {
save_and_next(ls);
if (ls->current == '.') {
@@ -170,14 +178,15 @@
TK_NUMBER);
}
}
- while (isdigit(ls->current)) {
+ while (hex ? isxdigit(ls->current) : isdigit(ls->current)) {
save_and_next(ls);
}
- if (ls->current == 'e' || ls->current == 'E') {
+ if (hex ? (ls->current == 'p' || ls->current == 'P') :
+ (ls->current == 'e' || ls->current == 'E')) {
save_and_next(ls); /* read `E' */
if (ls->current == '+' || ls->current == '-')
save_and_next(ls); /* optional exponent sign */
- while (isdigit(ls->current)) {
+ while (hex ? isxdigit(ls->current) : isdigit(ls->current)) {
save_and_next(ls);
}
}
@@ -277,6 +286,18 @@
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'v': c = '\v'; break;
+ case 'x':
+ next(ls);
+ if (isxdigit(ls->current)) {
+ c = ((ls->current & 15) + (isdigit(ls->current) ? 0 : 9)) << 4;
+ next(ls);
+ if (isxdigit(ls->current)) {
+ c += (ls->current & 15) + (isdigit(ls->current) ? 0 : 9);
+ break;
+ }
+ }
+ luaX_lexerror(ls, "bad hex escape sequence", TK_STRING);
+ return;
case '\n': /* go through */
case '\r': save(ls, '\n'); inclinenumber(ls); continue;
case EOZ: continue; /* will raise an error next loop */
diff -u lua-5.1-alpha/src/lobject.c lua51alpha-hex/src/lobject.c
--- lua-5.1-alpha/src/lobject.c 2005-08-01 06:22:23 +0200
+++ lua51alpha-hex/src/lobject.c 2005-09-04 22:46:44 +0200
@@ -90,11 +90,22 @@
int luaO_str2d (const char *s, lua_Number *result) {
char *endptr;
*result = lua_str2number(s, &endptr);
- if (endptr == s) return 0; /* conversion failed */
- if (*endptr == '\0') return 1; /* most common case */
- while (isspace(cast(unsigned char, *endptr))) endptr++;
- if (*endptr != '\0') return 0; /* invalid trailing characters? */
- return 1;
+ if (endptr != s) { /* at least one char was accepted */
+ if (*endptr == '\0') return 1; /* most common case */
+ while (isspace(cast(unsigned char, *endptr))) endptr++;
+ if (*endptr == '\0') return 1; /* ok, only trailing spaces */
+ }
+ /* fallback for non C99 compliant systems */
+ if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
+ lua_Number n = 0;
+ for (s += 2; isxdigit(*s); s++)
+ n = n * 16 + (*s & 15) + (isdigit(*s) ? 0 : 9);
+ if (*s == '\0') {
+ *result = n;
+ return 1; /* ok */
+ }
+ }
+ return 0; /* conversion failed */
}
diff -u lua-5.1-alpha/src/lmathlib.c lua51alpha-hex/src/lmathlib.c
--- lua-5.1-alpha/src/lmathlib.c 2005-08-26 19:36:32 +0200
+++ lua51alpha-hex/src/lmathlib.c 2005-09-04 22:46:44 +0200
@@ -212,6 +212,43 @@
}
+static int bit_and (lua_State *L) { /* aka tobit */
+ lua_pushinteger(L, luaL_checkinteger(L, 1) & luaL_optinteger(L, 2, -1));
+ return 1;
+}
+
+
+static int bit_or (lua_State *L) {
+ lua_pushinteger(L, luaL_checkinteger(L, 1) | luaL_checkinteger(L, 2));
+ return 1;
+}
+
+
+static int bit_xor (lua_State *L) { /* aka bitnot */
+ lua_pushinteger(L, luaL_checkinteger(L, 1) ^ luaL_optinteger(L, 2, -1));
+ return 1;
+}
+
+
+#define LI_BITS (sizeof(lua_Integer)*8)
+#define LI_MASK(m) (~(((lua_Integer)-1) << (m)))
+
+static int bit_field (lua_State *L) { /* aka bitshift */
+ lua_Integer ii = luaL_checkinteger(L, 1);
+ int idx, num = lua_gettop(L);
+ for (idx = 2; idx <= num; idx += 2) {
+ lua_Integer i = ii;
+ int start = luaL_checkinteger(L, idx);
+ int len = luaL_optinteger(L, idx+1, LI_BITS);
+ if (start > 0) i = (i >> start) & LI_MASK(LI_BITS - start);
+ if (len < LI_BITS) i &= LI_MASK(len);
+ if (start < 0) i <<= -start;
+ lua_pushinteger(L, i);
+ }
+ return num >> 1;
+}
+
+
static const luaL_Reg mathlib[] = {
{"abs", math_abs},
{"acos", math_acos},
@@ -241,6 +278,10 @@
{"sqrt", math_sqrt},
{"tanh", math_tanh},
{"tan", math_tan},
+ {"bitand", bit_and},
+ {"bitor", bit_or},
+ {"bitxor", bit_xor},
+ {"bitfield", bit_field},
{NULL, NULL}
};