Subject: bug#44155: Print integers as characters

From: Juri Linkov <[email-masked]>
Date: Thu, 29 Oct 2020 23:00:48 +0200

>> >> The existing 'prin1-char' used as a reference implementation
>> >> doesn't print integers like 4194176 as characters, so the patch
>> >> does the same.
>> >
>> > I don't think it's right, FWIW.  Displaying something like \100 would
>> > be better, IMO.
>>
>> Sorry, I don't understand why 4194176 could be printed as \100.
>
> I meant \200, sorry.  That's the raw byte that 4194176 stands for.

OK, in this patch the condition !CHAR_BYTE8_P(c) is removed, so
it prints \200:

diff --git a/src/print.c b/src/print.c
index 53aa353769..20841eba61 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)))
+          {
+            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 && !NILP (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'.  */);