GNU bug report logs - #32252
[PATCH] %o and %x now format signed numbers

Previous Next

Package: emacs;

Reported by: Paul Eggert <eggert <at> cs.ucla.edu>

Date: Mon, 23 Jul 2018 19:14:02 UTC

Severity: normal

Tags: patch

Done: Paul Eggert <eggert <at> cs.ucla.edu>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: help-debbugs <at> gnu.org (GNU bug Tracking System)
To: Paul Eggert <eggert <at> cs.ucla.edu>
Subject: bug#32252: closed (Re: bug#32252: [PATCH] %o and %x now format
 signed numbers)
Date: Thu, 26 Jul 2018 07:45:02 +0000
[Message part 1 (text/plain, inline)]
Your bug report

#32252: [PATCH] %o and %x now format signed numbers

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to 32252 <at> debbugs.gnu.org.

-- 
32252: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=32252
GNU Bug Tracking System
Contact help-debbugs <at> gnu.org with problems
[Message part 2 (message/rfc822, inline)]
From: Paul Eggert <eggert <at> cs.ucla.edu>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 32252-done <at> debbugs.gnu.org, eller.helmut <at> gmail.com
Subject: Re: bug#32252: [PATCH] %o and %x now format signed numbers
Date: Thu, 26 Jul 2018 00:44:34 -0700
[Message part 3 (text/plain, inline)]
Eli Zaretskii wrote:
>> Cc: eller.helmut <at> gmail.com, 32252 <at> debbugs.gnu.org
>> From: Paul Eggert <eggert <at> cs.ucla.edu>
>>
>> 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.
[0001-o-and-x-can-now-format-signed-integers.txt (text/plain, attachment)]
[Message part 5 (message/rfc822, inline)]
From: Paul Eggert <eggert <at> cs.ucla.edu>
To: bug-gnu-emacs <at> gnu.org
Cc: Paul Eggert <eggert <at> cs.ucla.edu>
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
 30408 <at> debbugs.gnu.org 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 emacs-devel <at> gnu.org
+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 emacs-devel <at> gnu.org 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




This bug report was last modified 2 years and 322 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.