emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] master a4605cd 1/2: Improve octal-escape output in bool ve


From: Paul Eggert
Subject: [Emacs-diffs] master a4605cd 1/2: Improve octal-escape output in bool vectors and strings
Date: Thu, 1 Mar 2018 21:16:49 -0500 (EST)

branch: master
commit a4605cd60d79e5dc050d722f8c4360f11ce65232
Author: Paul Eggert <address@hidden>
Commit: Paul Eggert <address@hidden>

    Improve octal-escape output in bool vectors and strings
    
    * src/print.c (octalout): New function.
    (print_vectorlike): When printing bool vectors, use
    octal escapes for control characters when
    print-escape-control-characters is non-nil, so that
    the printed representation avoids encoding issues.
    Rename locals to avoid byte-vs-char confusion.
    (print_object): Don't output unnecessary zeros when
    printing octal escapes.  Simplify by using octalout.
---
 src/print.c | 57 ++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 34 insertions(+), 23 deletions(-)

diff --git a/src/print.c b/src/print.c
index b3c0f6f..a8bbb9d 100644
--- a/src/print.c
+++ b/src/print.c
@@ -313,6 +313,25 @@ printchar (unsigned int ch, Lisp_Object fun)
     }
 }
 
+/* Output an octal escape for C.  If C is less than '\100' consult the
+   following character (if any) to see whether to use three octal
+   digits to avoid misinterpretation of the next character.  The next
+   character after C will be taken from DATA, starting at byte
+   location I, if I is less than SIZE.  Use PRINTCHARFUN to output
+   each character.  */
+
+static void
+octalout (unsigned char c, unsigned char *data, ptrdiff_t i, ptrdiff_t size,
+         Lisp_Object printcharfun)
+{
+  int digits = (c > '\77' || (i < size && '0' <= data[i] && data[i] <= '7')
+               ? 3
+               : c > '\7' ? 2 : 1);
+  printchar ('\\', printcharfun);
+  do
+    printchar ('0' + ((c >> (3 * --digits)) & 7), printcharfun);
+  while (digits != 0);
+}
 
 /* Output SIZE characters, SIZE_BYTE bytes from string PTR using
    method PRINTCHARFUN.  PRINTCHARFUN nil means output to
@@ -1367,32 +1386,33 @@ print_vectorlike (Lisp_Object obj, Lisp_Object 
printcharfun, bool escapeflag,
     case PVEC_BOOL_VECTOR:
       {
        EMACS_INT size = bool_vector_size (obj);
-       ptrdiff_t size_in_chars = bool_vector_bytes (size);
-       ptrdiff_t real_size_in_chars = size_in_chars;
+       ptrdiff_t size_in_bytes = bool_vector_bytes (size);
+       ptrdiff_t real_size_in_bytes = size_in_bytes;
+       unsigned char *data = bool_vector_uchar_data (obj);
 
        int len = sprintf (buf, "#&%"pI"d\"", size);
        strout (buf, len, len, printcharfun);
 
-       /* Don't print more characters than the specified maximum.
+       /* Don't print more bytes than the specified maximum.
           Negative values of print-length are invalid.  Treat them
           like a print-length of nil.  */
        if (NATNUMP (Vprint_length)
-           && XFASTINT (Vprint_length) < size_in_chars)
-         size_in_chars = XFASTINT (Vprint_length);
+           && XFASTINT (Vprint_length) < size_in_bytes)
+         size_in_bytes = XFASTINT (Vprint_length);
 
-       for (ptrdiff_t i = 0; i < size_in_chars; i++)
+       for (ptrdiff_t i = 0; i < size_in_bytes; i++)
          {
            maybe_quit ();
-           unsigned char c = bool_vector_uchar_data (obj)[i];
+           unsigned char c = data[i];
            if (c == '\n' && print_escape_newlines)
              print_c_string ("\\n", printcharfun);
            else if (c == '\f' && print_escape_newlines)
              print_c_string ("\\f", printcharfun);
-           else if (c > '\177')
+           else if (c > '\177'
+                    || (print_escape_control_characters && c_iscntrl (c)))
              {
                /* Use octal escapes to avoid encoding issues.  */
-               int len = sprintf (buf, "\\%o", c);
-               strout (buf, len, len, printcharfun);
+               octalout (c, data, i + 1, size_in_bytes, printcharfun);
              }
            else
              {
@@ -1402,7 +1422,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object 
printcharfun, bool escapeflag,
              }
          }
 
-       if (size_in_chars < real_size_in_chars)
+       if (size_in_bytes < real_size_in_bytes)
          print_c_string (" ...", printcharfun);
        printchar ('\"', printcharfun);
       }
@@ -1854,9 +1874,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, 
bool escapeflag)
                     (when requested) a non-ASCII character in a unibyte buffer,
                     print single-byte non-ASCII string chars
                     using octal escapes.  */
-                 char outbuf[5];
-                 int len = sprintf (outbuf, "\\%03o", c + 0u);
-                 strout (outbuf, len, len, printcharfun);
+                 octalout (c, SDATA (obj), i_byte, size_byte, printcharfun);
                  need_nonhex = false;
                }
              else if (multibyte
@@ -1870,7 +1888,6 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, 
bool escapeflag)
                }
              else
                {
-                  bool still_need_nonhex = false;
                  /* If we just had a hex escape, and this character
                     could be taken as part of it,
                     output `\ ' to prevent that.  */
@@ -1884,22 +1901,16 @@ print_object (Lisp_Object obj, Lisp_Object 
printcharfun, bool escapeflag)
                            ? (c = 'n', true)
                            : c == '\f' && print_escape_newlines
                            ? (c = 'f', true)
-                           : c == '\0' && print_escape_control_characters
-                           ? (c = '0', still_need_nonhex = true)
                            : c == '\"' || c == '\\')
                     {
                       printchar ('\\', printcharfun);
                       printchar (c, printcharfun);
                     }
                   else if (print_escape_control_characters && c_iscntrl (c))
-                    {
-                      char outbuf[1 + 3 + 1];
-                      int len = sprintf (outbuf, "\\%03o", c + 0u);
-                      strout (outbuf, len, len, printcharfun);
-                    }
+                   octalout (c, SDATA (obj), i_byte, size_byte, printcharfun);
                   else
                     printchar (c, printcharfun);
-                 need_nonhex = still_need_nonhex;
+                 need_nonhex = false;
                }
            }
          printchar ('\"', printcharfun);



reply via email to

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