aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-12-27 16:00:38 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-12-27 16:00:38 -0200
commitaa6faa6331e3e5e326bf5830474ffd9b04425678 (patch)
treeea8db67fabdda7fbaa9a5c30a8d2613b473430d0
parent0b3f4e254e52f7497b813098c79619a4aaa83c4d (diff)
downloadlua-aa6faa6331e3e5e326bf5830474ffd9b04425678.tar.gz
lua-aa6faa6331e3e5e326bf5830474ffd9b04425678.tar.bz2
lua-aa6faa6331e3e5e326bf5830474ffd9b04425678.zip
own implementation of 'tunumber', so that it works correctly with
numbers outside the 'int' range
-rw-r--r--lbaselib.c42
1 files changed, 24 insertions, 18 deletions
diff --git a/lbaselib.c b/lbaselib.c
index c71a670f..64dfb549 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.255 2010/12/13 16:38:00 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.256 2010/12/17 15:14:58 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -47,33 +47,39 @@ static int luaB_print (lua_State *L) {
47 47
48static int luaB_tonumber (lua_State *L) { 48static int luaB_tonumber (lua_State *L) {
49 int base = luaL_optint(L, 2, 10); 49 int base = luaL_optint(L, 2, 10);
50 luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
50 if (base == 10) { /* standard conversion */ 51 if (base == 10) { /* standard conversion */
51 luaL_checkany(L, 1); 52 luaL_checkany(L, 1);
52 if (lua_isnumber(L, 1)) { 53 if (lua_isnumber(L, 1)) {
53 lua_pushnumber(L, lua_tonumber(L, 1)); 54 lua_pushnumber(L, lua_tonumber(L, 1));
54 return 1; 55 return 1;
55 } 56 } /* else not a number */
56 } 57 }
57 else { 58 else {
58 size_t l1; 59 size_t l;
59 const char *s1 = luaL_checklstring(L, 1, &l1); 60 const char *s = luaL_checklstring(L, 1, &l);
60 const char *e1 = s1 + l1; 61 const char *e = s + l; /* end point for 's' */
61 char *s2;
62 unsigned long n;
63 int neg = 0; 62 int neg = 0;
64 luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); 63 s += strspn(s, SPACECHARS); /* skip initial spaces */
65 s1 += strspn(s1, SPACECHARS); /* skip initial spaces */ 64 if (*s == '-') { s++; neg = 1; } /* handle signal */
66 if (*s1 == '-') { s1++; neg = 1; } 65 else if (*s == '+') s++;
67 n = strtoul(s1, &s2, base); 66 if (isalnum((unsigned char)*s)) {
68 if (s1 != s2) { /* at least one valid digit? */ 67 lua_Number n = 0;
69 s2 += strspn(s2, SPACECHARS); /* skip trailing spaces */ 68 do {
70 if (s2 == e1) { /* no invalid trailing characters? */ 69 int digit = (isdigit((unsigned char)*s)) ? *s - '0'
71 lua_pushnumber(L, (neg) ? -(lua_Number)n : (lua_Number)n); 70 : toupper((unsigned char)*s) - 'A' + 10;
71 if (digit >= base) break; /* invalid numeral; force a fail */
72 n = n * (lua_Number)base + (lua_Number)digit;
73 s++;
74 } while (isalnum((unsigned char)*s));
75 s += strspn(s, SPACECHARS); /* skip trailing spaces */
76 if (s == e) { /* no invalid trailing characters? */
77 lua_pushnumber(L, (neg) ? -n : n);
72 return 1; 78 return 1;
73 } 79 } /* else not a number */
74 } 80 } /* else not a number */
75 } 81 }
76 lua_pushnil(L); /* else not a number */ 82 lua_pushnil(L); /* not a number */
77 return 1; 83 return 1;
78} 84}
79 85