emacs-bug-tracker
[Top][All Lists]
Advanced

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

[debbugs-tracker] bug#32252: closed ([PATCH] %o and %x now format signed


From: GNU bug Tracking System
Subject: [debbugs-tracker] bug#32252: closed ([PATCH] %o and %x now format signed numbers)
Date: Thu, 26 Jul 2018 07:45:01 +0000

Your message dated Thu, 26 Jul 2018 00:44:34 -0700
with message-id <address@hidden>
and subject line Re: bug#32252: [PATCH] %o and %x now format signed numbers
has caused the debbugs.gnu.org bug report #32252,
regarding [PATCH] %o and %x now format signed numbers
to be marked as done.

(If you believe you have received this mail in error, please contact
address@hidden)


-- 
32252: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=32252
GNU Bug Tracking System
Contact address@hidden with problems
--- Begin Message --- Subject: [PATCH] %o and %x now format signed numbers Date: Mon, 23 Jul 2018 12:12:50 -0700
Treat integers as signed numbers when using the %o
and %x format specifiers, instead of treating them as
a machine-dependent two’s complement representation.
This should make Emacs more machine-independent, and
better-insulated for future changes involving bignums.
The new compatibility variable ‘binary-as-unsigned’
enables the old machine-dependent behavior.
This is a simplified version of the change proposed in:
https://lists.gnu.org/r/emacs-devel/2018-07/msg00763.html
I simplified that proposal by omitting bitwidth modifiers, as
I could not find an any example uses in the Emacs source code
that needed them and doing them correctly would have been
quite a bit more work for apparently little benefit.
* doc/lispref/strings.texi (Formatting Strings):
* etc/NEWS: Document change.
* src/editfns.c (styled_format): Treat integers as signed
numbers even with %o and %x.  Support the + and space
flags with %o and %x, since they’re about signs.
(syms_of_editfns): New compatibility variable binary-as-signed.
* test/src/editfns-tests.el (read-large-integer):
Test that maximal integers can be read after printing
with all integer formats.
(format-%o-invalid-float): Adjust test to match new
behavior, which allows negative octal.
---
 doc/lispref/strings.texi  |  6 +++---
 etc/NEWS                  |  8 ++++++++
 src/editfns.c             | 42 ++++++++++++++++++++++++++++++++++-----
 test/src/editfns-tests.el | 11 +++++-----
 4 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 2fff3c7c75..582561fe42 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -922,7 +922,7 @@ Formatting Strings
 @item %o
 @cindex integer to octal
 Replace the specification with the base-eight representation of an
-unsigned integer.  The object can also be a nonnegative floating-point
+integer.  The object can also be a floating-point
 number that is formatted as an integer, dropping any fraction, if the
 integer does not exceed machine limits.
 
@@ -935,8 +935,8 @@ Formatting Strings
 @itemx %X
 @cindex integer to hexadecimal
 Replace the specification with the base-sixteen representation of an
-unsigned integer.  @samp{%x} uses lower case and @samp{%X} uses upper
-case.  The object can also be a nonnegative floating-point number that
+integer.  @samp{%x} uses lower case and @samp{%X} uses upper
+case.  The object can also be a floating-point number that
 is formatted as an integer, dropping any fraction, if the integer does
 not exceed machine limits.
 
diff --git a/etc/NEWS b/etc/NEWS
index fc2a5d4c03..b735cf49b3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -697,6 +697,14 @@ To get the old behavior, set the new, experimental variable
 read-integer-overflow-as-float to t and please email
 address@hidden if you need that.  (Bug#30408).
 
++++
+** Numbers formatted via %o or %x are now formatted as signed integers.
+Formerly they were formatted using machine-dependent two's complement
+representations.  To get the old behavior, set the new, experimental
+variable binary-as-unsigned to t and please email address@hidden
+if you need that.  Because %o and %x now format signed integers, they
+now support the + and space flags.
+
 ---
 ** Some functions and variables obsolete since Emacs 22 have been removed:
 archive-mouse-extract, assoc-ignore-case, assoc-ignore-representation,
diff --git a/src/editfns.c b/src/editfns.c
index 09f836c3eb..a8fc499d63 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -4196,8 +4196,8 @@ contain either numbered or unnumbered %-sequences but not 
both, except
 that %% can be mixed with numbered %-sequences.
 
 The + flag character inserts a + before any nonnegative number, while a
-space inserts a space before any nonnegative number; these flags only
-affect %d, %e, %f, and %g sequences, and the + flag takes precedence.
+space inserts a space before any nonnegative number; these flags
+affect only numeric %-sequences, and the + flag takes precedence.
 The - and 0 flags affect the width specifier, as described below.
 
 The # flag means to use an alternate display form for %o, %x, %X, %e,
@@ -4736,19 +4736,42 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool 
message)
                }
              else
                {
-                 /* Don't sign-extend for octal or hex printing.  */
                  uprintmax_t x;
+                 bool negative;
                  if (INTEGERP (arg))
-                   x = XUINT (arg);
+                   {
+                     EMACS_INT i;
+                     if (binary_as_unsigned)
+                       {
+                         i = XUINT (arg);
+                         negative = false;
+                       }
+                     else
+                       {
+                         i = XINT (arg);
+                         negative = i < 0;
+                         if (negative)
+                           i = -i;
+                       }
+                     x = i;
+                   }
                  else
                    {
                      double d = XFLOAT_DATA (arg);
                      double uprintmax = TYPE_MAXIMUM (uprintmax_t);
+                     negative = d < 0;
+                     if (negative)
+                       d = -d;
                      if (! (0 <= d && d < uprintmax + 1))
                        xsignal1 (Qoverflow_error, arg);
                      x = d;
+                     negative &= x != 0;
                    }
-                 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
+                 sprintf_buf[0] = negative ? '-' : plus_flag ? '+' : ' ';
+                 bool signedp = negative | plus_flag | space_flag;
+                 sprintf_bytes = sprintf (sprintf_buf + signedp,
+                                          convspec, prec, x);
+                 sprintf_bytes += signedp;
                }
 
              /* Now the length of the formatted item is known, except it omits
@@ -5558,6 +5581,15 @@ functions if all the text being accessed has this 
property.  */);
   DEFVAR_LISP ("operating-system-release", Voperating_system_release,
               doc: /* The release of the operating system Emacs is running on. 
 */);
 
+  DEFVAR_BOOL ("binary-as-unsigned",
+              binary_as_unsigned,
+              doc: /* Non-nil means `format' %x and %o treat numbers as 
unsigned.
+Nil (the default) means to treat them as signed.
+Treating them as unsigned has machine-dependent results.
+
+This variable is experimental; email address@hidden if you need it.  */);
+  binary_as_unsigned = false;
+
   defsubr (&Spropertize);
   defsubr (&Schar_equal);
   defsubr (&Sgoto_char);
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
index c828000bb4..57a2081fc5 100644
--- a/test/src/editfns-tests.el
+++ b/test/src/editfns-tests.el
@@ -165,15 +165,16 @@ transpose-test-get-byte-positions
                 :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)
+  (dolist (fmt '("%d" "%s" "#o%o" "#x%x"))
+    (dolist (val (list most-negative-fixnum (1+ most-negative-fixnum)
+                       -1 0 1
+                       (1- most-positive-fixnum) most-positive-fixnum))
+      (should (eq val (read (format fmt val))))))
   (should-error (read (format "#32rG%x" most-positive-fixnum))
                 :type 'overflow-error))
 
 (ert-deftest format-%o-invalid-float ()
-  (should-error (format "%o" -1e-37)
+  (should-error (format "%o" -1e+INF)
                 :type 'overflow-error))
 
 ;; Bug#31938
-- 
2.17.1




--- End Message ---
--- Begin Message --- Subject: Re: bug#32252: [PATCH] %o and %x now format signed numbers Date: Thu, 26 Jul 2018 00:44:34 -0700 User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1
Eli Zaretskii wrote:
Cc: address@hidden, address@hidden
From: Paul Eggert <address@hidden>

That being said, it appears that there are enough qualms about the
change that I plan to install it with the new variable set the other
way. I.e., the default will be the current behavior and people can set
the new variable to get the new behavior, to try it this behavior out to
see whether they have problems.

Thank you.

OK, I installed the attached patch which does that, and am closing the bug report. I plan to run with binary-as-unsigned set to nil and to report any problems I encounter. I encourage others (particularly skeptics :-) to do the same.

Attachment: 0001-o-and-x-can-now-format-signed-integers.txt
Description: Text document


--- End Message ---

reply via email to

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