% \iffalse meta-comment
%
%% File: l3candidates.dtx
%
% Copyright (C) 2012-2023 The LaTeX 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
%
%    https://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,kernel]{l3doc}
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
% \title{^^A
%   The \textsf{l3candidates} package\\ Experimental additions to
%   \pkg{l3kernel}^^A
% }
%
% \author{^^A
%  The \LaTeX{} Project\thanks
%    {^^A
%      E-mail:
%        \href{mailto:latex-team@latex-project.org}
%          {latex-team@latex-project.org}^^A
%    }^^A
% }
%
% \date{Released 2023-02-07}
%
% \maketitle
%
% \begin{documentation}
%
% \section{Important notice}
%
% This module provides a space in which functions can be added to
% \pkg{l3kernel} (\pkg{expl3}) while still being experimental.
% \begin{quote}
%  \bfseries
% As such, the
% functions here may not remain in their current form, or indeed at all,
% in \pkg{l3kernel} in the future.
% \end{quote}
%  In contrast to the material in
% \pkg{l3experimental}, the functions here are all \emph{small} additions to
% the kernel. We encourage programmers to test them out and report back on
% the \texttt{LaTeX-L} mailing list.
%
% \medskip
%
%   Thus, if you intend to use any of these functions from the candidate module in a public package
%  offered to others for productive use (e.g., being placed on CTAN) please consider the following points carefully:
% \begin{itemize}
% \item Be prepared that your public packages might require updating when such functions
%        are being finalized.
% \item Consider informing us that you use a particular function in your public package, e.g., by
%         discussing this on the \texttt{LaTeX-L}
%    mailing list. This way it becomes easier to coordinate any updates necessary without issues
%    for the users of your package.
% \item Discussing and understanding use cases for a particular addition or concept also helps to
%         ensure that we provide the right interfaces in the final version so please give us feedback
%         if you consider a certain candidate function useful (or not).
% \end{itemize}
% We only add functions in this space if we consider them being serious candidates for a final inclusion
% into the kernel. However, real use sometimes leads to better ideas, so functions from this module are
% \textbf{not necessarily stable} and we may have to adjust them!
%
% \section{Additions to \pkg{l3box}}
%
% \begin{function}[updated = 2019-01-23]
%   {\box_clip:N, \box_clip:c, \box_gclip:N, \box_gclip:c}
%   \begin{syntax}
%     \cs{box_clip:N} \meta{box}
%   \end{syntax}
%   Clips the \meta{box} in the output so that only material inside the
%   bounding box is displayed in the output. The updated \meta{box} is an
%   hbox, irrespective of the nature of the \meta{box} before the clipping is
%   applied.
%
%   \textbf{These functions require the \LaTeX3 native drivers: they do
%   not work with the \LaTeXe{} \pkg{graphics} drivers!}
%
%   \begin{texnote}
%     Clipping is implemented by the driver, and as such the full content of
%     the box is placed in the output file. Thus clipping does not remove
%     any information from the raw output, and hidden material can therefore
%     be viewed by direct examination of the file.
%   \end{texnote}
% \end{function}
%
% \begin{function}[added = 2019-01-23]
%   {
%     \box_set_trim:Nnnnn, \box_set_trim:cnnnn,
%     \box_gset_trim:Nnnnn, \box_gset_trim:cnnnn
%   }
%   \begin{syntax}
%     \cs{box_set_trim:Nnnnn} \meta{box} \Arg{left} \Arg{bottom} \Arg{right} \Arg{top}
%   \end{syntax}
%   Adjusts the bounding box of the \meta{box} \meta{left} is removed from
%   the left-hand edge of the bounding box, \meta{right} from the right-hand
%   edge and so fourth. All adjustments are \meta{dimension expressions}.
%   Material outside of the bounding box is still displayed in the output
%   unless \cs{box_clip:N} is subsequently applied.
%   The updated \meta{box} is an
%   hbox, irrespective of the nature of the \meta{box} before the trim
%   operation is applied.
%   The behavior of the operation where the trims requested is
%   greater than the size of the box is undefined.
% \end{function}
%
% \begin{function}[added = 2019-01-23]
%   {
%     \box_set_viewport:Nnnnn, \box_set_viewport:cnnnn,
%     \box_gset_viewport:Nnnnn, \box_gset_viewport:cnnnn
%   }
%   \begin{syntax}
%     \cs{box_set_viewport:Nnnnn} \meta{box} \Arg{llx} \Arg{lly} \Arg{urx} \Arg{ury}
%   \end{syntax}
%   Adjusts the bounding box of the \meta{box} such that it has lower-left
%   co-ordinates (\meta{llx}, \meta{lly}) and upper-right co-ordinates
%   (\meta{urx}, \meta{ury}). All four co-ordinate positions are
%   \meta{dimension expressions}. Material outside of the bounding box is
%   still displayed in the output unless \cs{box_clip:N} is
%   subsequently applied.
%   The updated \meta{box} is an
%   hbox, irrespective of the nature of the \meta{box} before the viewport
%   operation is applied.
% \end{function}
%
% \section{Additions to \pkg{l3expan}}
%
% \begin{function}[added = 2018-04-04, updated = 2019-02-08]
%   {\exp_args_generate:n}
%   \begin{syntax}
%     \cs{exp_args_generate:n} \Arg{variant argument specifiers}
%   \end{syntax}
%   Defines \cs[no-index]{exp_args:N\meta{variant}} functions for each
%   \meta{variant} given in the comma list \Arg{variant argument
%   specifiers}.  Each \meta{variant} should consist of the letters |N|,
%   |c|, |n|, |V|, |v|, |o|, |f|, |e|, |x|, |p| and the resulting function is
%   protected if the letter |x| appears in the \meta{variant}.  This is
%   only useful for cases where \cs{cs_generate_variant:Nn} is not
%   applicable.
% \end{function}
%
% \section{Additions to \pkg{l3fp}}
%
% \begin{function}[pTF, added = 2019-08-25]{\fp_if_nan:n}
%   \begin{syntax}
%     \cs{fp_if_nan:n} \Arg{fpexpr}
%   \end{syntax}
%   Evaluates the \meta{fpexpr} and tests whether the result is exactly
%   \nan{}.  The test returns \texttt{false} for any other result, even
%   a tuple containing \nan{}.
% \end{function}
%
% \section{Additions to \pkg{l3file}}
%
% \begin{function}[added = 2018-12-29]{\iow_allow_break:}
%   \begin{syntax}
%     \cs{iow_allow_break:}
%   \end{syntax}
%   In the first argument of \cs{iow_wrap:nnnN} (for instance in
%   messages), inserts a break-point that allows a line break.
%   In other words this is a zero-width breaking space.
% \end{function}
%
% \begin{function}[added = 2019-03-23]{\ior_get_term:nN, \ior_str_get_term:nN}
%   \begin{syntax}
%     \cs{ior_get_term:nN} \meta{prompt} \meta{token list variable}
%   \end{syntax}
%   Function that reads one or more lines (until an equal number of left
%   and right braces are found) from the terminal and stores
%   the result locally in the \meta{token list} variable. Tokenization
%   occurs as described for \cs{ior_get:NN} or \cs{ior_str_get:NN}, respectively.
%   When the \meta{prompt}
%   is empty, \TeX{} will wait for input without any other indication:
%   typically the programmer will have provided a suitable text using
%   e.g.~\cs{iow_term:n}. Where the \meta{prompt} is given, it will appear
%   in the terminal followed by an |=|, e.g.
%   \begin{verbatim}
%     prompt=
%   \end{verbatim}
% \end{function}
%
% \begin{function}[added = 2019-05-08]{\ior_shell_open:Nn}
%   \begin{syntax}
%     \cs{ior_shell_open:Nn} \meta{stream} \Arg{shell~command}
%   \end{syntax}
%   Opens the \emph{pseudo}-file created by the output of the
%   \meta{shell command} for reading using \meta{stream} as the
%   control sequence for access. If the \meta{stream} was already
%   open it is closed before the new operation begins. The
%   \meta{stream} is available for access immediately and will remain
%   allocated to \meta{shell command} until a \cs{ior_close:N} instruction
%   is given or the \TeX{} run ends.
%   If piped system calls are disabled an error is raised.
%
%   For details of handling of the \meta{shell command}, see
%   \cs{sys_get_shell:nnNTF}.
% \end{function}
%
% \section{Additions to \pkg{l3flag}}
%
% \begin{function}[EXP, added = 2018-04-02]{\flag_raise_if_clear:n}
%   \begin{syntax}
%     \cs{flag_raise_if_clear:n} \Arg{flag name}
%   \end{syntax}
%   Ensures the \meta{flag} is raised by making its height at least~$1$,
%   locally.
% \end{function}
%
% \section{Additions to \pkg{l3intarray}}
%
% \begin{function}[added = 2018-05-05]
%   {
%     \intarray_gset_rand:Nnn, \intarray_gset_rand:cnn,
%     \intarray_gset_rand:Nn, \intarray_gset_rand:cn
%   }
%   \begin{syntax}
%     \cs{intarray_gset_rand:Nnn} \meta{intarray~var} \Arg{minimum} \Arg{maximum}
%     \cs{intarray_gset_rand:Nn} \meta{intarray~var} \Arg{maximum}
%   \end{syntax}
%   Evaluates the integer expressions \meta{minimum} and \meta{maximum}
%   then sets each entry (independently) of the \meta{integer array
%   variable} to a pseudo-random number between the two (with bounds
%   included).  If the absolute value of either bound is bigger than
%   $2^{30}-1$, an error occurs.  Entries are generated in the same way
%   as repeated calls to \cs{int_rand:nn} or \cs{int_rand:n}
%   respectively, in particular for the second function the
%   \meta{minimum} is $1$.
%   Assignments are always global.
%   This is not available in older versions of \XeTeX{}.
% \end{function}
%
% \begin{function}[added = 2018-05-04, rEXP]{\intarray_to_clist:N}
%   \begin{syntax}
%     \cs{intarray_to_clist:N} \meta{intarray~var}
%   \end{syntax}
%   Converts the \meta{intarray} to integer denotations separated by
%   commas.  All tokens have category code other.  If the
%   \meta{intarray} has no entry the result is empty; otherwise the
%   result has one fewer comma than the number of items.
% \end{function}
%
% \section{Additions to \pkg{l3msg}}
%
% \begin{function}[added = 2017-12-04]{\msg_show_eval:Nn, \msg_log_eval:Nn}
%   \begin{syntax}
%     \cs{msg_show_eval:Nn} \meta{function} \Arg{expression}
%   \end{syntax}
%   Shows or logs the \meta{expression} (turned into a string), an equal
%   sign, and the result of applying the \meta{function} to the
%   \Arg{expression} (with \texttt{f}-expansion).  For instance, if the
%   \meta{function} is \cs{int_eval:n} and the \meta{expression} is
%   |1+2| then this logs |> 1+2=3.|
% \end{function}
%
% \begin{function}[EXP, added = 2017-12-04]
%   {\msg_show_item:n, \msg_show_item_unbraced:n, \msg_show_item:nn, \msg_show_item_unbraced:nn}
%   \begin{syntax}
%     \cs{seq_map_function:NN} \meta{seq} \cs{msg_show_item:n}
%     \cs{prop_map_function:NN} \meta{prop} \cs{msg_show_item:nn}
%   \end{syntax}
%   Used in the text of messages for \cs{msg_show:nnxxxx} to show or log
%   a list of items or key--value pairs.  The one-argument functions are
%   used for sequences, clist or token lists and the others for property
%   lists.  These functions turn their arguments to strings.
% \end{function}
%
% \section{Additions to \pkg{l3prg}}
%
% \begin{function}[added = 2018-05-10]
%   {
%     \bool_set_inverse:N , \bool_set_inverse:c ,
%     \bool_gset_inverse:N, \bool_gset_inverse:c
%   }
%   \begin{syntax}
%     \cs{bool_set_inverse:N} \meta{boolean}
%   \end{syntax}
%   Toggles the \meta{boolean} from \texttt{true} to \texttt{false} and
%   conversely: sets it to the inverse of its current value.
% \end{function}
%
% \begin{function}[added = 2019-02-10, EXP, noTF]
%   {\bool_case_true:n, \bool_case_false:n}
%   \begin{syntax}
%     \cs{bool_case_true:nTF} \\
%     ~~|{| \\
%     ~~~~\Arg{boolexpr case_1} \Arg{code case_1} \\
%     ~~~~\Arg{boolexpr case_2} \Arg{code case_2} \\
%     ~~~~\ldots \\
%     ~~~~\Arg{boolexpr case_n} \Arg{code case_n} \\
%     ~~|}| \\
%     ~~\Arg{true code}
%     ~~\Arg{false code}
%   \end{syntax}
%   Evaluates in turn each of the \meta{boolean expression cases} until
%   the first one that evaluates to \texttt{true} or to \texttt{false},
%   for \cs{bool_case_true:n} and \cs{bool_case_false:n}, respectively.
%   The \meta{code} associated to this first case is left in the input
%   stream, followed by the \meta{true code}, and other cases are
%   discarded.  If none of the cases match then only the \meta{false
%   code} is inserted. The functions \cs{bool_case_true:n} and
%   \cs{bool_case_false:n}, which do nothing if there is no match, are
%   also available. For example
%   \begin{verbatim}
%     \bool_case_true:nF
%       {
%         { \dim_compare_p:n { \l__mypkg_wd_dim <= 10pt } }
%             { Fits }
%         { \int_compare_p:n { \l__mypkg_total_int >= 10 } }
%             { Many }
%         { \l__mypkg_special_bool }
%             { Special }
%       }
%       { No idea! }
%   \end{verbatim}
%   leaves \enquote{\texttt{Fits}} or \enquote{\texttt{Many}} or
%   \enquote{\texttt{Special}} or \enquote{\texttt{No idea!}} in the
%   input stream, in a way similar to some other language's
%   \enquote{\texttt{if} \ldots\ \texttt{elseif} \ldots\ \texttt{elseif} \ldots\
%   \texttt{else} \ldots}.
% \end{function}
%
% \section{Additions to \pkg{l3prop}}
%
% \begin{function}[EXP, added = 2016-12-06]
%   {\prop_rand_key_value:N, \prop_rand_key_value:c}
%   \begin{syntax}
%     \cs{prop_rand_key_value:N} \meta{property list}
%   \end{syntax}
%   Selects a pseudo-random key--value pair from the \meta{property list}
%   and returns \Arg{key} and \Arg{value}.  If the \meta{property list} is
%   empty the result is empty.
%   This is not available in older versions of \XeTeX{}.
%   \begin{texnote}
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the \meta{value}
%     does not expand further when appearing in an \texttt{x}-type
%     or \texttt{e}-type argument expansion.
%   \end{texnote}
% \end{function}
%
% \section{Additions to \pkg{l3seq}}
%
% \begin{function}[rEXP]
%   {
%     \seq_mapthread_function:NNN, \seq_mapthread_function:NcN,
%     \seq_mapthread_function:cNN, \seq_mapthread_function:ccN
%   }
%   \begin{syntax}
%     \cs{seq_mapthread_function:NNN} \meta{seq_1} \meta{seq_2} \meta{function}
%   \end{syntax}
%   Applies \meta{function} to every pair of items
%   \meta{seq_1-item}--\meta{seq_2-item} from the two sequences, returning
%   items from both sequences from left to right.   The \meta{function}
%   receives two \texttt{n}-type arguments for each iteration. The  mapping
%   terminates when
%   the end of either sequence is reached (\emph{i.e.}~whichever sequence has
%   fewer items determines how many iterations
%   occur).
% \end{function}
%
% \begin{function}{\seq_set_filter:NNn, \seq_gset_filter:NNn}
%   \begin{syntax}
%     \cs{seq_set_filter:NNn} \meta{sequence_1} \meta{sequence_2} \Arg{inline boolexpr}
%   \end{syntax}
%   Evaluates the \meta{inline boolexpr} for every \meta{item} stored
%   within the \meta{sequence_2}. The \meta{inline boolexpr}
%   receives the \meta{item} as |#1|. The sequence of all \meta{items}
%   for which the \meta{inline boolexpr} evaluated to \texttt{true}
%   is assigned to \meta{sequence_1}.
%   \begin{texnote}
%     Contrarily to other mapping functions, \cs{seq_map_break:} cannot
%     be used in this function, and would lead to low-level \TeX{} errors.
%   \end{texnote}
% \end{function}
%
% \begin{function}[added = 2018-04-06]
%   {\seq_set_from_function:NnN, \seq_gset_from_function:NnN}
%   \begin{syntax}
%     \cs{seq_set_from_function:NnN} \meta{seq~var} \Arg{loop~code} \meta{function}
%   \end{syntax}
%   Sets the \meta{seq~var} equal to a sequence whose items are obtained
%   by \texttt{x}-expanding \meta{loop~code} \meta{function}.  This
%   expansion must result in successive calls to the \meta{function}
%   with no nonexpandable tokens in between.  More precisely the
%   \meta{function} is replaced by a wrapper function that inserts the
%   appropriate separators between items in the sequence.  The
%   \meta{loop~code} must be expandable; it can be for example
%   \cs{tl_map_function:NN} \meta{tl~var} or \cs{clist_map_function:nN}
%   \Arg{clist} or \cs{int_step_function:nnnN} \Arg{initial value}
%   \Arg{step} \Arg{final value}.
% \end{function}
%
% \begin{function}[added = 2018-04-06]
%   {\seq_set_from_inline_x:Nnn, \seq_gset_from_inline_x:Nnn}
%   \begin{syntax}
%     \cs{seq_set_from_inline_x:Nnn} \meta{seq~var} \Arg{loop~code} \Arg{inline~code}
%   \end{syntax}
%   Sets the \meta{seq~var} equal to a sequence whose items are obtained
%   by \texttt{x}-expanding \meta{loop~code} applied to a
%   \meta{function} derived from the \meta{inline~code}.  A
%   \meta{function} is defined, that takes one argument,
%   \texttt{x}-expands the \meta{inline~code} with that argument
%   as~|#1|, then adds appropriate separators to turn the result into an
%   item of the sequence.  The \texttt{x}-expansion of \meta{loop~code}
%   \meta{function} must result in successive calls to the
%   \meta{function} with no nonexpandable tokens in between.  The
%   \meta{loop~code} must be expandable; it can be for example
%   \cs{tl_map_function:NN} \meta{tl~var} or \cs{clist_map_function:nN}
%   \Arg{clist} or \cs{int_step_function:nnnN} \Arg{initial value}
%   \Arg{step} \Arg{final value}, but not the analogous \enquote{inline}
%   mappings.
% \end{function}
%
% \begin{function}[added = 2021-04-29, noTF]
%   {\seq_set_item:Nnn, \seq_set_item:cnn, \seq_gset_item:Nnn, \seq_gset_item:cnn}
%   \begin{syntax}
%     \cs{seq_set_item:Nnn} \meta{seq~var} \Arg{intexpr} \Arg{item}
%     \cs{seq_set_item:NnnTF} \meta{seq~var} \Arg{intexpr} \Arg{item} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Removes the item of \meta{sequence} at the position given by
%   evaluating the \meta{integer expression} and replaces it by
%   \meta{item}.  Items are indexed from $1$ on the left/top of the
%   \meta{sequence}, or from $-1$ on the right/bottom.  If the
%   \meta{integer expression} is zero or is larger (in absolute value)
%   than the number of items in the sequence, the \meta{sequence} is not
%   modified.  In these cases, \cs{seq_set_item:Nnn} raises an error
%   while \cs{seq_set_item:NnnTF} runs the \meta{false code}.  In cases
%   where the assignment was successful, \meta{true code} is run
%   afterwards.
% \end{function}
%
% \begin{function}[added = 2021-04-28, noTF]
%   {\seq_pop_item:NnN, \seq_pop_item:cnN, \seq_gpop_item:NnN, \seq_gpop_item:cnN}
%   \begin{syntax}
%     \cs{seq_pop_item:NnN} \meta{seq~var} \Arg{intexpr} \Arg{tl~var}
%     \cs{seq_pop_item:NnNTF} \meta{seq~var} \Arg{intexpr} \Arg{tl~var} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Removes the \meta{item} at position \meta{integer expression} in the
%   \meta{sequence}, and places it in the \meta{token list variable}.
%   Items are indexed from $1$ on the left/top of the \meta{sequence},
%   or from $-1$ on the right/bottom.  If the position is zero or is
%   larger (in absolute value) than the number of items in the sequence,
%   the \meta{seq~var} is not modified, the \meta{token list} is set to
%   the special marker \cs{q_no_value}, and the \meta{false code} is
%   left in the input stream; otherwise the \meta{true code} is.  The
%   \meta{token list} assignment is local while the \meta{sequence} is
%   assigned locally for |pop| or globally for |gpop| functions.
% \end{function}
%
% \section{Additions to \pkg{l3sys}}
%
% \begin{variable}[added = 2018-05-02]{\c_sys_engine_version_str}
%   The version string of the current engine, in the same form as
%   given in the banner issued when running a job. For \pdfTeX{}
%   and \LuaTeX{} this is of the form
%   \begin{quote}
%     \meta{major}.\meta{minor}.\meta{revision}
%   \end{quote}
%   For \XeTeX{}, the form is
%   \begin{quote}
%     \meta{major}.\meta{minor}
%   \end{quote}
%   For \pTeX{} and \upTeX{}, only releases since \TeX{} Live 2018
%   make the data available, and the form is more complex, as it comprises
%   the \pTeX{} version, the \upTeX{} version and the e-\pTeX{} version.
%   \begin{quote}
%     p\meta{major}.\meta{minor}.\meta{revision}-u\meta{major}.\meta{minor}^^A
%     -\meta{epTeX}
%   \end{quote}
%   where the |u| part is only present for \upTeX{}.
% \end{variable}
%
% \begin{function}[added = 2017-05-27, EXP, pTF]{\sys_if_rand_exist:}
%   \begin{syntax}
%     \cs{sys_if_rand_exist_p:}
%     \cs{sys_if_rand_exist:TF} \Arg{true code} \Arg{false code}
%   \end{syntax}
%   Tests if the engine has a pseudo-random number generator.  Currently
%   this is the case in \pdfTeX{}, \LuaTeX{}, \pTeX{}, \upTeX{} and recent
%   releases of \XeTeX{}.
% \end{function}
%
% \section{Additions to \pkg{l3tl}}
%
% \begin{function}[EXP, added = 2017-07-15]
%   {
%     \tl_range_braced:Nnn, \tl_range_braced:cnn, \tl_range_braced:nnn,
%     \tl_range_unbraced:Nnn, \tl_range_unbraced:cnn, \tl_range_unbraced:nnn
%   }
%   \begin{syntax}
%     \cs{tl_range_braced:Nnn} \meta{tl~var} \Arg{start index} \Arg{end index}
%     \cs{tl_range_braced:nnn} \Arg{token list} \Arg{start index} \Arg{end index}
%     \cs{tl_range_unbraced:Nnn} \meta{tl~var} \Arg{start index} \Arg{end index}
%     \cs{tl_range_unbraced:nnn} \Arg{token list} \Arg{start index} \Arg{end index}
%   \end{syntax}
%   Leaves in the input stream the items from the \meta{start index} to
%   the \meta{end index} inclusive, using the same indexing as
%   \cs{tl_range:nnn}.  Spaces are ignored.  Regardless of whether items
%   appear with or without braces in the \meta{token list}, the
%   \cs{tl_range_braced:nnn} function wraps each item in braces, while
%   \cs{tl_range_unbraced:nnn} does not (overall it removes an outer set
%   of braces).  For instance,
%   \begin{verbatim}
%     \iow_term:x { \tl_range_braced:nnn { abcd~{e{}}f } { 2 } { 5 } }
%     \iow_term:x { \tl_range_braced:nnn { abcd~{e{}}f } { -4 } { -1 } }
%     \iow_term:x { \tl_range_braced:nnn { abcd~{e{}}f } { -2 } { -1 } }
%     \iow_term:x { \tl_range_braced:nnn { abcd~{e{}}f } { 0 } { -1 } }
%   \end{verbatim}
%   prints \verb*|{b}{c}{d}{e{}}|, \verb*|{c}{d}{e{}}{f}|, \verb*|{e{}}{f}|, and an empty
%   line to the terminal, while
%   \begin{verbatim}
%     \iow_term:x { \tl_range_unbraced:nnn { abcd~{e{}}f } { 2 } { 5 } }
%     \iow_term:x { \tl_range_unbraced:nnn { abcd~{e{}}f } { -4 } { -1 } }
%     \iow_term:x { \tl_range_unbraced:nnn { abcd~{e{}}f } { -2 } { -1 } }
%     \iow_term:x { \tl_range_unbraced:nnn { abcd~{e{}}f } { 0 } { -1 } }
%   \end{verbatim}
%   prints \verb*|bcde{}|, \verb*|cde{}f|, \verb*|e{}f|, and an empty
%   line to the terminal.  Because braces are removed, the result of
%   \cs{tl_range_unbraced:nnn} may have a different number of items as
%   for \cs{tl_range:nnn} or \cs{tl_range_braced:nnn}.  In cases where
%   preserving spaces is important, consider the slower function
%   \cs{tl_range:nnn}.
%   \begin{texnote}
%     The result is returned within the \tn{unexpanded}
%     primitive (\cs{exp_not:n}), which means that the \meta{item}
%     does not expand further when appearing in an \texttt{x}-type
%     or \texttt{e}-type argument expansion.
%   \end{texnote}
% \end{function}
%
% \begin{function}[added = 2018-04-01]{\tl_build_begin:N, \tl_build_gbegin:N}
%   \begin{syntax}
%     \cs{tl_build_begin:N} \meta{tl~var}
%   \end{syntax}
%   Clears the \meta{tl~var} and sets it up to support other
%   \cs[no-index]{tl_build_\ldots{}} functions, which allow accumulating
%   large numbers of tokens piece by piece much more efficiently than
%   standard \pkg{l3tl} functions.  Until \cs{tl_build_end:N}
%   \meta{tl~var} is called, applying any function from \pkg{l3tl} other
%   than \cs[no-index]{tl_build_\ldots{}} will lead to incorrect
%   results.  The |begin| and |gbegin| functions must be used for local
%   and global \meta{tl~var} respectively.
% \end{function}
%
% \begin{function}[added = 2018-04-01]{\tl_build_clear:N, \tl_build_gclear:N}
%   \begin{syntax}
%     \cs{tl_build_clear:N} \meta{tl~var}
%   \end{syntax}
%   Clears the \meta{tl~var} and sets it up to support other
%   \cs[no-index]{tl_build_\ldots{}} functions.  The |clear| and
%   |gclear| functions must be used for local and global \meta{tl~var}
%   respectively.
% \end{function}
%
% \begin{function}[added = 2018-04-01]
%   {
%     \tl_build_put_left:Nn, \tl_build_put_left:Nx,
%     \tl_build_gput_left:Nn, \tl_build_gput_left:Nx,
%     \tl_build_put_right:Nn, \tl_build_put_right:Nx,
%     \tl_build_gput_right:Nn, \tl_build_gput_right:Nx,
%   }
%   \begin{syntax}
%     \cs{tl_build_put_left:Nn} \meta{tl~var} \Arg{tokens}
%     \cs{tl_build_put_right:Nn} \meta{tl~var} \Arg{tokens}
%   \end{syntax}
%   Adds \meta{tokens} to the left or right side of the current contents
%   of \meta{tl~var}.  The \meta{tl~var} must have been set up with
%   \cs{tl_build_begin:N} or \cs{tl_build_gbegin:N}.  The |put| and
%   |gput| functions must be used for local and global \meta{tl~var}
%   respectively.  The |right| functions are about twice faster than the
%   |left| functions.
% \end{function}
%
% \begin{function}[added = 2018-04-01]{\tl_build_get:NN}
%   \begin{syntax}
%     \cs{tl_build_get:NN} \meta{tl~var_1} \meta{tl~var_2}
%   \end{syntax}
%   Stores the contents of the \meta{tl~var_1} in the \meta{tl~var_2}.
%   The \meta{tl~var_1} must have been set up with \cs{tl_build_begin:N}
%   or \cs{tl_build_gbegin:N}.  The \meta{tl~var_2} is a
%   \enquote{normal} token list variable, assigned locally using
%   \cs{tl_set:Nn}.
% \end{function}
%
% \begin{function}[added = 2018-04-01]{\tl_build_end:N, \tl_build_gend:N}
%   \begin{syntax}
%     \cs{tl_build_end:N} \meta{tl~var}
%   \end{syntax}
%   Gets the contents of \meta{tl~var} and stores that into the
%   \meta{tl~var} using \cs{tl_set:Nn} or \cs{tl_gset:Nn}.
%   The \meta{tl~var} must have
%   been set up with \cs{tl_build_begin:N} or \cs{tl_build_gbegin:N}.
%   The |end| and |gend| functions must be used for local and global
%   \meta{tl~var} respectively.  These functions completely remove the
%   setup code that enabled \meta{tl~var} to be used for other
%   \cs[no-index]{tl_build_\ldots{}} functions.
% \end{function}
%
% \section{Additions to \pkg{l3token}}
%
% \begin{variable}[added = 2017-08-07]{\c_catcode_active_space_tl}
%   Token list containing one character with category code $13$,
%   (\enquote{active}), and character code $32$ (space).
% \end{variable}
%
% \begin{function}[added = 2018-09-23]
%   {
%     \peek_catcode_collect_inline:Nn,
%     \peek_charcode_collect_inline:Nn,
%     \peek_meaning_collect_inline:Nn
%   }
%   \begin{syntax}
%     \cs{peek_catcode_collect_inline:Nn} \meta{test token} \Arg{inline code}
%     \cs{peek_charcode_collect_inline:Nn} \meta{test token} \Arg{inline code}
%     \cs{peek_meaning_collect_inline:Nn} \meta{test token} \Arg{inline code}
%   \end{syntax}
%   Collects and removes tokens from the input stream until finding a
%   token that does not match the \meta{test token} (as defined by the
%   test \cs{token_if_eq_catcode:NNTF} or \cs{token_if_eq_charcode:NNTF}
%   or \cs{token_if_eq_meaning:NNTF}).  The collected tokens are passed
%   to the \meta{inline code} as~|#1|.  When begin-group or end-group
%   tokens (usually |{| or~|}|) are collected they are replaced by
%   implicit \cs{c_group_begin_token} and \cs{c_group_end_token}, and
%   when spaces (including \cs{c_space_token}) are collected they are
%   replaced by explicit spaces.
%
%   For example the following code prints ``Hello'' to the terminal and
%   leave ``, world!'' in the input stream.
% \begin{verbatim}
% \peek_catcode_collect_inline:Nn A { \iow_term:n {#1} } Hello,~world!
% \end{verbatim}
%   Another example is that the following code tests if the next token is |*|, ignoring intervening spaces, but putting them back using |#1| if there is no~|*|.
% \begin{verbatim}
% \peek_meaning_collect_inline:Nn \c_space_token
%   { \peek_charcode:NTF * { star } { no~star #1 } }
% \end{verbatim}
% \end{function}
%
% \end{documentation}
%
% \begin{implementation}
%
% \section{\pkg{l3candidates} implementation}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
% \subsection{Additions to \pkg{l3box}}
%
%    \begin{macrocode}
%<@@=box>
%    \end{macrocode}
%
% \subsubsection{Viewing part of a box}
%
% \begin{macro}{\box_clip:N, \box_clip:c, \box_gclip:N, \box_gclip:c}
%   A wrapper around the driver-dependent code.
%    \begin{macrocode}
\cs_new_protected:Npn \box_clip:N #1
  { \hbox_set:Nn #1 { \@@_backend_clip:N #1 } }
\cs_generate_variant:Nn \box_clip:N { c }
\cs_new_protected:Npn \box_gclip:N #1
  { \hbox_gset:Nn #1 { \@@_backend_clip:N #1 } }
\cs_generate_variant:Nn \box_gclip:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \box_set_trim:Nnnnn, \box_set_trim:cnnnn,
%     \box_gset_trim:Nnnnn, \box_gset_trim:cnnnn
%   }
% \begin{macro}{\@@_set_trim:NnnnnN}
%   Trimming from the left- and right-hand edges of the box is easy: kern the
%   appropriate parts off each side.
%    \begin{macrocode}
\cs_new_protected:Npn \box_set_trim:Nnnnn #1#2#3#4#5
  { \@@_set_trim:NnnnnN #1 {#2} {#3} {#4} {#5} \box_set_eq:NN }
\cs_generate_variant:Nn \box_set_trim:Nnnnn { c }
\cs_new_protected:Npn \box_gset_trim:Nnnnn #1#2#3#4#5
  { \@@_set_trim:NnnnnN #1 {#2} {#3} {#4} {#5} \box_gset_eq:NN }
\cs_generate_variant:Nn \box_gset_trim:Nnnnn { c }
\cs_new_protected:Npn \@@_set_trim:NnnnnN #1#2#3#4#5#6
  {
    \hbox_set:Nn \l_@@_internal_box
      {
        \__kernel_kern:n { -#2 }
        \box_use:N #1
        \__kernel_kern:n { -#4 }
      }
%    \end{macrocode}
%   For the height and depth, there is a need to watch the baseline is
%   respected. Material always has to stay on the correct side, so trimming
%   has to check that there is enough material to trim. First, the bottom
%   edge. If there is enough depth, simply set the depth, or if not move
%   down so the result is zero depth. \cs{box_move_down:nn} is used in both
%   cases so the resulting box always contains a \tn{lower} primitive.
%   The internal box is used here as it allows safe use of \cs{box_set_dp:Nn}.
%    \begin{macrocode}
    \dim_compare:nNnTF { \box_dp:N #1 } > {#3}
      {
        \hbox_set:Nn \l_@@_internal_box
          {
            \box_move_down:nn \c_zero_dim
              { \box_use_drop:N \l_@@_internal_box }
          }
        \box_set_dp:Nn \l_@@_internal_box { \box_dp:N #1 - (#3) }
      }
      {
        \hbox_set:Nn \l_@@_internal_box
          {
            \box_move_down:nn { (#3) - \box_dp:N #1 }
              { \box_use_drop:N \l_@@_internal_box }
          }
        \box_set_dp:Nn \l_@@_internal_box \c_zero_dim
      }
%    \end{macrocode}
%   Same thing, this time from the top of the box.
%    \begin{macrocode}
    \dim_compare:nNnTF { \box_ht:N \l_@@_internal_box } > {#5}
      {
        \hbox_set:Nn \l_@@_internal_box
          {
            \box_move_up:nn \c_zero_dim
              { \box_use_drop:N \l_@@_internal_box }
          }
        \box_set_ht:Nn \l_@@_internal_box
          { \box_ht:N \l_@@_internal_box - (#5) }
      }
      {
        \hbox_set:Nn \l_@@_internal_box
          {
            \box_move_up:nn { (#5) - \box_ht:N \l_@@_internal_box }
              { \box_use_drop:N \l_@@_internal_box }
          }
        \box_set_ht:Nn \l_@@_internal_box \c_zero_dim
      }
    #6 #1 \l_@@_internal_box
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}
%   {
%     \box_set_viewport:Nnnnn, \box_set_viewport:cnnnn,
%     \box_gset_viewport:Nnnnn, \box_gset_viewport:cnnnn
%   }
% \begin{macro}{\@@_viewport:NnnnnN}
%   The same general logic as for the trim operation, but with absolute
%   dimensions. As a result, there are some things to watch out for in the
%   vertical direction.
%    \begin{macrocode}
\cs_new_protected:Npn \box_set_viewport:Nnnnn #1#2#3#4#5
  { \@@_set_viewport:NnnnnN #1 {#2} {#3} {#4} {#5} \box_set_eq:NN }
\cs_generate_variant:Nn \box_set_viewport:Nnnnn { c }
\cs_new_protected:Npn \box_gset_viewport:Nnnnn #1#2#3#4#5
  { \@@_set_viewport:NnnnnN #1 {#2} {#3} {#4} {#5} \box_gset_eq:NN }
\cs_generate_variant:Nn \box_gset_viewport:Nnnnn { c }
\cs_new_protected:Npn \@@_set_viewport:NnnnnN #1#2#3#4#5#6
  {
    \hbox_set:Nn \l_@@_internal_box
      {
        \__kernel_kern:n { -#2 }
        \box_use:N #1
        \__kernel_kern:n { #4 - \box_wd:N #1 }
      }
    \dim_compare:nNnTF {#3} < \c_zero_dim
      {
        \hbox_set:Nn \l_@@_internal_box
          {
            \box_move_down:nn \c_zero_dim
              { \box_use_drop:N \l_@@_internal_box }
          }
        \box_set_dp:Nn \l_@@_internal_box { - \@@_dim_eval:n {#3} }
      }
      {
        \hbox_set:Nn \l_@@_internal_box
          { \box_move_down:nn {#3} { \box_use_drop:N \l_@@_internal_box } }
        \box_set_dp:Nn \l_@@_internal_box \c_zero_dim
      }
    \dim_compare:nNnTF {#5} > \c_zero_dim
      {
        \hbox_set:Nn \l_@@_internal_box
          {
            \box_move_up:nn \c_zero_dim
              { \box_use_drop:N \l_@@_internal_box }
          }
        \box_set_ht:Nn \l_@@_internal_box
          {
            (#5)
            \dim_compare:nNnT {#3} > \c_zero_dim
              { - (#3) }
          }
      }
      {
        \hbox_set:Nn \l_@@_internal_box
          {
            \box_move_up:nn { - \@@_dim_eval:n {#5} }
              { \box_use_drop:N \l_@@_internal_box }
          }
        \box_set_ht:Nn \l_@@_internal_box \c_zero_dim
      }
    #6 #1 \l_@@_internal_box
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3flag}}
%
%    \begin{macrocode}
%<@@=flag>
%    \end{macrocode}
%
% \begin{macro}[EXP]{\flag_raise_if_clear:n}
%   It might be faster to just call the \enquote{trap} function in all
%   cases but conceptually the function name suggests we should only run
%   it if the flag is zero in case the \enquote{trap} made customizable
%   in the future.
%    \begin{macrocode}
\cs_new:Npn \flag_raise_if_clear:n #1
  {
    \if_cs_exist:w flag~#1~0 \cs_end:
    \else:
      \cs:w flag~#1 \cs_end: 0 ;
    \fi:
  }
%    \end{macrocode}
% \end{macro}
%
% \subsection{Additions to \pkg{l3msg}}
%
%    \begin{macrocode}
%<@@=msg>
%    \end{macrocode}
%
% \begin{macro}{\msg_show_eval:Nn, \msg_log_eval:Nn, \@@_show_eval:nnN}
%   A short-hand used for \cs{int_show:n} and similar functions that
%   passes to \cs{tl_show:n} the result of applying |#1| (a
%   function such as \cs{int_eval:n}) to the expression |#2|.  The use of
%   \texttt{f}-expansion ensures that |#1| is expanded in the scope in which the
%   show command is called, rather than in the group created by
%   \cs{iow_wrap:nnnN}.  This is only important for expressions
%   involving the \tn{currentgrouplevel} or \tn{currentgrouptype}.
%   On the other hand we want the expression to be converted to a string
%   with the usual escape character, hence within the wrapping code.
%    \begin{macrocode}
\cs_new_protected:Npn \msg_show_eval:Nn #1#2
  { \exp_args:Nf \@@_show_eval:nnN { #1 {#2} } {#2} \tl_show:n }
\cs_new_protected:Npn \msg_log_eval:Nn #1#2
  { \exp_args:Nf \@@_show_eval:nnN { #1 {#2} } {#2} \tl_log:n }
\cs_new_protected:Npn \@@_show_eval:nnN #1#2#3 { #3 { #2 = #1 } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\msg_show_item:n}
% \begin{macro}[EXP]{\msg_show_item_unbraced:n}
% \begin{macro}[EXP]{\msg_show_item:nn}
% \begin{macro}[EXP]{\msg_show_item_unbraced:nn}
%   Each item in the variable is formatted using one of the following
%   functions.  We cannot use |\\| and so on because these short-hands
%   cannot be used inside the arguments of messages, only when defining
%   the messages.
%    \begin{macrocode}
\cs_new:Npx \msg_show_item:n #1
  { \iow_newline: > ~ \c_space_tl \exp_not:N \tl_to_str:n { {#1} } }
\cs_new:Npx \msg_show_item_unbraced:n #1
  { \iow_newline: > ~ \c_space_tl \exp_not:N \tl_to_str:n {#1} }
\cs_new:Npx \msg_show_item:nn #1#2
  {
    \iow_newline: > \use:nn { ~ } { ~ }
    \exp_not:N \tl_to_str:n { {#1} }
    \use:nn { ~ } { ~ } => \use:nn { ~ } { ~ }
    \exp_not:N \tl_to_str:n { {#2} }
  }
\cs_new:Npx \msg_show_item_unbraced:nn #1#2
  {
    \iow_newline: > \use:nn { ~ } { ~ }
    \exp_not:N \tl_to_str:n {#1}
    \use:nn { ~ } { ~ } => \use:nn { ~ } { ~ }
    \exp_not:N \tl_to_str:n {#2}
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3prg}}
%
%    \begin{macrocode}
%<@@=bool>
%    \end{macrocode}
%
% \begin{macro}[added = 2018-05-10]
%   {\bool_set_inverse:N, \bool_set_inverse:c, \bool_gset_inverse:N, \bool_gset_inverse:c}
%   Set to \texttt{false} or \texttt{true} locally or globally.
%    \begin{macrocode}
\cs_new_protected:Npn \bool_set_inverse:N #1
  { \bool_if:NTF #1 { \bool_set_false:N } { \bool_set_true:N } #1 }
\cs_generate_variant:Nn \bool_set_inverse:N { c }
\cs_new_protected:Npn \bool_gset_inverse:N #1
  { \bool_if:NTF #1 { \bool_gset_false:N } { \bool_gset_true:N } #1 }
\cs_generate_variant:Nn \bool_gset_inverse:N { c }
%    \end{macrocode}
% \end{macro}
%
% \begin{variable}{\s_@@_mark,\s_@@_stop}
%   Internal scan marks.
%    \begin{macrocode}
\scan_new:N \s_@@_mark
\scan_new:N \s_@@_stop
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}[EXP, noTF]{\bool_case_true:n, \bool_case_false:n}
% \begin{macro}{\@@_case:NnTF}
% \begin{macro}{\@@_case_true:w, \@@_case_false:w, \@@_case_end:nw}
%   For boolean cases the overall idea is the same as for
%   \cs{tl_case:nnTF} as described in \pkg{l3tl}.
%    \begin{macrocode}
\cs_new:Npn \bool_case_true:nTF
  { \exp:w \@@_case:NnTF \c_true_bool }
\cs_new:Npn \bool_case_true:nT #1#2
  { \exp:w \@@_case:NnTF \c_true_bool {#1} {#2} { } }
\cs_new:Npn \bool_case_true:nF #1
  { \exp:w \@@_case:NnTF \c_true_bool {#1} { } }
\cs_new:Npn \bool_case_true:n #1
  { \exp:w \@@_case:NnTF \c_true_bool {#1} { } { } }
\cs_new:Npn \bool_case_false:nTF
  { \exp:w \@@_case:NnTF \c_false_bool }
\cs_new:Npn \bool_case_false:nT #1#2
  { \exp:w \@@_case:NnTF \c_false_bool {#1} {#2} { } }
\cs_new:Npn \bool_case_false:nF #1
  { \exp:w \@@_case:NnTF \c_false_bool {#1} { } }
\cs_new:Npn \bool_case_false:n #1
  { \exp:w \@@_case:NnTF \c_false_bool {#1} { } { } }
\cs_new:Npn \@@_case:NnTF #1#2#3#4
  {
    \bool_if:NTF #1 \@@_case_true:w \@@_case_false:w
    #2 #1 { } \s_@@_mark {#3} \s_@@_mark {#4} \s_@@_stop
  }
\cs_new:Npn \@@_case_true:w #1#2
  {
    \bool_if:nTF {#1}
      { \@@_case_end:nw {#2} }
      { \@@_case_true:w }
  }
\cs_new:Npn \@@_case_false:w #1#2
  {
    \bool_if:nTF {#1}
      { \@@_case_false:w }
      { \@@_case_end:nw {#2} }
  }
\cs_new:Npn \@@_case_end:nw #1#2#3 \s_@@_mark #4#5 \s_@@_stop
  { \exp_end: #1 #4 }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3prop}}
%
%    \begin{macrocode}
%<@@=prop>
%    \end{macrocode}
%
% \begin{macro}[EXP]{\@@_use_i_delimit_by_s_stop:nw}
%   Functions to gobble up to a scan mark.
%    \begin{macrocode}
\cs_new:Npn \@@_use_i_delimit_by_s_stop:nw #1 #2 \s_@@_stop {#1}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]
%   {\prop_rand_key_value:N, \prop_rand_key_value:c}
% \begin{macro}[EXP]{\@@_rand_item:w}
%   Contrarily to |clist|, |seq| and |tl|, there is no function to get
%   an item of a |prop| given an integer between $1$ and the number of
%   items, so we write the appropriate code.  There is no bounds
%   checking because \cs{int_rand:nn} is always within bounds.  The
%   initial \cs{int_value:w} is stopped by the first \cs{s_@@} in~|#1|.
%    \begin{macrocode}
\cs_new:Npn \prop_rand_key_value:N #1
  {
    \prop_if_empty:NF #1
      {
        \exp_after:wN \@@_rand_item:w
        \int_value:w \int_rand:nn { 1 } { \prop_count:N #1 }
        #1 \s_@@_stop
      }
  }
\cs_generate_variant:Nn \prop_rand_key_value:N { c }
\cs_new:Npn \@@_rand_item:w #1 \s_@@ \@@_pair:wn #2 \s_@@ #3
  {
    \int_compare:nNnF {#1} > 1
      { \@@_use_i_delimit_by_s_stop:nw { \exp_not:n { {#2} {#3} } } }
    \exp_after:wN \@@_rand_item:w
    \int_value:w \int_eval:n { #1 - 1 } \s_@@
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3seq}}
%
%    \begin{macrocode}
%<@@=seq>
%    \end{macrocode}
%
% \begin{macro}
%   {
%     \seq_mapthread_function:NNN, \seq_mapthread_function:NcN,
%     \seq_mapthread_function:cNN, \seq_mapthread_function:ccN
%   }
% \begin{macro}
%   {
%     \@@_mapthread_function:wNN, \@@_mapthread_function:wNw,
%     \@@_mapthread_function:Nnnwnn
%   }
%   The idea is to first expand both sequences, adding the
%   usual |{ ? \prg_break: } { }| to the end of each one.  This is
%   most conveniently done in two steps using an auxiliary function.
%   The mapping then throws away the first tokens of |#2| and |#5|,
%   which for items in both sequences are \cs{s_@@}
%   \cs{@@_item:n}.  The function to be mapped are then be applied to
%   the two entries.  When the code hits the end of one of the
%   sequences, the break material stops the entire loop and tidy up.
%   This avoids needing to find the count of the two sequences, or
%   worrying about which is longer.
%    \begin{macrocode}
\cs_new:Npn \seq_mapthread_function:NNN #1#2#3
  { \exp_after:wN \@@_mapthread_function:wNN #2 \s_@@_stop #1 #3 }
\cs_new:Npn \@@_mapthread_function:wNN \s_@@ #1 \s_@@_stop #2#3
  {
    \exp_after:wN \@@_mapthread_function:wNw #2 \s_@@_stop #3
      #1 { ? \prg_break: } { }
    \prg_break_point:
  }
\cs_new:Npn \@@_mapthread_function:wNw \s_@@ #1 \s_@@_stop #2
  {
    \@@_mapthread_function:Nnnwnn #2
      #1 { ? \prg_break: } { }
    \s_@@_stop
  }
\cs_new:Npn \@@_mapthread_function:Nnnwnn #1#2#3#4 \s_@@_stop #5#6
  {
    \use_none:n #2
    \use_none:n #5
    #1 {#3} {#6}
    \@@_mapthread_function:Nnnwnn #1 #4 \s_@@_stop
  }
\cs_generate_variant:Nn \seq_mapthread_function:NNN { Nc , c , cc }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\seq_set_filter:NNn, \seq_gset_filter:NNn}
% \begin{macro}{\@@_set_filter:NNNn}
%   Similar to \cs{seq_map_inline:Nn}, without a
%   \cs{prg_break_point:} because the user's code
%   is performed within the evaluation of a boolean expression,
%   and skipping out of that would break horribly.
%   The \cs{@@_wrap_item:n} function inserts the relevant
%   \cs{@@_item:n} without expansion in the input stream,
%   hence in the \texttt{x}-expanding assignment.
%    \begin{macrocode}
\cs_new_protected:Npn \seq_set_filter:NNn
  { \@@_set_filter:NNNn \__kernel_tl_set:Nx }
\cs_new_protected:Npn \seq_gset_filter:NNn
  { \@@_set_filter:NNNn \__kernel_tl_gset:Nx }
\cs_new_protected:Npn \@@_set_filter:NNNn #1#2#3#4
  {
    \@@_push_item_def:n { \bool_if:nT {#4} { \@@_wrap_item:n {##1} } }
    #1 #2 { #3 }
    \@@_pop_item_def:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\seq_set_from_inline_x:Nnn, \seq_gset_from_inline_x:Nnn}
% \begin{macro}{\@@_set_from_inline_x:NNnn}
%   Set \cs{@@_item:n} then map it using the loop code.
%    \begin{macrocode}
\cs_new_protected:Npn \seq_set_from_inline_x:Nnn
  { \@@_set_from_inline_x:NNnn \__kernel_tl_set:Nx }
\cs_new_protected:Npn \seq_gset_from_inline_x:Nnn
  { \@@_set_from_inline_x:NNnn \__kernel_tl_gset:Nx }
\cs_new_protected:Npn \@@_set_from_inline_x:NNnn #1#2#3#4
  {
    \@@_push_item_def:n { \exp_not:N \@@_item:n {#4} }
    #1 #2 { \s_@@ #3 \@@_item:n }
    \@@_pop_item_def:
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\seq_set_from_function:NnN, \seq_gset_from_function:NnN}
%   Reuse \cs{seq_set_from_inline_x:Nnn}.
%    \begin{macrocode}
\cs_new_protected:Npn \seq_set_from_function:NnN #1#2#3
  { \seq_set_from_inline_x:Nnn #1 {#2} { #3 {##1} } }
\cs_new_protected:Npn \seq_gset_from_function:NnN #1#2#3
  { \seq_gset_from_inline_x:Nnn #1 {#2} { #3 {##1} } }
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@@_int_eval:w}
%   Useful to more quickly go through items.
%    \begin{macrocode}
\cs_new_eq:NN \@@_int_eval:w \tex_numexpr:D
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}[noTF]{\seq_set_item:Nnn, \seq_set_item:cnn, \seq_gset_item:Nnn, \seq_gset_item:cnn}
% \begin{macro}{\@@_set_item:NnnNN, \@@_set_item:nnNNNN, \@@_set_item_false:nnNNNN, \@@_set_item:nNnnNNNN}
% \begin{macro}[rEXP]{\@@_set_item:wn, \@@_set_item_end:w}
%   The conditionals are distinguished from the |Nnn| versions by the
%   last argument \cs{use_ii:nn} vs \cs{use_i:nn}.
%    \begin{macrocode}
\cs_new_protected:Npn \seq_set_item:Nnn #1#2#3
  { \@@_set_item:NnnNN #1 {#2} {#3} \__kernel_tl_set:Nx \use_i:nn }
\cs_new_protected:Npn \seq_gset_item:Nnn #1#2#3
  { \@@_set_item:NnnNN #1 {#2} {#3} \__kernel_tl_gset:Nx \use_i:nn }
\cs_generate_variant:Nn \seq_set_item:Nnn { c }
\cs_generate_variant:Nn \seq_gset_item:Nnn { c }
\prg_new_protected_conditional:Npnn \seq_set_item:Nnn #1#2#3 { TF , T , F }
  { \@@_set_item:NnnNN #1 {#2} {#3} \__kernel_tl_set:Nx \use_ii:nn }
\prg_new_protected_conditional:Npnn \seq_gset_item:Nnn #1#2#3 { TF , T , F }
  { \@@_set_item:NnnNN #1 {#2} {#3} \__kernel_tl_gset:Nx \use_ii:nn }
\prg_generate_conditional_variant:Nnn \seq_set_item:Nnn { c } { TF , T , F }
\prg_generate_conditional_variant:Nnn \seq_gset_item:Nnn { c } { TF , T , F }
%    \end{macrocode}
%   Save the item to be stored and evaluate the position and the sequence
%   length only once.  Then depending on the sign of the position, check
%   that it is not bigger than the length (in absolute value) nor zero.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_item:NnnNN #1#2#3
  {
    \tl_set:Nn \l_@@_internal_a_tl { \@@_item:n {#3} }
    \exp_args:Nff \@@_set_item:nnNNNN
      { \int_eval:n {#2} } { \seq_count:N #1 } #1 \use_none:nn
  }
\cs_new_protected:Npn \@@_set_item:nnNNNN #1#2
  {
    \int_compare:nNnTF {#1} > 0
      { \int_compare:nNnF {#1} > {#2} { \@@_set_item:nNnnNNNN { #1 - 1 } } }
      {
        \int_compare:nNnF {#1} < {-#2}
          {
            \int_compare:nNnF {#1} = 0
              { \@@_set_item:nNnnNNNN { #2 + #1 } }
          }
      }
    \@@_set_item_false:nnNNNN {#1} {#2}
  }
%    \end{macrocode}
%   If the position is not ok, \cs{@@_set_item_false:nnNNNN} calls an
%   error or returns \texttt{false} (depending on the \cs{use_i:nn} vs
%   \cs{use_ii:nn} argument mentioned above).
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_item_false:nnNNNN #1#2#3#4#5#6
  {
    #6
      {
        \msg_error:nnxxx { seq } { item-too-large }
          { \token_to_str:N #3 } {#2} {#1}
      }
      { \prg_return_false: }
  }
\msg_new:nnnn { seq } { item-too-large }
  { Sequence~'#1'~does~not~have~an~item~#3 }
  {
    An~attempt~was~made~to~push~or~pop~the~item~at~position~#3~
    of~'#1',~but~this~
    \int_compare:nTF { #3 = 0 }
      { position~does~not~exist. }
      { sequence~only~has~#2~item \int_compare:nF { #2 = 1 } {s}. }
  }
%    \end{macrocode}
%   If the position is ok, \cs{@@_set_item:nNnnNNNN} makes the assignment
%   and returns \texttt{true} (in the case of conditionnals).  Here |#1|
%   is an integer expression (position minus one), it needs to be
%   evaluated.  The sequence |#5| starts with \cs{s_@@} (even if empty),
%   which stops the integer expression and is absorbed by it.  The
%   \cs{if_meaning:w} test is slightly faster than an integer test (but
%   only works when testing against zero, hence the offset we chose in
%   the position).  When we are done skipping items, insert the saved
%   item \cs{l_@@_internal_a_tl}.  For |put| functions the last argument
%   of \cs{@@_set_item_end:w} is \cs{use_none:nn} and it absorbs the
%   item |#2| that we are removing: this is only useful for the |pop|
%   functions.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_set_item:nNnnNNNN #1#2#3#4#5#6#7#8
  {
    #7 #5
      {
        \s_@@
        \exp_after:wN \@@_set_item:wn
        \int_value:w \@@_int_eval:w #1
        #5 \s_@@_stop #6
      }
    #8 { } { \prg_return_true: }
  }
\cs_new:Npn \@@_set_item:wn #1 \@@_item:n #2
  {
    \if_meaning:w 0 #1 \@@_set_item_end:w \fi:
    \exp_not:n { \@@_item:n {#2} }
    \exp_after:wN \@@_set_item:wn
    \int_value:w \@@_int_eval:w #1 - 1 \s_@@
  }
\cs_new:Npn \@@_set_item_end:w #1 \exp_not:n #2 #3 \s_@@ #4 \s_@@_stop #5
  {
    #1
    \exp_not:o \l_@@_internal_a_tl
    \exp_not:n {#4}
    #5 #2
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}[noTF]{\seq_pop_item:NnN, \seq_pop_item:cnN, \seq_gpop_item:NnN, \seq_gpop_item:cnN}
% \begin{macro}{\@@_pop_item:NnNNN}
%   The |NnN| versions simply call the conditionals, for which we will
%   rely on the internals of \cs{seq_set_item:Nnn}.
%    \begin{macrocode}
\cs_new_protected:Npn \seq_pop_item:NnN #1#2#3
  { \seq_pop_item:NnNTF #1 {#2} #3 { } { } }
\cs_new_protected:Npn \seq_gpop_item:NnN #1#2#3
  { \seq_gpop_item:NnNTF #1 {#2} #3 { } { } }
\cs_generate_variant:Nn \seq_pop_item:NnN { c }
\cs_generate_variant:Nn \seq_gpop_item:NnN { c }
\prg_new_protected_conditional:Npnn \seq_pop_item:NnN #1#2#3 { TF , T , F }
  { \@@_pop_item:NnNN #1 {#2} #3 \__kernel_tl_set:Nx }
\prg_new_protected_conditional:Npnn \seq_gpop_item:NnN #1#2#3 { TF , T , F }
  { \@@_pop_item:NnNN #1 {#2} #3 \__kernel_tl_gset:Nx }
\prg_generate_conditional_variant:Nnn \seq_pop_item:NnN { c } { TF , T , F }
\prg_generate_conditional_variant:Nnn \seq_gpop_item:NnN { c } { TF , T , F }
%    \end{macrocode}
%   Save in \cs{l_@@_internal_b_tl} the token list variable |#3| in
%   which we will store the item.  The \cs{@@_set_item:nnNNNN} auxiliary
%   eventually inserts \cs{l_@@_internal_a_tl} in place of the item
%   found in the sequence, so we empty that.  Instead of the last
%   argument \cs{use_i:nn} or \cs{use_ii:nn} used for |put| functions,
%   we introduce \cs{@@_pop_item:nn}, which stores \cs{q_no_value}
%   before calling its second argument
%   (\cs{prg_return_true:}/\texttt{false:}) to end the conditional.  The
%   item found is passed to \cs{@@_pop_item_aux:w}, which interrupts the
%   |x|-expanding sequence assignment and stores the item using the
%   assignment function in \cs{l_@@_internal_b_tl}.
%    \begin{macrocode}
\cs_new_protected:Npn \@@_pop_item:NnNN #1#2#3#4
  {
    \tl_clear:N \l_@@_internal_a_tl
    \tl_set:Nn \l_@@_internal_b_tl { \__kernel_tl_set:Nx #3 }
    \exp_args:Nff \@@_set_item:nnNNNN
      { \int_eval:n {#2} } { \seq_count:N #1 }
      #1 \@@_pop_item_aux:w #4 \@@_pop_item:nn
  }
\cs_new_protected:Npn \@@_pop_item:nn #1#2
  {
    \if_meaning:w \prg_return_false: #2
      \l_@@_internal_b_tl { \exp_not:N \q_no_value }
    \fi:
    #2
  }
\cs_new:Npn \@@_pop_item_aux:w \@@_item:n #1
  {
    \if_false: { \fi: }
    \l_@@_internal_b_tl { \if_false: } \fi: \exp_not:n {#1}
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3sys}}
%
%    \begin{macrocode}
%<@@=sys>
%    \end{macrocode}
%
% \begin{variable}{\c_sys_engine_version_str}
%   Various different engines, various different ways to extract the
%   data!
%    \begin{macrocode}
\str_const:Nx \c_sys_engine_version_str
  {
    \str_case:on \c_sys_engine_str
      {
        { pdftex }
          {
            \fp_eval:n { round(\int_use:N \tex_pdftexversion:D / 100 , 2) }
            .
            \tex_pdftexrevision:D
          }
        { ptex }
          {
            \cs_if_exist:NT \tex_ptexversion:D
              {
                p
                \int_use:N  \tex_ptexversion:D
                .
                \int_use:N \tex_ptexminorversion:D
                \tex_ptexrevision:D
                -
                \int_use:N \tex_epTeXversion:D
              }
          }
        { luatex }
          {
            \fp_eval:n { round(\int_use:N \tex_luatexversion:D / 100, 2) }
            .
            \tex_luatexrevision:D
          }
        { uptex }
          {
            \cs_if_exist:NT \tex_ptexversion:D
              {
                p
                \int_use:N  \tex_ptexversion:D
                .
                \int_use:N \tex_ptexminorversion:D
                \tex_ptexrevision:D
                -
                u
                \int_use:N  \tex_uptexversion:D
                \tex_uptexrevision:D
                -
                \int_use:N \tex_epTeXversion:D
              }
          }
        { xetex }
          {
            \int_use:N \tex_XeTeXversion:D
            \tex_XeTeXrevision:D
          }
      }
  }
%    \end{macrocode}
% \end{variable}
%
% \subsection{Additions to \pkg{l3file}}
%
%    \begin{macrocode}
%<@@=ior>
%    \end{macrocode}
%
% \begin{macro}{\ior_shell_open:Nn}
% \begin{macro}{\@@_shell_open:nN}
%   Actually much easier than either the standard open or input versions!
%   When calling \cs{__kernel_ior_open:Nn} the file the pipe is added to
%   signal a shell command, but the quotes are not added yet---they are
%   added later by \cs{__kernel_file_name_quote:n}.
%    \begin{macrocode}
\cs_new_protected:Npn \ior_shell_open:Nn #1#2
  {
    \sys_if_shell:TF
      { \exp_args:No \@@_shell_open:nN { \tl_to_str:n {#2} } #1 }
      { \msg_error:nn { ior } { pipe-failed } }
  }
\cs_new_protected:Npn \@@_shell_open:nN #1#2
  {
    \tl_if_in:nnTF {#1} { " }
      {
        \msg_error:nnx
          { kernel } { quote-in-shell } {#1}
      }
      { \__kernel_ior_open:Nn #2 { |#1 } }
  }
\msg_new:nnnn { ior } { pipe-failed }
  { Cannot~run~piped~system~commands. }
  {
    LaTeX~tried~to~call~a~system~process~but~this~was~not~possible.\\
    Try~the~"--shell-escape"~(or~"--enable-pipes")~option.
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3tl}}
%
% \subsubsection{Building a token list}
%
%    \begin{macrocode}
%<@@=tl>
%    \end{macrocode}
%
% Between \cs{tl_build_begin:N} \meta{tl~var} and \cs{tl_build_end:N}
% \meta{tl~var}, the \meta{tl~var} has the structure
% \begin{quote}
%   \cs{exp_end:} \ldots{} \cs{exp_end:} \cs{@@_build_last:NNn}
%   \meta{assignment} \meta{next~tl} \Arg{left} \meta{right}
% \end{quote}
% where \meta{right} is not braced.  The \enquote{data} it represents is
% \meta{left} followed by the \enquote{data} of \meta{next~tl} followed
% by \meta{right}.  The \meta{next~tl} is a token list variable whose
% name is that of \meta{tl~var} followed by~|'|.  There are between $0$
% and $4$ \cs{exp_end:} to keep track of when \meta{left} and
% \meta{right} should be put into the \meta{next~tl}.  The
% \meta{assignment} is \cs{cs_set_nopar:Npx} if the variable is local,
% and \cs{cs_gset_nopar:Npx} if it is global.
%
% \begin{macro}{\tl_build_begin:N, \tl_build_gbegin:N}
% \begin{macro}{\@@_build_begin:NN, \@@_build_begin:NNN}
%   First construct the \meta{next~tl}: using a prime here conflicts
%   with the usual \pkg{expl3} convention but we need a name that can be
%   derived from |#1| without any external data such as a counter.
%   Empty that \meta{next~tl} and setup the structure.  The local and
%   global versions only differ by a single function
%   \cs[no-index]{cs_(g)set_nopar:Npx} used for all assignments: this is
%   important because only that function is stored in the \meta{tl~var}
%   and \meta{next~tl} for subsequent assignments.  In principle
%   \cs{@@_build_begin:NNN} could use \cs[no-index]{tl_(g)clear_new:N}
%   to empty |#1| and make sure it is defined, but logging the
%   definition does not seem useful so we just do |#3| |#1| |{}| to
%   clear it locally or globally as appropriate.
%    \begin{macrocode}
\cs_new_protected:Npn \tl_build_begin:N #1
  { \@@_build_begin:NN \cs_set_nopar:Npx #1 }
\cs_new_protected:Npn \tl_build_gbegin:N #1
  { \@@_build_begin:NN \cs_gset_nopar:Npx #1 }
\cs_new_protected:Npn \@@_build_begin:NN #1#2
  { \exp_args:Nc \@@_build_begin:NNN { \cs_to_str:N #2 ' } #2 #1 }
\cs_new_protected:Npn \@@_build_begin:NNN #1#2#3
  {
    #3 #1 { }
    #3 #2
      {
        \exp_not:n { \exp_end: \exp_end: \exp_end: \exp_end: }
        \exp_not:n { \@@_build_last:NNn #3 #1 { } }
      }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\tl_build_clear:N, \tl_build_gclear:N}
%   The |begin| and |gbegin| functions already clear enough to make the
%   token list variable effectively empty.  Eventually the |begin| and
%   |gbegin| functions should check that |#1'| is empty or undefined,
%   while the |clear| and |gclear| functions ought to empty |#1'|,
%   |#1''| and so on, similar to \cs{tl_build_end:N}.  This only affects
%   memory usage.
%    \begin{macrocode}
\cs_new_eq:NN \tl_build_clear:N \tl_build_begin:N
\cs_new_eq:NN \tl_build_gclear:N \tl_build_gbegin:N
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \tl_build_put_right:Nn, \tl_build_put_right:Nx,
%     \tl_build_gput_right:Nn, \tl_build_gput_right:Nx,
%     \@@_build_last:NNn, \@@_build_put:nn, \@@_build_put:nw
%   }
%   Similar to \cs{tl_put_right:Nn}, but apply \cs{exp:w} to |#1|.  Most
%   of the time this just removes one \cs{exp_end:}.  When there are
%   none left, \cs{@@_build_last:NNn} is expanded instead.  It resets
%   the definition of the \meta{tl~var} by ending the \cs{exp_not:n} and
%   the definition early.  Then it makes sure the \meta{next~tl} (its
%   argument |#1|) is set-up and starts a new definition.  Then
%   \cs{@@_build_put:nn} and \cs{@@_build_put:nw} place the \meta{left}
%   part of the original \meta{tl~var} as appropriate for the definition
%   of the \meta{next~tl} (the \meta{right} part is left in the right
%   place without ever becoming a macro argument).  We use
%   \cs{exp_after:wN} rather than some \cs{exp_args:No} to avoid reading
%   arguments that are likely very long token lists.  We use
%   \cs[no-index]{cs_(g)set_nopar:Npx} rather than
%   \cs[no-index]{tl_(g)set:Nx} partly for the same reason and partly
%   because the assignments are interrupted by brace tricks, which
%   implies that the assignment does not simply set the token list to an
%   |x|-expansion of the second argument.
%    \begin{macrocode}
\cs_new_protected:Npn \tl_build_put_right:Nn #1#2
  {
    \cs_set_nopar:Npx #1
      { \exp_after:wN \exp_not:n \exp_after:wN { \exp:w #1 #2 } }
  }
\cs_new_protected:Npn \tl_build_put_right:Nx #1#2
  {
    \cs_set_nopar:Npx #1
      { \exp_after:wN \exp_not:n \exp_after:wN { \exp:w #1 } #2 }
  }
\cs_new_protected:Npn \tl_build_gput_right:Nn #1#2
  {
    \cs_gset_nopar:Npx #1
      { \exp_after:wN \exp_not:n \exp_after:wN { \exp:w #1 #2 } }
  }
\cs_new_protected:Npn \tl_build_gput_right:Nx #1#2
  {
    \cs_gset_nopar:Npx #1
      { \exp_after:wN \exp_not:n \exp_after:wN { \exp:w #1 } #2 }
  }
\cs_new_protected:Npn \@@_build_last:NNn #1#2
  {
    \if_false: { { \fi:
          \exp_end: \exp_end: \exp_end: \exp_end: \exp_end:
          \@@_build_last:NNn #1 #2 { }
        }
      }
    \if_meaning:w \c_empty_tl #2
      \@@_build_begin:NN #1 #2
    \fi:
    #1 #2
      {
        \exp_after:wN \exp_not:n \exp_after:wN
          {
            \exp:w \if_false: } } \fi:
            \exp_after:wN \@@_build_put:nn \exp_after:wN {#2}
  }
\cs_new_protected:Npn \@@_build_put:nn #1#2 { \@@_build_put:nw {#2} #1 }
\cs_new_protected:Npn \@@_build_put:nw #1#2 \@@_build_last:NNn #3#4#5
  { #2 \@@_build_last:NNn #3 #4 { #1 #5 } }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}
%   {
%     \tl_build_put_left:Nn, \tl_build_put_left:Nx,
%     \tl_build_gput_left:Nn, \tl_build_gput_left:Nx, \@@_build_put_left:NNn
%   }
%   See \cs{tl_build_put_right:Nn} for all the machinery.  We could
%   easily provide \cs[no-index]{tl_build_put_left_right:Nnn}, by just
%   add the \meta{right} material after the \Arg{left} in the
%   |x|-expanding assignment.
%    \begin{macrocode}
\cs_new_protected:Npn \tl_build_put_left:Nn #1
  { \@@_build_put_left:NNn \cs_set_nopar:Npx #1 }
\cs_generate_variant:Nn \tl_build_put_left:Nn { Nx }
\cs_new_protected:Npn \tl_build_gput_left:Nn #1
  { \@@_build_put_left:NNn \cs_gset_nopar:Npx #1 }
\cs_generate_variant:Nn \tl_build_gput_left:Nn { Nx }
\cs_new_protected:Npn \@@_build_put_left:NNn #1#2#3
  {
    #1 #2
      {
        \exp_after:wN \exp_not:n \exp_after:wN
          {
            \exp:w \exp_after:wN \@@_build_put:nn
              \exp_after:wN {#2} {#3}
          }
      }
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\tl_build_get:NN}
% \begin{macro}{\@@_build_get:NNN, \@@_build_get:w, \@@_build_get_end:w}
%   The idea is to expand the \meta{tl~var} then the \meta{next~tl} and
%   so on, all within an |x|-expanding assignment, and wrap as
%   appropriate in \cs{exp_not:n}.  The various \meta{left} parts are
%   left in the assignment as we go, which enables us to expand the
%   \meta{next~tl} at the right place.  The various \meta{right} parts
%   are eventually picked up in one last \cs{exp_not:n}, with a brace
%   trick to wrap all the \meta{right} parts together.
%    \begin{macrocode}
\cs_new_protected:Npn \tl_build_get:NN
  { \@@_build_get:NNN \__kernel_tl_set:Nx }
\cs_new_protected:Npn \@@_build_get:NNN #1#2#3
  { #1 #3 { \if_false: { \fi: \exp_after:wN \@@_build_get:w #2 } } }
\cs_new:Npn \@@_build_get:w #1 \@@_build_last:NNn #2#3#4
  {
    \exp_not:n {#4}
    \if_meaning:w \c_empty_tl #3
      \exp_after:wN \@@_build_get_end:w
    \fi:
    \exp_after:wN \@@_build_get:w #3
  }
\cs_new:Npn \@@_build_get_end:w #1#2#3
  { \exp_after:wN \exp_not:n \exp_after:wN { \if_false: } \fi: }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\tl_build_end:N, \tl_build_gend:N, \@@_build_end_loop:NN}
%   Get the data then clear the \meta{next~tl} recursively until finding
%   an empty one.  It is perhaps wasteful to repeatedly use
%   \cs{cs_to_str:N}.  The local/global scope is checked by
%   \cs{tl_set:Nx} or \cs{tl_gset:Nx}.
%    \begin{macrocode}
\cs_new_protected:Npn \tl_build_end:N #1
  {
    \@@_build_get:NNN \__kernel_tl_set:Nx #1 #1
    \exp_args:Nc \@@_build_end_loop:NN { \cs_to_str:N #1 ' } \tl_clear:N
  }
\cs_new_protected:Npn \tl_build_gend:N #1
  {
    \@@_build_get:NNN \__kernel_tl_gset:Nx #1 #1
    \exp_args:Nc \@@_build_end_loop:NN { \cs_to_str:N #1 ' } \tl_gclear:N
  }
\cs_new_protected:Npn \@@_build_end_loop:NN #1#2
  {
    \if_meaning:w \c_empty_tl #1
      \exp_after:wN \use_none:nnnnnn
    \fi:
    #2 #1
    \exp_args:Nc \@@_build_end_loop:NN { \cs_to_str:N #1 ' } #2
  }
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Other additions to \pkg{l3tl}}
%
% \begin{macro}{\tl_range_braced:Nnn, \tl_range_braced:cnn, \tl_range_braced:nnn}
% \begin{macro}
%   {\tl_range_unbraced:Nnn, \tl_range_unbraced:cnn, \tl_range_unbraced:nnn}
% \begin{macro}
%   {
%     \@@_range_braced:w, \@@_range_collect_braced:w,
%     \@@_range_unbraced:w, \@@_range_collect_unbraced:w,
%   }
%   For the braced version \cs{@@_range_braced:w} sets up
%   \cs{@@_range_collect_braced:w} which stores items one by one in an
%   argument after the semicolon.  The unbraced version is almost
%   identical.  The version preserving braces and spaces starts by
%   deleting spaces before the argument to avoid collecting them, and
%   sets up \cs{@@_range_collect:nn} with a first argument of the form
%   |{| \Arg{collected} \meta{tokens} |}|, whose head is the collected
%   tokens and whose tail is what remains of the original token list.
%   This form makes it easier to move tokens to the \meta{collected}
%   tokens.
%    \begin{macrocode}
\cs_new:Npn \tl_range_braced:Nnn { \exp_args:No \tl_range_braced:nnn }
\cs_generate_variant:Nn \tl_range_braced:Nnn { c }
\cs_new:Npn \tl_range_braced:nnn { \@@_range:Nnnn \@@_range_braced:w }
\cs_new:Npn \tl_range_unbraced:Nnn
  { \exp_args:No \tl_range_unbraced:nnn }
\cs_generate_variant:Nn \tl_range_unbraced:Nnn { c }
\cs_new:Npn \tl_range_unbraced:nnn
  { \@@_range:Nnnn \@@_range_unbraced:w }
\cs_new:Npn \@@_range_braced:w #1 ; #2
  { \@@_range_collect_braced:w #1 ; { } #2 }
\cs_new:Npn \@@_range_unbraced:w #1 ; #2
  { \@@_range_collect_unbraced:w #1 ; { } #2 }
\cs_new:Npn \@@_range_collect_braced:w #1 ; #2#3
  {
    \if_int_compare:w #1 > \c_one_int
      \exp_after:wN \@@_range_collect_braced:w
      \int_value:w \int_eval:n { #1 - 1 } \exp_after:wN ;
    \fi:
    { #2 {#3} }
  }
\cs_new:Npn \@@_range_collect_unbraced:w #1 ; #2#3
  {
    \if_int_compare:w #1 > \c_one_int
      \exp_after:wN \@@_range_collect_unbraced:w
      \int_value:w \int_eval:n { #1 - 1 } \exp_after:wN ;
    \fi:
    { #2 #3 }
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsection{Additions to \pkg{l3token}}
%
% \begin{variable}{\c_catcode_active_space_tl}
%   While \cs{char_generate:nn} can produce active characters in some
%   engines it cannot in general.  It would be possible to simply change
%   the catcode of space but then the code would need to avoid all
%   spaces, making it quite unreadable.  Instead we use the primitive
%   \cs{tex_lowercase:D} trick.
%    \begin{macrocode}
\group_begin:
  \char_set_catcode_active:N *
  \char_set_lccode:nn { `* } { `\ }
  \tex_lowercase:D { \tl_const:Nn \c_catcode_active_space_tl { * } }
\group_end:
%    \end{macrocode}
% \end{variable}
%
%    \begin{macrocode}
%<@@=peek>
%    \end{macrocode}
%
% \begin{variable}{\l_@@_collect_tl}
%    \begin{macrocode}
\tl_new:N \l_@@_collect_tl
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}
%   {
%     \peek_catcode_collect_inline:Nn,
%     \peek_charcode_collect_inline:Nn,
%     \peek_meaning_collect_inline:Nn
%   }
% \begin{macro}
%   {
%     \@@_collect:NNn, \@@_collect_true:w,
%     \@@_collect_remove:nw, \@@_collect:N
%   }
%     Most of the work is done by \cs{@@_execute_branches_\ldots{}:},
%     which calls either \cs{@@_true:w} or \cs{@@_false:w} according to
%     whether the next token \cs{l_peek_token} matches the search token
%     (stored in \cs{l_@@_search_token} and \cs{l_@@_search_tl}).
%     Here, in the \texttt{true} case we run \cs{@@_collect_true:w},
%     which generally calls \cs{@@_collect:N} to store the peeked token
%     into \cs{l_@@_collect_tl}, except in special non-\texttt{N}-type
%     cases (begin-group, end-group, or space), where a frozen token is
%     stored.  The \texttt{true} branch calls
%     \cs{@@_execute_branches_\ldots{}:} to fetch more matching tokens.
%     Once there are no more, \cs{@@_false_aux:n} closes the safe-align
%     group and runs the user's inline code.
%    \begin{macrocode}
\cs_new_protected:Npn \peek_catcode_collect_inline:Nn
  { \@@_collect:NNn \@@_execute_branches_catcode: }
\cs_new_protected:Npn \peek_charcode_collect_inline:Nn
  { \@@_collect:NNn \@@_execute_branches_charcode: }
\cs_new_protected:Npn \peek_meaning_collect_inline:Nn
  { \@@_collect:NNn \@@_execute_branches_meaning: }
\cs_new_protected:Npn \@@_collect:NNn #1#2#3
  {
    \group_align_safe_begin:
    \cs_set_eq:NN \l_@@_search_token #2
    \tl_set:Nn \l_@@_search_tl {#2}
    \tl_clear:N \l_@@_collect_tl
    \cs_set:Npn \@@_false:w
      { \exp_args:No \@@_false_aux:n \l_@@_collect_tl }
    \cs_set:Npn \@@_false_aux:n ##1
      {
        \group_align_safe_end:
        #3
      }
    \cs_set_eq:NN \@@_true:w \@@_collect_true:w
    \cs_set:Npn \@@_true_aux:w { \peek_after:Nw #1 }
    \@@_true_aux:w
  }
\cs_new_protected:Npn \@@_collect_true:w
  {
    \if_case:w
        \if_catcode:w \exp_not:N \l_peek_token {   1 \exp_stop_f: \fi:
        \if_catcode:w \exp_not:N \l_peek_token }   2 \exp_stop_f: \fi:
        \if_meaning:w \l_peek_token \c_space_token 3 \exp_stop_f: \fi:
        0 \exp_stop_f:
      \exp_after:wN \@@_collect:N
    \or: \@@_collect_remove:nw { \c_group_begin_token }
    \or: \@@_collect_remove:nw { \c_group_end_token }
    \or: \@@_collect_remove:nw { ~ }
    \fi:
  }
\cs_new_protected:Npn \@@_collect:N #1
  {
    \tl_put_right:Nn \l_@@_collect_tl {#1}
    \@@_true_aux:w
  }
\cs_new_protected:Npn \@@_collect_remove:nw #1
  {
    \tl_put_right:Nn \l_@@_collect_tl {#1}
    \exp_after:wN \@@_true_remove:w
  }
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%    \begin{macrocode}
%</package>
%    \end{macrocode}
%
% \end{implementation}
%
% \PrintIndex
