diff options
| author | Paul Eggert <eggert@cs.ucla.edu> | 2018-07-26 00:34:10 -0700 |
|---|---|---|
| committer | Paul Eggert <eggert@cs.ucla.edu> | 2018-07-26 00:39:17 -0700 |
| commit | 4a56ca5bbfabbb9c581828cd91648346e6b03844 (patch) | |
| tree | 90b804ea4ec22a8b7be181f0b505b57c40a85c27 /src | |
| parent | 19f5f7b19b0dcdae87476a3fd51c41f840b2b80f (diff) | |
| download | emacs-4a56ca5bbfabbb9c581828cd91648346e6b03844.tar.gz | |
%o and %x can now format signed integers
Optionally treat integers as signed numbers with %o
and %x format specifiers, instead of treating them as
a machine-dependent two’s complement representation.
This option is more machine-independent, allows formats
like "#x%x" to be useful for reading later, and is
better-insulated for future changes involving bignums.
Setting the new variable ‘binary-as-unsigned’ to nil
enables the new behavior (Bug#32252).
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):
Document that %x and %o format negative integers in a
platform-dependent way. Also, document how to format
numbers so that the same values can be read back in.
* etc/NEWS: Document the change.
* src/editfns.c (styled_format): Treat integers as signed
numbers even with %o and %x, if binary-as-unsigned is nil.
Support the + and space flags with %o and %x, since they’re
about signs.
(syms_of_editfns): New variable binary-as-unsigned.
* test/src/editfns-tests.el (read-large-integer):
Test that maximal integers can be read after printing
with all integer formats, if binary-as-unsigned is nil.
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/src/editfns.c b/src/editfns.c index 1d6040da3f7..df257219e8f 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,10 +4736,22 @@ 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); + { + if (binary_as_unsigned) + { + x = XUINT (arg); + negative = false; + } + else + { + EMACS_INT i = XINT (arg); + negative = i < 0; + x = negative ? -i : i; + } + } else { double d = XFLOAT_DATA (arg); @@ -4747,8 +4759,13 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) if (! (0 <= d && d < uprintmax + 1)) xsignal1 (Qoverflow_error, arg); x = d; + negative = false; } - 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 +5575,22 @@ 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 integers as unsigned. +This has machine-dependent results. Nil means to treat integers as +signed, which is portable; for example, if N is a negative integer, +(read (format "#x%x") N) returns N only when this variable is nil. + +This variable is experimental; email 32252@debbugs.gnu.org if you need +it to be non-nil. */); + /* For now, default to true if bignums exist, false in traditional Emacs. */ +#ifdef lisp_h_FIXNUMP + binary_as_unsigned = true; +#else + binary_as_unsigned = false; +#endif + defsubr (&Spropertize); defsubr (&Schar_equal); defsubr (&Sgoto_char); |
