guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] GNU Guile branch, master, updated. release_1-9-13-52-ga6


From: Andy Wingo
Subject: [Guile-commits] GNU Guile branch, master, updated. release_1-9-13-52-ga6f3af1
Date: Mon, 15 Nov 2010 22:41:07 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Guile".

http://git.savannah.gnu.org/cgit/guile.git/commit/?id=a6f3af1618bb28b96ac44b77f6a69afe97995516

The branch, master has been updated
       via  a6f3af1618bb28b96ac44b77f6a69afe97995516 (commit)
      from  8b755a759eb7d07e82285e925bae02c19e7a3107 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a6f3af1618bb28b96ac44b77f6a69afe97995516
Author: Andy Wingo <address@hidden>
Date:   Mon Nov 15 23:43:30 2010 +0100

    fix string->number for bases > 16
    
    * libguile/numbers.c (scm_iuint2str): Add an assertion on the domain of
      the radix. Use the number_chars table to write the string, instead of
      doing strange math. Same effect, though.
      (mem2uinteger, char_decimal_value): Change logic to allow all ascii
      alphabetic chars as decimals, not just a-f. Thanks to Nils Gey for the
      report.
    
    * test-suite/tests/numbers.test ("number->string"): Add some tests.

-----------------------------------------------------------------------

Summary of changes:
 THANKS                        |    1 +
 libguile/numbers.c            |   54 ++++++++++++++++++++++++++--------------
 test-suite/tests/numbers.test |   10 +++++++
 3 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/THANKS b/THANKS
index c9a46e2..714346d 100644
--- a/THANKS
+++ b/THANKS
@@ -44,6 +44,7 @@ For fixes or providing information which led to a fix:
           Barry Fishman
         Charles Gagnon
           Peter Gavin
+           Nils Gey
            Eric Gillespie, Jr
          Didier Godefroy
   Panicz Maciej Godek
diff --git a/libguile/numbers.c b/libguile/numbers.c
index fbc6cc8..c9fd891 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -2402,6 +2402,9 @@ scm_iuint2str (scm_t_uintmax num, int rad, char *p)
   size_t i;
   scm_t_uintmax n = num;
 
+  if (rad < 2 || rad > 36)
+    scm_out_of_range ("scm_iuint2str", scm_from_int (rad));
+
   for (n /= rad; n > 0; n /= rad)
     j++;
 
@@ -2412,7 +2415,7 @@ scm_iuint2str (scm_t_uintmax num, int rad, char *p)
       int d = n % rad;
 
       n /= rad;
-      p[i] = d + ((d < 10) ? '0' : 'a' - 10);
+      p[i] = number_chars[d];
     }
   return j;
 }
@@ -2545,11 +2548,26 @@ enum t_exactness {NO_EXACTNESS, INEXACT, EXACT};
 
 /* R5RS, section 7.1.1, lexical structure of numbers: <uinteger R>. */
 
-/* In non ASCII-style encodings the following macro might not work. */
-#define XDIGIT2UINT(d)                                                  \
-  (uc_is_property_decimal_digit ((int) (unsigned char) d)               \
-   ? (d) - '0'                                                          \
-   : uc_tolower ((int) (unsigned char) d) - 'a' + 10)
+/* Caller is responsible for checking that the return value is in range
+   for the given radix, which should be <= 36. */
+static unsigned int
+char_decimal_value (scm_t_uint32 c)
+{
+  /* uc_decimal_value returns -1 on error. When cast to an unsigned int,
+     that's certainly above any valid decimal, so we take advantage of
+     that to elide some tests. */
+  unsigned int d = (unsigned int) uc_decimal_value (c);
+
+  /* If that failed, try extended hexadecimals, then. Only accept ascii
+     hexadecimals. */
+  if (d >= 10U)
+    {
+      c = uc_tolower (c);
+      if (c >= (scm_t_uint32) 'a')
+        d = c - (scm_t_uint32)'a' + 10U;
+    }
+  return d;
+}
 
 static SCM
 mem2uinteger (SCM mem, unsigned int *p_idx,
@@ -2568,9 +2586,7 @@ mem2uinteger (SCM mem, unsigned int *p_idx,
     return SCM_BOOL_F;
 
   c = scm_i_string_ref (mem, idx);
-  if (!uc_is_property_ascii_hex_digit ((scm_t_uint32) c))
-    return SCM_BOOL_F;
-  digit_value = XDIGIT2UINT (c);
+  digit_value = char_decimal_value (c);
   if (digit_value >= radix)
     return SCM_BOOL_F;
 
@@ -2579,21 +2595,21 @@ mem2uinteger (SCM mem, unsigned int *p_idx,
   while (idx != len)
     {
       scm_t_wchar c = scm_i_string_ref (mem, idx);
-      if (uc_is_property_ascii_hex_digit ((scm_t_uint32) c))
-       {
-         if (hash_seen)
-           break;
-         digit_value = XDIGIT2UINT (c);
-         if (digit_value >= radix)
-           break;
-       }
-      else if (c == '#')
+      if (c == '#')
        {
          hash_seen = 1;
          digit_value = 0;
        }
+      else if (hash_seen)
+        break;
       else
-       break;
+        {
+          digit_value = char_decimal_value (c);
+          /* This check catches non-decimals in addition to out-of-range
+             decimals.  */
+          if (digit_value >= radix)
+           break;
+       }
 
       idx++;
       if (SCM_MOST_POSITIVE_FIXNUM / radix < shift)
diff --git a/test-suite/tests/numbers.test b/test-suite/tests/numbers.test
index 3c3e14f..3432d7a 100644
--- a/test-suite/tests/numbers.test
+++ b/test-suite/tests/numbers.test
@@ -1288,6 +1288,16 @@
     (pass-if (string=? (number->string 255.0625 16) "FF.1"))
     (pass-if (string=? (number->string (/ 1 3) 3) "1/10"))
 
+    (pass-if (string=? (number->string 10) "10"))
+    (pass-if (string=? (number->string 10 11) "A"))
+    (pass-if (string=? (number->string 36 36) "10"))
+    (pass-if (= (num->str->num 36 36) 36))
+    (pass-if (= (string->number "z" 36) 35))
+    (pass-if (= (string->number "Z" 36) 35))
+    (pass-if (not (string->number "Z" 35)))
+    (pass-if (string=? (number->string 35 36) "Z"))
+    (pass-if (= (num->str->num 35 36) 35))
+
     ;; Numeric conversion from decimal is not precise, in its current
     ;; implementation, so 11.333... and 1.324... can't be expected to
     ;; reliably come out to precise values.  These tests did actually work


hooks/post-receive
-- 
GNU Guile



reply via email to

[Prev in Thread] Current Thread [Next in Thread]