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

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

bug#44155: Print integers as characters


From: Juri Linkov
Subject: bug#44155: Print integers as characters
Date: Sat, 24 Oct 2020 22:53:44 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (x86_64-pc-linux-gnu)

>>> +        if (print_integers_as_characters && CHARACTERP (obj))
>>> +          {
>>> +            printchar ('?', printcharfun);
>>> +            print_string (CALLN (Fstring, obj), printcharfun);
>>
>> That will create ambigous output.
>
> Or do you mean:
>
> (dotimes (i (max-char))
>   (condition-case err
>       (unless (eq i (read (concat "?" (string i))))
>         (message "%d ?%s" i (string i)))
>     (error (message "%d ?%s ;; %s" i (string i) (error-message-string err)))))
>
> 92 ?\ ;; End of file during parsing
> 4194176 ?\200
> ...
> 4194302 ?\376

Now the following patch on this code

(let ((integer-output-format t))
  (pp '(?\; ?\( ?\) ?\{ ?\} ?\[ ?\] ?\" ?\' ?\\ 4194176)
      (current-buffer)))

outputs

(?\; ?\( ?\) ?\{ ?\} ?\[ ?\] ?\" ?\' ?\\ 4194176)

and no ambiguities found with

(let ((integer-output-format t))
  (dotimes (i (+ (max-char) 2))
    (condition-case err
        (unless (eq i (read (format "%S" i)))
          (message "%d ?%s" i (string i)))
      (error (message "%d ?%s ;; %s" i (string i) (error-message-string 
err))))))

The list of escaped characters was taken from 'prin1-char',
not from a similar list in 'print_object' in 'case Lisp_Symbol' branch.

Also 'integer-output-format' prints integers in hex format when set to 16.

(let ((integer-output-format 16))
  (pp '(?\; ?\( ?\) ?\{ ?\} ?\[ ?\] ?\" ?\' ?\\ 4194176)
      (current-buffer)))
=>
(#x3b #x28 #x29 #x7b #x7d #x5b #x5d #x22 #x27 #x5c #x3fff80)
diff --git a/src/print.c b/src/print.c
index 53aa353769..53c8c4c91a 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1908,8 +1908,29 @@ 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);
+        EMACS_INT c = XFIXNUM (obj);
+
+        if (EQ (Vinteger_output_format, Qt) && CHARACTERP (obj) && c < 4194176)
+          {
+            printchar ('?', printcharfun);
+
+            if (escapeflag
+                && (c == ';' || c == '(' || c == ')' || c == '{' || c == '}'
+                    || c == '[' || c == ']' || c == '\"' || c == '\'' || c == 
'\\'))
+              printchar ('\\', printcharfun);
+            print_string (Fchar_to_string (obj), printcharfun);
+          }
+        else if (INTEGERP (Vinteger_output_format)
+                 && XFIXNUM (Vinteger_output_format) == 16 && c >= 0)
+          {
+            int len = sprintf (buf, "#x%"pI"x", (EMACS_UINT) c);
+            strout (buf, len, len, printcharfun);
+          }
+        else
+          {
+            int len = sprintf (buf, "%"pI"d", c);
+            strout (buf, len, len, printcharfun);
+          }
       }
       break;
 
@@ -2247,6 +2268,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 integers as characters.
+When a number 16, print numbers in hex format.
+Otherwise, print integers in 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'.  */);

reply via email to

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