aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2018-06-25 12:21:40 -0700
committerPaul Eggert2018-06-25 12:23:08 -0700
commitd0e2a341dd9a9a365fd311748df024ecb25b70ec (patch)
treeaa5b4e9f33777155349c3aacefece4d25199b887
parent27a21970f6faa9baf42823f731b7842b075e86eb (diff)
downloademacs-d0e2a341dd9a9a365fd311748df024ecb25b70ec.tar.gz
emacs-d0e2a341dd9a9a365fd311748df024ecb25b70ec.zip
(format "%d" F) now truncates floating F
Problem reported by Paul Pogonyshev (Bug#31938). * src/editfns.c: Include math.h, for trunc. (styled_format): For %d, truncate floating-point numbers and convert -0 to 0, going back to how Emacs 26 did things. * doc/lispref/strings.texi (Formatting Strings): Document behavior of %o, %d, %x, %X on floating-point numbers. * src/floatfns.c (trunc) [!HAVE_TRUNC]: Rename from emacs_trunc and make it an extern function, so that editfns.c can use it. All callers changed. * test/src/editfns-tests.el (format-%d-float): New test.
-rw-r--r--doc/lispref/strings.texi11
-rw-r--r--src/editfns.c7
-rw-r--r--src/floatfns.c13
-rw-r--r--src/lisp.h5
-rw-r--r--test/src/editfns-tests.el8
5 files changed, 32 insertions, 12 deletions
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 70ba1aa613e..026ba749cbd 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -922,18 +922,23 @@ Functions}). Thus, strings are enclosed in @samp{"} characters, and
922@item %o 922@item %o
923@cindex integer to octal 923@cindex integer to octal
924Replace the specification with the base-eight representation of an 924Replace the specification with the base-eight representation of an
925unsigned integer. 925unsigned integer. The object can also be a nonnegative floating-point
926number that is formatted as an integer, dropping any fraction, if the
927integer does not exceed machine limits.
926 928
927@item %d 929@item %d
928Replace the specification with the base-ten representation of a signed 930Replace the specification with the base-ten representation of a signed
929integer. 931integer. The object can also be a floating-point number that is
932formatted as an integer, dropping any fraction.
930 933
931@item %x 934@item %x
932@itemx %X 935@itemx %X
933@cindex integer to hexadecimal 936@cindex integer to hexadecimal
934Replace the specification with the base-sixteen representation of an 937Replace the specification with the base-sixteen representation of an
935unsigned integer. @samp{%x} uses lower case and @samp{%X} uses upper 938unsigned integer. @samp{%x} uses lower case and @samp{%X} uses upper
936case. 939case. The object can also be a nonnegative floating-point number that
940is formatted as an integer, dropping any fraction, if the integer does
941not exceed machine limits.
937 942
938@item %c 943@item %c
939Replace the specification with the character which is the value given. 944Replace the specification with the character which is the value given.
diff --git a/src/editfns.c b/src/editfns.c
index 30d585cd018..7d032a7ca4c 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -47,6 +47,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
47#include <errno.h> 47#include <errno.h>
48#include <float.h> 48#include <float.h>
49#include <limits.h> 49#include <limits.h>
50#include <math.h>
50 51
51#ifdef HAVE_TIMEZONE_T 52#ifdef HAVE_TIMEZONE_T
52# include <sys/param.h> 53# include <sys/param.h>
@@ -4671,6 +4672,12 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4671 { 4672 {
4672 strcpy (f - pMlen - 1, "f"); 4673 strcpy (f - pMlen - 1, "f");
4673 double x = XFLOAT_DATA (arg); 4674 double x = XFLOAT_DATA (arg);
4675
4676 /* Truncate and then convert -0 to 0, to be more
4677 consistent with %x etc.; see Bug#31938. */
4678 x = trunc (x);
4679 x = x ? x : 0;
4680
4674 sprintf_bytes = sprintf (sprintf_buf, convspec, 0, x); 4681 sprintf_bytes = sprintf (sprintf_buf, convspec, 0, x);
4675 char c0 = sprintf_buf[0]; 4682 char c0 = sprintf_buf[0];
4676 bool signedp = ! ('0' <= c0 && c0 <= '9'); 4683 bool signedp = ! ('0' <= c0 && c0 <= '9');
diff --git a/src/floatfns.c b/src/floatfns.c
index ec0349fbf40..e7d404a84e0 100644
--- a/src/floatfns.c
+++ b/src/floatfns.c
@@ -435,11 +435,9 @@ emacs_rint (double d)
435} 435}
436#endif 436#endif
437 437
438#ifdef HAVE_TRUNC 438#ifndef HAVE_TRUNC
439#define emacs_trunc trunc 439double
440#else 440trunc (double d)
441static double
442emacs_trunc (double d)
443{ 441{
444 return (d < 0 ? ceil : floor) (d); 442 return (d < 0 ? ceil : floor) (d);
445} 443}
@@ -482,8 +480,7 @@ Rounds ARG toward zero.
482With optional DIVISOR, truncate ARG/DIVISOR. */) 480With optional DIVISOR, truncate ARG/DIVISOR. */)
483 (Lisp_Object arg, Lisp_Object divisor) 481 (Lisp_Object arg, Lisp_Object divisor)
484{ 482{
485 return rounding_driver (arg, divisor, emacs_trunc, truncate2, 483 return rounding_driver (arg, divisor, trunc, truncate2, "truncate");
486 "truncate");
487} 484}
488 485
489 486
@@ -543,7 +540,7 @@ DEFUN ("ftruncate", Fftruncate, Sftruncate, 1, 1, 0,
543{ 540{
544 CHECK_FLOAT (arg); 541 CHECK_FLOAT (arg);
545 double d = XFLOAT_DATA (arg); 542 double d = XFLOAT_DATA (arg);
546 d = emacs_trunc (d); 543 d = trunc (d);
547 return make_float (d); 544 return make_float (d);
548} 545}
549 546
diff --git a/src/lisp.h b/src/lisp.h
index d0c52d85672..8c884dce150 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3425,8 +3425,11 @@ extern Lisp_Object string_make_unibyte (Lisp_Object);
3425extern void syms_of_fns (void); 3425extern void syms_of_fns (void);
3426 3426
3427/* Defined in floatfns.c. */ 3427/* Defined in floatfns.c. */
3428extern void syms_of_floatfns (void); 3428#ifndef HAVE_TRUNC
3429extern double trunc (double);
3430#endif
3429extern Lisp_Object fmod_float (Lisp_Object x, Lisp_Object y); 3431extern Lisp_Object fmod_float (Lisp_Object x, Lisp_Object y);
3432extern void syms_of_floatfns (void);
3430 3433
3431/* Defined in fringe.c. */ 3434/* Defined in fringe.c. */
3432extern void syms_of_fringe (void); 3435extern void syms_of_fringe (void);
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
index 1ed0bd5bbaf..c828000bb4f 100644
--- a/test/src/editfns-tests.el
+++ b/test/src/editfns-tests.el
@@ -176,6 +176,14 @@
176 (should-error (format "%o" -1e-37) 176 (should-error (format "%o" -1e-37)
177 :type 'overflow-error)) 177 :type 'overflow-error))
178 178
179;; Bug#31938
180(ert-deftest format-%d-float ()
181 (should (string-equal (format "%d" -1.1) "-1"))
182 (should (string-equal (format "%d" -0.9) "0"))
183 (should (string-equal (format "%d" -0.0) "0"))
184 (should (string-equal (format "%d" 0.0) "0"))
185 (should (string-equal (format "%d" 0.9) "0"))
186 (should (string-equal (format "%d" 1.1) "1")))
179 187
180;;; Check format-time-string with various TZ settings. 188;;; Check format-time-string with various TZ settings.
181;;; Use only POSIX-compatible TZ values, since the tests should work 189;;; Use only POSIX-compatible TZ values, since the tests should work