summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2011-07-31 18:27:06 +0000
committerKarl Berry <karl@freefriends.org>2011-07-31 18:27:06 +0000
commitdac945b204407dae96f70ec228206516093156d7 (patch)
tree02ca182689947e45dec95e17ba08b503c959bd17 /Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
parentc1840548792cfbc7c9f746da1d53d89b94406e72 (diff)
l3kernel (5jun11)
git-svn-id: svn://tug.org/texlive/trunk@23282 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.dtx1416
1 files changed, 1416 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
new file mode 100644
index 00000000000..5b37fd49aaf
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
@@ -0,0 +1,1416 @@
+% \iffalse meta-comment
+%
+%% File: l3expan.dtx Copyright (C) 1990-2011 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 "expl3 bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The released version of this bundle is available from CTAN.
+%%
+%% -----------------------------------------------------------------------
+%%
+%% The development version of the bundle can be found at
+%%
+%% http://www.latex-project.org/svnroot/experimental/trunk/
+%%
+%% for those people who are interested.
+%%
+%%%%%%%%%%%
+%% NOTE: %%
+%%%%%%%%%%%
+%%
+%% Snapshots taken from the repository represent work in progress and may
+%% not work or may contain conflicting material! We therefore ask
+%% people _not_ to put them into distributions, archives, etc. without
+%% prior consultation with the LaTeX3 Project.
+%%
+%% -----------------------------------------------------------------------
+%
+%<*driver|package>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3expan.dtx 2480 2011-06-20 17:25:23Z bruno $
+ {L3 Experimental argument expansion}
+%</driver|package>
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \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}
+%
+% 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
+% |\exp_args:NNo|. This function has three arguments, the first and the
+% second are a single tokens the third argument gets
+% expanded once. If |\seq_gpush:No| was not defined the example
+% above 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 |\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_new_nopar: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_new_nopar:Npn| function will silently accept definitions whenever the
+% new definition is identical to an already given one. 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_generate_variant:Nn|, described next.
+%
+% \section{Methods for defining variants}
+%
+% \begin{function}{\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 \cs{foo:cn} which will expand its first
+% argument into a control sequence name and pass the result to
+% \cs{foo:Nn}. Similarly
+% \begin{verbatim}
+% \cs_generate_variant:Nn \foo:Nn { NV , cV }
+% \end{verbatim}
+% would generate the functions \cs{foo:NV} and \cs{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. If
+% the \meta{parent control sequence} is protected then the new sequence
+% will also be protected. The \meta{variant} is created globally, as
+% is any \cs{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 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 itself subject to |x|
+% expansion.
+% \item
+% In general, unless in the last position, multi-token arguments
+% |n|, |f|, and |o| will need special processing which 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|, |num|, |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. This recent addition to the argument specifiers may shake
+% things up a bit as most places where |o| is used will be replaced by
+% |V|. The documentation you are currently reading will therefore
+% require a fair bit of re-writing.
+%
+% 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.
+% Let's pretend we want to set |\aaa| equal to the control sequence
+% stemming from turning |b \l_tmpa_tl b| into a control
+% sequence. Furthermore we want to store the execution of it in a
+% \meta{tl~var}. In this example we assume |\l_tmpa_tl| contains
+% the text string |lur|. The straightforward approach is
+% \begin{quote}
+% |\tl_set:No \l_tmpb_tl {\cs_set_eq:Nc \aaa { b \l_tmpa_tl b } }|
+% \end{quote}
+% Unfortunately this only puts
+% |\exp_args:NNc \cs_set_eq:NN \aaa {b \l_tmpa_tl b}| into |\l_tmpb_tl|
+% and not |\cs_set_eq:NwN \aaa = \blurb| as we probably wanted. Using
+% |\tl_set:Nx| is not an option as that will die horribly. Instead
+% we can do a
+% \begin{quote}
+% |\tl_set:Nf \l_tmpb_tl {\cs_set_eq:Nc \aaa { b \l_tmpa_tl b } }|
+% \end{quote}
+% which puts the desired result in |\l_tmpb_tl|. It requires
+% |\toks_set:Nf| to be defined as
+% \begin{quote}
+% |\cs_set_nopar:Npn \tl_set:Nf { \exp_args:NNf \tl_set:Nn }|
+% \end{quote}
+% 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!
+%
+% \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} \Arg{tokens2} ...
+% \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} \Arg{tokens2} ...
+% \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} \Arg{tokens2} ...
+% \end{syntax}
+% This function absorbs two arguments (the names of the \meta{function} and
+% the 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} \Arg{tokens2} ...
+% \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} \Arg{tokens2} ...
+% \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} \Arg{tokens2} ...
+% \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{token1} \meta{token2} \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]
+% {
+% \exp_args:Nno,
+% \exp_args:NnV,
+% \exp_args:Nnf,
+% \exp_args:Noo,
+% \exp_args:Noc,
+% \exp_args:Nff,
+% \exp_args:Nfo,
+% \exp_args:Nnc
+% }
+% \begin{syntax}
+% \cs{exp_args:Noo} \meta{token} \Arg{tokens1} \Arg{tokens2}
+% \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{token1} \meta{token2} \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{token1} \meta{token2} \meta{token3}
+% ~~\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:NNNo} \meta{token1} \meta{token2} \meta{token3}
+% ~~\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}
+% {
+% \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{token1} \meta{token2} \meta{tokens1}
+% ~~\Arg{tokens2}
+% \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_last_unbraced:Nf,
+% \exp_last_unbraced:NV,
+% \exp_last_unbraced:No,
+% \exp_last_unbraced:Nv,
+% \exp_last_unbraced:NcV,
+% \exp_last_unbraced:NNV,
+% \exp_last_unbraced:NNo,
+% \exp_last_unbraced:Nfo,
+% \exp_last_unbraced:NNNV,
+% \exp_last_unbraced:NNNo
+% }
+% \begin{syntax}
+% \cs{exp_last_unbraced:Nno} \meta{token} \meta{tokens1} \meta{tokens2}
+% \end{syntax}
+% These functions absorb the number of arguments given by their
+% specification, carry out the expansion
+% indicated and leave the the results in the input stream, with the
+% last argument not surrounded by the usual braces.
+% Of these, \cs{exp_last_unbraced:Nfo} needs special (slower) processing.
+% \end{function}
+%
+% \begin{function}[EXP]{\exp_last_two_unbraced:Noo}
+% \begin{syntax}
+% \cs{exp_last_two_unbraced:Noo} \meta{token} \meta{tokens1} \Arg{tokens2}
+% \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{token1} \meta{token2}
+% \end{syntax}
+% Carries out a single expansion of \meta{token2} prior to expansion
+% of \meta{token1}. If \meta{token2} is a \TeX{} primitive, it will
+% be executed rather than expanded, while if \meta{token2} has not
+% expansion (for example, if it is a character) then it will be left
+% unchanged. It is important to notice that \meta{token1} 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 \cs{expandafter} renamed.
+% \end{texnote}
+% \end{function}
+%
+% \section{Preventing expansion}
+%
+% \begin{function}{\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{} \cs{noexpand} primitive.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}{\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_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{} \cs{unexpanded} primitive.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}{\exp_not:V}
+% \begin{syntax}
+% \cs{exp_not:V} \meta{variable}
+% \end{syntax}
+% Recovers the content of the \meta{variable}, then prevents expansion
+% of the this material in a context where it would otherwise
+% be expanded, for example an |x|-type argument.
+% \end{function}
+%
+% \begin{function}{\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_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} \meta{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}[EXP]{\exp_stop_f:}
+% \begin{syntax}
+% \cs{function:f} \meta{tokens} \cs{exp_stop_f:} \meta{more tokens}
+% \end{syntax}
+% This function terminates an \texttt{f}-type expansion. Thus if
+% a function \cs{function: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{Internal functions and variables}
+%
+% \begin{variable}{\l_exp_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}[EXP]{\exp_eval_register:N, \exp_eval_register:c}
+% \begin{syntax}
+% \cs{exp_eval_register:N} \meta{variable}
+% \end{syntax}
+% These functions evaluates a \meta{variable} as part of a |V| or |v|
+% expansion (respectively), preceeded by \cs{c_zero} which stops
+% the expansion of a previous \cs{tex_romannumeral:D}.
+% A \meta{variable} might exist as
+% one of two things: a parameter-less non-long, non-protected macro
+% or a built-in \TeX{} register such as |\count|.
+% \end{function}
+%
+% \begin{function}{\::n, \::N, \::c, \::o, \::f, \::x, \::v, \::V, \:::}
+% \begin{syntax}
+% |\cs_set_nopar: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}
+%
+% \begin{function}{\cs_generate_internal_variant:n}
+% \begin{syntax}
+% \cs{cs_generate_internal_variant:n} \meta{arg~spec}
+% \end{syntax}
+% Tests if the function |\exp_args:N|\meta{arg~spec} exists, and defines it
+% if it does not. The \meta{arg~spec} should be a series of one or more
+% of the letters |N|, |c|, |n|, |o|, |V|, |v|, |f| and |x|.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3expan} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% We start by ensuring that the required packages are loaded.
+% \begin{macrocode}
+%<*package>
+\ProvidesExplPackage
+ {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+\package_check_loaded_expl:
+%</package>
+% \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_set_nopar:Npx| at some point, and
+% so is never going to be expandable.\footnote{However, some
+% primitives have certain characteristics that means that their
+% arguments undergo an \texttt{x} type expansion but the primitive
+% is in fact still expandable. We shall make it very clear when such
+% a function is expandable.})
+%
+% The definition of expansion functions with this technique happens
+% in section~\ref{sec:gendef}.
+% In section~\ref{sec:handtune} some common cases are coded by a more direct
+% method for efficiency, typically using calls to |\exp_after:wN|.
+%
+% \begin{variable}{\l_exp_tl}
+% We need a scratch token list variable.
+% We don't use |tl| methods so that \pkg{l3expan} can be loaded earlier.
+% \begin{macrocode}
+\cs_new_nopar:Npn \l_exp_tl { }
+% \end{macrocode}
+% \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,
+% |\:::| 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.
+%
+% \begin{macro}[aux]{\exp_arg_next:nnn}
+% \begin{macro}[aux]{\exp_arg_next_nobrace: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 \exp_arg_next:nnn #1#2#3 { #2 \::: { #3 {#1} } }
+\cs_new:Npn \exp_arg_next_nobrace: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]{\::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]{\::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]{\::c}
+% This function is used to skip an argument that is turned into
+% as control sequence without expansion.
+% \begin{macrocode}
+\cs_new:Npn \::c #1 \::: #2#3
+ { \exp_after:wN \exp_arg_next_nobrace:nnn \cs:w #3 \cs_end: {#1} {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\::o}
+% This function is used to expand an argument once.
+% \begin{macrocode}
+\cs_new:Npn \::o #1 \::: #2#3
+ { \exp_after:wN \exp_arg_next:nnn \exp_after:wN {#3} {#1} {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\::f}
+% \begin{macro}{\exp_stop_f:}
+% This function is used to expand a token list until the first
+% unexpandable token is found. The underlying |\tex_romannumeral:D -`0|
+% expands everything in its way to find something terminating the
+% number and thereby expands the function in front of it. This
+% scanning procedure is terminated once the expansion hits
+% something non-expandable or a space. We introduce |\exp_stop_f:|
+% to mark such an end of expansion marker; in case the scanner hits
+% a number, this number also terminates the scanning and is left
+% untouched. 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:NwN \aaa = \blurb| which then turned out to contain
+% the non-expandable token |\cs_set_eq:NwN|. Since the expansion of
+% |\tex_romannumeral:D -`0| 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 \exp_arg_next:nnn
+ \exp_after:wN { \tex_romannumeral:D -`0 #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_exp_tl { {#3} }
+ \exp_after:wN \exp_arg_next:nnn \l_exp_tl {#1} {#2}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\::v}
+% \begin{macro}[int]{\::V}
+% These functions return the value of a register, i.e., one of
+% |tl|, |num|, |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 primitive \cs{tex_romannumeral:D} sets off an expansion
+% similar to an |f| type expansion, which we will terminate using
+% \cs{c_zero}. The argument is returned in braces.
+% \begin{macrocode}
+\cs_new:Npn \::V #1 \::: #2#3
+ {
+ \exp_after:wN \exp_arg_next:nnn
+ \exp_after:wN { \tex_romannumeral:D \exp_eval_register:N #3 }
+ {#1} {#2}
+}
+\cs_new:Npn \::v # 1\::: #2#3
+ {
+ \exp_after:wN \exp_arg_next:nnn
+ \exp_after:wN { \tex_romannumeral:D \exp_eval_register:c {#3} }
+ {#1} {#2}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]{\exp_eval_register:N, \exp_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 |\tex_the:D| whereas for the macros we merely have to
+% expand them once. The trick is to find out when to use
+% |\tex_the:D| and when not to. What we do here is try to find out
+% whether the token will expand to something else when hit with
+% |\exp_after:wN|. The technique is to compare the meaning of the
+% register in question when it has been prefixed with |\exp_not:N|
+% and the register itself. If it is a macro, the prefixed
+% |\exp_not:N| will temporarily turn it into the primitive
+% |\scan_stop:|.
+% \begin{macrocode}
+\cs_new_nopar:Npn \exp_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
+% |\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
+ \exp_eval_error_msg:w
+ \fi:
+% \end{macrocode}
+% The next bit requires some explanation. The function must be
+% initiated by the primitive \cs{tex_romannumeral:D} and we want to
+% terminate this expansion chain by inserting the \cs{c_zero} integer
+% constant. 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 \c_zero \tex_the:D #1| and if it is a macro we
+% need to execute |\exp_after:wN \c_zero #1|. We therefore issue
+% the longer of the two sequences and if the register is a macro, we
+% remove the |\tex_the:D|.
+% \begin{macrocode}
+ \else:
+ \exp_after:wN \use_i_ii:nnn
+ \fi:
+ \exp_after:wN \c_zero \tex_the:D #1
+ }
+\cs_new_nopar:Npn \exp_eval_register:c #1
+ { \exp_after:wN \exp_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.
+% \exp_eval_error_msg:w ...erroneous variable used!
+%
+% l.55 \tl_set:Nv \l_tmpa_tl {undefined_tl}
+% \end{verbatim}
+% \begin{macrocode}
+\group_begin:%
+\tex_catcode:D`\!=11\scan_stop:%
+\tex_catcode:D`\ =11\scan_stop:%
+\cs_new:Npn\exp_eval_error_msg:w#1\tex_the:D#2{%
+\fi:\fi:\exp_after:wN\c_zero\erroneous variable used!}%
+\group_end:%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Hand-tuned definitions}
+% \label{sec:handtune}
+%
+% One of the most important features of these functions is that they
+% are fully expandable and therefore allow to prefix them with
+% |\pref_global:D| for example.
+%
+% \begin{macro}{\exp_args:No}
+% \begin{macro}{\exp_args:NNo}
+% \begin{macro}{\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_args:Nc}
+% In \pkg{l3basics}
+%\end{macro}
+%
+% \begin{macro}{\exp_args:cc, \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:cc #1#2
+ { \cs:w #1 \exp_after:wN \cs_end: \cs:w #2 \cs_end: }
+\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_args:Nf, \exp_args:NV, \exp_args:Nv, \exp_args:Nx}
+% \begin{macrocode}
+\cs_new:Npn \exp_args:Nf #1#2
+ { \exp_after:wN #1 \exp_after:wN { \tex_romannumeral:D -`0 #2 } }
+\cs_new:Npn \exp_args:Nv #1#2
+ {
+ \exp_after:wN #1 \exp_after:wN
+ { \tex_romannumeral:D \exp_eval_register:c {#2} }
+ }
+\cs_new:Npn \exp_args:NV #1#2
+ {
+ \exp_after:wN #1 \exp_after:wN
+ { \tex_romannumeral:D \exp_eval_register:N #2 }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\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 force 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 { \tex_romannumeral:D -`0 #3 }
+ }
+\cs_new:Npn \exp_args:NNv #1#2#3
+ {
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \exp_after:wN { \tex_romannumeral:D \exp_eval_register:c {#3} }
+ }
+\cs_new:Npn \exp_args:NNV #1#2#3
+ {
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \exp_after:wN { \tex_romannumeral:D \exp_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 { \tex_romannumeral:D -`0 #3 }
+ }
+\cs_new_nopar:Npn \exp_args:NVV #1#2#3
+ {
+ \exp_after:wN #1
+ \exp_after:wN { \tex_romannumeral:D \exp_after:wN
+ \exp_eval_register:N \exp_after:wN #2 \exp_after:wN }
+ \exp_after:wN { \tex_romannumeral:D \exp_eval_register:N #3 }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\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 { \tex_romannumeral:D \exp_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: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_nopar:Npn \exp_args:Nx { \::x \::: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\exp_args:NNx,
+% \exp_args:Nnc,
+% \exp_args:Ncx,
+% \exp_args:Nfo,\exp_args:Nff,
+% \exp_args:Nnf,\exp_args:Nno,\exp_args:NnV,\exp_args:Nnx,
+% \exp_args:Noo,\exp_args:Noc,\exp_args:Nox,
+% \exp_args:Nxo,\exp_args:Nxx}
+% Here are the actual function definitions, using the helper functions
+% above.
+% \begin{macrocode}
+\cs_new_nopar:Npn \exp_args:Nnc { \::n \::c \::: }
+\cs_new_nopar:Npn \exp_args:Nfo { \::f \::o \::: }
+\cs_new_nopar:Npn \exp_args:Nff { \::f \::f \::: }
+\cs_new_nopar:Npn \exp_args:Nnf { \::n \::f \::: }
+\cs_new_nopar:Npn \exp_args:Nno { \::n \::o \::: }
+\cs_new_nopar:Npn \exp_args:NnV { \::n \::V \::: }
+\cs_new_nopar:Npn \exp_args:Noc { \::o \::c \::: }
+\cs_new_nopar:Npn \exp_args:Noo { \::o \::o \::: }
+\cs_new_protected_nopar:Npn \exp_args:NNx { \::N \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:Ncx { \::c \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:Nnx { \::n \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:Nox { \::o \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:Nxo { \::x \::o \::: }
+\cs_new_protected_nopar:Npn \exp_args:Nxx { \::x \::x \::: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\exp_args:Nccx,
+% \exp_args:Ncnx,
+% \exp_args:NNno,
+% \exp_args:Nnno,
+% \exp_args:Nnnx,
+% \exp_args:Nnox,
+% \exp_args:Nooo,
+% \exp_args:Noox,
+% \exp_args:Nnnc,
+% \exp_args:NNnx,
+% \exp_args:NNoo,
+% \exp_args:NNox}
+% \begin{macrocode}
+\cs_new_nopar:Npn \exp_args:NNno { \::N \::n \::o \::: }
+\cs_new_nopar:Npn \exp_args:NNoo { \::N \::o \::o \::: }
+\cs_new_nopar:Npn \exp_args:Nnnc { \::n \::n \::c \::: }
+\cs_new_nopar:Npn \exp_args:Nnno { \::n \::n \::o \::: }
+\cs_new_nopar:Npn \exp_args:Nooo { \::o \::o \::o \::: }
+\cs_new_protected_nopar:Npn \exp_args:NNnx { \::N \::n \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:NNox { \::N \::o \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:Nnnx { \::n \::n \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:Nnox { \::n \::o \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:Nccx { \::c \::c \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:Ncnx { \::c \::n \::x \::: }
+\cs_new_protected_nopar:Npn \exp_args:Noox { \::o \::o \::x \::: }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Last-unbraced versions}
+%
+% \begin{macro}[aux]{\exp_arg_last_unbraced:nn}
+% \begin{macro}[aux]{\::f_unbraced}
+% \begin{macro}[aux]{\::o_unbraced}
+% \begin{macro}[aux]{\::V_unbraced}
+% \begin{macro}[aux]{\::v_unbraced}
+% There are a few places where the last argument needs to be available
+% unbraced. First some helper macros.
+% \begin{macrocode}
+\cs_new:Npn \exp_arg_last_unbraced:nn #1#2 { #2#1 }
+\cs_new:Npn \::f_unbraced \::: #1#2
+ {
+ \exp_after:wN \exp_arg_last_unbraced:nn
+ \exp_after:wN { \tex_romannumeral:D -`0 #2 } {#1}
+ }
+\cs_new:Npn \::o_unbraced \::: #1#2
+ { \exp_after:wN \exp_arg_last_unbraced:nn \exp_after:wN {#2} {#1} }
+\cs_new:Npn \::V_unbraced \::: #1#2
+ {
+ \exp_after:wN \exp_arg_last_unbraced:nn
+ \exp_after:wN { \tex_romannumeral:D \exp_eval_register:N #2 } {#1}
+ }
+\cs_new:Npn \::v_unbraced \::: #1#2
+ {
+ \exp_after:wN \exp_arg_last_unbraced:nn
+ \exp_after:wN { \tex_romannumeral:D \exp_eval_register:c {#2} } {#1}
+ }
+% \end{macrocode}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%\end{macro}
+%
+% \begin{macro}{\exp_last_unbraced:NV}
+% \begin{macro}{\exp_last_unbraced:Nv}
+% \begin{macro}{\exp_last_unbraced:Nf}
+% \begin{macro}{\exp_last_unbraced:No}
+% \begin{macro}{\exp_last_unbraced:NcV}
+% \begin{macro}{\exp_last_unbraced:NNV}
+% \begin{macro}{\exp_last_unbraced:NNo}
+% \begin{macro}{\exp_last_unbraced:Noo}
+% \begin{macro}{\exp_last_unbraced:Nfo}
+% \begin{macro}{\exp_last_unbraced:NNNV}
+% \begin{macro}{\exp_last_unbraced:NNNo}
+% 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 \tex_romannumeral:D \exp_eval_register:N #2 }
+\cs_new:Npn \exp_last_unbraced:Nv #1#2
+ { \exp_after:wN #1 \tex_romannumeral:D \exp_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 \tex_romannumeral:D -`0 #2 }
+\cs_new:Npn \exp_last_unbraced:NcV #1#2#3
+ {
+ \exp_after:wN #1
+ \cs:w #2 \exp_after:wN \cs_end:
+ \tex_romannumeral:D \exp_eval_register:N #3
+ }
+\cs_new:Npn \exp_last_unbraced:NNV #1#2#3
+ {
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \tex_romannumeral:D \exp_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_nopar:Npn \exp_last_unbraced:Noo { \::o \::o_unbraced \::: }
+\cs_new_nopar:Npn \exp_last_unbraced:Nfo { \::f \::o_unbraced \::: }
+\cs_new:Npn \exp_last_unbraced:NNNV #1#2#3#4
+ {
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \exp_after:wN #3
+ \tex_romannumeral:D \exp_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 }
+% \end{macrocode}
+% \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_last_two_unbraced:Noo}
+% 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 \exp_last_two_unbraced_aux:nnN \exp_after:wN {#3} {#2} #1 }
+\cs_new:Npn \exp_last_two_unbraced_aux:nnN #1#2#3
+ { \exp_after:wN #3 #2 #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Preventing expansion}
+%
+% \begin{macro}{\exp_not:o}
+% \begin{macro}{\exp_not:f}
+% \begin{macro}{\exp_not:V}
+% \begin{macro}{\exp_not:v}
+% \begin{macrocode}
+\cs_new:Npn \exp_not:o #1 { \etex_unexpanded:D \exp_after:wN {#1} }
+\cs_new:Npn \exp_not:f #1
+ { \etex_unexpanded:D \exp_after:wN { \tex_romannumeral:D -`0 #1 } }
+\cs_new:Npn \exp_not:V #1
+ {
+ \etex_unexpanded:D \exp_after:wN
+ { \tex_romannumeral:D \exp_eval_register:N #1 }
+ }
+\cs_new:Npn \exp_not:v #1
+ {
+ \etex_unexpanded:D \exp_after:wN
+ { \tex_romannumeral:D \exp_eval_register:c {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\exp_not:c}
+% A helper function.
+% \begin{macrocode}
+\cs_new:Npn \exp_not:c #1 { \exp_after:wN \exp_not:N \cs:w #1 \cs_end: }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Defining function variants}
+%
+% \begin{macro}{\cs_generate_variant:Nn}
+% \begin{macro}[aux]{\cs_generate_variant_aux:nnNNn}
+% \begin{macro}[aux]{\cs_generate_variant_aux:Nnnw}
+% \begin{macro}[aux]{\cs_generate_variant_aux:NNn}
+% \begin{macro}[aux]{\cs_generate_variant_aux:N}
+% \begin{arguments}
+% \item Base form of a function; \emph{e.g.},~|\tl_set:Nn|
+% \item One or more variant argument specifiers; e.g., |{Nx,c,cx}|
+% \end{arguments}
+% Split up the original base function to grab its name and signature
+% consisting of $k$ letters. Then we wish to iterate through the list
+% of variant argument specifiers, and for each one 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. For example, for a base function |\tl_set:Nn| which
+% needs a |c| variant form, we want the new signature to be |cn|.
+% \begin{macrocode}
+\cs_new_protected:Npn \cs_generate_variant:Nn #1
+ {
+ \chk_if_exist_cs:N #1
+ \cs_split_function:NN #1 \cs_generate_variant_aux:nnNNn
+ #1
+ }
+% \end{macrocode}
+% We discard the boolean |#3| and then set off a loop through the desired
+% variant forms. The original function is retained as |#4| for efficiency.
+% \begin{macrocode}
+\cs_new:Npn \cs_generate_variant_aux:nnNNn #1#2#3#4#5
+ { \cs_generate_variant_aux:Nnnw #4 {#1}{#2} #5 , ? , \q_recursion_stop }
+% \end{macrocode}
+% Next is the real work to be done. We now have 1: original function,
+% 2: base name, 3: base signature, 4: beginning of variant signature.
+% To construct the new
+% csname and the |\exp_args:Ncc| form, we need the variant signature.
+% In our example, we wanted to discard the first two letters of the
+% base signature because the variant form started with |cc|. This is
+% the same as putting first |cc| in the signature and then
+% |\use_none:nn| followed by the base signature |NNn|. We therefore
+% call a small loop that outputs an |n| for each letter in the variant
+% signature and use this to call the correct |\use_none:| variant.
+%
+% Firstly though, we check whether to terminate the loop.
+% Then build the variant function once, to avoid repeating this
+% relatively expensive operation. Then recurse.
+% \begin{macrocode}
+\cs_new:Npn \cs_generate_variant_aux:Nnnw #1#2#3#4 ,
+ {
+ \if:w ? #4
+ \exp_after:wN \use_none_delimit_by_q_recursion_stop:w
+ \fi:
+ \exp_args:NNc \cs_generate_variant_aux:NNn
+ #1
+ { #2 : #4 \use:c { use_none: \cs_generate_variant_aux:N #4 ? } #3 }
+ {#4}
+ \cs_generate_variant_aux:Nnnw #1 {#2} {#3}
+ }
+% \end{macrocode}
+% Check if the variant form has already been defined.
+% If not, then define it and then additionally check if
+% the |\exp_args:N| form needed is defined.
+% Otherwise tell that it was already defined.
+% \begin{macrocode}
+\cs_new:Npn \cs_generate_variant_aux:NNn #1 #2 #3
+ {
+ \cs_if_free:NTF #2
+ {
+ \cs_generate_variant_aux:NNpx #1 #2
+ { \exp_not:c { exp_args:N #3 } \exp_not:N #1 }
+ \cs_generate_internal_variant:n {#3}
+ }
+ {
+ \iow_log:x
+ {
+ Variant~\token_to_str:N #2~%
+ already~defined;~ not~ changing~ it~on~line~%
+ \tex_the:D \tex_inputlineno:D
+ }
+ }
+ }
+% \end{macrocode}
+% The small loop for defining the required number of |n|s. Break when
+% seeing a |?|.
+% \begin{macrocode}
+\cs_new:Npn \cs_generate_variant_aux:N #1
+ {
+ \if:w ? #1
+ \exp_after:wN \use_none:nn
+ \fi:
+ n
+ \cs_generate_variant_aux:N
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux]{\cs_generate_variant_aux:NNpx}
+% \begin{macro}[aux]{\cs_generate_variant_aux:w}
+% The idea here is to pick up protected parent functions, using the
+% nature of the meaning string that they generate. The test here is
+% almost the same as \cs{tl_if_empty:nTF}, but has to be hard-coded as
+% that function is not yet available and because it has to match both
+% long and short macros.
+% \begin{macrocode}
+\group_begin:
+ \tex_lccode:D `\Z = `\d \scan_stop:
+ \tex_lccode:D `\? =`\\ \scan_stop:
+ \tex_catcode:D `\P = 12 \scan_stop:
+ \tex_catcode:D `\R = 12 \scan_stop:
+ \tex_catcode:D `\O = 12 \scan_stop:
+ \tex_catcode:D `\T = 12 \scan_stop:
+ \tex_catcode:D `\E = 12 \scan_stop:
+ \tex_catcode:D `\C = 12 \scan_stop:
+ \tex_catcode:D `\Z = 12 \scan_stop:
+\tex_lowercase:D
+ {
+ \group_end:
+ \cs_new_nopar:Npn \cs_generate_variant_aux:NNpx #1
+ {
+ \exp_after:wN \cs_generate_variant_aux:w
+ \token_to_meaning:N #1 ? PROTECTEZ \q_stop
+ }
+ \cs_new:Npn \cs_generate_variant_aux:w #1 ? PROTECTEZ #2 \q_stop
+ {
+ \if_catcode:w a \etex_detokenize:D \exp_after:wN {#1} a
+ \exp_after:wN \cs_new_protected_nopar:Npx
+ \else:
+ \exp_after:wN \cs_new_nopar:Npx
+ \fi:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]{\cs_generate_internal_variant:n}
+% \begin{macro}[aux]{\cs_generate_internal_variant_aux:N}
+% Test if |exp_args:N #1| is already defined
+% and if not define it via the
+% |\::| commands using the chars in |#1|
+% \begin{macrocode}
+\cs_new_protected:Npn \cs_generate_internal_variant:n #1
+ {
+ \cs_if_free:cT { exp_args:N #1 }
+ {
+ \cs_new:cpx { exp_args:N #1 }
+ { \cs_generate_internal_variant_aux:N #1 : }
+ }
+ }
+% \end{macrocode}
+% This command grabs char by char outputting |\::#1| (not expanded
+% further) until we see a |:|. That colon is in fact also turned into
+% |\:::| so that the required structure for |\exp_args...| commands
+% is correctly terminated.
+% \begin{macrocode}
+\cs_new:Npn \cs_generate_internal_variant_aux:N #1
+ {
+ \exp_not:c { :: #1 }
+ \if_meaning:w #1 :
+ \exp_after:wN \use_none:n
+ \fi:
+ \cs_generate_internal_variant_aux:N
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%\subsection{Variants which cannot be created earlier}
+%
+% \begin{macro}[pTF]
+% {\str_if_eq:Vn, \str_if_eq:on, \str_if_eq:nV, \str_if_eq:no, \str_if_eq:VV}
+% These cannot come earlier as they need \cs{cs_generate_variant:Nn}.
+% \begin{macrocode}
+\cs_generate_variant:Nn \str_if_eq_p:nn { V , o }
+\cs_generate_variant:Nn \str_if_eq_p:nn { nV , no , VV }
+\cs_generate_variant:Nn \str_if_eq:nnT { V , o }
+\cs_generate_variant:Nn \str_if_eq:nnT { nV , no , VV }
+\cs_generate_variant:Nn \str_if_eq:nnF { V , o }
+\cs_generate_variant:Nn \str_if_eq:nnF { nV , no , VV }
+\cs_generate_variant:Nn \str_if_eq:nnTF { V , o }
+\cs_generate_variant:Nn \str_if_eq:nnTF { nV , no , VV }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex