[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: We got hex numbers! (almost)
- From: Mike Pall <mikelu-0601@...>
- Date: Wed, 25 Jan 2006 00:33:08 +0100
Hi,
our prayers have been answered with the latest 5.1-rc:
$ lua -e 'print(0xff)'
255
Well ... almost. This only works if your strtod() is C99
compliant -- which is probably true for most systems nowadays.
AFAIK a prominent exception is the MSVC library. :-/
A patch for non-C99 compliant systems is attached. This fixes
(plain) hex number parsing for both the lexer and tonumber().
On C99 compliant systems you also get hex numbers with exponents
(0x1p10 == 1024). But negative exponents don't work (this is
tricky to fix). So I didn't bother to add this to my patch.
[
Important note if you redefine lua_Number to use integers:
The correct way to change the number parsing is:
#define lua_str2number(s,p) strtoul((s), (p), 10)
Do not use strtol or base 0. This either breaks large positive
hex numbers or misparses numbers with a leading zero as octal.
But base 10 disables parsing of hex numbers. So you need to use
the attached patch, too.
]
BTW: The lexer is now mostly ignorant about the exact syntax of
numbers. It accepts anything matching /[\d.]+([eE][+-])?[\w_]*/.
This could be (ab)used for global constants, like 0_FOO_BAR. :-)
Bye,
Mike
--- lua-5.1-rc2/src/lobject.c 2006-01-10 13:50:00.000000000 +0100
+++ lua-5.1-rc2a/src/lobject.c 2006-01-24 23:34:33.000000000 +0100
@@ -87,14 +87,34 @@
}
+/* fallback for non C99 compliant systems */
+static int hexnum (const char *s, lua_Number *result) {
+ int sign = 0;
+ while (isspace(cast(unsigned char, *s))) s++;
+ if (*s == '-') { sign = 1; s++; }
+ else if (*s == '+') s++;
+ if (*s++ == '0' && (*s == 'x' || *s == 'X')) {
+ lua_Number n = 0;
+ for (s++; isxdigit(*s); s++)
+ n = n * 16 + (*s & 15) + (isdigit(*s) ? 0 : 9);
+ if (sign) n = -n;
+ *result = n;
+ while (isspace(cast(unsigned char, *s))) s++;
+ if (*s == '\0') return 1; /* ok */
+ }
+ return 0; /* conversion failed */
+}
+
+
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 */
+ }
+ return hexnum(s, result); /* else try fallback */
}