% \iffalse
%% File: l3io.dtx Copyright (C) 1990-2009 LaTeX3 project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
%% license or (at your option) any later version.  The latest version
%% of this license is in the file
%%
%%    http://www.latex-project.org/lppl.txt
%%
%% This file is part of the ``expl3 bundle'' (The Work in LPPL)
%% and all files in that bundle must be distributed together.
%%
%% The released version of this bundle is available from CTAN.
%%
%% -----------------------------------------------------------------------
%%
%% The development version of the bundle can be found at
%%
%%    http://www.latex-project.org/svnroot/experimental/trunk/
%%
%% for those people who are interested.
%%
%%%%%%%%%%%
%% NOTE: %%
%%%%%%%%%%%
%%
%%   Snapshots taken from the repository represent work in progress and may
%%   not work or may contain conflicting material!  We therefore ask
%%   people _not_ to put them into distributions, archives, etc. without
%%   prior consultation with the LaTeX Project Team.
%%
%% -----------------------------------------------------------------------
%
%<*driver|package>
\RequirePackage{l3names}
%</driver|package>
%\fi
\GetIdInfo$Id: l3io.dtx 1369 2009-05-31 21:36:35Z joseph $
          {L3 Experimental i/o module}
%\iffalse
%<*driver>
%\fi
\ProvidesFile{\filename.\filenameext}
  [\filedate\space v\fileversion\space\filedescription]
%\iffalse
\documentclass[full]{l3doc}
\begin{document}
\DocInput{l3io.dtx}
\end{document}
%</driver>
% \fi
%
% \title{The \textsf{l3io} package\thanks{This file
%         has version number \fileversion, last
%         revised \filedate.}\\
% Low-level file i/o}
% \author{\Team}
% \date{\filedate}
% \maketitle
%
% \begin{documentation}
%
% \TeX{} is capable of reading from and writing up to 16 individual
% streams. These i/o operations are accessable in \LaTeX3 with functions
% from the "\io.."  modules. In most cases it will be
% sufficiant for the programmer to use the functions provided by the
% auxiliary file module, but here are the necessary functions for
% manipulating private streams.
%
% Sometimes it is not known beforehand how much text is going to be
% written with a single call. As a result some internal \TeX{} buffer
% may overflow. To avoid this kind of problem, \LaTeX3 maintains beside
% direct write operations like "\iow_now:Nx" also so called ``long''
% writes where the output is broken into individual lines on every blank
% in the text to be written. The resulting files are difficult to read
% for humans but since they usually serve only as internal storage this
% poses no problem.
%
% Beside the functions that immediately act (e.g., "\iow_now:Nx",
% etc.) we also have deferred operations that are saved away until the
% next page is finished. This allow to expand the <tokens> at the right
% time to get correct page numbers etc.
%
% \section{Functions for output streams}
%
% \begin{function}{ \iow_new:N |
%                   \iow_new:c }
% \begin{syntax}
%   "\iow_new:N" <stream>
% \end{syntax}
% Defines <stream> to be a new identifer denoting an output stream for
% use in subsequent functions.
% \begin{texnote}
% "\iow_new:N" corresponds to the plain \TeX{} \tn{newwrite}
% allocation routine.
% \end{texnote}
% \end{function}
%
% \begin{function}{ \iow_open:Nn |
%                   \iow_open:cn }
% \begin{syntax}
%   "\iow_open:Nn" <stream> \Arg{file name}
% \end{syntax}
% Opens output stream <stream> to write to <file name>. The output
% stream is immediately available for use. If the <stream> was already
% used as an output stream to some other file, this file gets closed
% first.\footnote{This is a precaution since on some OS it is possible
% to open the same file for output more than once which then results in
% some internal errors at the end of the run.} Also, all output streams
% still open at the end of the \TeX{} run will be automatically closed.
% \end{function}
%
% \begin{function}{ \iow_close:N }
% \begin{syntax}
%   "\iow_open:Nn" <stream>
% \end{syntax}
% Closes output stream <stream>.
% \end{function}
%
% \subsection{Immediate writing}
%
% \begin{function}{ \iow_now:Nx |
%                   \iow_now:Nn }
% \begin{syntax}
%  "\iow_now:Nx" <stream> \Arg{tokens}
% \end{syntax}
% "\iow_now:Nx" immediately writes the expansion of <tokens> to the
% output stream <stream>. If <stream> is not open output goes to the
% terminal. The variant "\iow_now:Nn" writes out <tokens> without any
% further expansion.
% \begin{texnote}
% These are the equivalent of \TeX's "\immediate\write" with and without
% expansion control.
% \end{texnote}
% \end{function}
%
% \begin{function}{ \iow_log:n  | \iow_log:x  |
%                   \iow_term:x | \iow_term:n }
% \begin{syntax}
%  "\iow_log:x" \Arg{tokens}
% \end{syntax}
% These functions write to the log file (also known as the transcript file) or
% to the terminal respectively. They are equivalent to "\iow_now:Nx" where
% <stream> is the transcript file ("\c_iow_log_stream") or the terminal
% ("\c_iow_term_stream").
% \end{function}
%
% \begin{function}{ \iow_now_buffer_safe:Nn |
%                   \iow_now_buffer_safe:Nx }
% \begin{syntax}
%  "\iow_now_buffer_safe:Nn" <stream> \Arg{tokens}
% \end{syntax}
% Like "\iow_now:Nx" but splits <tokens> at every blank into separate
% lines. When potentially (very) long token lists are being written, this
% avoids the problem of
% buffer overflow when reading back the file.
% \end{function}
%
% \begin{function}{ \iow_now_when_avail:Nn |
%                   \iow_now_when_avail:cn }
% \begin{syntax}
%  "\iow_now_when_avail:Nn" <stream> \Arg{tokens}
% \end{syntax}
% This special function first checks if the <stream> is open for writing.
% If not it does nothing otherwise it behaves like "\iow_now:Nn".
% \end{function}
%
% \subsection{Deferred writing}
%
% \begin{function}{ \iow_shipout:Nn | \iow_shipout:Nx }
% \begin{syntax}
%   "\iow_shipout_x:Nn"  <stream> \Arg{tokens}
% \end{syntax}
% These functions write <tokens> to the specified <stream>, but unlike with
% "\iow_now:Nn" which write the material immediately, "\iow_shipout:Nn" waits
% until the processing of the current page has finished.
% \end{function}
%
% \begin{function}{ \iow_shipout_x:Nn | \iow_shipout_x:Nx }
% \begin{syntax}
%   "\iow_shipout_x:Nn"  <stream> \Arg{tokens}
% \end{syntax}
% More useful than the "\iow_shipout:Nn" functions, these functions also write
% <tokens> to <stream> at the end of the processing of the current page;
% however, before <tokens> are written they are subjected to a further
% "x" expansion stage.
%
% This is useful for writing messages that depend
% on counters (such as the page number) that are not known until the page has
% been completed.
%
% "\iow_shipout_x:Nn" always needs "{}" around the second argument.
% \begin{texnote}
% "\iow_shipout_x:Nn" is equivalent to \TeX's \tn{write}.
% \end{texnote}
% \end{function}
%
% \subsection{Special characters for writing}
%
% \begin{function}{\iow_newline:}
% \begin{syntax}
%   "\iow_newline:"
% \end{syntax}
% Function that produces a new line when used within the <token list>
% that gets written some output stream in non-verbatim mode.
% \end{function}
%
% \begin{function}{\iow_space:}
% \begin{syntax}
%   "\iow_space:"
% \end{syntax}
% Function that produces a space when used within the <token list>
% that gets written to some output stream in an expanding mode.
% \end{function}
%
% \begin{function}{\iow_char:N}
% \begin{syntax}
%   "\iow_space:N" "\"<char>
%   "\iow_space:N" "\%"
% \end{syntax}
% Inserts <char> into the output stream. Useful when trying to write difficult
% characters such as "%", "{", "}", etc., in messages.
% \end{function}
%
% \section{Functions for input streams}
%
% \begin{function}{\ior_new:N}
% \begin{syntax}
%   "\ior_new:N" <stream>
% \end{syntax}
% This function defines <stream> to be a new input stream constant.
% \begin{texnote}
% This is the new name and new implementation for plain \TeX's
% \tn{newread}.
% \end{texnote}
% \end{function}
%
% \begin{function}{\ior_open:Nn}
% \begin{syntax}
%   "\ior_open:Nn" <stream> \Arg{file name}
% \end{syntax}
% This function opens <stream> as an input stream for the external file
% <file name>. If <file name> doesn't exist or is an empty file the
% stream is considered to be fully read, a condition which can be tested
% with "\ior_if_eof:NTF" etc. If <stream> was already used to read from some
% other file this file will be closed first. The input stream is ready
% for immediate use.
% \end{function}
%
% \begin{function}{\ior_close:N}
% \begin{syntax}
%   "\ior_close:N" <stream>
% \end{syntax}
% This function closes the read stream <stream>.
% \begin{texnote}
% This is a new name for \tn{closein} but it is considered bad practice
% to make use of this knowledge :-)
% \end{texnote}
% \end{function}
%
% \begin{function}{ \ior_if_eof_p:N / (EXP) | \ior_if_eof:N / (TF)(EXP) }
% \begin{syntax}
%   "\ior_if_eof:NTF" <stream> \Arg{true code} \Arg{false code}
% \end{syntax}
% Conditional that tests if some input stream is fully read. The
% condition is also true if the input stream is not open.
% \end{function}
%
% \begin{function}{\if_eof:w}
% \begin{syntax}
%   "\if_eof:w" <stream> <true code> "\else:" <false code> "\fi:"
% \end{syntax}
% \begin{texnote}
% This is the primitive \tn{ifeof} but we allow only a <stream> and not
% a plain number after it.
% \end{texnote}
% \end{function}
%
% \begin{function}{ \ior_to:NN  |
%                   \ior_gto:NN }
% \begin{syntax}
%   "\ior_to:NN" <stream> <tl var.>
% \end{syntax}
% Functions that reads one or more lines (until an equal number of left
% and right braces are found) from the input stream <stream> and places
% the result locally or globally into the token list variable.
% If <stream> is not open, input is requested from the terminal.
% \end{function}
%
% \section{Constants}
%
% \begin{variable}{\c_iow_comment_char |
%                  \c_iow_lbrace_char  |
%                  \c_iow_rbrace_char}
% Constants that can be used to represent comment character, left and
% right brace in token lists that should be written to a file.
% \end{variable}
%
% \begin{variable}{ \c_iow_term_stream | \c_ior_term_stream }
% Input or output stream denoting the terminal. If used as an input
% stream the user is prompted with the name of the token list variable
% (that is used
% in the call "\ior_to:NN" or "\ior_gto:NN") followed by an equal sign.
% If you don't want an automatic prompt of this sort ``misuse''
% "\c_iow_log_stream" as an input stream.
% \end{variable}
%
% \begin{variable}{ \c_iow_log_stream | \c_ior_log_stream }
% Output stream that writes only to the transcript file (e.g., the
% ".log" file on most systems). You may ``misuse'' this stream as an
% input stream. In this case it acts as a terminal stream without user
% prompting.
% \end{variable}
%
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3io} implementation}
%
%    We start by ensuring that the required packages are loaded.
%    \begin{macrocode}
%<*package>
\ProvidesExplPackage
  {\filename}{\filedate}{\fileversion}{\filedescription}
\package_check_loaded_expl:
%</package>
%<*initex|package>
%    \end{macrocode}
%
% This section is primarily concerned with input and output streams.
% The naming conventions for i/o streams is |ior| (for read) and |iow|
% (for write) as module names. e.g.\ |\c_ior_test_stream| is an input stream
% variable called `test'.
%
% \subsection{Output streams}
%
% \begin{macro}{\iow_new:N,\iow_new:c}
%    Allocation of new output streams is done by these functions.
%    As we currently do not distribute a new allocation module we nick
%    the |\newwrite| function.
%    \begin{macrocode}
%<*initex>
\alloc_setup_type:nnn {iow} \c_zero \c_sixteen
\cs_new_nopar:Npn \iow_new:N #1 {\alloc_reg:NnNN g {iow} \tex_chardef:D #1}
%</initex>
%<*package>
\cs_set_eq:NN \iow_new:N \newwrite
%</package>
\cs_generate_variant:Nn \iow_new:N {c}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\iow_open:Nn,\iow_open:cn}
%    To open streams for reading or writing the following two functions
%    are provided. The streams are opened immediately.
%
%    From some bad experiences on the mainframe, I learned that it is
%    better to force the close before opening a dataset for writing.
%    We have to check whether this is also necessary in case of
%    |\tex_openin:D|.
%    \begin{macrocode}
\cs_new_nopar:Npn \iow_open:Nn #1#2 {
  \iow_close:N #1
  \tex_immediate:D \tex_openout:D #1#2 \scan_stop:
}
\cs_generate_variant:Nn \iow_open:Nn {c}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\iow_close:N}
%    Since we close output streams prior to opening, a separate closing
%    operation is probably not necessary. But here it is, just in
%    case\ldots. Actually you will need this if you intend to write
%    and then read in the same pass from a stream.
%    \begin{macrocode}
\cs_new_nopar:Npn \iow_close:N { \tex_immediate:D \tex_closeout:D }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\c_iow_term_stream,\c_ior_term_stream}
% \begin{macro}{\c_iow_log_stream,\c_ior_log_stream}
%    Here we allocate two output streams for writing to the transcript
%    file only (|\c_iow_log_stream|) and to both the terminal and transcript
%    file (|\c_iow_term_stream|). Both can be used to read from and have
%    equivalent "\c_ior" versions.
%    \begin{macrocode}
\cs_new_eq:NN \c_iow_term_stream \c_sixteen
\cs_new_eq:NN \c_ior_term_stream \c_sixteen
\cs_new_eq:NN \c_iow_log_stream \c_minus_one
\cs_new_eq:NN \c_ior_log_stream \c_minus_one
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \paragraph{Immediate writing}
%
% \begin{macro}{\iow_now:Nx}
%    An abbreviation for an often used operation, which immediately
%    writes its second argument expanded to the output stream.
%    \begin{macrocode}
\cs_new_nopar:Npn \iow_now:Nx { \tex_immediate:D \iow_shipout_x:Nn }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\iow_now:Nn}
%    This routine writes the second argument onto the output
%    stream without expansion. If this stream isn't open, the output goes to
%    the terminal instead.
%    If the first argument is no output stream at all, we get an
%    internal error.
%    \begin{macrocode}
\cs_new_nopar:Npn \iow_now:Nn #1#2 {
  \iow_now:Nx #1 { \exp_not:n {#2} }
}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\iow_log:n,\iow_log:x,\iow_term:n,\iow_term:x}
%    Now we redefine two functions for which we needed a definition
%    very early on.
%    \begin{macrocode}
\cs_set_nopar:Npn \iow_log:x  { \iow_now:Nx \c_iow_log_stream  }
\cs_new_nopar:Npn \iow_log:n  { \iow_now:Nn \c_iow_log_stream  }
\cs_set_nopar:Npn \iow_term:x { \iow_now:Nx \c_iow_term_stream }
\cs_new_nopar:Npn \iow_term:n { \iow_now:Nn \c_iow_term_stream }
%    \end{macrocode}
%    "\iow_term:x" isn't exactly equivalent to the old |\typeout| since
%    we need to control expansion in the function we provide for the user.
%  \end{macro}
%
%
% \begin{macro}{\iow_now_when_avail:Nn,\iow_now_when_avail:cn}
%    |\iow_now_when_avail:Nn | \m{stream} \m{code}.  This routine writes
%    its second argument unexpanded to the stream given by the first
%    argument, provided that this stream was opened for writing. Note,
%    that |#| characters get doubled within \m{code}.
%
%    In this routine we have to check whether or not the output stream
%    that was requested is defined at all.
%    So we check if the name is still free.
%
%    \begin{macrocode}
\cs_new_nopar:Npn \iow_now_when_avail:Nn #1 {
  \cs_if_free:NTF #1 {\use_none:n} {\iow_now:Nn #1}
}
\cs_generate_variant:Nn \iow_now_when_avail:Nn {c}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\iow_now_buffer_safe:Nn,\iow_now_buffer_safe:Nx}
% \begin{macro}[aux]{\iow_now_buffer_safe_expanded_aux:w}
%    Another type of writing onto an output stream is used for
%    potentially long token sequences. We break the output lines at
%    every blank in the second argument. This avoids the problem of
%    buffer overflow when reading back, or badly broken lines on
%    systems with limited file records.  The only thing we have to
%    take care of, is the danger of two blanks in succession since
%    these get converted into a |\par| when we read the stuff back.
%    But this can happen only if things like
%    two spaces find their way into the second argument.
%    Usually, multiple spaces are removed by \TeX's scanner.
%    \begin{macrocode}
\cs_new_nopar:Npn \iow_now_buffer_safe_aux:w #1#2#3 {
  \group_begin: \tex_newlinechar:D`\ #1#2{#3} \group_end:
}
\cs_new_nopar:Npn \iow_now_buffer_safe:Nx {
  \iow_now_buffer_safe_aux:w \iow_now:Nx
}
\cs_new_nopar:Npn \iow_now_buffer_safe:Nn {
  \iow_now_buffer_safe_aux:w \iow_now:Nn
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \paragraph{Deferred writing}
%
% \begin{macro}{\iow_shipout_x:Nn,\iow_shipout_x:Nx}
% First the easy part, this is the primitive.
%    \begin{macrocode}
\cs_set_eq:NN \iow_shipout_x:Nn \tex_write:D
\cs_generate_variant:Nn \iow_shipout_x:Nn {Nx}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\iow_shipout:Nn,\iow_shipout:Nx}
% With \eTeX\ available deferred writing is easy.
%    \begin{macrocode}
\cs_new_nopar:Npn \iow_shipout:Nn #1#2{
  \iow_shipout_x:Nn #1 { \exp_not:n {#2} }
}
\cs_generate_variant:Nn \iow_shipout:Nn {Nx}
%    \end{macrocode}
% \end{macro}
%
% `Buffer safe' forms of these functions are not possible since the deferred
% writing will restore the value of |\tex_newlinechar:D| before it will have
% a chance to act. But on the other hand it is nevertheless possible
% to make all deferred writes long by setting the |\tex_newlinechar:D|
% inside the output routine just before the |\tex_shipout:D|. The only
% disadvantage of this method is the fact that messages to the
% terminal during this time will also then break at spaces. But we
% should consider this.
%
% \paragraph{Special characters for writing}
%
% \begin{macro}{\iow_newline:}
%    Global variable holding the character that forces a new line when
%    something is written to an output stream.
%    \begin{macrocode}
\cs_new_nopar:Npn \iow_newline: {^^J}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\iow_space:}
%    Global variable holding the character that inserts a space char when
%    writing to an output stream.
%    \begin{macrocode}
\cs_new_nopar:Npn \iow_space: {~}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\iow_char:N}
% Function to write any escaped char to an output stream.
%    \begin{macrocode}
\cs_new:Nn \iow_char:N { \cs_to_str:N #1 }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\c_iow_comment_char}
% \begin{macro}{\c_iow_lbrace_char}
% \begin{macro}{\c_iow_rbrace_char}
% TODO: remove these in favour of "\iow_char:N" (Will, Apr 2009)
%
%   We also need to be able to write braces and the comment character.  We
%   achieve this by defining global constants to expand into a version of
%   these characters with |\tex_catcode:D|${}=12$.
%    \begin{macrocode}
\tl_new:Nx \c_iow_comment_char {\cs_to_str:N\%}
%    \end{macrocode}
%    To avoid another allocation function which is probably only
%    necessary here we use the |\cs_set_nopar:Npx| command directly.
%    \begin{macrocode}
\tl_new:Nx \c_iow_lbrace_char{\cs_to_str:N\{}
\tl_new:Nx \c_iow_rbrace_char{\cs_to_str:N\}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \subsection{Input streams}
%
% \begin{macro}{\ior_new:N}
%    Allocation of new input streams is done by this function.
%    As we currently do not distribute a new allocation module we nick
%    the |\newwread| function.
%    \begin{macrocode}
%<*initex>
\alloc_setup_type:nnn {ior} \c_zero \c_sixteen
\cs_new_nopar:Npn \ior_new:N #1 {\alloc_reg:NnNN g {ior} \tex_chardef:D #1}
%</initex>
%<package>\cs_set_eq:NN \ior_new:N \newread
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ior_open:Nn}
% \begin{macro}{\ior_close:N}
%    Processing of input-streams (via |\tex_openin:D| and |closein|) is
%    always `immediate' as far as \TeX{} is concerned. An extra
%    |\tex_immediate:D| is silently ignored.
%    \begin{macrocode}
\cs_set_eq:NN \ior_close:N \tex_closein:D
\cs_new_nopar:Npn \ior_open:Nn #1#2 {
  \ior_close:N #1 \scan_stop:
  \tex_openin:D #1#2 \scan_stop:
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\if_eof:w}
%    \begin{macrocode}
\cs_new_eq:NN \if_eof:w \tex_ifeof:D
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\ior_if_eof_p:N}
% \begin{macro}[TF]{\ior_if_eof:N}
%    |\ior_if_eof:NTF | \m{stream} \m{true case} \m{false case}.  To
%    test if some particular input stream is exhausted the following
%    conditional is provided:
%    \begin{macrocode}
\prg_new_conditional:Nnn \ior_if_eof:N {p,TF,T,F} {
  \tex_ifeof:D #1 \prg_return_true: \else: \prg_return_false: \fi:
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
%
% \begin{macro}{\ior_to:NN}
% \begin{macro}{\ior_gto:NN}
%    And here we read from files.
%    \begin{macrocode}
\cs_new_nopar:Npn \ior_to:NN #1#2 {
  \tex_read:D #1 to #2
%<check>  \chk_local_or_pref_global:N #2
}
\cs_new_nopar:Npn \ior_gto:NN {
%<+check>  \pref_global_chk:
%<-check>  \pref_global:D
  \ior_to:NN
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%</initex|package>
%    \end{macrocode}
%
%    Show token usage:
%    \begin{macrocode}
%<*showmemory>
\showMemUsage
%</showmemory>
%    \end{macrocode}
%
% \end{implementation}
% \PrintIndex
%
% \endinput
