From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.bugs Subject: bug#44155: Print integers as characters Date: Tue, 27 Oct 2020 22:08:12 +0200 Organization: LINKOV.NET Message-ID: <878sbrc317.fsf@mail.linkov.net> References: <877drh7unm.fsf@igel.home> <87lffxuwgn.fsf@mail.linkov.net> <87d0172yev.fsf@mail.linkov.net> <83mu0afcex.fsf@gnu.org> <87wnzenmwc.fsf@mail.linkov.net> <83imayf5f2.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="17159"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (x86_64-pc-linux-gnu) Cc: 44155@debbugs.gnu.org, schwab@linux-m68k.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Oct 27 21:55:22 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kXW02-0004MV-Hv for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 27 Oct 2020 21:55:22 +0100 Original-Received: from localhost ([::1]:38008 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kXW01-0004nD-Ft for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 27 Oct 2020 16:55:21 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:39970) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kXVyl-00046g-Dt for bug-gnu-emacs@gnu.org; Tue, 27 Oct 2020 16:54:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:34579) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kXVyl-0008Lm-4o for bug-gnu-emacs@gnu.org; Tue, 27 Oct 2020 16:54:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1kXVyl-0007cX-4O for bug-gnu-emacs@gnu.org; Tue, 27 Oct 2020 16:54:03 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Juri Linkov Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 27 Oct 2020 20:54:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 44155 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 44155-submit@debbugs.gnu.org id=B44155.160383199629152 (code B ref 44155); Tue, 27 Oct 2020 20:54:03 +0000 Original-Received: (at 44155) by debbugs.gnu.org; 27 Oct 2020 20:53:16 +0000 Original-Received: from localhost ([127.0.0.1]:46110 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kXVy0-0007a8-21 for submit@debbugs.gnu.org; Tue, 27 Oct 2020 16:53:16 -0400 Original-Received: from relay3-d.mail.gandi.net ([217.70.183.195]:33577) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kXVxy-0007Zv-Fj for 44155@debbugs.gnu.org; Tue, 27 Oct 2020 16:53:15 -0400 X-Originating-IP: 91.129.102.160 Original-Received: from mail.gandi.net (m91-129-102-160.cust.tele2.ee [91.129.102.160]) (Authenticated sender: juri@linkov.net) by relay3-d.mail.gandi.net (Postfix) with ESMTPSA id 739FF60005; Tue, 27 Oct 2020 20:53:06 +0000 (UTC) In-Reply-To: <83imayf5f2.fsf@gnu.org> (Eli Zaretskii's message of "Sun, 25 Oct 2020 21:53:53 +0200") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:191796 Archived-At: --=-=-= Content-Type: text/plain >> > And, btw, why not allow raw bytes here as well? is there some problem? >> >> Because of ambiguity, both these return the same value: >> >> (read (concat "?" (string 128))) => 128 >> (read (concat "?" (string 4194176))) => 128 > > And why is that a problem? I don't know, Andreas remarked that it creates ambiguous output, and I fixed the reported problem. > Alternatively, we could print raw bytes in some special way. But not > treating them as characters sounds some subtlety that will be hard to > explain. The existing 'prin1-char' used as a reference implementation doesn't print integers like 4194176 as characters, so the patch does the same. Anyway, here is a complete patch with tests and documentation: --=-=-= Content-Type: text/x-diff; charset=iso-8859-1 Content-Disposition: inline; filename=integer-output-format-3.patch Content-Transfer-Encoding: 8bit diff --git a/doc/lispref/streams.texi b/doc/lispref/streams.texi index 2cd61ad04f..f171f13779 100644 --- a/doc/lispref/streams.texi +++ b/doc/lispref/streams.texi @@ -902,3 +902,11 @@ Output Variables in the C function @code{sprintf}. For further restrictions on what you can use, see the variable's documentation string. @end defvar + +@defvar integer-output-format +This variable specifies how to print integer numbers. The default is +@code{nil}, meaning use the decimal format. When bound to @code{t}, +print integers as characters when an integer represents a character +(@pxref{Basic Char Syntax}). When bound to the number @code{16}, +print non-negative integers in the hexadecimal format. +@end defvar diff --git a/etc/NEWS b/etc/NEWS index a77c1c883e..2f7d08ad08 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1631,6 +1631,12 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el. * Lisp Changes in Emacs 28.1 +** New variable 'integer-output-format' defines the format of integers. +When this variable is bound to the value 't', integers are printed by +printing functions as characters when an integer represents a character. +When bound to the number 16, non-negative integers are printed in the +hexadecimal format. + +++ ** 'define-globalized-minor-mode' now takes a :predicate parameter. This can be used to control which major modes the minor mode should be diff --git a/src/print.c b/src/print.c index 53aa353769..a5c56c6b48 100644 --- a/src/print.c +++ b/src/print.c @@ -1908,8 +1908,31 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) { case_Lisp_Int: { - int len = sprintf (buf, "%"pI"d", XFIXNUM (obj)); - strout (buf, len, len, printcharfun); + int c; + intmax_t i; + + if (EQ (Vinteger_output_format, Qt) && CHARACTERP (obj) + && (c = XFIXNUM (obj)) && ! CHAR_BYTE8_P (c)) + { + printchar ('?', printcharfun); + if (escapeflag + && (c == ';' || c == '(' || c == ')' || c == '{' || c == '}' + || c == '[' || c == ']' || c == '\"' || c == '\'' || c == '\\')) + printchar ('\\', printcharfun); + printchar (c, printcharfun); + } + else if (INTEGERP (Vinteger_output_format) + && integer_to_intmax (Vinteger_output_format, &i) + && i == 16 && Fnatnump (obj)) + { + int len = sprintf (buf, "#x%"pI"x", (EMACS_UINT) XFIXNUM (obj)); + strout (buf, len, len, printcharfun); + } + else + { + int len = sprintf (buf, "%"pI"d", XFIXNUM (obj)); + strout (buf, len, len, printcharfun); + } } break; @@ -2247,6 +2270,13 @@ syms_of_print (void) that represents the number without losing information. */); Vfloat_output_format = Qnil; + DEFVAR_LISP ("integer-output-format", Vinteger_output_format, + doc: /* The format used to print integers. +When t, print characters from integers that represent a character. +When a number 16, print non-negative integers in the hexadecimal format. +Otherwise, by default print integers in the decimal format. */); + Vinteger_output_format = Qnil; + DEFVAR_LISP ("print-length", Vprint_length, doc: /* Maximum length of list to print before abbreviating. A value of nil means no limit. See also `eval-expression-print-length'. */); diff --git a/test/src/print-tests.el b/test/src/print-tests.el index eb9572dbdf..7b026b6b21 100644 --- a/test/src/print-tests.el +++ b/test/src/print-tests.el @@ -383,5 +383,25 @@ print-hash-table-test (let ((print-length 1)) (format "%S" h)))))) +(print-tests--deftest print-integer-output-format () + ;; Bug#44155. + (let ((integer-output-format t) + (syms (list ?? ?\; ?\( ?\) ?\{ ?\} ?\[ ?\] ?\" ?\' ?\\ ?Á))) + (should (equal (read (print-tests--prin1-to-string syms)) syms)) + (should (equal (print-tests--prin1-to-string syms) + (concat "(" (mapconcat #'prin1-char syms " ") ")")))) + (let ((integer-output-format t) + (syms (list -1 0 1 ?\120 4194175 4194176 (max-char) (1+ (max-char))))) + (should (equal (read (print-tests--prin1-to-string syms)) syms))) + (let ((integer-output-format 16) + (syms (list -1 0 1 most-positive-fixnum (1+ most-positive-fixnum)))) + (should (equal (read (print-tests--prin1-to-string syms)) syms)) + (should (equal (print-tests--prin1-to-string syms) + (concat "(" (mapconcat + (lambda (i) + (if (and (>= i 0) (<= i most-positive-fixnum)) + (format "#x%x" i) (format "%d" i))) + syms " ") ")"))))) + (provide 'print-tests) ;;; print-tests.el ends here --=-=-=--