~ chicken-core (chicken-5) ffb9d81052efd9df073eff285f01c1753156bab5
commit ffb9d81052efd9df073eff285f01c1753156bab5
Author: felix <felix@call-with-current-continuation.org>
AuthorDate: Wed Aug 18 09:27:31 2010 -0400
Commit: felix <felix@call-with-current-continuation.org>
CommitDate: Wed Aug 18 09:27:31 2010 -0400
allow arbitrary large non-decimal integers in str->num conversion
diff --git a/runtime.c b/runtime.c
index 688ca5ff..3b8076e2 100644
--- a/runtime.c
+++ b/runtime.c
@@ -7220,11 +7220,11 @@ void C_ccall C_string_to_number(C_word c, C_word closure, C_word k, C_word str,
/* convert number and return result: */
switch(convert_string_to_number(sptr, radix, &n, &fn)) {
- case 0:
+ case 0: /* failed */
n = C_SCHEME_FALSE;
break;
- case 1:
+ case 1: /* fixnum */
if(sharpf || ratp || (exactpf && !exactf)) {
n = C_flonum(&a, ratp ? fn1 / (double)n : (double)n);
@@ -7234,7 +7234,7 @@ void C_ccall C_string_to_number(C_word c, C_word closure, C_word k, C_word str,
break;
- case 2:
+ case 2: /* flonum */
n = C_flonum(&a, ratp ? fn1 / fn : fn);
if(exactpf && exactf) n = C_i_inexact_to_exact(n);
@@ -7247,6 +7247,29 @@ void C_ccall C_string_to_number(C_word c, C_word closure, C_word k, C_word str,
}
+static int from_n_nary(C_char *str, int base, double *r)
+{
+ double n = 0;
+ C_char *ptr = str;
+
+ while(*ptr != '\0') {
+ int c = C_tolower(*(ptr++));
+
+ if(c < '0') return 0;
+ else if(c >= '0' + base) {
+ if(base < 10) return 0;
+ else if(c < 'a') return 0;
+ else if(c >= 'a' + base) return 0;
+ else n = n * base + c - 'a' + 10;
+ }
+ else n = n * base + c - '0';
+ }
+
+ *r = n;
+ return 1;
+}
+
+
C_regparm C_word C_fcall convert_string_to_number(C_char *str, int radix, C_word *fix, double *flo)
{
unsigned long ln;
@@ -7282,17 +7305,8 @@ C_regparm C_word C_fcall convert_string_to_number(C_char *str, int radix, C_word
n = C_strtol(str, &eptr, radix);
if(((n == LONG_MAX || n == LONG_MIN) && errno == ERANGE) || *eptr != '\0') {
- if(radix != 10) {
- errno = 0;
- ln = C_strtoul(str, &eptr, radix);
-
- if((ln == 0 && errno == EINVAL) || (ln == ULONG_MAX && errno == ERANGE) ||
- *eptr != '\0')
- return 0;
-
- *flo = (double)ln;
- return 2;
- }
+ if(radix != 10)
+ return from_n_nary(str, radix, flo) ? 2 : 0;
errno = 0;
fn = C_strtod(str, &eptr2);
@@ -7319,10 +7333,11 @@ C_regparm C_word C_fcall convert_string_to_number(C_char *str, int radix, C_word
}
}
+
static char *to_n_nary(C_uword num, C_uword base)
{
char *p;
- char digits[] ={ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
+ static char digits[] ={ '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
buffer [ 66 ] = '\0';
p = buffer + 66;
Trap