diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-12-10 17:03:46 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-12-10 17:03:46 -0200 |
| commit | af119c8b55f15910df17e02633d8a5ca656b209a (patch) | |
| tree | 74c0e645490a9114a3f3e81108ac8627e2e184d8 | |
| parent | 1aead7f5536c92cfbd1dd7dbb51f5ac95f239e14 (diff) | |
| download | lua-af119c8b55f15910df17e02633d8a5ca656b209a.tar.gz lua-af119c8b55f15910df17e02633d8a5ca656b209a.tar.bz2 lua-af119c8b55f15910df17e02633d8a5ca656b209a.zip | |
official support for floating hexa numerals
| -rw-r--r-- | lobject.c | 87 | ||||
| -rw-r--r-- | lstrlib.c | 5 | ||||
| -rw-r--r-- | luaconf.h | 20 |
3 files changed, 99 insertions, 13 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.c,v 2.43 2010/10/29 15:54:55 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 2.44 2010/12/06 21:08:36 roberto Exp roberto $ |
| 3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -106,20 +106,87 @@ lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { | |||
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | 108 | ||
| 109 | static int checkend (const char *s, const char *e, const char *endptr) { | 109 | int luaO_hexavalue (int c) { |
| 110 | if (endptr == s) return 0; /* no characters converted */ | 110 | if (lisdigit(c)) return c - '0'; |
| 111 | while (lisspace(cast(unsigned char, *endptr))) endptr++; | 111 | else if (lisupper(c)) return c - 'A' + 10; |
| 112 | return (endptr == e); /* OK if no trailing characters */ | 112 | else return c - 'a' + 10; |
| 113 | } | 113 | } |
| 114 | 114 | ||
| 115 | 115 | ||
| 116 | #if !defined(lua_strx2number) | ||
| 117 | |||
| 118 | #include <math.h> | ||
| 119 | |||
| 120 | |||
| 121 | static int isneg (const char **s) { | ||
| 122 | if (**s == '-') { (*s)++; return 1; } | ||
| 123 | else if (**s == '+') (*s)++; | ||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | |||
| 128 | static lua_Number readhexa (const char **s, lua_Number r, int *count) { | ||
| 129 | while (lisxdigit(cast_uchar(**s))) { /* read integer part */ | ||
| 130 | r = (r * 16.0) + (double)luaO_hexavalue(*(*s)++); | ||
| 131 | (*count)++; | ||
| 132 | } | ||
| 133 | return r; | ||
| 134 | } | ||
| 135 | |||
| 136 | |||
| 137 | /* | ||
| 138 | ** convert an hexadecimal numeric string to a number, following | ||
| 139 | ** C99 specification for 'strtod' | ||
| 140 | */ | ||
| 141 | static lua_Number lua_strx2number (const char *s, char **endptr) { | ||
| 142 | lua_Number r = 0.0; | ||
| 143 | int e = 0, i = 0; | ||
| 144 | int neg = 0; /* 1 if number is negative */ | ||
| 145 | *endptr = cast(char *, s); /* nothing is valid yet */ | ||
| 146 | while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ | ||
| 147 | neg = isneg(&s); /* check signal */ | ||
| 148 | if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ | ||
| 149 | return 0.0; /* invalid format (no '0x') */ | ||
| 150 | s += 2; /* skip '0x' */ | ||
| 151 | r = readhexa(&s, r, &i); /* read integer part */ | ||
| 152 | if (*s == '.') { | ||
| 153 | s++; /* skip dot */ | ||
| 154 | r = readhexa(&s, r, &e); /* read fractional part */ | ||
| 155 | } | ||
| 156 | if (i == 0 && e == 0) | ||
| 157 | return 0.0; /* invalid format (no digit) */ | ||
| 158 | e *= -4; /* each fractional digit divides value by 2^-4 */ | ||
| 159 | *endptr = cast(char *, s); /* valid up to here */ | ||
| 160 | if (*s == 'p' || *s == 'P') { /* exponent part? */ | ||
| 161 | int exp1 = 0; | ||
| 162 | int neg1; | ||
| 163 | s++; /* skip 'p' */ | ||
| 164 | neg1 = isneg(&s); /* signal */ | ||
| 165 | if (!lisdigit(cast_uchar(*s))) | ||
| 166 | goto ret; /* must have at least one digit */ | ||
| 167 | while (lisdigit(cast_uchar(*s))) /* read exponent */ | ||
| 168 | exp1 = exp1 * 10 + *(s++) - '0'; | ||
| 169 | if (neg1) exp1 = -exp1; | ||
| 170 | e += exp1; | ||
| 171 | } | ||
| 172 | *endptr = cast(char *, s); /* valid up to here */ | ||
| 173 | ret: | ||
| 174 | if (neg) r = -r; | ||
| 175 | return ldexp(r, e); | ||
| 176 | } | ||
| 177 | |||
| 178 | #endif | ||
| 179 | |||
| 180 | |||
| 116 | int luaO_str2d (const char *s, size_t len, lua_Number *result) { | 181 | int luaO_str2d (const char *s, size_t len, lua_Number *result) { |
| 117 | char *endptr; | 182 | char *endptr; |
| 118 | const char *e = s + len; /* string 's' ends here */ | 183 | if (strpbrk(s, "xX")) /* hexa? */ |
| 119 | *result = lua_str2number(s, &endptr); | 184 | *result = lua_strx2number(s, &endptr); |
| 120 | if (checkend(s, e, endptr)) return 1; /* conversion OK? */ | 185 | else |
| 121 | *result = cast_num(strtoul(s, &endptr, 0)); /* try hexadecimal */ | 186 | *result = lua_str2number(s, &endptr); |
| 122 | return checkend(s, e, endptr); | 187 | if (endptr == s) return 0; /* nothing recognized */ |
| 188 | while (lisspace(cast_uchar(*endptr))) endptr++; | ||
| 189 | return (endptr == s + len); /* OK if no trailing characters */ | ||
| 123 | } | 190 | } |
| 124 | 191 | ||
| 125 | 192 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstrlib.c,v 1.158 2010/11/16 20:39:41 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.159 2010/11/19 16:25:51 roberto Exp roberto $ |
| 3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -861,6 +861,9 @@ static int str_format (lua_State *L) { | |||
| 861 | break; | 861 | break; |
| 862 | } | 862 | } |
| 863 | case 'e': case 'E': case 'f': | 863 | case 'e': case 'E': case 'f': |
| 864 | #if defined(LUA_USE_AFORMAT) | ||
| 865 | case 'a': case 'A': | ||
| 866 | #endif | ||
| 864 | case 'g': case 'G': { | 867 | case 'g': case 'G': { |
| 865 | addlenmod(form, LUA_FLTFRMLEN); | 868 | addlenmod(form, LUA_FLTFRMLEN); |
| 866 | nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); | 869 | nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: luaconf.h,v 1.151 2010/11/12 15:48:30 roberto Exp roberto $ | 2 | ** $Id: luaconf.h,v 1.152 2010/12/08 12:58:04 roberto Exp roberto $ |
| 3 | ** Configuration file for Lua | 3 | ** Configuration file for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -35,6 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #if defined(LUA_WIN) | 36 | #if defined(LUA_WIN) |
| 37 | #define LUA_DL_DLL | 37 | #define LUA_DL_DLL |
| 38 | #define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ | ||
| 38 | #endif | 39 | #endif |
| 39 | 40 | ||
| 40 | 41 | ||
| @@ -43,6 +44,8 @@ | |||
| 43 | #define LUA_USE_POSIX | 44 | #define LUA_USE_POSIX |
| 44 | #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ | 45 | #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ |
| 45 | #define LUA_USE_READLINE /* needs some extra libraries */ | 46 | #define LUA_USE_READLINE /* needs some extra libraries */ |
| 47 | #define LUA_USE_HEXAFLOAT /* assume 'strtod' handles hexa formats */ | ||
| 48 | #define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ | ||
| 46 | #endif | 49 | #endif |
| 47 | 50 | ||
| 48 | #if defined(LUA_USE_MACOSX) | 51 | #if defined(LUA_USE_MACOSX) |
| @@ -377,14 +380,27 @@ | |||
| 377 | @@ LUA_NUMBER_FMT is the format for writing numbers. | 380 | @@ LUA_NUMBER_FMT is the format for writing numbers. |
| 378 | @@ lua_number2str converts a number to a string. | 381 | @@ lua_number2str converts a number to a string. |
| 379 | @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. | 382 | @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. |
| 380 | @@ lua_str2number converts a string to a number. | ||
| 381 | */ | 383 | */ |
| 382 | #define LUA_NUMBER_SCAN "%lf" | 384 | #define LUA_NUMBER_SCAN "%lf" |
| 383 | #define LUA_NUMBER_FMT "%.14g" | 385 | #define LUA_NUMBER_FMT "%.14g" |
| 384 | #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) | 386 | #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) |
| 385 | #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ | 387 | #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ |
| 388 | |||
| 389 | |||
| 390 | /* | ||
| 391 | @@ lua_str2number converts a decimal numeric string to a number. | ||
| 392 | @@ lua_strx2number converts an hexadecimal numeric string to a number. | ||
| 393 | ** In C99, 'strtod' do both conversions. C89, however, has no function | ||
| 394 | ** to convert floating hexadecimal strings to numbers. For these | ||
| 395 | ** systems, you can leave 'lua_strx2number' undefined and Lua will | ||
| 396 | ** provide its own implementation. | ||
| 397 | */ | ||
| 386 | #define lua_str2number(s,p) strtod((s), (p)) | 398 | #define lua_str2number(s,p) strtod((s), (p)) |
| 387 | 399 | ||
| 400 | #if defined(LUA_USE_HEXAFLOAT) | ||
| 401 | #define lua_strx2number(s,p) strtod((s), (p)) | ||
| 402 | #endif | ||
| 403 | |||
| 388 | 404 | ||
| 389 | /* | 405 | /* |
| 390 | @@ The luai_num* macros define the primitive operations over numbers. | 406 | @@ The luai_num* macros define the primitive operations over numbers. |
