% \iffalse meta-comment
%
%% File: l3expan.dtx Copyright (C) 1990-2017 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
% 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 "l3kernel bundle" (The Work in LPPL)
% and all files in that bundle must be distributed together.
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
% https://github.com/latex3/latex3
%
% for those people who are interested.
%
%<*driver>
\documentclass[full]{l3doc}
\def\ExplFileDate{2017/03/18}
\def\ExplFileVersion{7019}
\begin{document}
\DocInput{\jobname.dtx}
\end{document}
%
% \fi
%
% \title{^^A
% The \pkg{l3expan} package\\ Argument expansion^^A
% \thanks{This file describes v\ExplFileVersion,
% last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
% The \LaTeX3 Project\thanks
% {^^A
% E-mail:
% \href{mailto:latex-team@latex-project.org}
% {latex-team@latex-project.org}^^A
% }^^A
% }
%
% \date{Released \ExplFileDate}
%
% \maketitle
%
% \begin{documentation}
%
% This module provides generic methods for expanding \TeX{} arguments in a
% systematic manner. The functions in this module all have prefix |exp|.
%
% Not all possible variations are implemented for every base
% function. Instead only those that are used within the \LaTeX3 kernel
% or otherwise seem to be of general interest are implemented.
% Consult the module description to find out which functions are
% actually defined. The next section explains how to define missing
% variants.
%
% \section{Defining new variants}
% \label{sec:l3expan:defining-variants}
%
% The definition of variant forms for base functions may be necessary
% when writing new functions or when applying a kernel function in a
% situation that we haven't thought of before.
%
% Internally preprocessing of arguments is done with functions from the
% |\exp_| module. They all look alike, an example would be
% \cs{exp_args:NNo}. This function has three arguments, the first and the
% second are a single tokens, while the third argument should be given
% in braces. Applying \cs{exp_args:NNo} will expand the content of third
% argument once before any expansion of the first and second arguments.
% If \cs{seq_gpush:No} was not defined it could be coded in the following way:
% \begin{verbatim}
% \exp_args:NNo \seq_gpush:Nn
% \g_file_name_stack
% \l_tmpa_tl
% \end{verbatim}
% In other words, the first argument to \cs{exp_args:NNo} is the base
% function and the other arguments are preprocessed and then passed to
% this base function. In the example the first argument to the base
% function should be a single token which is left unchanged while the
% second argument is expanded once. From this example we can also see
% how the variants are defined. They just expand into the appropriate
% |\exp_| function followed by the desired base function, \emph{e.g.}
% \begin{quote}
% |\cs_generate_variant:Nn \seq_gpush:Nn { No } |
% \end{quote}
% results in the definition of |\seq_gpush:No|
% \begin{quote}
% |\cs_new:Npn \seq_gpush:No { \exp_args:NNo \seq_gpush:Nn }|
% \end{quote}
% Providing variants in this way in style files is uncritical as the
% \cs{cs_generate_variant:Nn} function will only create new definitions if
% there is not already one available. Therefore adding
% such definition to later releases of the kernel will not make such
% style files obsolete.
%
% The steps above may be automated by using the function
% \cs{cs_generate_variant:Nn}, described next.
%
% \section{Methods for defining variants}
% \label{sec:l3expan:variants-method}
%
% ^^A Bruno: Should we put a table of variant types (N, c, n, V, v, o, f, x) for reference here?
%
% ^^A Bruno: Should \cs_generate_variant:Nn \foo:n { c } and \foo:N { o } really be ok?
%
% \begin{function}[updated = 2015-08-06]{\cs_generate_variant:Nn}
% \begin{syntax}
% \cs{cs_generate_variant:Nn} \meta{parent control sequence} \Arg{variant argument specifiers}
% \end{syntax}
% This function is used to define argument-specifier variants of the
% \meta{parent control sequence} for \LaTeX3 code-level macros. The
% \meta{parent control sequence} is first separated into the
% \meta{base name} and \meta{original argument specifier}. The
% comma-separated list of \meta{variant argument specifiers} is
% then used to define variants of the
% \meta{original argument specifier} where these are not already
% defined. For each \meta{variant} given, a function is created
% which will expand its arguments as detailed and pass them
% to the \meta{parent control sequence}. So for example
% \begin{verbatim}
% \cs_set:Npn \foo:Nn #1#2 { code here }
% \cs_generate_variant:Nn \foo:Nn { c }
% \end{verbatim}
% will create a new function |\foo:cn| which will expand its first
% argument into a control sequence name and pass the result to
% |\foo:Nn|. Similarly
% \begin{verbatim}
% \cs_generate_variant:Nn \foo:Nn { NV , cV }
% \end{verbatim}
% would generate the functions |\foo:NV| and |\foo:cV| in the same
% way. The \cs{cs_generate_variant:Nn} function can only be applied if
% the \meta{parent control sequence} is already defined. Only |n|~and
% |N| arguments can be changed to other types. If the \meta{parent
% control sequence} is protected or if the \meta{variant} involves
% |x|~arguments, then the \meta{variant control sequence} will also be
% protected. The \meta{variant} is created globally, as is any
% \cs[no-index]{exp_args:N\meta{variant}} function needed to carry out the
% expansion.
% \end{function}
%
% \section{Introducing the variants}
%
% The available internal functions for argument expansion come in two
% flavours, some of them are faster then others. Therefore
% (when speed is important) it is usually
% best to follow the following guidelines when defining new functions
% that are supposed to come with variant forms:
% \begin{itemize}
% \item
% Arguments that might need expansion should come first in the list of
% arguments to make processing faster.
% \item
% Arguments that should consist of single tokens should come first.
% \item
% Arguments that need full expansion (\emph{i.e.}, are denoted
% with |x|) should be avoided if possible as they can not be
% processed expandably, \emph{i.e.}, functions of this type will
% not work correctly in arguments that are themselves subject to |x|
% expansion.
% \item
% In general, unless in the last position, multi-token arguments
% |n|, |f|, and |o| will need special processing when more than
% one argument is being expanded. This special processing is not fast.
% Therefore it is best to use the optimized functions, namely
% those that contain only |N|, |c|, |V|, and |v|, and, in the last
% position, |o|, |f|, with possible trailing |N| or |n|, which are
% not expanded.
% \end{itemize}
%
% The |V| type returns the value of a register, which can be one of
% |tl|, |int|, |skip|, |dim|, |toks|, or built-in \TeX{}
% registers. The |v| type is the same except it first creates a
% control sequence out of its argument before returning the
% value.
%
% In general, the programmer should not need to be concerned with
% expansion control. When simply using the content of a variable,
% functions with a |V| specifier should be used. For those referred to by
% (cs)name, the |v| specifier is available for the same purpose. Only when
% specific expansion steps are needed, such as when using delimited
% arguments, should the lower-level functions with |o| specifiers be employed.
%
% The |f| type is so special that it deserves an example. It is
% typically used in contexts where only expandable commands are allowed.
% Then |x|-expansion cannot be used, and |f|-expansion provides an
% alternative that expands as much as can be done in such contexts. For
% instance, say that we want to evaluate the integer expression $3 + 4$
% and pass the result $7$ as an argument to an expandable function
% |\example:n|. For this, one should define a variant using
% \cs{cs_generate_variant:Nn} |\example:n| |{| |f| |}|, then do
% \begin{quote}
% |\example:f { \int_eval:n { 3 + 4 } }|
% \end{quote}
% Note that |x|-expansion would also expand \cs{int_eval:n} fully to its
% result~$7$, but the variant |\example:x| cannot be expandable. Note
% also that |o|-expansion would not expand \cs{int_eval:n} fully to its
% result since that function requires several expansions. Besides the
% fact that |x|-expansion is protected rather than expandable, another
% difference between |f|-expansion and |x|-expansion is that
% |f|-expansion expands tokens from the beginning and stops as soon as a
% non-expandable token is encountered, while |x|-expansion continues
% expanding further tokens. Thus, for instance
% \begin{quote}
% |\example:f { \int_eval:n { 1 + 2 } , \int_eval:n { 3 + 4 } }|
% \end{quote}
% will result in the call |\example:n { 3 , \int_eval:n { 3 + 4 } }|
% while using |\example:x| instead results in |\example:n { 3 , 7 }|
% 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 it does not
% try to finish any |\if... \fi:| itself!
%
% If is important to note that both \texttt{f}- and \texttt{o}-type
% expansion are concerned with the expansion of tokens from left to
% right in their arguments. In particular, \texttt{o}-type expansion
% applies to the first \emph{token} in the argument it receives: it
% is conceptually similar to
% \begin{verbatim}
% \exp_after:wN \exp_after:wN { }
% \end{verbatim}
% At the same time, \texttt{f}-type expansion stops at the emph{first}
% non-expandable token. This means for example that both
% \begin{verbatim}
% \tl_set:No \l_tmpa_tl { { \g_tmpb_tl } }
% \end{verbatim}
% and
% \begin{verbatim}
% \tl_set:Nf \l_tmpa_tl { { \g_tmpb_tl } }
% \end{verbatim}
% leave |\g_tmpb_tl| unchanged: |{| is the first token in the
% argument and is non-expandable.
%
% \section{Manipulating the first argument}
%
% These functions are described in detail: expansion of multiple tokens follows
% the same rules but is described in a shorter fashion.
%
% \begin{function}[EXP]{\exp_args:No}
% \begin{syntax}
% \cs{exp_args:No} \meta{function} \Arg{tokens} ...
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}). The \meta{tokens} are expanded once, and the result
% is inserted in braces into the input stream \emph{after} reinsertion
% of the \meta{function}. Thus the \meta{function} may take more than
% one argument: all others will be left unchanged.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:Nc, \exp_args:cc}
% \begin{syntax}
% \cs{exp_args:Nc} \meta{function} \Arg{tokens}
% \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
% will occur if such a conversion is not possible). 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 will be left unchanged.
%
% The |:cc| variant constructs the \meta{function} name in the same
% manner as described for the \meta{tokens}.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:NV}
% \begin{syntax}
% \cs{exp_args:NV} \meta{function} \meta{variable}
% \end{syntax}
% This function absorbs two arguments (the names of the \meta{function} and
% the \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 will be left unchanged.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:Nv}
% \begin{syntax}
% \cs{exp_args:Nv} \meta{function} \Arg{tokens}
% \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
% will occur if such a conversion is not possible). 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 will be left unchanged.
% \end{function}
%
% \begin{function}[EXP]{\exp_args:Nf}
% \begin{syntax}
% \cs{exp_args:Nf} \meta{function} \Arg{tokens}
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}). The \meta{tokens} are fully expanded until the
% first non-expandable token or space is found, and the result
% is inserted in braces into the input stream \emph{after} reinsertion
% of the \meta{function}. Thus the \meta{function} may take more than
% one argument: all others will be left unchanged.
% \end{function}
%
% \begin{function}{\exp_args:Nx}
% \begin{syntax}
% \cs{exp_args:Nx} \meta{function} \Arg{tokens}
% \end{syntax}
% This function absorbs two arguments (the \meta{function} name and
% the \meta{tokens}) and exhaustively expands the \meta{tokens}
% second. The result is inserted in braces into the input stream
% \emph{after} reinsertion of the \meta{function}.
% Thus the \meta{function} may take more
% than one argument: all others will be left unchanged.
% \end{function}
%
% \section{Manipulating two arguments}
%
% \begin{function}[EXP]
% {
% \exp_args:NNo,
% \exp_args:NNc,
% \exp_args:NNv,
% \exp_args:NNV,
% \exp_args:NNf,
% \exp_args:Nco,
% \exp_args:Ncf,
% \exp_args:Ncc,
% \exp_args:NVV
% }
% \begin{syntax}
% \cs{exp_args:NNc} \meta{token_1} \meta{token_2} \Arg{tokens}
% \end{syntax}
% These optimized functions absorb three arguments and expand the second and
% third as detailed by their argument specifier. The first argument
% of the function is then the next item on the input stream, followed
% by the expansion of the second and third arguments.
% \end{function}
%
% \begin{function}[EXP, updated = 2012-01-14]
% {
% \exp_args:Nno,
% \exp_args:NnV,
% \exp_args:Nnf,
% \exp_args:Noo,
% \exp_args:Nof,
% \exp_args:Noc,
% \exp_args:Nff,
% \exp_args:Nfo,
% \exp_args:Nnc
% }
% \begin{syntax}
% \cs{exp_args:Noo} \meta{token} \Arg{tokens_1} \Arg{tokens_2}
% \end{syntax}
% These functions absorb three arguments and expand the second and
% third as detailed by their argument specifier. The first argument
% of the function is then the next item on the input stream, followed
% by the expansion of the second and third arguments.
% These functions need special (slower) processing.
% \end{function}
%
% \begin{function}
% {
% \exp_args:NNx,
% \exp_args:Nnx,
% \exp_args:Ncx,
% \exp_args:Nox,
% \exp_args:Nxo,
% \exp_args:Nxx
% }
% \begin{syntax}
% \cs{exp_args:NNx} \meta{token_1} \meta{token_2} \Arg{tokens}
% \end{syntax}
% These functions absorb three arguments and expand the second and
% third as detailed by their argument specifier. The first argument
% of the function is then the next item on the input stream, followed
% by the expansion of the second and third arguments. These functions
% are not expandable.
% \end{function}
%
% \section{Manipulating three arguments}
%
% \begin{function}[EXP]
% {
% \exp_args:NNNo,
% \exp_args:NNNV,
% \exp_args:Nccc,
% \exp_args:NcNc,
% \exp_args:NcNo,
% \exp_args:Ncco
% }
% \begin{syntax}
% \cs{exp_args:NNNo} \meta{token_1} \meta{token_2} \meta{token_3} \Arg{tokens}
% \end{syntax}
% These optimized functions absorb four arguments and expand the second, third
% and fourth as detailed by their argument specifier. The first
% argument of the function is then the next item on the input stream,
% followed by the expansion of the second argument, \emph{etc}.
% \end{function}
%
% \begin{function}[EXP]
% {
% \exp_args:NNoo,
% \exp_args:NNno,
% \exp_args:Nnno,
% \exp_args:Nnnc,
% \exp_args:Nooo,
% }
% \begin{syntax}
% \cs{exp_args:NNoo} \meta{token_1} \meta{token_2} \Arg{token_3} \Arg{tokens}
% \end{syntax}
% These functions absorb four arguments and expand the second, third
% and fourth as detailed by their argument specifier. The first
% argument of the function is then the next item on the input stream,
% followed by the expansion of the second argument, \emph{etc}.
% These functions need special (slower) processing.
% \end{function}
%
% \begin{function}[added = 2015-08-12]
% {
% \exp_args:NNNx,
% \exp_args:NNnx,
% \exp_args:NNox,
% \exp_args:Nnnx,
% \exp_args:Nnox,
% \exp_args:Noox,
% \exp_args:Ncnx,
% \exp_args:Nccx
% }
% \begin{syntax}
% \cs{exp_args:NNnx} \meta{token_1} \meta{token_2} \Arg{tokens_1} \Arg{tokens_2}
% \end{syntax}
% These functions absorb four arguments and expand the second, third
% and fourth as detailed by their argument specifier. The first
% argument of the function is then the next item on the input stream,
% followed by the expansion of the second argument, \emph{etc.}
% \end{function}
%
% \section{Unbraced expansion}
%
% \begin{function}[EXP, updated = 2012-02-12]
% {
% \exp_last_unbraced:NV,
% \exp_last_unbraced:Nf,
% \exp_last_unbraced:No,
% \exp_last_unbraced:Nv,
% \exp_last_unbraced:Nco,
% \exp_last_unbraced:NcV,
% \exp_last_unbraced:NNV,
% \exp_last_unbraced:NNo,
% \exp_last_unbraced:Nno,
% \exp_last_unbraced:Noo,
% \exp_last_unbraced:Nfo,
% \exp_last_unbraced:NNNV,
% \exp_last_unbraced:NNNo,
% \exp_last_unbraced:NnNo
% }
% \begin{syntax}
% \cs{exp_last_unbraced:Nno} \meta{token} \meta{tokens_1} \meta{tokens_2}
% \end{syntax}
% These functions absorb the number of arguments given by their
% specification, carry out the expansion
% indicated and leave the results in the input stream, with the
% last argument not surrounded by the usual braces.
% Of these, the \texttt{:Nno}, \texttt{:Noo}, and \texttt{:Nfo}
% variants need special (slower) processing.
% \begin{texnote}
% As an optimization, the last argument is unbraced by some
% of those functions before expansion. This can cause problems
% if the argument is empty: for instance,
% \cs{exp_last_unbraced:Nf} |\foo_bar:w| |{ }| \cs{q_stop}
% leads to an infinite loop, as the quark is \texttt{f}-expanded.
% \end{texnote}
% \end{function}
%
% \begin{function}{\exp_last_unbraced:Nx}
% \begin{syntax}
% \cs{exp_last_unbraced:Nx} \meta{function} \Arg{tokens}
% \end{syntax}
% This functions fully expands the \meta{tokens} and leaves
% the result in the input stream after reinsertion of \meta{function}.
% This function is not expandable.
% \end{function}
%
% \begin{function}[EXP]{\exp_last_two_unbraced:Noo}
% \begin{syntax}
% \cs{exp_last_two_unbraced:Noo} \meta{token} \meta{tokens_1} \Arg{tokens_2}
% \end{syntax}
% This function absorbs three arguments and expand the second and third
% once. The first argument of the function is then the next item on the
% input stream, followed by the expansion of the second and third arguments,
% which are not wrapped in braces.
% This function needs special (slower) processing.
% \end{function}
%
% \begin{function}[EXP]{\exp_after:wN}
% \begin{syntax}
% \cs{exp_after:wN} \meta{token_1} \meta{token_2}
% \end{syntax}
% Carries out a single expansion of \meta{token_2} (which may consume
% arguments) prior to the expansion
% of \meta{token_1}. If \meta{token_2} is a \TeX{} primitive, it will
% be executed rather than expanded, while if \meta{token_2} has not
% expansion (for example, if it is a character) then it will be left
% unchanged. It is important to notice that \meta{token_1} may be
% \emph{any} single token, including group-opening and -closing
% tokens (|{| or |}| assuming normal \TeX{} category codes). Unless
% specifically required, expansion should be carried out using an
% appropriate argument specifier variant or the appropriate
% \cs{exp_arg:N} function.
% \begin{texnote}
% This is the \TeX{} primitive \tn{expandafter} renamed.
% \end{texnote}
% \end{function}
%
%
% \section{Preventing expansion}
%
% Despite the fact that the following functions are all about preventing
% expansion, they're designed to be used in an expandable context and hence
% are all marked as being `expandable' since they themselves will not appear
% after the expansion has completed.
%
% \begin{function}[EXP]{\exp_not:N}
% \begin{syntax}
% \cs{exp_not:N} \meta{token}
% \end{syntax}
% Prevents expansion of the \meta{token} in a context where it would otherwise
% be expanded, for example an |x|-type argument.
% \begin{texnote}
% This is the \TeX{} \tn{noexpand} primitive.
% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_not:c}
% \begin{syntax}
% \cs{exp_not:c} \Arg{tokens}
% \end{syntax}
% Expands the \meta{tokens} until only unexpandable content remains, and then
% converts this into a control sequence. Further expansion of this control
% sequence is then inhibited.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:n}
% \begin{syntax}
% \cs{exp_not:n} \Arg{tokens}
% \end{syntax}
% Prevents expansion of the \meta{tokens} in a context where they
% would otherwise be expanded, for example an |x|-type argument.
% \begin{texnote}
% This is the \eTeX{} \tn{unexpanded} primitive. Hence its argument
% \emph{must} be surrounded by braces.
% \end{texnote}
% \end{function}
%
% \begin{function}[EXP]{\exp_not:V}
% \begin{syntax}
% \cs{exp_not:V} \meta{variable}
% \end{syntax}
% Recovers the content of the \meta{variable}, then prevents expansion
% of this material in a context where it would otherwise
% be expanded, for example an |x|-type argument.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:v}
% \begin{syntax}
% \cs{exp_not:v} \Arg{tokens}
% \end{syntax}
% Expands the \meta{tokens} until only unexpandable content remains, and then
% converts this into a control sequence (which should be a \meta{variable}
% name). The content of the \meta{variable} is recovered, and further
% expansion is prevented in a context where it would otherwise
% be expanded, for example an |x|-type argument.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:o}
% \begin{syntax}
% \cs{exp_not:o} \Arg{tokens}
% \end{syntax}
% Expands the \meta{tokens} once, then prevents any further expansion in a
% context where they would otherwise
% be expanded, for example an |x|-type argument.
% \end{function}
%
% \begin{function}[EXP]{\exp_not:f}
% \begin{syntax}
% \cs{exp_not:f} \Arg{tokens}
% \end{syntax}
% Expands \meta{tokens} fully until the first unexpandable token
% is found. Expansion then stops, and the result of the expansion
% (including any tokens which were not expanded) is protected from
% further expansion.
% \end{function}
%
% \begin{function}[updated = 2011-06-03, EXP]{\exp_stop_f:}
% \begin{syntax}
% |\foo_bar:f| \{ \meta{tokens} \cs{exp_stop_f:} \meta{more tokens} \}
% \end{syntax}
% This function terminates an \texttt{f}-type expansion. Thus if
% a function |\foo_bar:f| starts an \texttt{f}-type expansion
% and all of \meta{tokens} are expandable \cs{exp_stop_f:} will
% terminate the expansion of tokens even if \meta{more tokens}
% are also expandable. The function itself is an implicit space
% token. Inside an \texttt{x}-type expansion, it will retain its
% form, but when typeset it produces the underlying space (\verb*| |).
% \end{function}
%
%
% \section{Controlled expansion}
%
% The \pkg{expl3} language makes all efforts to hide the complexity of
% \TeX{} expansion from the programmer by providing concepts that
% evaluate/expand arguments of functions prior to calling the \enquote{base}
% functions. Thus, instead of using many \tn{expandafter} calls and
% other trickery it is usually a matter of choosing the right variant
% of a function to achieve a desired result.
%
% Of course, deep down \TeX{} is using expansion as always and there
% are cases where a programmer needs to control that expansion
% directly; typical situations are basic data manipulation tools. This
% section documents the functions for that level. You will find these
% commands used throughout the kernel code, but we hope that outside
% the kernel there will be little need to resort to them. Instead the
% argument manipulation methods document above should usually be sufficient.
%
% While \cs{exp_after:wN} expands one token (out of order) it is
% sometimes necessary to expand several tokens in one go. The next set
% of commands provide this functionality. Be aware that it is
% absolutely required that the programmer has full control over the
% tokens to be expanded, i.e., it is not possible to use these
% functions to expand unknown input as part of
% \meta{expandable-tokens} as that will break badly if unexpandable
% tokens are encountered in that place!
%
% \begin{function}[added=2015-08-23,EXP]
% {
% \exp:w ,
% \exp_end:
% }
% \begin{syntax}
% \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
% 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
%
% In typical use cases the \cs{exp_end:} will be hidden somewhere
% in the replacement text of \meta{expandable-tokens} rather than
% being on the same expansion level than \cs{exp:w}, e.g., you may
% see code such as
%\begin{verbatim}
% \exp:w \@@_case:NnTF #1 {#2} { } { }
%\end{verbatim}
% where somewhere during the expansion of |\@@_case:NnTF| the
% \cs{exp_end:} gets generated.
% \end{function}
% \footnotetext{Due to the implementation you might get the character
% in position 0 in the current font (typically \enquote{\texttt{`}})
% in the output without any error message!}
%
% \begin{function}[added=2015-08-23, EXP, label = \exp_end_continue_f:w]
% {
% \exp:w ,
% \exp_end_continue_f:w
% }
% \begin{syntax}
% \cs{exp:w} \meta{expandable-tokens} \cs{exp_end_continue_f:w} \meta{further-tokens}
% \end{syntax}
% Expands \meta{expandable-tokens} until reaching \cs{exp_end_continue_f:w} at
% which point expansion continues as an f-type expansion expanding
% \meta{further-tokens} until an unexpandable token is encountered (or
% the f-type expansion is explicitly terminated by
% \cs{exp_stop_f:}). As with all f-type expansions a space ending
% the expansion will get removed.
%
% 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_continue_f:w} will be misinterpreted
% later on.\footnotemark
%
%
% In typical use cases \meta{expandable-tokens} contains no tokens at all,
% e.g., you will see code such as
%\begin{verbatim}
% \exp_after:wN { \exp:w \exp_end_continue_f:w #2 }
%\end{verbatim}
% where the \cs{exp_after:wN} triggers an f-expansion of the tokens
% in |#2|. For technical reasons this has to happen using two tokens
% (if they would be hidden inside another command \cs{exp_after:wN}
% would only expand the command but not trigger any additional
% f-expansion).
%
% You might wonder why there are two different approaches available,
% after all the effect of
% \begin{quote}
% \cs{exp:w} \meta{expandable-tokens} \cs{exp_end:}
% \end{quote}
% can be alternatively achieved through an f-type expansion by using
% \cs{exp_stop_f:}, i.e.
% \begin{quote}
% \cs{exp:w} \cs{exp_end_continue_f:w} \meta{expandable-tokens} \cs{exp_stop_f:}
% \end{quote}
% The reason is simply that the first approach is slightly faster
% (one less token to parse and less expansion internally)
% so in places where such performance really matters and where we
% want to explicitly stop the expansion at a defined point the first
% form is preferable.
% \end{function}
% \footnotetext{In this particular case you may get a character into
% the output as well as an error message.}
%
% \begin{function}[added=2015-08-23, EXP, label = \exp_end_continue_f:nw]
% {
% \exp:w ,
% \exp_end_continue_f:nw
% }
% \begin{syntax}
% \cs{exp:w} \meta{expandable-tokens} \cs{exp_end_continue_f:nw} \meta{further-tokens}
% \end{syntax}
% The difference to \cs{exp_end_continue_f:w} is that we first we pick
% up an argument which is then returned to the input stream. If
% \meta{further-tokens} starts with a brace group then the braces
% are removed. If on the other hand it starts with space tokens then
% these space tokens are removed while searching for the
% argument. Thus such space tokens will not terminate the f-type expansion.
% \end{function}
%
% \section{Internal functions and variables}
%
% \begin{variable}{\l__exp_internal_tl}
% The |\exp_| module has its private variables to temporarily store
% results of the argument expansion. This is done to avoid interference
% with other functions using temporary variables.
% \end{variable}
%
% \begin{function}{\::n, \::N, \::p, \::c, \::o, \::f, \::x, \::v, \::V, \:::}
% \begin{syntax}
% |\cs_set: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.
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3expan} implementation}
%
% \begin{macrocode}
%<*initex|package>
% \end{macrocode}
%
% \begin{macrocode}
%<@@=exp>
% \end{macrocode}
%
% \begin{macro}{\exp_after:wN}
% \begin{macro}{\exp_not:N}
% \begin{macro}{\exp_not:n}
% These are defined in \pkg{l3basics}.
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{General expansion}
%
% In this section a general mechanism for defining functions to handle
% argument handling is defined. These general expansion functions are
% expandable unless |x| is used. (Any version of |x| is going to have
% to use one of the \LaTeX3 names for \cs{cs_set:Npx} at some
% point, and so is never going to be expandable.)
%
% The definition of expansion functions with this technique happens
% in section~\ref{sec:l3expan:gendef}.
% In section~\ref{sec:l3expan:handtune} some common cases are coded by a more direct
% method for efficiency, typically using calls to \cs{exp_after:wN}.
%
% \begin{variable}{\l_@@_internal_tl}
% This scratch token list variable is defined in \pkg{l3basics}, as it
% is needed \enquote{early}. This is just a reminder that is the
% case!
% \end{variable}
%
% This code uses internal functions with names that start with |\::|
% to perform the expansions. All macros are |long| as this turned out
% to be desirable since the tokens undergoing expansion may be
% arbitrary user input.
%
% An argument manipulator |\::|\meta{Z} always has signature |#1\:::#2#3|
% where |#1| holds the remaining argument manipulations to be performed,
% \cs{:::} serves as an end marker for the list of manipulations, |#2|
% is the carried over result of the previous expansion steps and |#3| is
% the argument about to be processed.
% One exception to this rule is \cs{::p}, which has to grab an argument
% delimited by a left brace.
%
% \begin{macro}[aux, EXP]{\@@_arg_next:nnn}
% \begin{macro}[aux, EXP]{\@@_arg_next:Nnn}
% |#1| is the result of an expansion step, |#2| is the remaining
% argument manipulations and |#3| is the current result of the
% expansion chain. This auxiliary function moves |#1| back after
% |#3| in the input stream and checks if any expansion is left to
% be done by calling |#2|. In by far the most cases we will require
% to add a set of braces to the result of an argument manipulation
% so it is more effective to do it directly here. Actually, so far
% only the |c| of the final argument manipulation variants does not
% require a set of braces.
% \begin{macrocode}
\cs_new:Npn \@@_arg_next:nnn #1#2#3 { #2 \::: { #3 {#1} } }
\cs_new:Npn \@@_arg_next:Nnn #1#2#3 { #2 \::: { #3 #1 } }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[int]{\:::}
% The end marker is just another name for the identity function.
% \begin{macrocode}
\cs_new:Npn \::: #1 {#1}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, EXP]{\::n}
% This function is used to skip an argument that doesn't need to
% be expanded.
% \begin{macrocode}
\cs_new:Npn \::n #1 \::: #2#3 { #1 \::: { #2 {#3} } }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, EXP]{\::N}
% This function is used to skip an argument that consists of a
% single token and doesn't need to be expanded.
% \begin{macrocode}
\cs_new:Npn \::N #1 \::: #2#3 { #1 \::: {#2#3} }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, EXP]{\::p}
% This function is used to skip an argument that is delimited by a
% left brace and doesn't need to be expanded. It should not be
% wrapped in braces in the result.
% \begin{macrocode}
\cs_new:Npn \::p #1 \::: #2#3# { #1 \::: {#2#3} }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, EXP]{\::c}
% This function is used to skip an argument that is turned into
% a control sequence without expansion.
% \begin{macrocode}
\cs_new:Npn \::c #1 \::: #2#3
{ \exp_after:wN \@@_arg_next:Nnn \cs:w #3 \cs_end: {#1} {#2} }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, EXP]{\::o}
% This function is used to expand an argument once.
% \begin{macrocode}
\cs_new:Npn \::o #1 \::: #2#3
{ \exp_after:wN \@@_arg_next:nnn \exp_after:wN {#3} {#1} {#2} }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, EXP]{\::f}
% \begin{macro}{\exp_stop_f:}
% This function is used to expand a token list until the first
% unexpandable token is found. This is achieved through \cs{exp:w}
% \cs{exp_end_continue_f:w} that
% expands everything in its way following it. This
% scanning procedure is terminated once the expansion hits
% something non-expandable or a space. We introduce \cs{exp_stop_f:}
% to mark such an end of expansion marker.
% In the example shown earlier the scanning was stopped
% once \TeX{} had fully expanded |\cs_set_eq:Nc \aaa { b \l_tmpa_tl b }|
% into |\cs_set_eq:NN \aaa = \blurb| which then turned out to contain
% the non-expandable token \cs{cs_set_eq:NN}. Since the expansion of
% \cs{exp:w} \cs{exp_end_continue_f:w} is \meta{null}, we wind up with a fully
% expanded list, only \TeX{} has not tried to execute any of the
% non-expandable tokens. This is what differentiates this function
% from the |x| argument type.
% \begin{macrocode}
\cs_new:Npn \::f #1 \::: #2#3
{
\exp_after:wN \@@_arg_next:nnn
\exp_after:wN { \exp:w \exp_end_continue_f:w #3 }
{#1} {#2}
}
\use:nn { \cs_new_eq:NN \exp_stop_f: } { ~ }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[int]{\::x}
% This function is used to expand an argument fully.
% \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}
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[int, EXP]{\::v}
% \begin{macro}[int, EXP]{\::V}
% These functions return the value of a register, i.e., one of
% |tl|, |clist|, |int|, |skip|, |dim| and |muskip|. The |V| version
% expects a single token whereas |v| like |c| creates a csname from
% its argument given in braces and then evaluates it as if it was a
% |V|. The \cs{exp:w} sets off an expansion
% similar to an |f| type expansion, which we will terminate using
% \cs{exp_end:}. The argument is returned in braces.
% \begin{macrocode}
\cs_new:Npn \::V #1 \::: #2#3
{
\exp_after:wN \@@_arg_next:nnn
\exp_after:wN { \exp:w \@@_eval_register:N #3 }
{#1} {#2}
}
\cs_new:Npn \::v # 1\::: #2#3
{
\exp_after:wN \@@_arg_next:nnn
\exp_after:wN { \exp:w \@@_eval_register:c {#3} }
{#1} {#2}
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[int, EXP]{\@@_eval_register:N, \@@_eval_register:c}
% \begin{macro}[aux, EXP]{\@@_eval_error_msg:w}
% This function evaluates a register. Now a register might exist as
% one of two things: A parameter-less macro or a built-in \TeX{}
% register such as |\count|. For the \TeX{} registers we have to
% utilize a \tn{the} whereas for the macros we merely have to
% expand them once. The trick is to find out when to use
% \tn{the} and when not to. What we do here is try to find out
% whether the token will expand to something else when hit with
% \cs{exp_after:wN}. The technique is to compare the meaning of the
% register in question when it has been prefixed with \cs{exp_not:N}
% and the register itself. If it is a macro, the prefixed
% \cs{exp_not:N} will temporarily turn it into the primitive
% \cs{scan_stop:}.
% \begin{macrocode}
\cs_new:Npn \@@_eval_register:N #1
{
\exp_after:wN \if_meaning:w \exp_not:N #1 #1
% \end{macrocode}
% If the token was not a macro it may be a malformed variable from a
% |c| expansion in which case it is equal to the primitive
% \cs{scan_stop:}. In that case we throw an error. We could let \TeX{}
% do it for us but that would result in the rather obscure
% \begin{quote}
% |! You can't use `\relax' after \the.|
% \end{quote}
% which while quite true doesn't give many hints as to what actually
% went wrong. We provide something more sensible.
% \begin{macrocode}
\if_meaning:w \scan_stop: #1
\@@_eval_error_msg:w
\fi:
% \end{macrocode}
% The next bit requires some explanation. The function must be
% initiated by \cs{exp:w} and we want to
% terminate this expansion chain by inserting the \cs{exp_end:}
% token.
% However, we have to expand the register |#1| before we do
% that. If it is a \TeX{} register, we need to execute the sequence
% |\exp_after:wN \exp_end: \tex_the:D #1| and if it is a macro we
% need to execute |\exp_after:wN \exp_end: #1|. We therefore issue
% the longer of the two sequences and if the register is a macro, we
% remove the \cs{tex_the:D}.
% \begin{macrocode}
\else:
\exp_after:wN \use_i_ii:nnn
\fi:
\exp_after:wN \exp_end: \tex_the:D #1
}
\cs_new:Npn \@@_eval_register:c #1
{ \exp_after:wN \@@_eval_register:N \cs:w #1 \cs_end: }
% \end{macrocode}
% Clean up nicely, then call the undefined control sequence. The
% result is an error message looking like this:
% \begin{verbatim}
% ! Undefined control sequence.
% \LaTeX3 error:
% Erroneous variable used!
% l.55 \tl_set:Nv \l_tmpa_tl {undefined_tl}
% \end{verbatim}
% \begin{macrocode}
\cs_new:Npn \@@_eval_error_msg:w #1 \tex_the:D #2
{
\fi:
\fi:
\__msg_kernel_expandable_error:nnn { kernel } { bad-variable } {#2}
\exp_end:
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Hand-tuned definitions}
% \label{sec:l3expan:handtune}
%
% One of the most important features of these functions is that they
% are fully expandable and therefore allow to prefix them with
% \cs{tex_global:D} for example.
%
% \begin{macro}[EXP]{\exp_args:No}
% \begin{macro}[EXP]{\exp_args:NNo}
% \begin{macro}[EXP]{\exp_args:NNNo}
% Those lovely runs of expansion!
% \begin{macrocode}
\cs_new:Npn \exp_args:No #1#2 { \exp_after:wN #1 \exp_after:wN {#2} }
\cs_new:Npn \exp_args:NNo #1#2#3
{ \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN {#3} }
\cs_new:Npn \exp_args:NNNo #1#2#3#4
{ \exp_after:wN #1 \exp_after:wN#2 \exp_after:wN #3 \exp_after:wN {#4} }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\exp_args:Nc, \exp_args:cc}
% In \pkg{l3basics}.
% \end{macro}
%
% \begin{macro}[EXP]{\exp_args:NNc, \exp_args:Ncc, \exp_args:Nccc}
% Here are the functions that turn their argument into csnames but are
% expandable.
% \begin{macrocode}
\cs_new:Npn \exp_args:NNc #1#2#3
{ \exp_after:wN #1 \exp_after:wN #2 \cs:w # 3\cs_end: }
\cs_new:Npn \exp_args:Ncc #1#2#3
{ \exp_after:wN #1 \cs:w #2 \exp_after:wN \cs_end: \cs:w #3 \cs_end: }
\cs_new:Npn \exp_args:Nccc #1#2#3#4
{
\exp_after:wN #1
\cs:w #2 \exp_after:wN \cs_end:
\cs:w #3 \exp_after:wN \cs_end:
\cs:w #4 \cs_end:
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\exp_args:Nf, \exp_args:NV, \exp_args:Nv}
% \begin{macrocode}
\cs_new:Npn \exp_args:Nf #1#2
{ \exp_after:wN #1 \exp_after:wN { \exp:w \exp_end_continue_f:w #2 } }
\cs_new:Npn \exp_args:Nv #1#2
{
\exp_after:wN #1 \exp_after:wN
{ \exp:w \@@_eval_register:c {#2} }
}
\cs_new:Npn \exp_args:NV #1#2
{
\exp_after:wN #1 \exp_after:wN
{ \exp:w \@@_eval_register:N #2 }
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
% {
% \exp_args:NNV, \exp_args:NNv, \exp_args:NNf,
% \exp_args:NVV,
% \exp_args:Ncf, \exp_args:Nco
% }
% Some more hand-tuned function with three arguments.
% If we forced that an |o| argument always has braces,
% we could implement \cs{exp_args:Nco} with less tokens
% and only two arguments.
% \begin{macrocode}
\cs_new:Npn \exp_args:NNf #1#2#3
{
\exp_after:wN #1
\exp_after:wN #2
\exp_after:wN { \exp:w \exp_end_continue_f:w #3 }
}
\cs_new:Npn \exp_args:NNv #1#2#3
{
\exp_after:wN #1
\exp_after:wN #2
\exp_after:wN { \exp:w \@@_eval_register:c {#3} }
}
\cs_new:Npn \exp_args:NNV #1#2#3
{
\exp_after:wN #1
\exp_after:wN #2
\exp_after:wN { \exp:w \@@_eval_register:N #3 }
}
\cs_new:Npn \exp_args:Nco #1#2#3
{
\exp_after:wN #1
\cs:w #2 \exp_after:wN \cs_end:
\exp_after:wN {#3}
}
\cs_new:Npn \exp_args:Ncf #1#2#3
{
\exp_after:wN #1
\cs:w #2 \exp_after:wN \cs_end:
\exp_after:wN { \exp:w \exp_end_continue_f:w #3 }
}
\cs_new:Npn \exp_args:NVV #1#2#3
{
\exp_after:wN #1
\exp_after:wN { \exp:w \exp_after:wN
\@@_eval_register:N \exp_after:wN #2 \exp_after:wN }
\exp_after:wN { \exp:w \@@_eval_register:N #3 }
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
% {
% \exp_args:Ncco, \exp_args:NcNc, \exp_args:NcNo,
% \exp_args:NNNV
% }
% A few more that we can hand-tune.
% \begin{macrocode}
\cs_new:Npn \exp_args:NNNV #1#2#3#4
{
\exp_after:wN #1
\exp_after:wN #2
\exp_after:wN #3
\exp_after:wN { \exp:w \@@_eval_register:N #4 }
}
\cs_new:Npn \exp_args:NcNc #1#2#3#4
{
\exp_after:wN #1
\cs:w #2 \exp_after:wN \cs_end:
\exp_after:wN #3
\cs:w #4 \cs_end:
}
\cs_new:Npn \exp_args:NcNo #1#2#3#4
{
\exp_after:wN #1
\cs:w #2 \exp_after:wN \cs_end:
\exp_after:wN #3
\exp_after:wN {#4}
}
\cs_new:Npn \exp_args:Ncco #1#2#3#4
{
\exp_after:wN #1
\cs:w #2 \exp_after:wN \cs_end:
\cs:w #3 \exp_after:wN \cs_end:
\exp_after:wN {#4}
}
% \end{macrocode}
% \end{macro}
%
% \subsection{Definitions with the automated technique}
% \label{sec:l3expan:gendef}
%
% Some of these could be done more efficiently, but the complexity of
% coding then becomes an issue. Notice that the auto-generated functions
% are all not long: they don't actually take any arguments themselves.
%
% \begin{macro}{\exp_args:Nx}
% \begin{macrocode}
\cs_new_protected:Npn \exp_args:Nx { \::x \::: }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
% {
% \exp_args:Nnc, \exp_args:Nfo, \exp_args:Nff, \exp_args:Nnf,
% \exp_args:Nno, \exp_args:NnV, \exp_args:Noo, \exp_args:Nof,
% \exp_args:Noc
% }
% \begin{macro}
% {
% \exp_args:NNx, \exp_args:Ncx, \exp_args:Nnx,
% \exp_args:Nox, \exp_args:Nxo, \exp_args:Nxx,
% }
% Here are the actual function definitions, using the helper functions
% above.
% \begin{macrocode}
\cs_new:Npn \exp_args:Nnc { \::n \::c \::: }
\cs_new:Npn \exp_args:Nfo { \::f \::o \::: }
\cs_new:Npn \exp_args:Nff { \::f \::f \::: }
\cs_new:Npn \exp_args:Nnf { \::n \::f \::: }
\cs_new:Npn \exp_args:Nno { \::n \::o \::: }
\cs_new:Npn \exp_args:NnV { \::n \::V \::: }
\cs_new:Npn \exp_args:Noo { \::o \::o \::: }
\cs_new:Npn \exp_args:Nof { \::o \::f \::: }
\cs_new:Npn \exp_args:Noc { \::o \::c \::: }
\cs_new_protected:Npn \exp_args:NNx { \::N \::x \::: }
\cs_new_protected:Npn \exp_args:Ncx { \::c \::x \::: }
\cs_new_protected:Npn \exp_args:Nnx { \::n \::x \::: }
\cs_new_protected:Npn \exp_args:Nox { \::o \::x \::: }
\cs_new_protected:Npn \exp_args:Nxo { \::x \::o \::: }
\cs_new_protected:Npn \exp_args:Nxx { \::x \::x \::: }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]
% {
% \exp_args:NNno, \exp_args:NNoo,
% \exp_args:Nnnc, \exp_args:Nnno, \exp_args:Nooo,
% }
% \begin{macro}
% {
% \exp_args:NNNx,
% \exp_args:NNnx, \exp_args:NNox, \exp_args:Nnnx, \exp_args:Nnox,
% \exp_args:Nccx, \exp_args:Ncnx, \exp_args:Noox,
% }
% \begin{macrocode}
\cs_new:Npn \exp_args:NNno { \::N \::n \::o \::: }
\cs_new:Npn \exp_args:NNoo { \::N \::o \::o \::: }
\cs_new:Npn \exp_args:Nnnc { \::n \::n \::c \::: }
\cs_new:Npn \exp_args:Nnno { \::n \::n \::o \::: }
\cs_new:Npn \exp_args:Nooo { \::o \::o \::o \::: }
\cs_new_protected:Npn \exp_args:NNNx { \::N \::N \::x \::: }
\cs_new_protected:Npn \exp_args:NNnx { \::N \::n \::x \::: }
\cs_new_protected:Npn \exp_args:NNox { \::N \::o \::x \::: }
\cs_new_protected:Npn \exp_args:Nnnx { \::n \::n \::x \::: }
\cs_new_protected:Npn \exp_args:Nnox { \::n \::o \::x \::: }
\cs_new_protected:Npn \exp_args:Nccx { \::c \::c \::x \::: }
\cs_new_protected:Npn \exp_args:Ncnx { \::c \::n \::x \::: }
\cs_new_protected:Npn \exp_args:Noox { \::o \::o \::x \::: }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Last-unbraced versions}
%
% \begin{macro}[aux, EXP]{\@@_arg_last_unbraced:nn}
% \begin{macro}[aux, EXP]{\::f_unbraced}
% \begin{macro}[aux, EXP]{\::o_unbraced}
% \begin{macro}[aux, EXP]{\::V_unbraced}
% \begin{macro}[aux, EXP]{\::v_unbraced}
% \begin{macro}[aux, EXP]{\::x_unbraced}
% There are a few places where the last argument needs to be available
% unbraced. First some helper macros.
% \begin{macrocode}
\cs_new:Npn \@@_arg_last_unbraced:nn #1#2 { #2#1 }
\cs_new:Npn \::f_unbraced \::: #1#2
{
\exp_after:wN \@@_arg_last_unbraced:nn
\exp_after:wN { \exp:w \exp_end_continue_f:w #2 } {#1}
}
\cs_new:Npn \::o_unbraced \::: #1#2
{ \exp_after:wN \@@_arg_last_unbraced:nn \exp_after:wN {#2} {#1} }
\cs_new:Npn \::V_unbraced \::: #1#2
{
\exp_after:wN \@@_arg_last_unbraced:nn
\exp_after:wN { \exp:w \@@_eval_register:N #2 } {#1}
}
\cs_new:Npn \::v_unbraced \::: #1#2
{
\exp_after:wN \@@_arg_last_unbraced:nn
\exp_after:wN { \exp:w \@@_eval_register:c {#2} } {#1}
}
\cs_new_protected:Npn \::x_unbraced \::: #1#2
{
\cs_set_nopar:Npx \l_@@_internal_tl { \exp_not:n {#1} #2 }
\l_@@_internal_tl
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\exp_last_unbraced:NV}
% \begin{macro}[EXP]{\exp_last_unbraced:Nv}
% \begin{macro}[EXP]{\exp_last_unbraced:Nf}
% \begin{macro}[EXP]{\exp_last_unbraced:No}
% \begin{macro}[EXP]{\exp_last_unbraced:Nco}
% \begin{macro}[EXP]{\exp_last_unbraced:NcV}
% \begin{macro}[EXP]{\exp_last_unbraced:NNV}
% \begin{macro}[EXP]{\exp_last_unbraced:NNo}
% \begin{macro}[EXP]{\exp_last_unbraced:NNNV}
% \begin{macro}[EXP]{\exp_last_unbraced:NNNo}
% \begin{macro}[EXP]{\exp_last_unbraced:Nno}
% \begin{macro}[EXP]{\exp_last_unbraced:Noo}
% \begin{macro}[EXP]{\exp_last_unbraced:Nfo}
% \begin{macro}[EXP]{\exp_last_unbraced:NnNo}
% \begin{macro}{\exp_last_unbraced:Nx}
% Now the business end: most of these are hand-tuned for speed, but the
% general system is in place.
% \begin{macrocode}
\cs_new:Npn \exp_last_unbraced:NV #1#2
{ \exp_after:wN #1 \exp:w \@@_eval_register:N #2 }
\cs_new:Npn \exp_last_unbraced:Nv #1#2
{ \exp_after:wN #1 \exp:w \@@_eval_register:c {#2} }
\cs_new:Npn \exp_last_unbraced:No #1#2 { \exp_after:wN #1 #2 }
\cs_new:Npn \exp_last_unbraced:Nf #1#2
{ \exp_after:wN #1 \exp:w \exp_end_continue_f:w #2 }
\cs_new:Npn \exp_last_unbraced:Nco #1#2#3
{ \exp_after:wN #1 \cs:w #2 \exp_after:wN \cs_end: #3 }
\cs_new:Npn \exp_last_unbraced:NcV #1#2#3
{
\exp_after:wN #1
\cs:w #2 \exp_after:wN \cs_end:
\exp:w \@@_eval_register:N #3
}
\cs_new:Npn \exp_last_unbraced:NNV #1#2#3
{
\exp_after:wN #1
\exp_after:wN #2
\exp:w \@@_eval_register:N #3
}
\cs_new:Npn \exp_last_unbraced:NNo #1#2#3
{ \exp_after:wN #1 \exp_after:wN #2 #3 }
\cs_new:Npn \exp_last_unbraced:NNNV #1#2#3#4
{
\exp_after:wN #1
\exp_after:wN #2
\exp_after:wN #3
\exp:w \@@_eval_register:N #4
}
\cs_new:Npn \exp_last_unbraced:NNNo #1#2#3#4
{ \exp_after:wN #1 \exp_after:wN #2 \exp_after:wN #3 #4 }
\cs_new:Npn \exp_last_unbraced:Nno { \::n \::o_unbraced \::: }
\cs_new:Npn \exp_last_unbraced:Noo { \::o \::o_unbraced \::: }
\cs_new:Npn \exp_last_unbraced:Nfo { \::f \::o_unbraced \::: }
\cs_new:Npn \exp_last_unbraced:NnNo { \::n \::N \::o_unbraced \::: }
\cs_new_protected:Npn \exp_last_unbraced:Nx { \::x_unbraced \::: }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[EXP]{\exp_last_two_unbraced:Noo}
% \begin{macro}[EXP, aux]{\@@_last_two_unbraced:noN}
% If |#2| is a single token then this can be implemented as
% \begin{verbatim}
% \cs_new:Npn \exp_last_two_unbraced:Noo #1 #2 #3
% { \exp_after:wN \exp_after:wN \exp_after:wN #1 \exp_after:wN #2 #3 }
% \end{verbatim}
% However, for robustness this is not suitable. Instead, a bit of a
% shuffle is used to ensure that |#2| can be multiple tokens.
% \begin{macrocode}
\cs_new:Npn \exp_last_two_unbraced:Noo #1#2#3
{ \exp_after:wN \@@_last_two_unbraced:noN \exp_after:wN {#3} {#2} #1 }
\cs_new:Npn \@@_last_two_unbraced:noN #1#2#3
{ \exp_after:wN #3 #2 #1 }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Preventing expansion}
%
% \begin{macro}[EXP]{\exp_not:o}
% \begin{macro}[EXP]{\exp_not:c}
% \begin{macro}[EXP]{\exp_not:f}
% \begin{macro}[EXP]{\exp_not:V}
% \begin{macro}[EXP]{\exp_not:v}
% \begin{macrocode}
\cs_new:Npn \exp_not:o #1 { \etex_unexpanded:D \exp_after:wN {#1} }
\cs_new:Npn \exp_not:c #1 { \exp_after:wN \exp_not:N \cs:w #1 \cs_end: }
\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
{ \exp:w \@@_eval_register:N #1 }
}
\cs_new:Npn \exp_not:v #1
{
\etex_unexpanded:D \exp_after:wN
{ \exp:w \@@_eval_register:c {#1} }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Controlled expansion}
%
% \begin{macro}{\exp:w}
% \begin{macro}{\exp_end:}
% \begin{macro}{\exp_end_continue_f:w}
% \begin{macro}{\exp_end_continue_f:nw}
%
% To trigger a sequence of \enquote{arbitrary} many expansions we need a
% method to invoke \TeX's expansion mechanism in such a way that a)
% we are able to stop it in a controlled manner and b) that the
% result of what triggered the expansion in the first place is
% null, i.e., that we do not get any unwanted side effects. There
% aren't that many possibilities in \TeX{}; in fact the one
% explained below might well be the only one (as normally the
% result of expansion is not null).
%
% The trick here is to make use of the fact that
% \cs{tex_romannumeral:D} expands the tokens following it when
% looking for a number and that its expansion is null if that
% number turns out to be zero or negative. So we use that to start
% the expansion sequence.
% \begin{macrocode}
%\cs_new_eq:NN \exp:w \tex_romannumeral:D
% \end{macrocode}
% So to stop the expansion sequence in a controlled way all we need
% to provide is a constant integer zero as part of expanded tokens. As this is
% an integer constant it will immediately stop
% \cs{tex_romannumerl:D}'s search for a number.
% \begin{macrocode}
%\int_const:Nn \exp_end: { 0 }
% \end{macrocode}
% (Note that according to our specification all tokens we expand
% initiated by \cs{exp:w} are supposed to be expandable (as well as
% their replacement text in the expansion) so we will not encounter
% a \enquote{number} that actually result in a roman numeral being
% generated. Or if we do then the programmer made a mistake.)
%
% If on the other hand we want to stop the initial expansion
% sequence but continue with an f-type expansion we provide the
% alphabetic constant |`^^@| that also represents |0| but this time
% \TeX's syntax for a \meta{number} will continue searching for an
% optional space (and it will continue expansion doing that) ---
% see \TeX{}book page~269 for details.
% \begin{macrocode}
\tex_catcode:D `\^^@=13
\cs_new_protected:Npn \exp_end_continue_f:w {`^^@}
% \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.\footnote{Need to get a real error message.}
% \begin{macrocode}
\cs_new:Npn ^^@{\expansionERROR}
% \end{macrocode}
%
% \begin{macrocode}
\cs_new:Npn \exp_end_continue_f:nw #1 { `^^@ #1 }
\tex_catcode:D `\^^@=15
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \subsection{Defining function variants}
%
% \begin{macrocode}
%<@@=cs>
% \end{macrocode}
%
% \begin{macro}{\cs_generate_variant:Nn}
% \begin{arguments}
% \item Base form of a function; \emph{e.g.},~\cs{tl_set:Nn}
% \item One or more variant argument specifiers; e.g., |{Nx,c,cx}|
% \end{arguments}
% After making sure that the base form exists, test whether it is
% protected or not and define \cs{@@_tmp:w} as either
% \cs{cs_new:Npx} or \cs{cs_new_protected:Npx}, which is
% then used to define all the variants (except those involving
% \texttt{x}-expansion, always protected). Split up the original base
% function only once, to grab its name and signature. Then we wish to
% iterate through the comma list of variant argument specifiers, which
% we first convert to a string: the reason is explained later.
% \begin{macrocode}
\cs_new_protected:Npn \cs_generate_variant:Nn #1#2
{
\__chk_if_exist_cs:N #1
\@@_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
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_generate_variant:N}
% \begin{macro}[aux]{\@@_generate_variant:ww, \@@_generate_variant:wwNw}
% The goal here is to pick up protected parent functions. There are
% four cases: the parent function can be a primitive or a macro, and
% can be expandable or not. For non-expandable primitives, all
% variants should be protected; skipping the \cs{else:} branch is safe
% because all primitive \TeX{} conditionals are expandable.
%
% The other case where variants should be protected is when the parent
% function is a protected macro: then |protected| appears in the
% meaning before the fist occurrence of |macro|. The |ww| auxiliary
% removes everything in the meaning string after the first |ma|. We
% use |ma| rather than the full |macro| because the meaning of the
% \tn{firstmark} primitive (and four others) can contain an arbitrary
% string after a leading |firstmark:|. Then, look for |pr| in the
% part we extracted: no need to look for anything longer: the only
% strings we can have are an empty string, \verb*|\long |,
% \verb*|\protected |, \verb*|\protected\long |, |\first|, |\top|,
% |\bot|, |\splittop|, or |\splitbot|, with |\| replaced by the
% appropriate escape character. If |pr| appears in the part before
% |ma|, the first \cs{q_mark} is taken as an argument of the |wwNw|
% auxiliary, and |#3| is \cs{cs_new_protected:Npx}, otherwise it
% is \cs{cs_new:Npx}.
% \begin{macrocode}
\cs_new_protected:Npx \@@_generate_variant:N #1
{
\exp_not:N \exp_after:wN \exp_not:N \if_meaning:w
\exp_not:N \exp_not:N #1 #1
\cs_set_eq:NN \exp_not:N \@@_tmp:w \cs_new_protected:Npx
\exp_not:N \else:
\exp_not:N \exp_after:wN \exp_not:N \@@_generate_variant:ww
\exp_not:N \token_to_meaning:N #1 \tl_to_str:n { ma }
\exp_not:N \q_mark
\exp_not:N \q_mark \cs_new_protected:Npx
\tl_to_str:n { pr }
\exp_not:N \q_mark \cs_new:Npx
\exp_not:N \q_stop
\exp_not:N \fi:
}
\use:x
{
\cs_new_protected:Npn \exp_not:N \@@_generate_variant:ww
##1 \tl_to_str:n { ma } ##2 \exp_not:N \q_mark
}
{ \@@_generate_variant:wwNw #1 }
\use:x
{
\cs_new_protected:Npn \exp_not:N \@@_generate_variant:wwNw
##1 \tl_to_str:n { pr } ##2 \exp_not:N \q_mark
##3 ##4 \exp_not:N \q_stop
}
{ \cs_set_eq:NN \@@_tmp:w #3 }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}[aux]{\@@_generate_variant:nnNN}
% \begin{arguments}
% \item Base name.
% \item Base signature.
% \item Boolean.
% \item Base function.
% \end{arguments}
% If the boolean is \cs{c_false_bool}, the base function has no colon
% and we abort with an error; otherwise, set off a loop through the
% desired variant forms. The original function is retained as |#4| for
% efficiency.
% \begin{macrocode}
\cs_new_protected:Npn \@@_generate_variant:nnNN #1#2#3#4
{
\if_meaning:w \c_false_bool #3
\__msg_kernel_error:nnx { kernel } { missing-colon }
{ \token_to_str:c {#1} }
\exp_after:wN \use_none_delimit_by_q_recursion_stop:w
\fi:
\@@_generate_variant:Nnnw #4 {#1}{#2}
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_generate_variant:Nnnw}
% \begin{arguments}
% \item Base function.
% \item Base name.
% \item Base signature.
% \item Beginning of variant signature.
% \end{arguments}
% First check whether to terminate the loop over variant forms. Then,
% for each variant form, construct a new function name using the
% original base name, the variant signature consisting of $l$ letters
% and the last $k-l$ letters of the base signature (of length $k$).
% For example, for a base function \cs{prop_put:Nnn} which needs a
% |cV| variant form, we want the new signature to be |cVn|.
%
% There are further subtleties:
% \begin{itemize}
% \item In \cs{cs_generate_variant:Nn} |\foo:nnTF| |{xxTF}|, it
% would be better to define |\foo:xxTF| using |\exp_args:Nxx|,
% rather than a hypothetical |\exp_args:NxxTF|. Thus, we wish to
% trim a common trailing part from the base signature and the
% variant signature.
% \item In \cs{cs_generate_variant:Nn} |\foo:on| |{ox}|, the
% function |\foo:ox| should be defined using |\exp_args:Nnx|, not
% |\exp_args:Nox|, to avoid double |o| expansion.
% \item Lastly, \cs{cs_generate_variant:Nn} |\foo:on| |{xn}| should
% trigger an error, because we do not have a means to replace
% |o|-expansion by |x|-expansion.
% \end{itemize}
% All this boils down to a few rules. Only |n| and |N|-type
% arguments can be replaced by \cs{cs_generate_variant:Nn}. Other
% argument types are allowed to be passed unchanged from the base
% form to the variant: in the process they are changed to |n|
% (except for two cases: |N| and |p|-type arguments). A common
% trailing part is ignored.
%
% We compare the base and variant signatures one character at a time
% within |x|-expansion. The result is given to
% \cs{@@_generate_variant:wwNN} in the form \meta{processed variant
% signature} \cs{q_mark} \meta{errors} \cs{q_stop} \meta{base
% function} \meta{new function}. If all went well, \meta{errors}
% is empty; otherwise, it is a kernel error message, followed by
% some clean-up code (\cs{use_none:nnnn}).
%
% Note the space after |#3| and after the following brace group.
% Those are ignored by \TeX{} when fetching the last argument for
% \cs{@@_generate_variant_loop:nNwN}, but can be used as a delimiter
% for \cs{@@_generate_variant_loop_end:nwwwNNnn}.
% \begin{macrocode}
\cs_new_protected:Npn \@@_generate_variant:Nnnw #1#2#3#4 ,
{
\if_meaning:w \scan_stop: #4
\exp_after:wN \use_none_delimit_by_q_recursion_stop:w
\fi:
\use:x
{
\exp_not:N \@@_generate_variant:wwNN
\@@_generate_variant_loop:nNwN { }
#4
\@@_generate_variant_loop_end:nwwwNNnn
\q_mark
#3 ~
{ ~ { } \fi: \@@_generate_variant_loop_long:wNNnn } ~
{ }
\q_stop
\exp_not:N #1 {#2} {#4}
}
\@@_generate_variant:Nnnw #1 {#2} {#3}
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux, EXP]
% {
% \@@_generate_variant_loop:nNwN,
% \@@_generate_variant_loop_same:w,
% \@@_generate_variant_loop_end:nwwwNNnn,
% \@@_generate_variant_loop_long:wNNnn,
% \@@_generate_variant_loop_invalid:NNwNNnn,
% }
% \begin{arguments}
% \item Last few (consecutive) letters common between the base
% and variant (in fact, \cs{@@_generate_variant_same:N}
% \meta{letter} for each letter).
% \item Next variant letter.
% \item Remainder of variant form.
% \item Next base letter.
% \end{arguments}
% The first argument is populated by
% \cs{@@_generate_variant_loop_same:w} when a variant letter and a
% base letter match. It is flushed into the input stream whenever the
% two letters are different: if the loop ends before, the argument is
% dropped, which means that trailing common letters are ignored.
%
% The case where the two letters are different is only allowed with a
% base letter of |N| or |n|. Otherwise, call
% \cs{@@_generate_variant_loop_invalid:NNwNNnn} to remove the end of
% the loop, get arguments at the end of the loop, and place an
% appropriate error message as a second argument of
% \cs{@@_generate_variant:wwNN}. If the letters are distinct and
% the base letter is indeed |n| or |N|, leave in the input stream
% whatever argument was collected, and the next variant letter |#2|,
% then loop by calling \cs{@@_generate_variant_loop:nNwN}.
%
% The loop can stop in three ways.
% \begin{itemize}
% \item If the end of the variant form is encountered first, |#2| is
% \cs{@@_generate_variant_loop_end:nwwwNNnn} (expanded by the
% conditional \cs{if:w}), which inserts some tokens to end the
% conditional; grabs the \meta{base name} as |#7|, the
% \meta{variant signature} |#8|, the \meta{next base letter} |#1|
% and the part |#3| of the base signature that wasn't read yet;
% and combines those into the \meta{new function} to be defined.
% \item If the end of the base form is encountered first, |#4| is
% |~{}\fi:| which ends the conditional (with an empty expansion),
% followed by \cs{@@_generate_variant_loop_long:wNNnn}, which
% places an error as the second argument of
% \cs{@@_generate_variant:wwNN}.
% \item The loop can be interrupted early if the requested expansion
% is unavailable, namely when the variant and base letters differ
% and the base is neither |n| nor |N|. Again, an error is placed
% as the second argument of \cs{@@_generate_variant:wwNN}.
% \end{itemize}
% Note that if the variant form has the same length as the base form,
% |#2| is as described in the first point, and |#4| as described in
% the second point above. The \cs{@@_generate_variant_loop_end:nwwwNNnn}
% breaking function takes the empty brace group in |#4| as its first
% argument: this empty brace group produces the correct signature for
% the full variant.
% \begin{macrocode}
\cs_new:Npn \@@_generate_variant_loop:nNwN #1#2#3 \q_mark #4
{
\if:w #2 #4
\exp_after:wN \@@_generate_variant_loop_same:w
\else:
\if:w N #4 \else:
\if:w n #4 \else:
\@@_generate_variant_loop_invalid:NNwNNnn #4#2
\fi:
\fi:
\fi:
#1
\prg_do_nothing:
#2
\@@_generate_variant_loop:nNwN { } #3 \q_mark
}
\cs_new:Npn \@@_generate_variant_loop_same:w
#1 \prg_do_nothing: #2#3#4
{
#3 { #1 \@@_generate_variant_same:N #2 }
}
\cs_new:Npn \@@_generate_variant_loop_end:nwwwNNnn
#1#2 \q_mark #3 ~ #4 \q_stop #5#6#7#8
{
\scan_stop: \scan_stop: \fi:
\exp_not:N \q_mark
\exp_not:N \q_stop
\exp_not:N #6
\exp_not:c { #7 : #8 #1 #3 }
}
\cs_new:Npn \@@_generate_variant_loop_long:wNNnn #1 \q_stop #2#3#4#5
{
\exp_not:n
{
\q_mark
\__msg_kernel_error:nnxx { kernel } { variant-too-long }
{#5} { \token_to_str:N #3 }
\use_none:nnnn
\q_stop
#3
#3
}
}
\cs_new:Npn \@@_generate_variant_loop_invalid:NNwNNnn
#1#2 \fi: \fi: \fi: #3 \q_stop #4#5#6#7
{
\fi: \fi: \fi:
\exp_not:n
{
\q_mark
\__msg_kernel_error:nnxxxx { kernel } { invalid-variant }
{#7} { \token_to_str:N #5 } {#1} {#2}
\use_none:nnnn
\q_stop
#5
#5
}
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux, rEXP]{\@@_generate_variant_same:N}
% When the base and variant letters are identical, don't do any
% expansion. For most argument types, we can use the |n|-type
% no-expansion, but the |N| and |p| types require a slightly different
% behaviour with respect to braces.
% \begin{macrocode}
\cs_new:Npn \@@_generate_variant_same:N #1
{
\if:w N #1
N
\else:
\if:w p #1
p
\else:
n
\fi:
\fi:
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]{\@@_generate_variant:wwNN}
% If the variant form has already been defined, log its existence.
% Otherwise, make sure that the |\exp_args:N #3| form is defined, and
% if it contains |x|, change \cs{@@_tmp:w} locally to
% \cs{cs_new_protected:Npx}. Then define the variant by
% combining the |\exp_args:N #3| variant and the base function.
% \begin{macrocode}
\cs_new_protected:Npn \@@_generate_variant:wwNN
#1 \q_mark #2 \q_stop #3#4
{
#2
\cs_if_free:NTF #4
{
\group_begin:
\@@_generate_internal_variant:n {#1}
\@@_tmp:w #4 { \exp_not:c { exp_args:N #1 } \exp_not:N #3 }
\group_end:
}
{
\__chk_log:x
{
Variant~\token_to_str:N #4~%
already~defined;~ not~ changing~ it~ \msg_line_context:
}
}
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[int]{\@@_generate_internal_variant:n}
% \begin{macro}[aux]{\@@_generate_internal_variant:wwnw}
% \begin{macro}[aux, rEXP]{\@@_generate_internal_variant_loop:n}
% Test if |\exp_args:N #1| is already defined and if not define it via
% the |\::| commands using the chars in |#1|. If |#1| contains an |x|
% (this is the place where having converted the original comma-list
% argument to a string is very important), the result should be
% protected, and the next variant to be defined using that internal
% variant should be protected.
% \begin{macrocode}
\cs_new_protected:Npx \@@_generate_internal_variant:n #1
{
\exp_not:N \@@_generate_internal_variant:wwnNwnn
#1 \exp_not:N \q_mark
{ \cs_set_eq:NN \exp_not:N \@@_tmp:w \cs_new_protected:Npx }
\cs_new_protected:cpx
\token_to_str:N x \exp_not:N \q_mark
{ }
\cs_new:cpx
\exp_not:N \q_stop
{ exp_args:N #1 }
{
\exp_not:N \@@_generate_internal_variant_loop:n #1
{ : \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
}
{
#3
\cs_if_free:cT {#6} { #4 {#6} {#7} }
}
% \end{macrocode}
% This command grabs char by char outputting |\::#1| (not expanded
% further). We avoid tests by putting a trailing |: \use_i:nn|, which
% leaves \cs{cs_end:} and removes the looping macro. The colon is in
% fact also turned into \cs{:::} so that the required structure for
% |\exp_args:N...| commands is correctly terminated.
% \begin{macrocode}
\cs_new:Npn \@@_generate_internal_variant_loop:n #1
{
\exp_after:wN \exp_not:N \cs:w :: #1 \cs_end:
\@@_generate_internal_variant_loop:n
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macrocode}
%
% \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex