summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2018-04-30 22:39:09 +0000
committerKarl Berry <karl@freefriends.org>2018-04-30 22:39:09 +0000
commita28e1bfccd6fe522fcd296426e4d89c7fb4f19b6 (patch)
treeb72347e08575b56fcfed87c4d837b48dcfd1e02a /Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
parentb40c37a9e22b8235ff9c0bc256d00f7af94304c3 (diff)
l3 (30apr18)
git-svn-id: svn://tug.org/texlive/trunk@47516 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3expan.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3expan.dtx223
1 files changed, 167 insertions, 56 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
index 871763ed5fe..46c4acf4cec 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
@@ -41,7 +41,7 @@
% }^^A
% }
%
-% \date{Released 2018/03/05}
+% \date{Released 2018-04-30}
%
% \maketitle
%
@@ -246,8 +246,14 @@
% \begin{quote}
% |\example:f { \int_eval:n { 1 + 2 } , \int_eval:n { 3 + 4 } }|
% \end{quote}
-% results in the call |\example:n { 3 , \int_eval:n { 3 + 4 } }|
-% while using |\example:x| instead results in |\example:n { 3 , 7 }|
+% results in the call
+% \begin{quote}
+% |\example:n { 3 , \int_eval:n { 3 + 4 } }|
+% \end{quote}
+% while using |\example:x| instead results in
+% \begin{quote}
+% |\example:n { 3 , 7 }|
+% \end{quote}
% at the cost of being protected.
% If you use this type of expansion in conditional processing then
% you should stick to using |TF| type functions only as the expansion
@@ -284,14 +290,20 @@
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}). The \meta{tokens} are expanded until only characters
-% remain, and are then turned into a control sequence. (An internal error
-% occurs if non-characters remain, as the conversion is not possible.)
+% remain, and are then turned into a control sequence.
% The result is inserted into the input stream \emph{after} reinsertion
% of the \meta{function}. Thus the \meta{function} may take more than
% one argument: all others are left unchanged.
%
% The |:cc| variant constructs the \meta{function} name in the same
% manner as described for the \meta{tokens}.
+% \begin{texnote}
+% Protected macros that appear in a \texttt{c}-type argument are
+% expanded despite being protected; \cs{exp_not:n} also has no
+% effect. An internal error occurs if non-characters or active
+% characters remain after full expansion, as the conversion to a
+% control sequence is not possible.
+% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_args:No}
@@ -322,13 +334,19 @@
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}). The \meta{tokens} are expanded until only characters
-% remain, and are then turned into a control sequence. (An internal error
-% occurs if non-characters remain, as the conversion is not possible.)
+% remain, and are then turned into a control sequence.
% This control sequence should
% be the name of a \meta{variable}. The content of the \meta{variable} are
% recovered and placed inside braces into the input stream \emph{after}
% reinsertion of the \meta{function}. Thus the \meta{function} may take more
% than one argument: all others are left unchanged.
+% \begin{texnote}
+% Protected macros that appear in a \texttt{v}-type argument are
+% expanded despite being protected; \cs{exp_not:n} also has no
+% effect. An internal error occurs if non-characters or active
+% characters remain after full expansion, as the conversion to a
+% control sequence is not possible.
+% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_args:Nf}
@@ -587,10 +605,11 @@
% \begin{texnote}
% This is the \TeX{} \tn{noexpand} primitive. It only prevents
% expansion. At the beginning of an |f|-type argument, a space
-% \meta{token} is removed despite \cs{exp_not:N}. In an
-% |x|-expanding definition (\cs{cs_new:Npx}) a macro parameter
-% \meta{token} (normally~|#|) denotes an argument despite
-% \cs{exp_not:N} (see \cs{exp_not:n}).
+% \meta{token} is removed even if it appears as \cs{exp_not:N}
+% \cs{c_space_token}. In an |x|-expanding definition
+% (\cs{cs_new:Npx}), a macro parameter introduces an argument even
+% if it appears as \cs{exp_not:N} |#| |1|. This differs from
+% \cs{exp_not:n}.
% \end{texnote}
% \end{function}
%
@@ -599,10 +618,16 @@
% \cs{exp_not:c} \Arg{tokens}
% \end{syntax}
% Expands the \meta{tokens} until only characters remain, and then
-% converts this into a control sequence. (An internal error occurs if
-% non-characters remain, as the conversion is not possible.)
+% converts this into a control sequence.
% Further expansion of this control sequence is then inhibited using
% \cs{exp_not:N}.
+% \begin{texnote}
+% Protected macros that appear in a \texttt{c}-type argument are
+% expanded despite being protected; \cs{exp_not:n} also has no
+% effect. An internal error occurs if non-characters or active
+% characters remain after full expansion, as the conversion to a
+% control sequence is not possible.
+% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_not:n}
@@ -610,13 +635,15 @@
% \cs{exp_not:n} \Arg{tokens}
% \end{syntax}
% Prevents expansion of the \meta{tokens} in an |x|-type argument. In
-% other cases (input stream or |o| or |f| arguments) the \meta{tokens}
-% continue being expanded.
+% all other cases the \meta{tokens} continue to be expanded, for
+% example in the input stream or in other types of arguments such as
+% \texttt{c}, \texttt{f}, \texttt{v}. The argument of \cs{exp_not:n}
+% \emph{must} be surrounded by braces.
% \begin{texnote}
-% This is the \eTeX{} \tn{unexpanded} primitive. Hence its argument
-% \emph{must} be surrounded by braces. In an |x|-expanding
-% definition (\cs{cs_new:Npx}), \cs{exp_not:n}~|{#}| inserts a macro
-% parameter character in the replacement text.
+% This is the \eTeX{} \tn{unexpanded} primitive. In an
+% |x|-expanding definition (\cs{cs_new:Npx}), \cs{exp_not:n}~|{#1}|
+% is equivalent to |##1| rather than to~|#1|, namely it inserts the
+% two characters |#| and~|1|.
% \end{texnote}
% \end{function}
%
@@ -642,10 +669,16 @@
% \end{syntax}
% Expands the \meta{tokens} until only characters remains, and then
% converts this into a control sequence which should be a \meta{variable}
-% name. (An internal error occurs if
-% non-characters remain, as the conversion is not possible.)
+% name.
% The content of the \meta{variable} is recovered, and further
% expansion in |x|-type arguments is prevented using \cs{exp_not:n}.
+% \begin{texnote}
+% Protected macros that appear in a \texttt{v}-type argument are
+% expanded despite being protected; \cs{exp_not:n} also has no
+% effect. An internal error occurs if non-characters or active
+% characters remain after full expansion, as the conversion to a
+% control sequence is not possible.
+% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_not:f}
@@ -705,12 +738,12 @@
% \exp_end:
% }
% \begin{syntax}
-% \cs{exp:w} \meta{expandable-tokens} \cs{exp_end:} \\
+% \cs{exp:w} \meta{expandable tokens} \cs{exp_end:} \\
% \end{syntax}
% Expands \meta{expandable-tokens} until reaching \cs{exp_end:} at
% which point expansion stops.
-% The full expansion of \meta{expandable-tokens} has to be empty.
-% If any token in \meta{expandable-tokens} or any token generated by
+% The full expansion of \meta{expandable tokens} has to be empty.
+% If any token in \meta{expandable tokens} or any token generated by
% expanding the tokens therein is not expandable the expansion will end
% prematurely and as a result \cs{exp_end:} will be misinterpreted
% later on.\footnotemark
@@ -724,6 +757,11 @@
%\end{verbatim}
% where somewhere during the expansion of |\@@_case:NnTF| the
% \cs{exp_end:} gets generated.
+% \begin{texnote}
+% The current implementation uses \tn{romannumeral} hence ignores
+% space tokens and explicit signs |+| and |-| in the expansion of the
+% \meta{expandable tokens}, but this should not be relied upon.
+% \end{texnote}
% \end{function}
% \footnotetext{Due to the implementation you might get the character
% in position 0 in the current font (typically \enquote{\texttt{`}})
@@ -797,21 +835,26 @@
% braces will not terminate the \texttt{f}-type expansion.
% \end{function}
%
-% \section{Internal functions and variables}
-%
-% \begin{variable}{\l__exp_internal_tl}
-% The |\exp_| module has its private variable to temporarily store the
-% result of |x|-type argument expansion. This is done to avoid interference
-% with other functions using temporary variables.
-% \end{variable}
+% \section{Internal functions}
%
% \begin{function}{\::n, \::N, \::p, \::c, \::o, \::f, \::x, \::v, \::V, \:::}
% \begin{syntax}
-% |\cs_set:Npn \exp_args:Ncof { \::c \::o \::f \::: }|
+% |\cs_new:Npn \exp_args:Ncof { \::c \::o \::f \::: }|
% \end{syntax}
% Internal forms for the base expansion types. These names do \emph{not}
% conform to the general \LaTeX3 approach as this makes them more readily
-% visible in the log and so forth.
+% visible in the log and so forth. They should not be used outside this module.
+% \end{function}
+%
+% \begin{function}
+% {\::o_unbraced, \::f_unbraced, \::x_unbraced, \::v_unbraced, \::V_unbraced}
+% \begin{syntax}
+% |\cs_new:Npn \exp_last_unbraced:Nno { \::n \::o_unbraced \::: }|
+% \end{syntax}
+% Internal forms for the expansion types which leave the terminal argument
+% unbraced. These names do \emph{not}
+% conform to the general \LaTeX3 approach as this makes them more readily
+% visible in the log and so forth. They should not be used outside this module.
% \end{function}
%
% \end{documentation}
@@ -828,6 +871,12 @@
%<@@=exp>
% \end{macrocode}
%
+% \begin{variable}{\l_@@_internal_tl}
+% The |\exp_| module has its private variable to temporarily store the
+% result of |x|-type argument expansion. This is done to avoid interference
+% with other functions using temporary variables.
+% \end{variable}
+%
% \begin{macro}{\exp_after:wN}
% \begin{macro}{\exp_not:N}
% \begin{macro}{\exp_not:n}
@@ -963,11 +1012,13 @@
%
% \begin{macro}{\::x}
% This function is used to expand an argument fully.
+% We build in the expansion of \cs{@@_arg_next:nnn}.
% \begin{macrocode}
\cs_new_protected:Npn \::x #1 \::: #2#3
{
- \cs_set_nopar:Npx \l_@@_internal_tl { {#3} }
- \exp_after:wN \@@_arg_next:nnn \l_@@_internal_tl {#1} {#2}
+ \cs_set_nopar:Npx \l_@@_internal_tl
+ { \exp_not:n { #1 \::: } { \exp_not:n {#2} {#3} } }
+ \l_@@_internal_tl
}
% \end{macrocode}
% \end{macro}
@@ -1450,26 +1501,34 @@
%
% \subsection{Preventing expansion}
%
+% \begin{macro}{\__kernel_exp_not:w}
+% At the kernel level, we need the primitive behaviour to allow expansion
+% \emph{before} the brace group.
+% \begin{macrocode}
+\cs_new_eq:NN \__kernel_exp_not:w \etex_unexpanded:D
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}[EXP]{\exp_not:c}
% \begin{macro}[EXP]{\exp_not:o}
% \begin{macro}[EXP]{\exp_not:f}
% \begin{macro}[EXP]{\exp_not:V}
% \begin{macro}[EXP]{\exp_not:v}
-% All these except \cs{exp_not:c} call the primitive
-% \cs{etex_unexpanded:D} namely \cs{exp_not:n}.
+% All these except \cs{exp_not:c} call the kernel-internal
+% \cs{__kernel_exp_not:w} namely \tn{etex_unexpanded:D}.
% \begin{macrocode}
\cs_new:Npn \exp_not:c #1 { \exp_after:wN \exp_not:N \cs:w #1 \cs_end: }
-\cs_new:Npn \exp_not:o #1 { \etex_unexpanded:D \exp_after:wN {#1} }
+\cs_new:Npn \exp_not:o #1 { \__kernel_exp_not:w \exp_after:wN {#1} }
\cs_new:Npn \exp_not:f #1
{ \etex_unexpanded:D \exp_after:wN { \exp:w \exp_end_continue_f:w #1 } }
\cs_new:Npn \exp_not:V #1
{
- \etex_unexpanded:D \exp_after:wN
+ \__kernel_exp_not:w \exp_after:wN
{ \exp:w \@@_eval_register:N #1 }
}
\cs_new:Npn \exp_not:v #1
{
- \etex_unexpanded:D \exp_after:wN
+ \__kernel_exp_not:w \exp_after:wN
{ \exp:w \@@_eval_register:c {#1} }
}
% \end{macrocode}
@@ -1524,10 +1583,15 @@
% \end{macrocode}
% If the above definition ever appears outside its proper context
% the active character |^^@| will be executed so we turn this into an
-% error.
+% error. The test for existence covers the (unlikely) case that some
+% other code has already defined |^^@|: this is true for example for
+% \texttt{xmltex.tex}.
% \begin{macrocode}
- \cs_new:Npn ^^@
- { \__kernel_msg_expandable_error:nn { kernel } { bad-exp-end-f } }
+ \if_cs_exist:N ^^@
+ \else:
+ \cs_new:Npn ^^@
+ { \__kernel_msg_expandable_error:nn { kernel } { bad-exp-end-f } }
+ \fi:
% \end{macrocode}
% The same but grabbing an argument to remove spaces and braces.
% \begin{macrocode}
@@ -1565,11 +1629,15 @@
\cs_new_protected:Npn \cs_generate_variant:Nn #1#2
{
\@@_generate_variant:N #1
- \exp_after:wN \@@_split_function:NN
- \exp_after:wN #1
- \exp_after:wN \@@_generate_variant:nnNN
- \exp_after:wN #1
- \tl_to_str:n {#2} , \scan_stop: , \q_recursion_stop
+ \use:x
+ {
+ \@@_generate_variant:nnNN
+ \cs_split_function:N #1
+ \exp_not:N #1
+ \tl_to_str:n {#2} ,
+ \exp_not:N \scan_stop: ,
+ \exp_not:N \q_recursion_stop
+ }
}
\cs_new_protected:Npn \cs_generate_variant:cn
{ \exp_args:Nc \cs_generate_variant:Nn }
@@ -1872,7 +1940,8 @@
#5
}
}
-\cs_new:Npn \@@_generate_variant_loop_special:NNwNNnn #1#2#3 \q_stop #4#5#6#7
+\cs_new:Npn \@@_generate_variant_loop_special:NNwNNnn
+ #1#2#3 \q_stop #4#5#6#7
{
#3 \q_stop #4 #5 {#6} {#7}
\exp_not:n
@@ -1969,12 +2038,9 @@
{ : \exp_not:N \use_i:nn }
}
}
-\use:x
- {
- \cs_new_protected:Npn \exp_not:N \@@_generate_internal_variant:wwnNwnn
- ##1 \token_to_str:N x ##2 \exp_not:N \q_mark
- ##3 ##4 ##5 \exp_not:N \q_stop ##6 ##7
- }
+\exp_last_unbraced:NNNNo
+ \cs_new_protected:Npn \@@_generate_internal_variant:wwnNwnn #1
+ { \token_to_str:N x } #2 \q_mark #3#4#5 \q_stop #6#7
{
#3
\cs_if_free:cT {#6} { #4 {#6} {#7} }
@@ -2009,7 +2075,13 @@
% }
% \begin{macrocode}
\cs_new_protected:Npn \prg_generate_conditional_variant:Nnn #1
- { \__cs_split_function:NN #1 \@@_generate_variant:nnNnn }
+ {
+ \use:x
+ {
+ \@@_generate_variant:nnNnn
+ \cs_split_function:N #1
+ }
+ }
\cs_new_protected:Npn \@@_generate_variant:nnNnn #1#2#3#4#5
{
\if_meaning:w \c_false_bool #3
@@ -2051,6 +2123,45 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\exp_args_generate:n, \@@_args_generate:Nn}
+% \begin{macro}[EXP]{\@@_args_generate:n}
+% This function is not used in the kernel hence we can use functions
+% that are defined in later modules. It also does not need to be fast
+% so use inline mappings. For each requested variant we check that
+% there are no characters besides |NnpcofVvx|, in particular that
+% there are no spaces. Then we loop through the variant specifier and
+% convert each letter to \cs[no-index]{::\meta{variant letter}}, with a
+% trailing \cs{:::}.
+% \begin{macrocode}
+\cs_new_protected:Npn \exp_args_generate:n #1
+ {
+ \exp_args:No \clist_map_inline:nn { \tl_to_str:n {#1} }
+ {
+ \str_map_inline:nn {##1}
+ {
+ \str_if_in:nnF { NnpcofVvx } {####1}
+ {
+ \__kernel_msg_error:nnnn { kernel } { invalid-exp-args }
+ {####1} {##1}
+ \str_map_break:n { \use_none:nnnn }
+ }
+ }
+ \exp_args:Nc \@@_args_generate:Nn { exp_args:N ##1 } {##1}
+ }
+ }
+\cs_new_protected:Npn \@@_args_generate:Nn #1#2
+ {
+ \cs_if_exist:NF #1
+ {
+ \str_if_in:nnTF {#2} { x } { \cs_new_protected:Npx } { \cs_new:Npx }
+ #1 { \tl_map_function:nN { #2 : } \@@_args_generate:n }
+ }
+ }
+\cs_new:Npn \@@_args_generate:n #1 { \exp_not:c { :: #1 } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}