diff options
author | Karl Berry <karl@freefriends.org> | 2013-03-12 22:38:22 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2013-03-12 22:38:22 +0000 |
commit | 574c4946ce553944c797750da25ba8844775996f (patch) | |
tree | 9ea4729ca09c49a4564d99d9134a5417eb7b2af3 /Master/texmf-dist/source/latex/l3kernel/l3file.dtx | |
parent | 5c30ca128a813719715e012a0d72c1ccaba2d811 (diff) |
latex3 (12mar13)
git-svn-id: svn://tug.org/texlive/trunk@29361 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3file.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3file.dtx | 420 |
1 files changed, 150 insertions, 270 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx index 416fc76cacb..67461fd01c9 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: l3file.dtx Copyright (C) 1990-2012 The LaTeX3 Project +%% File: l3file.dtx Copyright (C) 1990-2013 The 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 @@ -35,7 +35,7 @@ % %<*driver|package> \RequirePackage{l3bootstrap} -\GetIdInfo$Id: l3file.dtx 4377 2012-12-20 11:13:29Z bruno $ +\GetIdInfo$Id: l3file.dtx 4446 2013-01-14 00:03:17Z bruno $ {L3 File and I/O operations} %</driver|package> %<*driver> @@ -192,6 +192,20 @@ % allocated to \meta{file name} until a \cs{ior_close:N} instruction % is given or the \TeX{} run ends. % \end{function} +% +% \begin{function}[added = 2013-01-12, TF]{\ior_open:Nn, \ior_open:cn} +% \begin{syntax} +% \cs{ior_open:NnTF} \meta{stream} \Arg{file name} \Arg{true code} \Arg{false code} +% \end{syntax} +% Opens \meta{file name} for reading using \meta{stream} as the +% control sequence for file access. If the \meta{stream} was already +% open it is closed before the new operation begins. The +% \meta{stream} is available for access immediately and will remain +% allocated to \meta{file name} until a \cs{ior_close:N} instruction +% is given or the \TeX{} run ends. The \meta{true code} is then inserted +% into the input stream. If the file is not found, no error is raised and +% the \meta{false code} is inserted into the input stream. +% \end{function} % % \begin{function}[updated = 2012-02-09]{\iow_open:Nn, \iow_open:cn} % \begin{syntax} @@ -645,11 +659,11 @@ { \@@_name_sanitize:nn {#1} { \@@_add_path:nN } } \cs_new_protected:Npn \@@_add_path:nN #1#2 { - \__ior_open:Nn \g__file_internal_ior {#1} - \ior_if_eof:NTF \g__file_internal_ior + \__ior_open:Nn \g_@@_internal_ior {#1} + \ior_if_eof:NTF \g_@@_internal_ior { \@@_add_path_search:nN {#1} #2 } { \tl_set:Nn #2 {#1} } - \ior_close:N \g__file_internal_ior + \ior_close:N \g_@@_internal_ior } \cs_new_protected:Npn \@@_add_path_search:nN #1#2 { @@ -665,8 +679,8 @@ %</package> \seq_map_inline:Nn \l_@@_search_path_seq { - \__ior_open:Nn \g__file_internal_ior { ##1 #1 } - \ior_if_eof:NF \g__file_internal_ior + \__ior_open:Nn \g_@@_internal_ior { ##1 #1 } + \ior_if_eof:NF \g_@@_internal_ior { \tl_set:Nx #2 { ##1 #1 } \seq_map_break: @@ -824,71 +838,41 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\c_@@_streams_tl} -% The list of streams available, by number. +% \begin{variable}{\g_@@_streams_seq} +% A list of the currently-available input streams to be used as a +% stack. In format mode, all streams (from $0$ to~$15$) are +% available, while the package requests streams to \LaTeXe{} as they +% are needed (initially none are needed), so the starting point +% varies! % \begin{macrocode} -\tl_const:Nn \c_@@_streams_tl - { - \c_zero - \c_one - \c_two - \c_three - \c_four - \c_five - \c_six - \c_seven - \c_eight - \c_nine - \c_ten - \c_eleven - \c_twelve - \c_thirteen - \c_fourteen - \c_fifteen - } +\seq_new:N \g_@@_streams_seq +%<*initex> +\seq_gset_split:Nnn \g_@@_streams_seq { , } + { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 } +%</initex> % \end{macrocode} % \end{variable} % -% \begin{variable}{\g_@@_streams_prop} -% The allocations for streams are stored in property lists, which -% are set up to have a \enquote{full} set of allocations from the start. -% In package mode, a few slots are always taken, so these are -% blocked off from use. +% \begin{variable}{\l_@@_stream_tl} +% Used to recover the raw stream number from the stack. % \begin{macrocode} -\prop_new:N \g_@@_streams_prop -%<*package> -\prop_put:Nnn \g_@@_streams_prop { 0 } { LaTeX2e~reserved } -%</package> +\tl_new:N \l_@@_stream_tl % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_stream_int} -% Used to track the number allocated to the stream being created: -% this is taken from the property list but does alter. +% \begin{variable}{\g_@@_streams_prop} +% The name of the file attached to each stream is tracked in a property +% list. % \begin{macrocode} -\int_new:N \l_@@_stream_int +\prop_new:N \g_@@_streams_prop +%<*package> +\prop_gput:Nnn \g_@@_streams_prop { 0 } { LaTeX2e~reserved } +%</package> % \end{macrocode} % \end{variable} % % \subsubsection{Stream management} % -% \begin{macro}[int]{\@@_new:N, \@@_new:c} -% The lowest level for stream management is actually creating raw \TeX{} -% streams. As these are very limited (even with \eTeX{}), this should not -% be addressed directly. -% \begin{macrocode} -%<*initex> -\__alloc_setup_type:nnn { ior } \c_zero \c_sixteen -\cs_new_protected:Npn \@@_new:N #1 - { \__alloc_reg:nNN { ior } \tex_chardef:D #1 } -%</initex> -%<*package> -\cs_set_eq:NN \@@_new:N \newread -%</package> -\cs_generate_variant:Nn \@@_new:N { c } -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\ior_new:N, \ior_new:c} % Reserving a new stream is done by defining the name as equal to using the % terminal. @@ -897,27 +881,14 @@ \cs_generate_variant:Nn \ior_new:N { c } % \end{macrocode} % \end{macro} -% -% \begin{variable}{\g__file_internal_ior} -% Delayed from the \texttt{file} section so that the mechanisms are in place. -% \begin{macrocode} -\ior_new:N \g__file_internal_ior -% \end{macrocode} -% \end{variable} -% +% % \begin{macro}{\ior_open:Nn, \ior_open:cn} -% \begin{macro}[TF]{\ior_open:Nn} % \begin{macro}[aux]{\@@_open_aux:Nn} -% \begin{macro}[aux]{\@@_open_aux:NnTF} -% \begin{macro}[aux]{\@@_open:Nn, \@@_open:No} -% Opening a stream starts with a call to the closing function: this is -% safest. There is then a loop through the allocation number list to find -% the first free stream number. When one is found the allocation can take -% place, the information can be stored and finally the file can actually be -% opened. Before any actual file operations there is a precaution against -% special characters in file names. There is an intermediate auxiliary to -% allow path addition, keeping the internal function fast and avoiding an -% infinite loop. +% Opening an input stream requires a bit of pre-processing. The file name +% is sanitized to deal with active characters, before an auxiliary adds a +% path and checks that the file really exists. If those two tests pass, then +% pass the information on to the lower-level function which deals with +% streams. % \begin{macrocode} \cs_new_protected:Npn \ior_open:Nn #1#2 { \__file_name_sanitize:nn {#2} { \@@_open_aux:Nn #1 } } @@ -929,8 +900,20 @@ { \__msg_kernel_error:nnx { kernel } { file-not-found } {#2} } { \@@_open:No #1 \l__file_internal_name_tl } } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[TF]{\ior_open:Nn, \ior_open:cn} +% \begin{macro}[aux]{\@@_open_aux:NnTF} +% Much the same idea for opening a read with a conditional, except the +% auxiliary function does not issue an error if the file is not found. +% \begin{macrocode} \prg_new_protected_conditional:Npnn \ior_open:Nn #1#2 { T , F , TF } - { \__file_name_sanitize:nn {#2} { \@@_open_aux:NnTF #1 } } + { \__file_name_sanitize:nn {#2} { \@@_open:NnTF #1 } } +\cs_generate_variant:Nn \ior_open:NnT { c } +\cs_generate_variant:Nn \ior_open:NnF { c } +\cs_generate_variant:Nn \ior_open:NnTF { c } \cs_new_protected:Npn \@@_open_aux:NnTF #1#2 { \file_add_path:nN {#2} \l__file_internal_name_tl @@ -941,115 +924,63 @@ \prg_return_true: } } -\cs_generate_variant:Nn \ior_open:NnT { c } -\cs_generate_variant:Nn \ior_open:NnF { c } -\cs_generate_variant:Nn \ior_open:NnTF { c } -\cs_new_protected:Npn \@@_open:Nn #1#2 - { - \ior_close:N #1 - \int_set_eq:NN \l_@@_stream_int \c_sixteen - \tl_map_function:NN \c_@@_streams_tl \@@_alloc:n - \int_compare:nNnTF \l_@@_stream_int = \c_sixteen - { \__msg_kernel_fatal:nn { kernel } { input-streams-exhausted } } - { - \@@_alloc:N #1 - \prop_gput:NVn \g_@@_streams_prop \l_@@_stream_int {#2} - \tex_openin:D #1#2 \scan_stop: - } - } -\cs_generate_variant:Nn \@@_open:Nn { No } % \end{macrocode} % \end{macro} % \end{macro} -% \end{macro} -% \end{macro} -% \end{macro} -% -% \begin{macro}[aux]{\@@_alloc:n} -% See if a particular stream is available: the property list contains file -% names for streams in use, so any unused ones are for the taking. +% +% \begin{macro}[int]{\@@_open:Nn, \@@_open:No} +% \begin{macro}[aux]{\@@_open_stream:Nn} +% The stream allocation itself uses the fact that there is a list of all of +% those available, so allocation is simply a question of using the number at +% the top of the list. In package mode, life gets more complex as it's +% important to keep things in sync. That is done using a two-part approach: +% any streams that have already been taken up by \pkg{ior} but are now free +% are tracked, so we first try those. If that fails, ask \LaTeXe{} for a new +% stream and use that number (after a bit of conversion). % \begin{macrocode} -\cs_new_protected:Npn \@@_alloc:n #1 - { - \prop_if_in:NnF \g_@@_streams_prop {#1} - { - \int_set:Nn \l_@@_stream_int {#1} - \tl_map_break: - } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[aux]{\@@_alloc:N} -% \begin{macro}[aux]{\@@_alloc:} -% \begin{variable}{\g_@@_internal_ior} -% Allocating a raw stream is much easier in \IniTeX{} mode than for the -% package. For the format, all streams will be allocated by \pkg{l3file} and -% so there is a simple check to see if a raw stream is actually available. On -% the other hand, for the package there will be non-managed streams. So if -% the managed one is not open, a check is made to see if some other managed -% stream is available before deciding to open a new one. If a new one is -% needed, we get the number allocated by \LaTeXe{} to get \enquote{back on -% track} with allocation. -% \begin{macrocode} -\ior_new:N \g_@@_internal_ior -\cs_new_protected:Npn \@@_alloc:N #1 +\cs_new_protected:Npn \@@_open:Nn #1#2 { - \cs_if_exist:cF { g_ior_ \int_use:N \l_@@_stream_int _ior } - { -%<*package> - \@@_alloc: - \int_compare:nNnT \l_@@_stream_int = \c_sixteen - { - \@@_new:N \g_@@_internal_ior - \int_set:Nn \l_@@_stream_int { \g_@@_internal_ior } - \cs_gset_eq:cN - { g_ior_ \int_use:N \l_@@_stream_int _ior } \g_@@_internal_ior - } -%</package> + \ior_close:N #1 + \seq_gpop:NNTF \g_@@_streams_seq \l_@@_stream_tl + { \@@_open_stream:Nn #1 {#2} } %<*initex> - \@@_new:c { g_ior_ \int_use:N \l_@@_stream_int _ior } + { \__msg_kernel_fatal:nn { kernel } { input-streams-exhausted } } %</initex> - } - \cs_gset_eq:Nc #1 { g_ior_ \int_use:N \l_@@_stream_int _ior } - } %<*package> -\cs_new_protected_nopar:Npn \@@_alloc: - { - \int_incr:N \l_@@_stream_int - \int_compare:nNnT \l_@@_stream_int < \c_sixteen { - \cs_if_exist:cTF { g_ior_ \int_use:N \l_@@_stream_int _ior } - { - \prop_if_in:NVT \g_@@_streams_prop \l_@@_stream_int - { \@@_alloc: } - } - { \@@_alloc: } + \newread #1 + \tl_set:Nx \l_@@_stream_tl { \int_eval:n {#1} } + \@@_open_stream:Nn #1 {#2} } - } %</package> + } +\cs_generate_variant:Nn \@@_open:Nn { No } +\cs_new_protected:Npn \@@_open_stream:Nn #1#2 + { + \tex_global:D \tex_chardef:D #1 = \l_@@_stream_tl \scan_stop: + \prop_gput:NVn \g_@@_streams_prop #1 {#2} + \tex_openin:D #1 #2 \scan_stop: + } % \end{macrocode} -% \end{variable} % \end{macro} % \end{macro} % % \begin{macro}{\ior_close:N, \ior_close:c} -% Closing a stream is not quite the reverse of opening one. First, -% the close operation is easier than the open one, and second as the -% stream is actually a number we can use it directly to show that the -% slot has been freed up. +% Closing a stream means getting rid of it at the \TeX{} level and +% removing from the various data structures. Unless the name passed +% is an invalid stream number (outside the range $[0,15]$), it can be +% closed. On the other hand, it only gets added to the stack if it +% was not already there, to avoid duplicates building up. % \begin{macrocode} \cs_new_protected:Npn \ior_close:N #1 { - \__chk_if_exist_cs:N #1 - \int_compare:nNnF #1 < \c_zero + \int_compare:nT { \c_minus_one < #1 < \c_sixteen } { - \int_compare:nNnF #1 > \c_fifteen - { - \tex_closein:D #1 - \prop_gremove:NV \g_@@_streams_prop #1 - \cs_gset_eq:NN #1 \c_term_ior - } + \tex_closein:D #1 + \prop_gremove:NV \g_@@_streams_prop #1 + \seq_if_in:NVF \g_@@_streams_seq #1 + { \seq_gpush:NV \g_@@_streams_seq #1 } + \cs_gset_eq:NN #1 \c_term_ior } } \cs_generate_variant:Nn \ior_close:N { c } @@ -1135,6 +1066,13 @@ % \end{macrocode} % \end{macro} % +% \begin{variable}{\g__file_internal_ior} +% Needed by the higher-level code, but cannot be created until here. +% \begin{macrocode} +\ior_new:N \g__file_internal_ior +% \end{macrocode} +% \end{variable} +% % \subsection{Output operations} % % \begin{macrocode} @@ -1142,7 +1080,8 @@ % \end{macrocode} % % There is a lot of similarity here to the input operations, at least for -% many of the basics. Thus quite a bit is copied from the earlier material. +% many of the basics. Thus quite a bit is copied from the earlier material +% with minor alterations. % % \subsubsection{Variables and constants} % @@ -1156,11 +1095,22 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\c_@@_streams_tl} -% The list of streams available, by number: copied from the input -% operations. +% \begin{variable}{\g_@@_streams_seq} +% A list of the currently-available input streams to be used as a stack. +% Things are done differently in format and package mode, so the starting +% point varies! % \begin{macrocode} -\cs_new_eq:NN \c_@@_streams_tl \c__ior_streams_tl +\seq_new:N \g_@@_streams_seq +%<*initex> +\seq_gset_eq:NN \g_@@_streams_seq \g__ior_streams_seq +%</initex> +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_@@_stream_tl} +% Used to recover the raw stream number from the stack. +% \begin{macrocode} +\tl_new:N \l_@@_stream_tl % \end{macrocode} % \end{variable} % @@ -1176,32 +1126,8 @@ % \end{macrocode} % \end{variable} % -% \begin{variable}{\l_@@_stream_int} -% Used to track the number allocated to the stream being created: -% this is taken from the property list but does alter. The two allocation -% routines only need one register, so we save one here. -% \begin{macrocode} -\cs_new_eq:NN \l_@@_stream_int \l__ior_stream_int -% \end{macrocode} -% \end{variable} -% % \subsection{Stream management} % -% \begin{macro}[aux]{\@@_new:N, \@@_new:c} -% The same idea as for input, but with a separate set of functions. -% \begin{macrocode} -%<*initex> -\__alloc_setup_type:nnn { iow } \c_zero \c_sixteen -\cs_new_protected:Npn \@@_new:N #1 - { \__alloc_reg:nNN { iow } \tex_chardef:D #1 } -%</initex> -%<*package> -\cs_set_eq:NN \@@_new:N \newwrite -%</package> -\cs_generate_variant:Nn \@@_new:N { c } -% \end{macrocode} -% \end{macro} -% % \begin{macro}{\iow_new:N, \iow_new:c} % Reserving a new stream is done by defining the name as equal to writing % to the terminal: odd but at least consistent. @@ -1212,8 +1138,10 @@ % \end{macro} % % \begin{macro}{\iow_open:Nn, \iow_open:cn} -% \begin{macro}[aux]{\@@_open:Nn} -% The same idea as for reading, but without the path. +% \begin{macro}[int]{\@@_open:Nn} +% \begin{macro}[aux]{\@@_open_stream:Nn} +% The same idea as for reading, but without the path and without the need +% to allow for a conditional version. % \begin{macrocode} \cs_new_protected:Npn \iow_open:Nn #1#2 { \__file_name_sanitize:nn {#2} { \@@_open:Nn #1 } } @@ -1221,78 +1149,28 @@ \cs_new_protected:Npn \@@_open:Nn #1#2 { \iow_close:N #1 - \int_set_eq:NN \l_@@_stream_int \c_sixteen - \tl_map_function:NN \c_@@_streams_tl \@@_alloc:n - \int_compare:nNnTF \l_@@_stream_int = \c_sixteen + \seq_gpop:NNTF \g_@@_streams_seq \l_@@_stream_tl + { \@@_open_stream:Nn #1 {#2} } +%<*initex> { \__msg_kernel_fatal:nn { kernel } { output-streams-exhausted } } +%</initex> +%<*package> { - \@@_alloc:N #1 - \prop_gput:NVn \g_@@_streams_prop \l_@@_stream_int {#2} - \tex_immediate:D \tex_openout:D #1#2 \scan_stop: - } - } -% \end{macrocode} -% \end{macro} -% \end{macro} -% -% \begin{macro}[aux]{\@@_alloc:n} -% Identical to the input routine, but with the appropriate names used -% (when \pkg{l3docstrip} has done it's job!). -% \begin{macrocode} -\cs_new_protected:Npn \@@_alloc:n #1 - { - \prop_if_in:NnF \g_@@_streams_prop {#1} - { - \int_set:Nn \l_@@_stream_int {#1} - \tl_map_break: + \newwrite #1 + \tl_set:Nx \l_@@_stream_tl { \int_eval:n {#1} } + \@@_open_stream:Nn #1 {#2} } - } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}[aux]{\@@_alloc:N} -% \begin{macro}[aux]{\@@_alloc:} -% \begin{variable}{\g_@@_internal_iow} -% Exactly the same as for reading! -% \begin{macrocode} -\iow_new:N \g_@@_internal_iow -\cs_new_protected:Npn \@@_alloc:N #1 - { - \cs_if_exist:cF { g_iow_ \int_use:N \l_@@_stream_int _iow } - { -%<*package> - \@@_alloc: - \int_compare:nNnT \l_@@_stream_int = \c_sixteen - { - \@@_new:N \g_@@_internal_iow - \int_set:Nn \l_@@_stream_int { \g_@@_internal_iow } - \cs_gset_eq:cN - { g_iow_ \int_use:N \l_@@_stream_int _iow } \g_@@_internal_iow - } %</package> -%<*initex> - \@@_new:c { g_iow_ \int_use:N \l_@@_stream_int _iow } -%</initex> - } - \cs_gset_eq:Nc #1 { g_iow_ \int_use:N \l_@@_stream_int _iow } } -%<*package> -\cs_new_protected_nopar:Npn \@@_alloc: +\cs_generate_variant:Nn \@@_open:Nn { No } +\cs_new_protected:Npn \@@_open_stream:Nn #1#2 { - \int_incr:N \l_@@_stream_int - \int_compare:nNnT \l_@@_stream_int < \c_sixteen - { - \cs_if_exist:cTF { g_iow_ \int_use:N \l_@@_stream_int _iow } - { - \prop_if_in:NVT \g_@@_streams_prop \l_@@_stream_int - { \@@_alloc: } - } - { \@@_alloc: } - } + \tex_global:D \tex_chardef:D #1 = \l_@@_stream_tl \scan_stop: + \prop_gput:NVn \g_@@_streams_prop #1 {#2} + \tex_immediate:D \tex_openout:D #1 #2 \scan_stop: } -%</package> % \end{macrocode} -% \end{variable} +% \end{macro} % \end{macro} % \end{macro} % @@ -1304,15 +1182,13 @@ % \begin{macrocode} \cs_new_protected:Npn \iow_close:N #1 { - \__chk_if_exist_cs:N #1 - \int_compare:nNnF #1 < \c_zero + \int_compare:nT { \c_minus_one < #1 < \c_sixteen } { - \int_compare:nNnF #1 > \c_fifteen - { - \tex_immediate:D \tex_closeout:D #1 - \prop_gremove:NV \g_@@_streams_prop #1 - \cs_gset_eq:NN #1 \c_term_iow - } + \tex_immediate:D \tex_closeout:D #1 + \prop_gremove:NV \g_@@_streams_prop #1 + \seq_if_in:NVF \g_@@_streams_seq #1 + { \seq_gpush:NV \g_@@_streams_seq #1 } + \cs_gset_eq:NN #1 \c_term_ior } } \cs_generate_variant:Nn \iow_close:N { c } @@ -1809,8 +1685,10 @@ % \begin{macro}{\iow_wrap:xnnnN} % This was renamed and one unneed argument was removed. % \begin{macrocode} +%<*deprecated> \cs_new_protected:Npn \iow_wrap:xnnnN #1#2#3#4#5 { \iow_wrap:nnnN {#1} {#2} {#4} #5 } +%</deprecated> % \end{macrocode} % \end{macro} % @@ -1819,7 +1697,9 @@ % \begin{variable}{\l_iow_line_length_int} % Simple rename. Here we copy the \TeX{} register. % \begin{macrocode} +%<*deprecated> \cs_new_eq:NN \l_iow_line_length_int \l_iow_line_count_int +%</deprecated> % \end{macrocode} % \end{variable} % |