Commit dfb0ba79 authored by Paul Eggert's avatar Paul Eggert

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.
parent 56a3e4a5
Pipeline #2532 passed with stage
in 52 minutes and 59 seconds
...@@ -923,9 +923,8 @@ Functions}). Thus, strings are enclosed in @samp{"} characters, and ...@@ -923,9 +923,8 @@ Functions}). Thus, strings are enclosed in @samp{"} characters, and
@cindex integer to octal @cindex integer to octal
Replace the specification with the base-eight representation of an Replace the specification with the base-eight representation of an
integer. Negative integers are formatted in a platform-dependent integer. Negative integers are formatted in a platform-dependent
way. The object can also be a nonnegative floating-point way. The object can also be a floating-point number that is formatted
number that is formatted as an integer, dropping any fraction, if the as an integer, dropping any fraction.
integer does not exceed machine limits.
@item %d @item %d
Replace the specification with the base-ten representation of a signed Replace the specification with the base-ten representation of a signed
...@@ -938,9 +937,8 @@ formatted as an integer, dropping any fraction. ...@@ -938,9 +937,8 @@ formatted as an integer, dropping any fraction.
Replace the specification with the base-sixteen representation of an Replace the specification with the base-sixteen representation of an
integer. Negative integers are formatted in a platform-dependent integer. Negative integers are formatted in a platform-dependent
way. @samp{%x} uses lower case and @samp{%X} uses upper way. @samp{%x} uses lower case and @samp{%X} uses upper
case. The object can also be a nonnegative floating-point number that case. The object can also be a floating-point number that is
is formatted as an integer, dropping any fraction, if the integer does formatted as an integer, dropping any fraction.
not exceed machine limits.
@item %c @item %c
Replace the specification with the character which is the value given. Replace the specification with the character which is the value given.
......
...@@ -3594,6 +3594,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) ...@@ -3594,6 +3594,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
sprintf_bytes = prec != 0; sprintf_bytes = prec != 0;
} }
else if (BIGNUMP (arg)) else if (BIGNUMP (arg))
bignum_arg:
{ {
int base = ((conversion == 'd' || conversion == 'i') ? 10 int base = ((conversion == 'd' || conversion == 'i') ? 10
: conversion == 'o' ? 8 : 16); : conversion == 'o' ? 8 : 16);
...@@ -3655,11 +3656,17 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) ...@@ -3655,11 +3656,17 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
else else
{ {
double d = XFLOAT_DATA (arg); double d = XFLOAT_DATA (arg);
double uintmax = UINTMAX_MAX; double abs_d = fabs (d);
if (! (0 <= d && d < uintmax + 1)) if (abs_d < UINTMAX_MAX + 1.0)
xsignal1 (Qoverflow_error, arg); {
x = d; negative = d <= -1;
negative = false; x = abs_d;
}
else
{
arg = double_to_integer (d);
goto bignum_arg;
}
} }
p[0] = negative ? '-' : plus_flag ? '+' : ' '; p[0] = negative ? '-' : plus_flag ? '+' : ' ';
bool signedp = negative | plus_flag | space_flag; bool signedp = negative | plus_flag | space_flag;
......
...@@ -165,13 +165,9 @@ ...@@ -165,13 +165,9 @@
(should (string-equal (format "%d" -18446744073709551616.0) (should (string-equal (format "%d" -18446744073709551616.0)
"-18446744073709551616"))) "-18446744073709551616")))
;; Perhaps Emacs will be improved someday to return the correct
;; answer for positive numbers instead of overflowing; in
;; that case these tests will need to be changed. In the meantime make
;; sure Emacs is reporting the overflow correctly.
(ert-deftest format-%x-large-float () (ert-deftest format-%x-large-float ()
(should-error (format "%x" 18446744073709551616.0) (should (string-equal (format "%x" 18446744073709551616.0)
:type 'overflow-error)) "10000000000000000")))
(ert-deftest read-large-integer () (ert-deftest read-large-integer ()
(should (eq (type-of (read (format "%d0" most-negative-fixnum))) 'integer)) (should (eq (type-of (read (format "%d0" most-negative-fixnum))) 'integer))
(should (eq (type-of (read (format "%+d" (* -8.0 most-negative-fixnum)))) (should (eq (type-of (read (format "%+d" (* -8.0 most-negative-fixnum))))
...@@ -188,11 +184,16 @@ ...@@ -188,11 +184,16 @@
(dolist (val (list most-negative-fixnum (1+ most-negative-fixnum) (dolist (val (list most-negative-fixnum (1+ most-negative-fixnum)
-1 0 1 -1 0 1
(1- most-positive-fixnum) most-positive-fixnum)) (1- most-positive-fixnum) most-positive-fixnum))
(should (eq val (read (format fmt val))))))) (should (eq val (read (format fmt val)))))
(dolist (val (list (1+ most-positive-fixnum)
(ert-deftest format-%o-invalid-float () (* 2 (1+ most-positive-fixnum))
(should-error (format "%o" -1e-37) (* 4 (1+ most-positive-fixnum))
:type 'overflow-error)) (* 8 (1+ most-positive-fixnum))
18446744073709551616.0))
(should (= val (read (format fmt val)))))))
(ert-deftest format-%o-negative-float ()
(should (string-equal (format "%o" -1e-37) "0")))
;; Bug#31938 ;; Bug#31938
(ert-deftest format-%d-float () (ert-deftest format-%d-float ()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment