~ 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