aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2015-05-31 20:04:05 -0700
committerPaul Eggert2015-05-31 20:04:43 -0700
commit467af178f53798e4cd102e04eb2990121eb655df (patch)
tree1e6e2cec1eb87963ae796289ef9a1afdd060a668
parent21d13bce38c2160bf21b3428cd8e56daadcf4698 (diff)
downloademacs-467af178f53798e4cd102e04eb2990121eb655df.tar.gz
emacs-467af178f53798e4cd102e04eb2990121eb655df.zip
Treat batch stdout/stderr like standard display
Calls like (print FOO) could generate improperly encoded or hard-to-read output if FOO contains characters outside the system locale. Fix this by treating batch stdout and stderr like interactive standard display, when it comes to transliterating and encoding characters (Bug#20545). * doc/emacs/mule.texi (Communication Coding): * doc/lispref/display.texi (Active Display Table): * doc/lispref/nonascii.texi (Locales): * etc/NEWS: * src/coding.c (syms_of_coding): * src/dispnew.c (syms_of_display): Document this. * src/print.c: Include disptab.h. (printchar_to_stream): New function, with much of the guts of the old Fexternal_debugging_output, except this one also uses the standard display table. (printchar, strout, Fexternal_debugging_output): Use it.
-rw-r--r--doc/emacs/mule.texi4
-rw-r--r--doc/lispref/display.texi5
-rw-r--r--doc/lispref/nonascii.texi1
-rw-r--r--etc/NEWS6
-rw-r--r--src/coding.c3
-rw-r--r--src/dispnew.c1
-rw-r--r--src/print.c106
7 files changed, 90 insertions, 36 deletions
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 7336fdc8f47..80b1384feb6 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -1164,7 +1164,9 @@ current language environment.
1164to use when encoding and decoding system strings such as system error 1164to use when encoding and decoding system strings such as system error
1165messages and @code{format-time-string} formats and time stamps. That 1165messages and @code{format-time-string} formats and time stamps. That
1166coding system is also used for decoding non-@acronym{ASCII} keyboard 1166coding system is also used for decoding non-@acronym{ASCII} keyboard
1167input on the X Window System. You should choose a coding system that is compatible 1167input on the X Window System and for encoding text sent to the
1168standard output and error streams when in batch mode. You should
1169choose a coding system that is compatible
1168with the underlying system's text representation, which is normally 1170with the underlying system's text representation, which is normally
1169specified by one of the environment variables @env{LC_ALL}, 1171specified by one of the environment variables @env{LC_ALL},
1170@env{LC_CTYPE}, and @env{LANG}. (The first one, in the order 1172@env{LC_CTYPE}, and @env{LANG}. (The first one, in the order
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index b12995be6ed..357a3c33fa3 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -6522,8 +6522,9 @@ no buffer display table.
6522@defvar standard-display-table 6522@defvar standard-display-table
6523The value of this variable is the standard display table, which is 6523The value of this variable is the standard display table, which is
6524used when Emacs is displaying a buffer in a window with neither a 6524used when Emacs is displaying a buffer in a window with neither a
6525window display table nor a buffer display table defined. Its default 6525window display table nor a buffer display table defined, or when Emacs
6526is @code{nil}. 6526is outputting text to the standard output or error streams. Its
6527default is @code{nil}.
6527@end defvar 6528@end defvar
6528 6529
6529The @file{disp-table} library defines several functions for changing 6530The @file{disp-table} library defines several functions for changing
diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi
index f16018417de..362c3a4dcbb 100644
--- a/doc/lispref/nonascii.texi
+++ b/doc/lispref/nonascii.texi
@@ -1959,6 +1959,7 @@ how Emacs interacts with these features.
1959@cindex keyboard input decoding on X 1959@cindex keyboard input decoding on X
1960This variable specifies the coding system to use for decoding system 1960This variable specifies the coding system to use for decoding system
1961error messages and---on X Window system only---keyboard input, for 1961error messages and---on X Window system only---keyboard input, for
1962sending batch output to the standard output and error streams, for
1962encoding the format argument to @code{format-time-string}, and for 1963encoding the format argument to @code{format-time-string}, and for
1963decoding the return value of @code{format-time-string}. 1964decoding the return value of @code{format-time-string}.
1964@end defvar 1965@end defvar
diff --git a/etc/NEWS b/etc/NEWS
index d07057ef4b2..57e63b1f208 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -947,6 +947,12 @@ integers.
947** New function `set-binary-mode' allows to switch a standard stream 947** New function `set-binary-mode' allows to switch a standard stream
948of the Emacs process to binary I/O mode. 948of the Emacs process to binary I/O mode.
949 949
950** In locales that cannot display curved quotes, ASCII approximations
951are installed in standard-display-table.
952
953** Standard output and error streams now transliterate characters via
954standard-display-table, and encode output using locale-coding-system.
955
950** Miscellaneous name change 956** Miscellaneous name change
951 957
952For consistency with the usual Emacs spelling, the Lisp variable 958For consistency with the usual Emacs spelling, the Lisp variable
diff --git a/src/coding.c b/src/coding.c
index 776ecac62d9..9342c3841f6 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -11121,7 +11121,8 @@ See also the function `find-operation-coding-system'. */);
11121 11121
11122 DEFVAR_LISP ("locale-coding-system", Vlocale_coding_system, 11122 DEFVAR_LISP ("locale-coding-system", Vlocale_coding_system,
11123 doc: /* Coding system to use with system messages. 11123 doc: /* Coding system to use with system messages.
11124Also used for decoding keyboard input on X Window system. */); 11124Also used for decoding keyboard input on X Window system, and for
11125encoding standard output and error streams. */);
11125 Vlocale_coding_system = Qnil; 11126 Vlocale_coding_system = Qnil;
11126 11127
11127 /* The eol mnemonics are reset in startup.el system-dependently. */ 11128 /* The eol mnemonics are reset in startup.el system-dependently. */
diff --git a/src/dispnew.c b/src/dispnew.c
index 693dd49825c..7e7afa71d20 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -6245,6 +6245,7 @@ Each element can be:
6245 6245
6246 DEFVAR_LISP ("standard-display-table", Vstandard_display_table, 6246 DEFVAR_LISP ("standard-display-table", Vstandard_display_table,
6247 doc: /* Display table to use for buffers that specify none. 6247 doc: /* Display table to use for buffers that specify none.
6248It is also used for standard output and error streams.
6248See `buffer-display-table' for more information. */); 6249See `buffer-display-table' for more information. */);
6249 Vstandard_display_table = Qnil; 6250 Vstandard_display_table = Qnil;
6250 6251
diff --git a/src/print.c b/src/print.c
index a182839ba7d..65c120dbb4f 100644
--- a/src/print.c
+++ b/src/print.c
@@ -31,6 +31,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31#include "window.h" 31#include "window.h"
32#include "process.h" 32#include "process.h"
33#include "dispextern.h" 33#include "dispextern.h"
34#include "disptab.h"
34#include "termchar.h" 35#include "termchar.h"
35#include "intervals.h" 36#include "intervals.h"
36#include "blockinput.h" 37#include "blockinput.h"
@@ -195,6 +196,61 @@ print_unwind (Lisp_Object saved_text)
195 memcpy (print_buffer, SDATA (saved_text), SCHARS (saved_text)); 196 memcpy (print_buffer, SDATA (saved_text), SCHARS (saved_text));
196} 197}
197 198
199/* Print character CH to the stdio stream STREAM. */
200
201static void
202printchar_to_stream (unsigned int ch, FILE *stream)
203{
204 Lisp_Object dv IF_LINT (= Qnil);
205 ptrdiff_t i = 0, n = 1;
206
207 if (CHAR_VALID_P (ch) && DISP_TABLE_P (Vstandard_display_table))
208 {
209 dv = DISP_CHAR_VECTOR (XCHAR_TABLE (Vstandard_display_table), ch);
210 if (VECTORP (dv))
211 {
212 n = ASIZE (dv);
213 goto next_char;
214 }
215 }
216
217 while (true)
218 {
219 if (ASCII_CHAR_P (ch))
220 {
221 putc (ch, stream);
222#ifdef WINDOWSNT
223 /* Send the output to a debugger (nothing happens if there
224 isn't one). */
225 if (print_output_debug_flag && stream == stderr)
226 OutputDebugString ((char []) {ch, '\0'});
227#endif
228 }
229 else
230 {
231 unsigned char mbstr[MAX_MULTIBYTE_LENGTH];
232 int len = CHAR_STRING (ch, mbstr);
233 Lisp_Object encoded_ch =
234 ENCODE_SYSTEM (make_multibyte_string ((char *) mbstr, 1, len));
235
236 fwrite (SSDATA (encoded_ch), 1, SBYTES (encoded_ch), stream);
237#ifdef WINDOWSNT
238 if (print_output_debug_flag && stream == stderr)
239 OutputDebugString (SSDATA (encoded_ch));
240#endif
241 }
242
243 i++;
244
245 next_char:
246 for (; i < n; i++)
247 if (CHARACTERP (AREF (dv, i)))
248 break;
249 if (! (i < n))
250 break;
251 ch = XFASTINT (AREF (dv, i));
252 }
253}
198 254
199/* Print character CH using method FUN. FUN nil means print to 255/* Print character CH using method FUN. FUN nil means print to
200 print_buffer. FUN t means print to echo area or stdout if 256 print_buffer. FUN t means print to echo area or stdout if
@@ -226,7 +282,10 @@ printchar (unsigned int ch, Lisp_Object fun)
226 else if (noninteractive) 282 else if (noninteractive)
227 { 283 {
228 printchar_stdout_last = ch; 284 printchar_stdout_last = ch;
229 fwrite (str, 1, len, stdout); 285 if (DISP_TABLE_P (Vstandard_display_table))
286 printchar_to_stream (ch, stdout);
287 else
288 fwrite (str, 1, len, stdout);
230 noninteractive_need_newline = 1; 289 noninteractive_need_newline = 1;
231 } 290 }
232 else 291 else
@@ -267,7 +326,19 @@ strout (const char *ptr, ptrdiff_t size, ptrdiff_t size_byte,
267 } 326 }
268 else if (noninteractive && EQ (printcharfun, Qt)) 327 else if (noninteractive && EQ (printcharfun, Qt))
269 { 328 {
270 fwrite (ptr, 1, size_byte, stdout); 329 if (DISP_TABLE_P (Vstandard_display_table))
330 {
331 int len;
332 for (ptrdiff_t i = 0; i < size_byte; i += len)
333 {
334 int ch = STRING_CHAR_AND_LENGTH ((const unsigned char *) ptr + i,
335 len);
336 printchar_to_stream (ch, stdout);
337 }
338 }
339 else
340 fwrite (ptr, 1, size_byte, stdout);
341
271 noninteractive_need_newline = 1; 342 noninteractive_need_newline = 1;
272 } 343 }
273 else if (EQ (printcharfun, Qt)) 344 else if (EQ (printcharfun, Qt))
@@ -688,37 +759,8 @@ You can call print while debugging emacs, and pass it this function
688to make it write to the debugging output. */) 759to make it write to the debugging output. */)
689 (Lisp_Object character) 760 (Lisp_Object character)
690{ 761{
691 unsigned int ch;
692
693 CHECK_NUMBER (character); 762 CHECK_NUMBER (character);
694 ch = XINT (character); 763 printchar_to_stream (XINT (character), stderr);
695 if (ASCII_CHAR_P (ch))
696 {
697 putc (ch, stderr);
698#ifdef WINDOWSNT
699 /* Send the output to a debugger (nothing happens if there isn't
700 one). */
701 if (print_output_debug_flag)
702 {
703 char buf[2] = {(char) XINT (character), '\0'};
704 OutputDebugString (buf);
705 }
706#endif
707 }
708 else
709 {
710 unsigned char mbstr[MAX_MULTIBYTE_LENGTH];
711 ptrdiff_t len = CHAR_STRING (ch, mbstr);
712 Lisp_Object encoded_ch =
713 ENCODE_SYSTEM (make_multibyte_string ((char *) mbstr, 1, len));
714
715 fwrite (SSDATA (encoded_ch), SBYTES (encoded_ch), 1, stderr);
716#ifdef WINDOWSNT
717 if (print_output_debug_flag)
718 OutputDebugString (SSDATA (encoded_ch));
719#endif
720 }
721
722 return character; 764 return character;
723} 765}
724 766