From 0f238ea450b3a976f04c95c4cf8befaadad1cdd0 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Thu, 15 Jan 2015 17:50:50 +0200 Subject: [PATCH] Add set-binary-mode primitive to switch a standard stream to binary I/O. src/fileio.c: Include binary-io.h. (Fset_binary_mode): New function. (syms_of_fileio): Defsubr it. (syms_of_fileio) : DEFSYM them. admin/unidata/unidata/uvs.el (uvs-print-table-ivd): Call set-binary-mode on stdout. doc/lispref/streams.texi (Input Functions): Document 'set-binary-mode'. (Output Functions): Cross-reference to documentation of 'set-binary-mode'. etc/NEWS: Mention 'set-binary-mode'. --- admin/ChangeLog | 5 ++++ admin/unidata/uvs.el | 1 + doc/lispref/ChangeLog | 6 +++++ doc/lispref/streams.texi | 24 +++++++++++++++++++ etc/ChangeLog | 4 ++++ etc/NEWS | 4 ++++ src/ChangeLog | 7 ++++++ src/fileio.c | 50 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 101 insertions(+) diff --git a/admin/ChangeLog b/admin/ChangeLog index 2b04281f400..70d1714f8eb 100644 --- a/admin/ChangeLog +++ b/admin/ChangeLog @@ -1,3 +1,8 @@ +2015-01-15 Eli Zaretskii + + * unidata/uvs.el (uvs-print-table-ivd): Call set-binary-mode on + stdout. + 2015-01-12 Paul Eggert Say "ELC foo.elc" instead of "GEN foo.elc" diff --git a/admin/unidata/uvs.el b/admin/unidata/uvs.el index 8bad523ce35..a6beac97db4 100644 --- a/admin/unidata/uvs.el +++ b/admin/unidata/uvs.el @@ -200,6 +200,7 @@ corresponding number." (insert-file-contents filename) (uvs-alist-from-ivd collection-id sequence-id-to-glyph-func)))) + (set-binary-mode 'stdout t) (princ "/* Automatically generated by uvs.el. */\n") (princ (format "static const unsigned char mac_uvs_table_%s_bytes[] =\n {\n" diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index 941be3cf582..4c0c116ba5a 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,9 @@ +2015-01-15 Eli Zaretskii + + * streams.texi (Input Functions): Document 'set-binary-mode'. + (Output Functions): Cross-reference to documentation of + 'set-binary-mode'. + 2015-01-04 Paul Eggert batch write-region no longer says "Wrote FOO" diff --git a/doc/lispref/streams.texi b/doc/lispref/streams.texi index 5e4df009b73..e52a543110b 100644 --- a/doc/lispref/streams.texi +++ b/doc/lispref/streams.texi @@ -339,6 +339,25 @@ shared structures. @xref{Circular Objects}. Its default value is @code{t}. @end defvar +@cindex binary I/O in batch mode +When reading or writing from the standard input/output streams of the +Emacs process in batch mode, it is sometimes required to make sure any +arbitrary binary data will be read/written verbatim, and/or that no +translation of newlines to or from CR-LF pairs are performed. This +issue does not exist on Posix hosts, only on MS-Windows and MS-DOS. +The following function allows to control the I/O mode of any standard +stream of the Emacs process. + +@defun set-binary-mode stream mode +Switch @var{stream} into binary or text I/O mode. If @var{mode} is +non-@code{nil}, switch to binary mode, otherwise switch to text mode. +The value of @var{stream} can be one of @code{stdin}, @code{stdout}, +or @code{stderr}. This function flushes any pending output data of +@var{stream} as a side effect, and returns the previous value of I/O +mode for @var{stream}. On Posix hosts, it always returns a +non-@code{nil} value and does nothing except flushing pending output. +@end defun + @node Output Streams @section Output Streams @cindex stream (for printing) @@ -686,6 +705,11 @@ This function outputs @var{object} to @var{stream}, just like indent and fill the object to make it more readable for humans. @end defun +If you need to use binary I/O in batch mode, e.g., use the functions +described in this section to write out arbitrary binary data or avoid +conversion of newlines on non-Posix hosts, see @ref{Input Functions, +set-binary-mode}. + @node Output Variables @section Variables Affecting Output @cindex output-controlling variables diff --git a/etc/ChangeLog b/etc/ChangeLog index 20f88bdecc3..681858e5977 100644 --- a/etc/ChangeLog +++ b/etc/ChangeLog @@ -1,3 +1,7 @@ +2015-01-15 Eli Zaretskii + + * NEWS: Mention 'set-binary-mode'. + 2015-01-11 Paul Eggert Default to 'configure --enable-silent-rules' diff --git a/etc/NEWS b/etc/NEWS index f291c0c9ad9..0bfd3fd2a2d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -588,6 +588,10 @@ been obsoleted. undocumented integer-pair format. Instead, they return a list of two integers. ++++ +** New function `set-binary-mode' allows to switch a standard stream +of the Emacs process to binary I/O mode. + * Changes in Frames and Windows Code in Emacs 25.1 diff --git a/src/ChangeLog b/src/ChangeLog index 898c10a48e1..40d8b267d84 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2015-01-15 Eli Zaretskii + + * fileio.c: Include binary-io.h. + (Fset_binary_mode): New function. + (syms_of_fileio): Defsubr it. + (syms_of_fileio) : DEFSYM them. + 2015-01-15 Teodor Zlatanov * gnutls.c (init_gnutls_functions): Import gnutls_x509_crt_check_issuer. diff --git a/src/fileio.c b/src/fileio.c index 6c443c91db7..dc67a00ed2a 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -86,6 +86,8 @@ along with GNU Emacs. If not, see . */ #include #include +#include + #ifdef HPUX #include #endif @@ -5754,6 +5756,48 @@ before any other event (mouse or keypress) is handled. */) return Qnil; } + +DEFUN ("set-binary-mode", Fset_binary_mode, Sset_binary_mode, 2, 2, 0, + doc: /* Switch STREAM to binary I/O mode or text I/O mode. +STREAM can be one of the symbols `stdin', `stdout', or `stderr'. +If MODE is non-nil, switch STREAM to binary mode, otherwise switch +it to text mode. + +As a side effect, this function flushes any pending STREAM's data. + +Value is the previous value of STREAM's I/O mode, nil for text mode, +non-nil for binary mode. + +On MS-Windows and MS-DOS, binary mode is needed to read or write +arbitrary binary data, and for disabling translation between CR-LF +pairs and a single newline character. Examples include generation +of text files with Unix-style end-of-line format using `princ' in +batch mode, with standard output redirected to a file. + +On Posix systems, this function always returns non-nil, and has no +effect except for flushing STREAM's data. */) + (Lisp_Object stream, Lisp_Object mode) +{ + FILE *fp = NULL; + int binmode; + + CHECK_SYMBOL (stream); + if (EQ (stream, Qstdin)) + fp = stdin; + else if (EQ (stream, Qstdout)) + fp = stdout; + else if (EQ (stream, Qstderr)) + fp = stderr; + else + xsignal2 (Qerror, build_string ("unsupported stream"), stream); + + binmode = NILP (mode) ? O_TEXT : O_BINARY; + if (fp != stdin) + fflush (fp); + + return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil; +} + void init_fileio (void) { @@ -6040,6 +6084,10 @@ This includes interactive calls to `delete-file' and DEFSYM (Qsubstitute_env_in_file_name, "substitute-env-in-file-name"); DEFSYM (Qget_buffer_window_list, "get-buffer-window-list"); + DEFSYM (Qstdin, "stdin"); + DEFSYM (Qstdout, "stdout"); + DEFSYM (Qstderr, "stderr"); + defsubr (&Sfind_file_name_handler); defsubr (&Sfile_name_directory); defsubr (&Sfile_name_nondirectory); @@ -6089,6 +6137,8 @@ This includes interactive calls to `delete-file' and defsubr (&Snext_read_file_uses_dialog_p); + defsubr (&Sset_binary_mode); + #ifdef HAVE_SYNC defsubr (&Sunix_sync); #endif -- 2.39.2