diff options
| author | Paul Eggert | 2019-07-23 01:42:32 -0700 |
|---|---|---|
| committer | Paul Eggert | 2019-07-23 01:46:41 -0700 |
| commit | dfb0ba79b5f41ca6fed25a03d2a5cd6996ec4753 (patch) | |
| tree | 87426b1fde8da618b4e7657b09bc256f5c011dcc | |
| parent | 56a3e4a5d366a8453608d9a604ebd5ddb4e52245 (diff) | |
| download | emacs-dfb0ba79b5f41ca6fed25a03d2a5cd6996ec4753.tar.gz emacs-dfb0ba79b5f41ca6fed25a03d2a5cd6996ec4753.zip | |
Support "%x" etc. formats on more floats
* doc/lispref/strings.texi (Formatting Strings): Document this.
* src/editfns.c (styled_format): Support %o, %x, and %X on
finite floats less than zero or greater than UINTMAX_MAX.
* test/src/editfns-tests.el (format-%x-large-float)
(read-large-integer, format-%o-negative-float):
Adjust tests to match extended behavior.
Rename the latter test from format-%o-invalid-float,
since the float is no longer invalid.
* test/src/editfns-tests.el (format-%x-large-float)
(read-large-integer): Test this.
| -rw-r--r-- | doc/lispref/strings.texi | 10 | ||||
| -rw-r--r-- | src/editfns.c | 17 | ||||
| -rw-r--r-- | test/src/editfns-tests.el | 23 |
3 files changed, 28 insertions, 22 deletions
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 521f163663d..69d571fab8a 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi | |||
| @@ -923,9 +923,8 @@ Functions}). Thus, strings are enclosed in @samp{"} characters, and | |||
| 923 | @cindex integer to octal | 923 | @cindex integer to octal |
| 924 | Replace the specification with the base-eight representation of an | 924 | Replace the specification with the base-eight representation of an |
| 925 | integer. Negative integers are formatted in a platform-dependent | 925 | integer. Negative integers are formatted in a platform-dependent |
| 926 | way. The object can also be a nonnegative floating-point | 926 | way. The object can also be a floating-point number that is formatted |
| 927 | number that is formatted as an integer, dropping any fraction, if the | 927 | as an integer, dropping any fraction. |
| 928 | integer does not exceed machine limits. | ||
| 929 | 928 | ||
| 930 | @item %d | 929 | @item %d |
| 931 | Replace the specification with the base-ten representation of a signed | 930 | Replace the specification with the base-ten representation of a signed |
| @@ -938,9 +937,8 @@ formatted as an integer, dropping any fraction. | |||
| 938 | Replace the specification with the base-sixteen representation of an | 937 | Replace the specification with the base-sixteen representation of an |
| 939 | integer. Negative integers are formatted in a platform-dependent | 938 | integer. Negative integers are formatted in a platform-dependent |
| 940 | way. @samp{%x} uses lower case and @samp{%X} uses upper | 939 | way. @samp{%x} uses lower case and @samp{%X} uses upper |
| 941 | case. The object can also be a nonnegative floating-point number that | 940 | case. The object can also be a floating-point number that is |
| 942 | is formatted as an integer, dropping any fraction, if the integer does | 941 | formatted as an integer, dropping any fraction. |
| 943 | not exceed machine limits. | ||
| 944 | 942 | ||
| 945 | @item %c | 943 | @item %c |
| 946 | Replace the specification with the character which is the value given. | 944 | Replace the specification with the character which is the value given. |
diff --git a/src/editfns.c b/src/editfns.c index 8e0c0c451e6..1b33f397110 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -3594,6 +3594,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 3594 | sprintf_bytes = prec != 0; | 3594 | sprintf_bytes = prec != 0; |
| 3595 | } | 3595 | } |
| 3596 | else if (BIGNUMP (arg)) | 3596 | else if (BIGNUMP (arg)) |
| 3597 | bignum_arg: | ||
| 3597 | { | 3598 | { |
| 3598 | int base = ((conversion == 'd' || conversion == 'i') ? 10 | 3599 | int base = ((conversion == 'd' || conversion == 'i') ? 10 |
| 3599 | : conversion == 'o' ? 8 : 16); | 3600 | : conversion == 'o' ? 8 : 16); |
| @@ -3655,11 +3656,17 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 3655 | else | 3656 | else |
| 3656 | { | 3657 | { |
| 3657 | double d = XFLOAT_DATA (arg); | 3658 | double d = XFLOAT_DATA (arg); |
| 3658 | double uintmax = UINTMAX_MAX; | 3659 | double abs_d = fabs (d); |
| 3659 | if (! (0 <= d && d < uintmax + 1)) | 3660 | if (abs_d < UINTMAX_MAX + 1.0) |
| 3660 | xsignal1 (Qoverflow_error, arg); | 3661 | { |
| 3661 | x = d; | 3662 | negative = d <= -1; |
| 3662 | negative = false; | 3663 | x = abs_d; |
| 3664 | } | ||
| 3665 | else | ||
| 3666 | { | ||
| 3667 | arg = double_to_integer (d); | ||
| 3668 | goto bignum_arg; | ||
| 3669 | } | ||
| 3663 | } | 3670 | } |
| 3664 | p[0] = negative ? '-' : plus_flag ? '+' : ' '; | 3671 | p[0] = negative ? '-' : plus_flag ? '+' : ' '; |
| 3665 | bool signedp = negative | plus_flag | space_flag; | 3672 | bool signedp = negative | plus_flag | space_flag; |
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el index 69cca5d2bdd..a1060808f66 100644 --- a/test/src/editfns-tests.el +++ b/test/src/editfns-tests.el | |||
| @@ -165,13 +165,9 @@ | |||
| 165 | (should (string-equal (format "%d" -18446744073709551616.0) | 165 | (should (string-equal (format "%d" -18446744073709551616.0) |
| 166 | "-18446744073709551616"))) | 166 | "-18446744073709551616"))) |
| 167 | 167 | ||
| 168 | ;; Perhaps Emacs will be improved someday to return the correct | ||
| 169 | ;; answer for positive numbers instead of overflowing; in | ||
| 170 | ;; that case these tests will need to be changed. In the meantime make | ||
| 171 | ;; sure Emacs is reporting the overflow correctly. | ||
| 172 | (ert-deftest format-%x-large-float () | 168 | (ert-deftest format-%x-large-float () |
| 173 | (should-error (format "%x" 18446744073709551616.0) | 169 | (should (string-equal (format "%x" 18446744073709551616.0) |
| 174 | :type 'overflow-error)) | 170 | "10000000000000000"))) |
| 175 | (ert-deftest read-large-integer () | 171 | (ert-deftest read-large-integer () |
| 176 | (should (eq (type-of (read (format "%d0" most-negative-fixnum))) 'integer)) | 172 | (should (eq (type-of (read (format "%d0" most-negative-fixnum))) 'integer)) |
| 177 | (should (eq (type-of (read (format "%+d" (* -8.0 most-negative-fixnum)))) | 173 | (should (eq (type-of (read (format "%+d" (* -8.0 most-negative-fixnum)))) |
| @@ -188,11 +184,16 @@ | |||
| 188 | (dolist (val (list most-negative-fixnum (1+ most-negative-fixnum) | 184 | (dolist (val (list most-negative-fixnum (1+ most-negative-fixnum) |
| 189 | -1 0 1 | 185 | -1 0 1 |
| 190 | (1- most-positive-fixnum) most-positive-fixnum)) | 186 | (1- most-positive-fixnum) most-positive-fixnum)) |
| 191 | (should (eq val (read (format fmt val))))))) | 187 | (should (eq val (read (format fmt val))))) |
| 192 | 188 | (dolist (val (list (1+ most-positive-fixnum) | |
| 193 | (ert-deftest format-%o-invalid-float () | 189 | (* 2 (1+ most-positive-fixnum)) |
| 194 | (should-error (format "%o" -1e-37) | 190 | (* 4 (1+ most-positive-fixnum)) |
| 195 | :type 'overflow-error)) | 191 | (* 8 (1+ most-positive-fixnum)) |
| 192 | 18446744073709551616.0)) | ||
| 193 | (should (= val (read (format fmt val))))))) | ||
| 194 | |||
| 195 | (ert-deftest format-%o-negative-float () | ||
| 196 | (should (string-equal (format "%o" -1e-37) "0"))) | ||
| 196 | 197 | ||
| 197 | ;; Bug#31938 | 198 | ;; Bug#31938 |
| 198 | (ert-deftest format-%d-float () | 199 | (ert-deftest format-%d-float () |