% \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} % %\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} % % \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 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" % \end{syntax} % Defines 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" \Arg{file name} % \end{syntax} % Opens output stream to write to . The output % stream is immediately available for use. If the 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" % \end{syntax} % Closes output stream . % \end{function} % % \subsection{Immediate writing} % % \begin{function}{ \iow_now:Nx | % \iow_now:Nn } % \begin{syntax} % "\iow_now:Nx" \Arg{tokens} % \end{syntax} % "\iow_now:Nx" immediately writes the expansion of to the % output stream . If is not open output goes to the % terminal. The variant "\iow_now:Nn" writes out 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 % 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" \Arg{tokens} % \end{syntax} % Like "\iow_now:Nx" but splits 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" \Arg{tokens} % \end{syntax} % This special function first checks if the 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" \Arg{tokens} % \end{syntax} % These functions write to the specified , 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" \Arg{tokens} % \end{syntax} % More useful than the "\iow_shipout:Nn" functions, these functions also write % to at the end of the processing of the current page; % however, before 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 % 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 % that gets written to some output stream in an expanding mode. % \end{function} % % \begin{function}{\iow_char:N} % \begin{syntax} % "\iow_space:N" "\" % "\iow_space:N" "\%" % \end{syntax} % Inserts 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" % \end{syntax} % This function defines 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" \Arg{file name} % \end{syntax} % This function opens as an input stream for the external file % . If 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 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" % \end{syntax} % This function closes the read 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" \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" "\else:" "\fi:" % \end{syntax} % \begin{texnote} % This is the primitive \tn{ifeof} but we allow only a and not % a plain number after it. % \end{texnote} % \end{function} % % \begin{function}{ \ior_to:NN | % \ior_gto:NN } % \begin{syntax} % "\ior_to:NN" % \end{syntax} % Functions that reads one or more lines (until an equal number of left % and right braces are found) from the input stream and places % the result locally or globally into the token list variable. % If 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: % %<*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} % %<*package> \cs_set_eq:NN \iow_new:N \newwrite % \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} % %\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 % \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} % % \end{macrocode} % % Show token usage: % \begin{macrocode} %<*showmemory> \showMemUsage % % \end{macrocode} % % \end{implementation} % \PrintIndex % % \endinput