aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2018-03-01 17:58:26 -0800
committerPaul Eggert2018-03-01 18:16:43 -0800
commita4605cd60d79e5dc050d722f8c4360f11ce65232 (patch)
tree72e3931ea034c261bfe61c37b40ce1afceb1f0f6
parentde92605038763d7f970891a8cc0edc0e106ed267 (diff)
downloademacs-a4605cd60d79e5dc050d722f8c4360f11ce65232.tar.gz
emacs-a4605cd60d79e5dc050d722f8c4360f11ce65232.zip
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.
-rw-r--r--src/print.c57
1 files changed, 34 insertions, 23 deletions
diff --git a/src/print.c b/src/print.c
index b3c0f6f38fc..a8bbb9d37a1 100644
--- a/src/print.c
+++ b/src/print.c
@@ -313,6 +313,25 @@ printchar (unsigned int ch, Lisp_Object fun)
313 } 313 }
314} 314}
315 315
316/* Output an octal escape for C. If C is less than '\100' consult the
317 following character (if any) to see whether to use three octal
318 digits to avoid misinterpretation of the next character. The next
319 character after C will be taken from DATA, starting at byte
320 location I, if I is less than SIZE. Use PRINTCHARFUN to output
321 each character. */
322
323static void
324octalout (unsigned char c, unsigned char *data, ptrdiff_t i, ptrdiff_t size,
325 Lisp_Object printcharfun)
326{
327 int digits = (c > '\77' || (i < size && '0' <= data[i] && data[i] <= '7')
328 ? 3
329 : c > '\7' ? 2 : 1);
330 printchar ('\\', printcharfun);
331 do
332 printchar ('0' + ((c >> (3 * --digits)) & 7), printcharfun);
333 while (digits != 0);
334}
316 335
317/* Output SIZE characters, SIZE_BYTE bytes from string PTR using 336/* Output SIZE characters, SIZE_BYTE bytes from string PTR using
318 method PRINTCHARFUN. PRINTCHARFUN nil means output to 337 method PRINTCHARFUN. PRINTCHARFUN nil means output to
@@ -1367,32 +1386,33 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
1367 case PVEC_BOOL_VECTOR: 1386 case PVEC_BOOL_VECTOR:
1368 { 1387 {
1369 EMACS_INT size = bool_vector_size (obj); 1388 EMACS_INT size = bool_vector_size (obj);
1370 ptrdiff_t size_in_chars = bool_vector_bytes (size); 1389 ptrdiff_t size_in_bytes = bool_vector_bytes (size);
1371 ptrdiff_t real_size_in_chars = size_in_chars; 1390 ptrdiff_t real_size_in_bytes = size_in_bytes;
1391 unsigned char *data = bool_vector_uchar_data (obj);
1372 1392
1373 int len = sprintf (buf, "#&%"pI"d\"", size); 1393 int len = sprintf (buf, "#&%"pI"d\"", size);
1374 strout (buf, len, len, printcharfun); 1394 strout (buf, len, len, printcharfun);
1375 1395
1376 /* Don't print more characters than the specified maximum. 1396 /* Don't print more bytes than the specified maximum.
1377 Negative values of print-length are invalid. Treat them 1397 Negative values of print-length are invalid. Treat them
1378 like a print-length of nil. */ 1398 like a print-length of nil. */
1379 if (NATNUMP (Vprint_length) 1399 if (NATNUMP (Vprint_length)
1380 && XFASTINT (Vprint_length) < size_in_chars) 1400 && XFASTINT (Vprint_length) < size_in_bytes)
1381 size_in_chars = XFASTINT (Vprint_length); 1401 size_in_bytes = XFASTINT (Vprint_length);
1382 1402
1383 for (ptrdiff_t i = 0; i < size_in_chars; i++) 1403 for (ptrdiff_t i = 0; i < size_in_bytes; i++)
1384 { 1404 {
1385 maybe_quit (); 1405 maybe_quit ();
1386 unsigned char c = bool_vector_uchar_data (obj)[i]; 1406 unsigned char c = data[i];
1387 if (c == '\n' && print_escape_newlines) 1407 if (c == '\n' && print_escape_newlines)
1388 print_c_string ("\\n", printcharfun); 1408 print_c_string ("\\n", printcharfun);
1389 else if (c == '\f' && print_escape_newlines) 1409 else if (c == '\f' && print_escape_newlines)
1390 print_c_string ("\\f", printcharfun); 1410 print_c_string ("\\f", printcharfun);
1391 else if (c > '\177') 1411 else if (c > '\177'
1412 || (print_escape_control_characters && c_iscntrl (c)))
1392 { 1413 {
1393 /* Use octal escapes to avoid encoding issues. */ 1414 /* Use octal escapes to avoid encoding issues. */
1394 int len = sprintf (buf, "\\%o", c); 1415 octalout (c, data, i + 1, size_in_bytes, printcharfun);
1395 strout (buf, len, len, printcharfun);
1396 } 1416 }
1397 else 1417 else
1398 { 1418 {
@@ -1402,7 +1422,7 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
1402 } 1422 }
1403 } 1423 }
1404 1424
1405 if (size_in_chars < real_size_in_chars) 1425 if (size_in_bytes < real_size_in_bytes)
1406 print_c_string (" ...", printcharfun); 1426 print_c_string (" ...", printcharfun);
1407 printchar ('\"', printcharfun); 1427 printchar ('\"', printcharfun);
1408 } 1428 }
@@ -1854,9 +1874,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1854 (when requested) a non-ASCII character in a unibyte buffer, 1874 (when requested) a non-ASCII character in a unibyte buffer,
1855 print single-byte non-ASCII string chars 1875 print single-byte non-ASCII string chars
1856 using octal escapes. */ 1876 using octal escapes. */
1857 char outbuf[5]; 1877 octalout (c, SDATA (obj), i_byte, size_byte, printcharfun);
1858 int len = sprintf (outbuf, "\\%03o", c + 0u);
1859 strout (outbuf, len, len, printcharfun);
1860 need_nonhex = false; 1878 need_nonhex = false;
1861 } 1879 }
1862 else if (multibyte 1880 else if (multibyte
@@ -1870,7 +1888,6 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1870 } 1888 }
1871 else 1889 else
1872 { 1890 {
1873 bool still_need_nonhex = false;
1874 /* If we just had a hex escape, and this character 1891 /* If we just had a hex escape, and this character
1875 could be taken as part of it, 1892 could be taken as part of it,
1876 output `\ ' to prevent that. */ 1893 output `\ ' to prevent that. */
@@ -1884,22 +1901,16 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1884 ? (c = 'n', true) 1901 ? (c = 'n', true)
1885 : c == '\f' && print_escape_newlines 1902 : c == '\f' && print_escape_newlines
1886 ? (c = 'f', true) 1903 ? (c = 'f', true)
1887 : c == '\0' && print_escape_control_characters
1888 ? (c = '0', still_need_nonhex = true)
1889 : c == '\"' || c == '\\') 1904 : c == '\"' || c == '\\')
1890 { 1905 {
1891 printchar ('\\', printcharfun); 1906 printchar ('\\', printcharfun);
1892 printchar (c, printcharfun); 1907 printchar (c, printcharfun);
1893 } 1908 }
1894 else if (print_escape_control_characters && c_iscntrl (c)) 1909 else if (print_escape_control_characters && c_iscntrl (c))
1895 { 1910 octalout (c, SDATA (obj), i_byte, size_byte, printcharfun);
1896 char outbuf[1 + 3 + 1];
1897 int len = sprintf (outbuf, "\\%03o", c + 0u);
1898 strout (outbuf, len, len, printcharfun);
1899 }
1900 else 1911 else
1901 printchar (c, printcharfun); 1912 printchar (c, printcharfun);
1902 need_nonhex = still_need_nonhex; 1913 need_nonhex = false;
1903 } 1914 }
1904 } 1915 }
1905 printchar ('\"', printcharfun); 1916 printchar ('\"', printcharfun);