From d14808cd271abf6a723bf495a6a01c14d18b5893 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 5 Jul 2018 14:46:26 -0600 Subject: [PATCH] Make format handle bignums * src/editfns.c (styled_format): Handle bignums. * test/src/editfns-tests.el (read-large-integer): Update. (format-bignum): New test. --- src/editfns.c | 22 +++++++++++++++++++++- test/src/editfns-tests.el | 33 +++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/src/editfns.c b/src/editfns.c index 6b54b41cbd9..09c17cbd926 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -4489,6 +4489,25 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) conversion = 's'; zero_flag = false; } + else if ((conversion == 'd' || conversion == 'i' + || conversion == 'o' || conversion == 'x' + || conversion == 'X') + && BIGNUMP (arg)) + { + int base = 10; + + if (conversion == 'o') + base = 8; + else if (conversion == 'x') + base = 16; + else if (conversion == 'X') + base = -16; + + char *str = mpz_get_str (NULL, base, XBIGNUM (arg)->value); + arg = make_unibyte_string (str, strlen (str)); + xfree (str); + conversion = 's'; + } if (SYMBOLP (arg)) { @@ -4600,7 +4619,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) || conversion == 'X')) error ("Invalid format operation %%%c", STRING_CHAR ((unsigned char *) format - 1)); - else if (! (FIXNUMP (arg) || (FLOATP (arg) && conversion != 'c'))) + else if (! (FIXNUMP (arg) || ((BIGNUMP (arg) || FLOATP (arg)) + && conversion != 'c'))) error ("Format specifier doesn't match argument type"); else { diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index c828000bb4f..501e0d87818 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el @@ -159,18 +159,17 @@ (should-error (format "%x" 18446744073709551616.0) :type 'overflow-error)) (ert-deftest read-large-integer () - (should-error (read (format "%d0" most-negative-fixnum)) - :type 'overflow-error) - (should-error (read (format "%+d" (* -8.0 most-negative-fixnum))) - :type 'overflow-error) - (should-error (read (substring (format "%d" most-negative-fixnum) 1)) - :type 'overflow-error) - (should-error (read (format "#x%x" most-negative-fixnum)) - :type 'overflow-error) - (should-error (read (format "#o%o" most-negative-fixnum)) - :type 'overflow-error) - (should-error (read (format "#32rG%x" most-positive-fixnum)) - :type 'overflow-error)) + (should (eq (type-of (read (format "%d0" most-negative-fixnum))) 'integer)) + (should (eq (type-of (read (format "%+d" (* -8.0 most-negative-fixnum)))) + 'integer)) + (should (eq (type-of (read (substring (format "%d" most-negative-fixnum) 1))) + 'integer)) + (should (eq (type-of (read (format "#x%x" most-negative-fixnum))) + 'integer)) + (should (eq (type-of (read (format "#o%o" most-negative-fixnum))) + 'integer)) + (should (eq (type-of (read (format "#32rG%x" most-positive-fixnum))) + 'integer))) (ert-deftest format-%o-invalid-float () (should-error (format "%o" -1e-37) @@ -358,4 +357,14 @@ (should (eq (type-of (car (nth 4 buffer-undo-list))) 'marker)) (garbage-collect))) +(ert-deftest format-bignum () + (let* ((s1 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") + (v1 (read (concat "#x" s1))) + (s2 "99999999999999999999999999999999") + (v2 (read s2))) + (should (> v1 most-positive-fixnum)) + (should (equal (format "%X" v1) s1)) + (should (> v2 most-positive-fixnum)) + (should (equal (format "%d" v2) s2)))) + ;;; editfns-tests.el ends here -- 2.39.2