]> code.delx.au - gnu-emacs/commitdiff
Treat batch stdout/stderr like standard display
authorPaul Eggert <eggert@cs.ucla.edu>
Mon, 1 Jun 2015 03:04:05 +0000 (20:04 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Mon, 1 Jun 2015 03:04:43 +0000 (20:04 -0700)
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.

doc/emacs/mule.texi
doc/lispref/display.texi
doc/lispref/nonascii.texi
etc/NEWS
src/coding.c
src/dispnew.c
src/print.c

index 7336fdc8f4735575852171bb49645ddcce008398..80b1384feb6b6b44f449c74519c97e309c75bb7f 100644 (file)
@@ -1164,7 +1164,9 @@ current language environment.
 to use when encoding and decoding system strings such as system error
 messages and @code{format-time-string} formats and time stamps.  That
 coding system is also used for decoding non-@acronym{ASCII} keyboard
-input on the X Window System.  You should choose a coding system that is compatible
+input on the X Window System and for encoding text sent to the
+standard output and error streams when in batch mode.  You should
+choose a coding system that is compatible
 with the underlying system's text representation, which is normally
 specified by one of the environment variables @env{LC_ALL},
 @env{LC_CTYPE}, and @env{LANG}.  (The first one, in the order
index b12995be6ede13389b5526b1db5df9035118bb47..357a3c33fa33b923e28a8067cab78c235330eca6 100644 (file)
@@ -6522,8 +6522,9 @@ no buffer display table.
 @defvar standard-display-table
 The value of this variable is the standard display table, which is
 used when Emacs is displaying a buffer in a window with neither a
-window display table nor a buffer display table defined.  Its default
-is @code{nil}.
+window display table nor a buffer display table defined, or when Emacs
+is outputting text to the standard output or error streams.  Its
+default is @code{nil}.
 @end defvar
 
 The @file{disp-table} library defines several functions for changing
index f16018417debcb91bae227691bf17a1b28e2c161..362c3a4dcbbfe69cf6cc9d26f30512f5b1fdbf33 100644 (file)
@@ -1959,6 +1959,7 @@ how Emacs interacts with these features.
 @cindex keyboard input decoding on X
 This variable specifies the coding system to use for decoding system
 error messages and---on X Window system only---keyboard input, for
+sending batch output to the standard output and error streams, for
 encoding the format argument to @code{format-time-string}, and for
 decoding the return value of @code{format-time-string}.
 @end defvar
index d07057ef4b2167537411e3b4234b2c7e049e8e44..57e63b1f20876fa9c3ec468711b8653f2a342615 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -947,6 +947,12 @@ integers.
 ** New function `set-binary-mode' allows to switch a standard stream
 of the Emacs process to binary I/O mode.
 
+** In locales that cannot display curved quotes, ASCII approximations
+are installed in standard-display-table.
+
+** Standard output and error streams now transliterate characters via
+standard-display-table, and encode output using locale-coding-system.
+
 ** Miscellaneous name change
 
 For consistency with the usual Emacs spelling, the Lisp variable
index 776ecac62d9395c122cf7fc29df4b15ad5507120..9342c3841f6bac20a20eb36ef73dba30bb89c7de 100644 (file)
@@ -11121,7 +11121,8 @@ See also the function `find-operation-coding-system'.  */);
 
   DEFVAR_LISP ("locale-coding-system", Vlocale_coding_system,
               doc: /* Coding system to use with system messages.
-Also used for decoding keyboard input on X Window system.  */);
+Also used for decoding keyboard input on X Window system, and for
+encoding standard output and error streams.  */);
   Vlocale_coding_system = Qnil;
 
   /* The eol mnemonics are reset in startup.el system-dependently.  */
index 693dd49825c4248c697920ba5d936c80c1d11d1d..7e7afa71d20e0cb869abb3e58a9c72c335cf60ad 100644 (file)
@@ -6245,6 +6245,7 @@ Each element can be:
 
   DEFVAR_LISP ("standard-display-table", Vstandard_display_table,
               doc: /* Display table to use for buffers that specify none.
+It is also used for standard output and error streams.
 See `buffer-display-table' for more information.  */);
   Vstandard_display_table = Qnil;
 
index a182839ba7d4972476c3f7761ffc8b512cc09294..65c120dbb4f6b491d8cf814ac42a1797bc613581 100644 (file)
@@ -31,6 +31,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "window.h"
 #include "process.h"
 #include "dispextern.h"
+#include "disptab.h"
 #include "termchar.h"
 #include "intervals.h"
 #include "blockinput.h"
@@ -195,6 +196,61 @@ print_unwind (Lisp_Object saved_text)
   memcpy (print_buffer, SDATA (saved_text), SCHARS (saved_text));
 }
 
+/* Print character CH to the stdio stream STREAM.  */
+
+static void
+printchar_to_stream (unsigned int ch, FILE *stream)
+{
+  Lisp_Object dv IF_LINT (= Qnil);
+  ptrdiff_t i = 0, n = 1;
+
+  if (CHAR_VALID_P (ch) && DISP_TABLE_P (Vstandard_display_table))
+    {
+      dv = DISP_CHAR_VECTOR (XCHAR_TABLE (Vstandard_display_table), ch);
+      if (VECTORP (dv))
+       {
+         n = ASIZE (dv);
+         goto next_char;
+       }
+    }
+
+  while (true)
+    {
+      if (ASCII_CHAR_P (ch))
+       {
+         putc (ch, stream);
+#ifdef WINDOWSNT
+         /* Send the output to a debugger (nothing happens if there
+            isn't one).  */
+         if (print_output_debug_flag && stream == stderr)
+           OutputDebugString ((char []) {ch, '\0'});
+#endif
+       }
+      else
+       {
+         unsigned char mbstr[MAX_MULTIBYTE_LENGTH];
+         int len = CHAR_STRING (ch, mbstr);
+         Lisp_Object encoded_ch =
+           ENCODE_SYSTEM (make_multibyte_string ((char *) mbstr, 1, len));
+
+         fwrite (SSDATA (encoded_ch), 1, SBYTES (encoded_ch), stream);
+#ifdef WINDOWSNT
+         if (print_output_debug_flag && stream == stderr)
+           OutputDebugString (SSDATA (encoded_ch));
+#endif
+       }
+
+      i++;
+
+    next_char:
+      for (; i < n; i++)
+       if (CHARACTERP (AREF (dv, i)))
+         break;
+      if (! (i < n))
+       break;
+      ch = XFASTINT (AREF (dv, i));
+    }
+}
 
 /* Print character CH using method FUN.  FUN nil means print to
    print_buffer.  FUN t means print to echo area or stdout if
@@ -226,7 +282,10 @@ printchar (unsigned int ch, Lisp_Object fun)
       else if (noninteractive)
        {
          printchar_stdout_last = ch;
-         fwrite (str, 1, len, stdout);
+         if (DISP_TABLE_P (Vstandard_display_table))
+           printchar_to_stream (ch, stdout);
+         else
+           fwrite (str, 1, len, stdout);
          noninteractive_need_newline = 1;
        }
       else
@@ -267,7 +326,19 @@ strout (const char *ptr, ptrdiff_t size, ptrdiff_t size_byte,
     }
   else if (noninteractive && EQ (printcharfun, Qt))
     {
-      fwrite (ptr, 1, size_byte, stdout);
+      if (DISP_TABLE_P (Vstandard_display_table))
+       {
+         int len;
+         for (ptrdiff_t i = 0; i < size_byte; i += len)
+           {
+             int ch = STRING_CHAR_AND_LENGTH ((const unsigned char *) ptr + i,
+                                              len);
+             printchar_to_stream (ch, stdout);
+           }
+       }
+      else
+       fwrite (ptr, 1, size_byte, stdout);
+
       noninteractive_need_newline = 1;
     }
   else if (EQ (printcharfun, Qt))
@@ -688,37 +759,8 @@ You can call print while debugging emacs, and pass it this function
 to make it write to the debugging output.  */)
   (Lisp_Object character)
 {
-  unsigned int ch;
-
   CHECK_NUMBER (character);
-  ch = XINT (character);
-  if (ASCII_CHAR_P (ch))
-    {
-      putc (ch, stderr);
-#ifdef WINDOWSNT
-      /* Send the output to a debugger (nothing happens if there isn't
-        one).  */
-      if (print_output_debug_flag)
-       {
-         char buf[2] = {(char) XINT (character), '\0'};
-         OutputDebugString (buf);
-       }
-#endif
-    }
-  else
-    {
-      unsigned char mbstr[MAX_MULTIBYTE_LENGTH];
-      ptrdiff_t len = CHAR_STRING (ch, mbstr);
-      Lisp_Object encoded_ch =
-       ENCODE_SYSTEM (make_multibyte_string ((char *) mbstr, 1, len));
-
-      fwrite (SSDATA (encoded_ch), SBYTES (encoded_ch), 1, stderr);
-#ifdef WINDOWSNT
-      if (print_output_debug_flag)
-       OutputDebugString (SSDATA (encoded_ch));
-#endif
-    }
-
+  printchar_to_stream (XINT (character), stderr);
   return character;
 }