diff options
| author | Paul Eggert | 2018-03-01 17:58:26 -0800 |
|---|---|---|
| committer | Paul Eggert | 2018-03-01 18:16:43 -0800 |
| commit | a4605cd60d79e5dc050d722f8c4360f11ce65232 (patch) | |
| tree | 72e3931ea034c261bfe61c37b40ce1afceb1f0f6 | |
| parent | de92605038763d7f970891a8cc0edc0e106ed267 (diff) | |
| download | emacs-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.c | 57 |
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 | |||
| 323 | static void | ||
| 324 | octalout (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); |