lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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 */
 }