summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/expl3.dtx450
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx132
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3basics.dtx1343
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx396
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3box.dtx963
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx2828
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3clist.dtx931
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx1587
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3color.dtx27
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3doc.dtx511
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx277
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx303
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3expan.dtx546
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3file.dtx1589
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3final.dtx2
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx235
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx850
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx1634
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx476
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx1252
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx674
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx393
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-old.dtx273
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx2601
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx424
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx418
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx581
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3fp.dtx6035
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3int.dtx868
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3keys.dtx1008
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx113
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3msg.dtx1823
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3names.dtx864
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prg.dtx1128
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3prop.dtx702
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3quark.dtx179
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3seq.dtx1411
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3skip.dtx496
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3tl.dtx1450
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3token.dtx623
40 files changed, 22786 insertions, 15610 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
index b9a053a8a27..179f45d11c8 100644
--- a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx
@@ -34,22 +34,23 @@
%% -----------------------------------------------------------------------
%
%<*driver|package>
-\RequirePackage{l3names}[2011/12/30]
-%<package>\@ifpackagelater{l3names}{2011/12/30}
+\RequirePackage{l3names}[2012/07/15]
+%<package>\@ifpackagelater{l3names}{2012/07/15}
%<package> {}
-%<package> {
+%<package> {%
%<package> \PackageError{expl3}{Mismatched LaTeX3 packages detected.}
-%<package> {
+%<package> {%
%<package> Please install an up to date version of l3kernel
-%<package> using your TeX package manager or from CTAN.\\ \\
-%<package> Loading expl3 will abort!
-%<package> }
+%<package> using your TeX package manager or from CTAN.%
+%<package> \MessageBreak \MessageBreak
+%<package> Loading expl3 will abort!%
+%<package> }%
%<package> \endinput
%<package> }
\def\ExplFileName{expl3}
\def\ExplFileDescription{L3 Experimental code bundle wrapper}
-\def\ExplFileDate{2012/04/23}
-\def\ExplFileVersion{3570}
+\def\ExplFileDate{2012/07/16}
+\def\ExplFileVersion{3990}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -163,8 +164,8 @@
% One problem with more traditional \TeX{} coding conventions (as
% described in~\cite{A-W:K-TB}) is that the names and syntax of \TeX{}'s
% primitive formatting commands are ingeniously designed to be
-% \enquote{natural} when used directly by the author as document mark-up or in
-% macros. Ironically, the ubiquity (and widely recognised
+% \enquote{natural} when used directly by the author as document mark-up
+% or in macros. Ironically, the ubiquity (and widely recognised
% superiority) of logical mark-up has meant that such explicit
% formatting commands are almost never needed in documents or in
% author-defined macros. Thus they are used almost exclusively by
@@ -309,6 +310,88 @@
% inferred from the presence or absence of a |g|. See the next subsection for
% more detail on variable scope.
%
+% \subsubsection{Separating private and public material}
+%
+% One of the issues with the \TeX{} language is that it doesn't support
+% name spaces and encapsulation other than by convention. As a result
+% nearly every internal command in the \LaTeXe{} kernel has eventually
+% be used by extension packages as an entry point for modifications or
+% extensions. The consequences of this is that nowadays it is next to
+% impossible to change anything in the \LaTeXe{} kernel (even if it is
+% clearly just an internal command) without breaking something.
+%
+% In \pkg{expl3} we hope to improve this situation drastically by
+% clearly separating public interfaces (that extension packages can use
+% and rely on) and private functions and variables (that should not
+% appear outside of their module). There is (nearly) no way to enforce
+% this without severe computing overhead, so we implement it only
+% through a naming convention, and some support mechanisms. However, we
+% think that this naming convention is easy to understand and to follow,
+% so that we are confident that this will adopted and provides the
+% desired results.
+%
+% Functions created by a module may either be \enquote{public} (documented
+% with a defined interface) or \enquote{private} (to be used only within
+% that module, and thus not formally documented). It is important that
+% only documented interfaces are used; at the same time, it is necessary to
+% show within the name of a function or variable whether it is public
+% or private.
+%
+% To allow clear separation of these two cases, the following convention
+% is used. Private functions should be defined with |__| added to the beginning
+% of the module name. Thus
+% \begin{verbatim}
+% \module_foo:nnn
+% \end{verbatim}
+% is a public function which should be documented while
+% \begin{verbatim}
+% \__module_foo:nnn
+% \end{verbatim}
+% is private to the module, and should \emph{not} be used outside of that
+% module.
+%
+% In the same way, private variables should use two "__" at the start of the
+% module name, such that
+% \begin{verbatim}
+% \l_module_foo_tl
+% \end{verbatim}
+% is a public variable and
+% \begin{verbatim}
+% \l__module_foo_tl
+% \end{verbatim}
+% is private.
+%
+% \subsubsection{Using \texttt{@@} and \pkg{l3docstrip} to mark private code}
+%
+% The formal syntax for internal functions allows clear separation of public
+% and private code, but includes redundant information (every internal function
+% or variable includes \texttt{__\meta{module}}). To aid programmers, the
+% \pkg{l3docstrip} program introduces the syntax
+% \begin{quote}
+% \ttfamily
+% |%<@@=|\meta{module}|>|
+% \end{quote}
+% which then allows |@@| (and |_@@| in case of variables) to be used as
+% a place holder for \texttt{__\meta{module}} in code. Thus for example
+% \begin{verbatim}
+% %<@@=foo>
+% % \begin{macrocode}
+% \cs_new:Npn \@@_function:n #1
+% ...
+% \tl_new:N \l_@@_my_tl
+% % \end{macrocode}
+% \end{verbatim}
+% will be converted by \pkg{l3docstrip} to
+% \begin{verbatim}
+% \cs_new:Npn \__foo_function:n #1
+% ...
+% \tl_new:N \l__foo_my_tl
+% \end{verbatim}
+% on extraction. As you can see both |_@@| and |@@| are mapped to
+% \texttt{__\meta{module}}, because we think that this helps to
+% distinguish variables from functions in the source when the |@@|
+% convention is used.
+%
% \subsubsection{Variables: scope and type}
%
% The \meta{scope} part of the name describes how the variable can be
@@ -323,11 +406,11 @@
% \end{arg-description}
%
% Separate functions are provided to assign data to local and global
-% variables; for example, |\tl_set:Nn| and |\tl_gset:Nn| respectively
+% variables; for example, \cs{tl_set:Nn} and \cs{tl_gset:Nn} respectively
% set the value of a local or global \enquote{token list} variable.
-% Note that it is a poor \TeX{} practise to intermix local and global
-% assignments to a variable; otherwise you risk exhausting the save stack.
-% \unskip\footnote{See \emph{The \TeX{}book}, p.\,301, for further
+% Note that it is a poor \TeX{} practice to intermix local and global
+% assignments to a variable; otherwise you risk exhausting the save
+% stack.\footnote{See \emph{The \TeX{}book}, p.\,301, for further
% information.}
%
% The \meta{type} will be in the list of available
@@ -335,7 +418,7 @@
% needed then this will not be the case. However, it is hoped that only
% the kernel team will need to create new data types.} these include the
% primitive \TeX{} data-types, such as the various registers, but to
-% these will be added data-types built within the \LaTeX{} programming
+% these are added data-types built within the \LaTeX{} programming
% system.
%
% The data types in \LaTeX3 are:
@@ -349,27 +432,25 @@
% \item[dim] \enquote{rigid} lengths;
% \item[fp] floating-point values;
% \item[ior] an input stream (for reading from a file);
-% \item[iow] an output stream (for writing from a file);
+% \item[iow] an output stream (for writing to a file);
% \item[int] integer-valued count register;
+% \item[muskip] math mode \enquote{rubber} lengths;
% \item[prop] property list;
% \item[seq] sequence: a data-type used to implement lists (with
% access at both ends) and stacks;
% \item[skip] \enquote{rubber} lengths;
-% \item[stream] an input or output stream (for reading from or writing
-% to, respectively);
% \item[tl] \enquote{token list variables}: placeholders for token lists.
% \end{description}
% When the \meta{type} and \meta{module} are identical (as often happens in
% the more basic modules) the \meta{module} part is often omitted for
% aesthetic reasons.
%
-% The name \enquote{token list} may cause confusion, and so some background is
-% useful. \TeX{} works with tokens and lists of tokens, rather than
-% characters. It provides two ways to store these token lists: within
-% macros and as token registers (|toks|). The implementation in \LaTeX3 means
-% that
-% |toks| are not required, and that all operations for storing tokens can us
-% the |tl| variable type.
+% The name \enquote{token list} may cause confusion, and so some
+% background is useful. \TeX{} works with tokens and lists of tokens,
+% rather than characters. It provides two ways to store these token
+% lists: within macros and as token registers (|toks|). The
+% implementation in \LaTeX3 means that |toks| are not required, and that
+% all operations for storing tokens can use the |tl| variable type.
%
% Experienced \TeX{} programmers will notice that some of the variable
% types listed are native \TeX{} registers whilst others are not. In
@@ -400,16 +481,16 @@
% then using the sequence functions which work in a stack manner
% (\cs{seq_push:Nn}, \emph{etc}.).
%
-% Due to the nature of the underlying \TeX{} implementation, it is
-% possible to assign values to token list variables and comma lists
-% without first declaring them. However, this is \emph{not supported
-% behaviour}. The \LaTeX3 coding convention is that all variables must
-% be declared before use.
+% Due to the nature of the underlying \TeX{} implementation, it is
+% possible to assign values to token list variables and comma lists
+% without first declaring them. However, this is \emph{not supported
+% behaviour}. The \LaTeX3 coding convention is that all variables must
+% be declared before use.
%
-% The \pkg{expl3} package can be loaded with the |check-declarations| option
-% to verify that all variables are declared before use. This has a
-% performance implication and is therefore intended for testing during
-% development and not for use in production documents.
+% The \pkg{expl3} package can be loaded with the |check-declarations|
+% option to verify that all variables are declared before use. This has
+% a performance implication and is therefore intended for testing during
+% development and not for use in production documents.
%
% \subsubsection{Functions: argument specifications}
%
@@ -443,13 +524,12 @@
% \end{arg-description}
% There are two other specifiers with more general meanings:
% \begin{arg-description}
-% \item[D] This means: \textbf{Do not use}. This special case is used
-% for \TeX{} primitives and other commands that are provided for use
-% only while bootstrapping the \LaTeX{} kernel. Programmers outside
-% the kernel team should not use these functions!
+% \item[D] This means: \textbf{Do not use}. This special case is used
+% for \TeX{} primitives. Programmers outside the kernel team should
+% not use these functions!
% \item[w] This means that the argument syntax is \enquote{weird} in that it
% does not follow any standard rule. It is used for functions with
-% arguments that take non standard forms: examples are \TeX-level
+% arguments that take non standard forms: examples are \TeX{}-level
% delimited arguments and the boolean tests needed after certain
% primitive |\if|\ldots{} commands.
% \end{arg-description}
@@ -468,13 +548,11 @@
%
% Let's take a look at some typical operations one might want to
% perform. Suppose we maintain a stack of open files and we use the
-% stack |\g_ior_file_name_seq| to keep track of them (|io| is the
-% file reading and writing module: it uses the module prefix
-% \texttt{ior} for reading functions and variables). The basic
-% operation here is to push a name onto this stack which could be
-% done by the operation
+% stack |\g_ior_file_name_seq| to keep track of them (\texttt{ior} is
+% the prefix used for the file reading module). The basic operation here
+% is to push a name onto this stack which could be done by the operation
% \begin{quote}
-% |\seq_gpush:Nn \g_ior_file_name_seq {#1}|
+% \cs{seq_gpush:Nn} |\g_ior_file_name_seq {#1}|
% \end{quote}
% where |#1| is the filename. In other words, this operation would
% push the file name as is onto the stack.
@@ -483,20 +561,20 @@
% a variable of some sort, say |\l_ior_curr_file_tl|. In this case we
% want to retrieve the value of the variable. If we simply use
% \begin{quote}
-% |\seq_gpush:Nn \g_io_file_name_seq \l_io_curr_file_tl|
+% \cs{seq_gpush:Nn} |\g_ior_file_name_seq| |\l_ior_curr_file_tl|
% \end{quote}
% we will not get the value of the variable pushed onto the stack,
% only the variable name itself. Instead a suitable number of
-% |\exp_after:wN| would be necessary (together with extra braces) to
+% \cs{exp_after:wN} would be necessary (together with extra braces) to
% change the order of expansion,\footnote{\cs{exp_after:wN} is
-% the \LaTeX3 name for the \TeX{} \tn{expandafter} primitive.}, \emph{i.e.}
+% the \LaTeX3 name for the \TeX{} \tn{expandafter} primitive.} \emph{i.e.}
% \begin{quote}
-% |\exp_after:wN| \\
-% | \seq_gpush:Nn| \\
-% |\exp_after:wN| \\
-% | \g_io_file_name_seq| \\
-% |\exp_after:wN| \\
-% | { \l_io_curr_file_tl }|
+% \cs{exp_after:wN} \\
+% | |\cs{seq_gpush:Nn} \\
+% \cs{exp_after:wN} \\
+% | \g_ior_file_name_seq| \\
+% \cs{exp_after:wN} \\
+% | { \l_ior_curr_file_tl }|
% \end{quote}
%
% The above example is probably the simplest case but already shows
@@ -512,7 +590,7 @@
% just uses different letters in the arg-spec part of the function to
% mark the desired behaviour. In the above example one would write
% \begin{quote}
-% |\seq_gpush:NV \g_io_file_name_seq \l_io_curr_file_tl|
+% \cs{seq_gpush:NV} |\g_ior_file_name_seq \l_ior_curr_file_tl|
% \end{quote}
% to achieve the desired effect. Here the |V| (the second argument)
% is for \enquote{retrieve the value of the variable} before passing it to
@@ -524,14 +602,15 @@
% \item[c] Character string used as a command name.\\ The argument (a
% token or braced token list) must, when fully expanded, produce a
% sequence of characters which is then used to construct a command
-% name (\emph{via}~|\csname| \ldots |\endcsname|). This command name is the
+% name (\emph{via}~\tn{csname} \ldots \tn{endcsname}).
+% This command name is the
% single token that is passed to the function as the argument. Hence
% \begin{quote}
-% |\seq_gpush:cV { g_file_name_seq } \l_tmpa_tl|
+% \cs{seq_gpush:cV} |{ g_file_name_seq }| \cs{l_tmpa_tl}
% \end{quote}
% is equivalent to
% \begin{quote}
-% |\seq_gpush:NV \g_file_name_seq \l_tmpa_tl"|
+% \cs{seq_gpush:NV} |\g_file_name_seq| \cs{l_tmpa_tl}.
% \end{quote}
% Remember that \texttt{c} arguments are \emph{fully expanded} by
% \TeX{} when creating csnames. This means that (a) the entire
@@ -539,13 +618,14 @@
% converted to their content. So the preceding examples are also
% equivalent to
% \begin{quote}
-% |\tl_new:N \g_file_seq_name_tl| \\
-% |\tl_gset:Nn \g_file_seq_name_tl { g_file_name_seq }| \\
-% |\seq_gpush:cV { \g_file_seq_name_tl } \l_tmpa_tl|.
+% \cs{tl_new:N} |\g_file_seq_name_tl| \\
+% \cs{tl_gset:Nn} |\g_file_seq_name_tl { g_file_name_seq }| \\
+% \cs{seq_gpush:cV} |{| \cs{tl_use:N} |\g_file_seq_name_tl }| \cs{l_tmpa_tl}.
% \end{quote}
-% (Token list variables are expandable and do not require an
-% accessor function. Other variable types require the appropriate
-% \cs{<var>_use:N} functions to be used in this context.)
+% (Token list variables are expandable and we could omit the
+% accessor function \cs{tl_use:N}. Other variable types require the
+% appropriate \cs{<var>_use:N} functions to be used in this
+% context.)
% \item[V] Value of a variable.\\
% This means that the contents of the register in question is used as the
% argument, be it an integer, a length-type register, a token list variable
@@ -557,21 +637,22 @@
% resulting register to the function.
% \item[x] Fully-expanded token or braced token list.\\
% This means that the argument is expanded as in the replacement
-% text of an~|\edef|, and the expansion is passed to the function as
-% a braced token list. This means that expansion takes place until
-% only unexpandable tokens are left.
-% \item[o] One-level-expanded token or braced token list.\\
+% text of an~\tn{edef}, and the expansion is passed to the function as
+% a braced token list. Expansion takes place until only unexpandable
+% tokens are left. |x|-type arguments cannot be nested.
+% \item[o] One-level-expanded token or braced token list.\\
% This means that the argument is expanded one level, as by
% \tn{expandafter}, and the expansion is passed to the function as a
% braced token list. Note that if the original argument is a braced
% token list then only the first token in that list is expanded.
% In general, using \texttt{V} should be preferred to using
% \texttt{o} for simple variable retrieval.
-% \item[f] Almost the same as the |x| type except here the token list
+% \item[f] Expanding the first token recursively in a braced token
+% list.\\ Almost the same as the |x| type except here the token list
% is expanded fully until the first unexpandable token is found and
% the rest is left unchanged. Note that if this function finds a
% space at the beginning of the argument it will gobble it and not
-% expand the next argument.
+% expand the next token.
% \end{description}
%
% \subsection{Simpler means better}
@@ -587,15 +668,15 @@
% \csname\cf@encoding \string#1\expandafter\endcsname
% \csname ?\string#1\endcsname
% \end{verbatim}
-% This first piece of code is in essence simply a global |\let| whose
-% two arguments firstly have to be constructed before |\let| is
+% This first piece of code is in essence simply a global \tn{let} whose
+% two arguments firstly have to be constructed before \tn{let} is
% executed. The |#1| is a control sequence name such as
% |\textcurrency|. The token to be defined is obtained by
% concatenating the characters of the current font encoding stored in
% |\cf@encoding|, which has to be fully expanded, and the name of the
% symbol. The second token is the same except it uses the default
-% encoding |?|. The result is a mess of interwoven |\expandafter|
-% and |\csname| beloved of all \TeX{} programmers, and the code is
+% encoding |?|. The result is a mess of interwoven \tn{expandafter}
+% and \tn{csname} beloved of all \TeX{} programmers, and the code is
% essentially unreadable.
%
% Using the conventions and functionality outlined here, the task would
@@ -604,7 +685,7 @@
% \cs_gset_eq:cc
% { \cf@encoding \token_to_str:N #1 } { ? \token_to_str:N #1 }
% \end{verbatim}
-% The command |\cs_gset_eq:cc| is a global~|\let| that generates
+% The command \cs{cs_gset_eq:cc} is a global~\tn{let} that generates
% command names out of both of its arguments before making the
% definition. This produces code that is far more readable and more
% likely to be correct first time. (\cs{token_to_str:N} is the \LaTeX3
@@ -623,29 +704,33 @@
% \end{verbatim}
% This piece of code is part of the definition of another function. It
% first produces two things: a token list, by expanding |\group@list| once;
-% and a token whose name comes from~`|sym#3|'. Then the function~|\in@|
+% and a token whose name comes from~`|sym#3|'. Then the function~\cs{in@}
% is called and this tests if its first argument occurs in the token list
% of its second argument.
%
% Again we can improve enormously on the code. First we shall rename
-% the function~|\in@| according to our conventions. A function such as
-% this but taking two normal \enquote{\texttt{n}} arguments might reasonably be
-% named |\seq_test_in:Nn|; thus the variant function we need will be
-% defined with the appropriate argument types and its name will be
-% |\seq_test_in:cV|. Now this code fragment will be simply:
+% the function~\cs{in@}, which tests if its first argument appears
+% within its second argument, according to our conventions. Such a
+% function takes two normal \enquote{\texttt{n}} arguments and operates
+% on token lists: it might reasonably be named |\tl_test_in:nn|. Thus
+% the variant function we need will be defined with the appropriate
+% argument types and its name will be |\tl_test_in:cV|. Now this code
+% fragment will be simply:
% \begin{verbatim}
-% \seq_test_in:cV { sym #3 } \l_group_seq
+% \tl_test_in:cV { sym #3 } \group@list
% \end{verbatim}
-% Note that, in addition to the lack of |\expandafter|, the space after
-% the~|}| will be silently ignored since all white space is ignored in
-% this programming environment.
+% This code could be improved further by using a sequence |\l_group_seq|
+% rather than the bare token list |\group@list|. Note that, in addition
+% to the lack of \tn{expandafter}, the space after the~|}| will be
+% silently ignored since all white space is ignored in this programming
+% environment.
%
% \subsection{New functions from old}
%
% For many common functions the \LaTeX3 kernel will provide variants
% with a range of argument forms, and similarly it is expected that
% extension packages providing new functions will make them available in
-% the all the commonly needed forms.
+% all the commonly needed forms.
%
% However, there will be occasions where it is necessary to construct a
% new such variant form; therefore the expansion module provides a
@@ -690,7 +775,7 @@
% |\demo_cmd_b:xcxcx|, a variant of an existing function
% |\demo_cmd_b:nnnnn|, that fully
% expands arguments 1,~3 and~5, and produces commands to pass as
-% arguments 2 and~4 using~|\csname|.
+% arguments 2 and~4 using~\tn{csname}.
% The definition you need is simply
% \begin{verbatim}
% \cs_generate_variant:Nn \demo_cmd_b:nnnnn { xcxcx }
@@ -715,10 +800,10 @@
% \pkg{expl3}.
% \end{bfseries}
%
-% New modules will be added to the distributed version of \pkg{expl3}
-% as they reach maturity. At present, the \pkg{expl3} bundle consists
-% of a number of modules, most of which are loaded by including the
-% line:
+% New modules will be added to the distributed version of \pkg{expl3}
+% as they reach maturity. At present, the \pkg{expl3} bundle consists
+% of a number of modules, most of which are loaded by including the
+% line:
% \begin{verbatim}
% \RequirePackage{expl3}
% \end{verbatim}
@@ -765,7 +850,7 @@
% }
% \explpkg{l3prg}{
% Program control structures such as boolean data type |bool|, generic
-% do-while loops, case-switches, sorting routines and stepwise loops.
+% do-while loops, and conditional flow.
% }
% \explpkg{l3prop}{
% This implements the data-type for \enquote{property lists} that are used, in
@@ -781,8 +866,9 @@
% This implements data-types such as queues and stacks.
% }
% \explpkg{l3skip}{
-% Implements the \enquote{rubber length} datatype \texttt{skip} and the
-% \enquote{rigid length} datatype |dim|.
+% Implements the \enquote{rubber length} datatype \texttt{skip}, the
+% \enquote{rigid length} datatype |dim|, and the math mode
+% \enquote{rubber length} datatype \texttt{muskip}.
% }
% \explpkg{l3tl}{
% This implements a basic data-type, called a \textit{token-list
@@ -809,8 +895,9 @@
% For example, you may well need \tn{@ifpackageloaded}, as there
% is currently no native \LaTeX3 package loading module.
% \item User level macros should be generated using the mechanism
-% available in the \pkg{xparse} package, which is available from CTAN
-% or the \LaTeX3 SVN repository.
+% available in the \pkg{xparse} package, which is part of the
+% \texttt{l3package} bundle, available from CTAN or the \LaTeX3 SVN
+% repository.
% \item At an internal level, most functions should be generated
% \tn{long} (using \cs{cs_new:Npn}) rather than \enquote{short} (using
% \cs{cs_new_nopar:Npn}). However, functions which take no arguments
@@ -818,7 +905,7 @@
% \item Where possible, declare all variables and functions (using
% \cs{cs_new:Npn}, \cs{tl_new:N}, etc.) before use.
% \item Prefer \enquote{higher-level} functions over \enquote{lower-level},
-% where possible. So for example use \cs{cs_if_exist:N(TF)} in preference
+% where possible. So for example use \cs{cs_if_exist:N(TF)} and not
% \cs{if_cs_exist:N}.
% \item Use space to make code readable. In general, we recommend
% a layout such as:
@@ -826,8 +913,8 @@
% \cs_new:Npn \foo_bar:Nn #1#2
% {
% \cs_if_exist:NTF #1
-% { \foo_bar_aux_i:n {#2} }
-% { \foo_bar_aux_ii:nn {#2} { literal } }
+% { \__foo_bar_aux_i:n {#2} }
+% { \__foo_bar_aux_ii:nn {#2} { literal } }
% }
% \end{verbatim}
% where spaces are used around |{| and |}| except for isolated
@@ -862,11 +949,11 @@
% function name in the \texttt{.log} file. This is useful for debugging
% purposes, as it means that there is a complete list of all functions
% created by each module loaded (with the exceptions of a very small number
-% required by he bootstrap code for \LaTeX3).
+% required by the bootstrap code for \LaTeX3).
%
% \DescribeOption{native-drivers}
% The \texttt{native-drivers} option instructs \LaTeX3 not to use the \LaTeXe{}
-% graphics and colour driver code. Setting this option \texttt{true} uses the
+% graphics driver code. Setting this option \texttt{true} uses the
% driver code intended for a \LaTeX3 format.
%
% \section{The \LaTeX3 Project}
@@ -890,8 +977,8 @@
% \begin{itemize}
% \item Michael Downes
% \item Denys Duchier
-% \item Alan Jeffrey
% \item Morten H{\o}gholm
+% \item Alan Jeffrey
% \item Martin Schr{\"o}der
% \end{itemize}
%
@@ -945,7 +1032,7 @@
% \end{macrocode}
%
% \begin{macro}[aux]{\expl@create@bool@option}
-% \begin{variable}
+% \begin{variable}[int]
% {
% \l@expl@check@declarations@bool ,
% \l@expl@log@functions@bool ,
@@ -965,84 +1052,74 @@
\expl@create@bool@option { check-declarations } \l@expl@check@declarations@bool
\expl@create@bool@option { log-functions } \l@expl@log@functions@bool
\expl@create@bool@option { native-drivers } \l@expl@native@drivers@bool
-\ProcessOptions \relax
\let \expl@create@bool@option \@undefined
+\ProcessOptions \relax
% \end{macrocode}
% \end{variable}
% \end{macro}
%
-% \begin{macrocode}
-\ifodd \l@expl@native@drivers@bool \relax
-\else
- \RequirePackage { color , graphics }
-\fi
-% \end{macrocode}
-%
% We already loaded \pkg{l3names} at the beginning of the \texttt{dtx} file.
% We now load the base of \LaTeX3, stopping once token list variables are
% defined.
% \begin{macrocode}
-\RequirePackage{ l3basics, l3expan, l3tl }
+\RequirePackage { l3basics, l3expan, l3tl }
% \end{macrocode}
%
-% \begin{macro}{\cs_check_exists:N}
+% \begin{macro}[int]{\__cs_check_exists:N}
% When used as a package, there is an option to be picky and to
% check definitions exist. This part of the process is done now, so that
% variable types based on |tl| (for example |clist|, |seq| and |prop|) will
% inherit the appropriate definitions.
% \begin{macrocode}
\ifodd \l@expl@check@declarations@bool \relax
- \cs_new_protected:Npn \cs_check_exists:N #1
+ \cs_new_protected:Npn \__cs_check_exists:N #1
{
\cs_if_exist:NF #1
{
- \msg_kernel_error:nnx { check } { non-declared-variable }
+ \__msg_kernel_error:nnx { check } { non-declared-variable }
{ \token_to_str:N #1 }
}
}
\cs_set_protected:Npn \tl_set:Nn #1#2
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_set_nopar:Npx #1 { \exp_not:n {#2} }
}
\cs_set_protected:Npn \tl_set:Nx #1#2
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_set_nopar:Npx #1 {#2}
}
\cs_set_protected:Npn \tl_gset:Nn #1#2
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_gset_nopar:Npx #1 { \exp_not:n {#2} }
}
\cs_set_protected:Npn \tl_gset:Nx #1#2
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_gset_nopar:Npx #1 {#2}
}
\cs_set_protected:Npn \tl_set_eq:NN #1#2
{
- \cs_check_exists:N #1
- \cs_check_exists:N #2
+ \__cs_check_exists:N #1
+ \__cs_check_exists:N #2
\cs_set_eq:NN #1 #2
}
\cs_set_protected:Npn \tl_gset_eq:NN #1#2
{
- \cs_check_exists:N #1
- \cs_check_exists:N #2
+ \__cs_check_exists:N #1
+ \__cs_check_exists:N #2
\cs_gset_eq:NN #1 #2
}
\fi
% \end{macrocode}
% \end{macro}
%
-% The rest of the code can now be loaded.
+% The second part of the file can now be loaded, stopping once the boolean
+% data type is defined.
% \begin{macrocode}
-\RequirePackage{
- l3seq,
- l3int,
- l3quark,
- l3prg}
+\RequirePackage { l3seq, l3int, l3quark, l3prg }
% \end{macrocode}
%
% Booleans are not based on token lists but do need checking: another
@@ -1051,62 +1128,65 @@
\ifodd \l@expl@check@declarations@bool \relax
\cs_set_protected:Npn \bool_set_true:N #1
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_set_eq:NN #1 \c_true_bool
}
\cs_set_protected:Npn \bool_set_false:N #1
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_set_eq:NN #1 \c_false_bool
}
\cs_set_protected:Npn \bool_gset_true:N #1
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_gset_eq:NN #1 \c_true_bool
}
\cs_set_protected:Npn \bool_gset_false:N #1
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_gset_eq:NN #1 \c_false_bool
}
\cs_set_protected:Npn \bool_set_eq:NN #1
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_set_eq:NN #1
}
\cs_set_protected:Npn \bool_gset_eq:NN #1
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\cs_gset_eq:NN #1
}
\cs_set_protected:Npn \bool_set:Nn #1#2
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\tex_chardef:D #1 = \bool_if_p:n {#2}
}
\cs_set_protected:Npn \bool_gset:Nn #1#2
{
- \cs_check_exists:N #1
+ \__cs_check_exists:N #1
\tex_global:D \tex_chardef:D #1 = \bool_if_p:n {#2}
}
\fi
% \end{macrocode}
%
+% Now everything else can be loaded.
% \begin{macrocode}
-\RequirePackage{
- l3clist,
- l3token,
- l3prop,
- l3msg,
- l3file,
- l3skip,
- l3keys,
- l3fp,
- l3box,
- l3coffins,
- l3color,
- l3luatex
-}
+\RequirePackage
+ {
+ l3clist,
+ l3token,
+ l3prop,
+ l3msg,
+ l3file,
+ l3skip,
+ l3keys,
+ l3fp,
+ l3box,
+ l3coffins,
+ l3color,
+ l3luatex,
+ l3candidates
+ }
% \end{macrocode}
%
% The error message for variables cannot be created before now: this means that
@@ -1114,11 +1194,11 @@
% \begin{macrocode}
\bool_if:nT { \l@expl@check@declarations@bool }
{
- \msg_kernel_new:nnnn { check } { non-declared-variable }
+ \__msg_kernel_new:nnnn { check } { non-declared-variable }
{ The~variable~#1~has~not~been~declared~\msg_line_context:. }
{
Checking~is~active,~and~you~have~tried~do~so~something~like: \\
- \ \ \tl_set:Nn ~ #1 ~ \iow_char:N \{ ~ ... ~ \iow_char:N \} \\
+ \ \ \tl_set:Nn ~ #1 ~ \{ ~ ... ~ \} \\
without~first~having: \\
\ \ \tl_new:N ~ #1 \\
\\
@@ -1128,10 +1208,19 @@
% \end{macrocode}
%
% \begin{macro}{\color}
-% If the native drivers are being used, they can be loaded now. The
-% \cs{color} macro must be defined for showing coffin poles, so
+% The \cs{color} macro must be defined for showing coffin poles, so
% a no-op version is provided here.
% \begin{macrocode}
+\AtBeginDocument
+ {
+ \cs_if_exist:NF \color
+ { \DeclareRobustCommand \color [2] [ ] { } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% If the native drivers are being used, they can be loaded now.
+% \begin{macrocode}
\bool_if:nTF { \l@expl@native@drivers@bool }
{
\xetex_if_engine:TF
@@ -1144,14 +1233,8 @@
\file_input:n { l3dvips.def }
\fi
}
- \AtBeginDocument
- {
- \cs_if_free:NT \color
- { \DeclareRobustCommand \color [2] [ ] { } }
- }
}
% \end{macrocode}
-% \end{macro}
% \begin{macro}
% {
% \box_rotate:Nn,
@@ -1160,10 +1243,24 @@
% \box_resize_to_wd:Nn,
% \box_scale:Nnn
% }
-% If not, alter various definitions to use the \pkg{graphicx} package
-% instead.
+% If not, alter various definitions to use the \pkg{graphics} package
+% instead. The package is loaded right at the start of the hook
+% as there is otherwise a potential issue with \pkg{(x)color}: see
+% \url{http://groups.google.com/group/comp.text.tex/msg/c9de8913c756ef4c}.
% \begin{macrocode}
{
+ \tl_gput_left:Nn \@begindocumenthook { \RequirePackage { graphics } }
+ \__msg_kernel_new:nnnn { box } { clipping-not-available }
+ { Box~clipping~not~available. }
+ {
+ The~\box_clip:N~function~is~only~available~when~loading~expl3~
+ with~the~"native-drivers"~option.
+ }
+ \cs_set_protected:Npn \box_clip:N #1
+ {
+ \hbox_set:Nn #1 { \box_use:N #1 }
+ \__msg_kernel_error:nn { box } { clipping-not-available }
+ }
\cs_set_protected:Npn \box_rotate:Nn #1#2
{ \hbox_set:Nn #1 { \rotatebox {#2} { \box_use:N #1 } } }
\cs_set_protected:Npn \box_resize:Nnn #1#2#3
@@ -1171,8 +1268,8 @@
\hbox_set:Nn #1
{
\resizebox *
- { \etex_dimexpr:D #2 \scan_stop: }
- { \etex_dimexpr:D #3 \scan_stop: }
+ { \__dim_eval:w #2 \__dim_eval_end: }
+ { \__dim_eval:w #3 \__dim_eval_end: }
{ \box_use:N #1 }
}
}
@@ -1180,7 +1277,7 @@
{
\hbox_set:Nn #1
{
- \resizebox * { ! } { \etex_dimexpr:D #2 \scan_stop: }
+ \resizebox * { ! } { \__dim_eval:w #2 \__dim_eval_end: }
{ \box_use:N #1 }
}
}
@@ -1188,12 +1285,19 @@
{
\hbox_set:Nn #1
{
- \resizebox * { \etex_dimexpr:D #2 \scan_stop: } { ! }
+ \resizebox * { \__dim_eval:w #2 \__dim_eval_end: } { ! }
{ \box_use:N #1 }
}
}
\cs_set_protected:Npn \box_scale:Nnn #1#2#3
- { \hbox_set:Nn #1 { \scalebox {#2} [#3] { \box_use:N #1 } } }
+ {
+ \hbox_set:Nn #1
+ {
+ \exp_last_unbraced:Nx \scalebox
+ { { \fp_eval:n {#2} } [ \fp_eval:n {#3} ] }
+ { \box_use:N #1 }
+ }
+ }
}
% \end{macrocode}
% \end{macro}
@@ -1205,7 +1309,7 @@
% \begin{macrocode}
\cs_set_protected_nopar:Npn \ExplSyntaxOn
{
- \bool_if:NF \l_expl_status_bool
+ \bool_if:NF \l__kernel_expl_bool
{
\cs_set_protected_nopar:Npx \ExplSyntaxOff
{
@@ -1220,7 +1324,7 @@
\char_set_catcode:nn { 124 } { \char_value_catcode:n { 124 } }
\char_set_catcode:nn { 126 } { \char_value_catcode:n { 126 } }
\tex_endlinechar:D = \tex_the:D \tex_endlinechar:D \scan_stop:
- \bool_set_false:N \l_expl_status_bool
+ \bool_set_false:N \l__kernel_expl_bool
\cs_set_protected_nopar:Npn \ExplSyntaxOff { }
}
}
@@ -1235,7 +1339,7 @@
\char_set_catcode_other:n { 124 } % pipe
\char_set_catcode_space:n { 126 } % tilde
\tex_endlinechar:D = 32 \scan_stop:
- \bool_set_true:N \l_expl_status_bool
+ \bool_set_true:N \l__kernel_expl_bool
}
\cs_set_protected_nopar:Npx \ExplSyntaxOff
{
@@ -1251,4 +1355,4 @@
%
% \end{implementation}
%
-% \PrintIndex
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx
index d9e59a686a7..6d8f58c86b0 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3alloc.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3alloc.dtx Copyright (C) 1990-2011 The LaTeX3 Project
+%% File: l3alloc.dtx Copyright (C) 1990-2012 The LaTeX3 Project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3alloc.dtx 3355 2012-02-09 07:18:22Z joseph $
- {L3 Experimental register allocation}
+\GetIdInfo$Id: l3alloc.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Register allocation}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -67,7 +67,7 @@
%
% \begin{documentation}
%
-% Note that this module is only used for generating an pkg{expl3}-based
+% Note that this module is only used for generating an \pkg{expl3}-based
% format. Under \LaTeX{}, the \pkg{etex} package is used for allocation
% management.
%
@@ -83,24 +83,29 @@
% \item \TeX{} supports no more than 16 I/O streams for reading
% (\tn{read}) and 16 I/O streams for writing (\tn{write}),
% \item \TeX{} supports no more than 256 inserts.
-% \item The other registers (\tn{count}, \tn{dimen},
-% \tn{skip}, \tn{muskip}, \tn{box}, and \tn{toks})
-% range from 0 to 32768, but registers numbered above 255 are
+% \item The other registers (\tn{count}, \tn{dimen}, \tn{skip},
+% \tn{muskip}, \tn{box}, and \tn{toks}) range from 0 to 32767
+% (65535 for \LuaTeX{}), but registers numbered above 255 are
% accessed somewhat less efficiently.
% \item Registers could be allocated both globally and locally; the
-% use of registers could also be globally or locally. Here we
+% use of registers could also be global or local. Here we
% provide support for globally allocated registers for both
% global and local use.
-% \end{itemize}
+% \end{itemize}
% We also need to allow for some bookkeeping: we need to know which
% register was allocated last and which registers can not be
% allocated by the standard mechanisms.
%
-% \begin{function}[updated = 2011-09-05]{\alloc_new:nnnN}
+% \section{Internal functions}
+%
+% Register-based allocation is a low-level process, and is therefore
+% only to be used as part of kernel code.
+%
+% \begin{function}[updated = 2011-09-05]{\__alloc_new:nnnN}
% \begin{syntax}
-% \cs{alloc_new:nnnN} \Arg{type} \Arg{min} \Arg{max} \meta{function}
+% \cs{__alloc_new:nnnN} \Arg{type} \Arg{min} \Arg{max} \meta{function}
% \end{syntax}
-% Shorthand for allocating new registers. Defines \cs{<type>_new:N} as
+% Shorthand for allocating new registers. Defines \cs{\meta{type}_new:N} as
% and allocator function of the specified \meta{type}, indexed up from
% \meta{min} to a \meta{max}, and with assignment carried out by
% the \meta{function}. This process will create two token lists,
@@ -110,20 +115,18 @@
% numbers which should not be used.
% \end{function}
%
-% \section{Internal functions}
-%
-% \begin{function}[updated = 2011-09-05]{\alloc_setup_type:nnn}
+% \begin{function}[updated = 2011-09-05]{\__alloc_setup_type:nnn}
% \begin{syntax}
-% \cs{alloc_setup_type:nnn} \Arg{type} \Arg{min} \Arg{max}
+% \cs{__alloc_setup_type:nnn} \Arg{type} \Arg{min} \Arg{max}
% \end{syntax}
% Sets up the storage needed for the administration of registers of
% \Arg{type}, which will start allocating at \meta{min} and will issue
% an error if there is an attempt to allocate past the \meta{max}.
% \end{function}
%
-% \begin{function}{\alloc_reg:nNN}
+% \begin{function}{\__alloc_reg:nNN}
% \begin{syntax}
-% \cs{alloc_reg:nNN} \Arg{type} \meta{function} \meta{register}
+% \cs{__alloc_reg:nNN} \Arg{type} \meta{function} \meta{register}
% \end{syntax}
% Preforms the allocation for a new \meta{register} of \meta{type},
% using the allocator \meta{function} (which will be either a
@@ -140,28 +143,33 @@
%<*initex>
% \end{macrocode}
%
-% \begin{macro}{\alloc_new:nnnN}
+% \begin{macrocode}
+%<@@=alloc>
+% \end{macrocode}
+%
+% \begin{macro}[int]{\@@_new:nnnN}
% Shorthand for defining new register types and their allocators:
% \begin{macrocode}
-\cs_new_protected:Npn \alloc_new:nnnN #1#2#3#4
+\cs_new_protected:Npn \@@_new:nnnN #1#2#3#4
{
- \alloc_setup_type:nnn {#1} {#2} {#3}
- \cs_new:cpn { #1 _new:N } ##1 { \alloc_reg:nNN {#1} #4 ##1 }
+ \@@_setup_type:nnn {#1} {#2} {#3}
+ \cs_new:cpn { #1 _new:N } ##1 { \@@_reg:nNN {#1} #4 ##1 }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\alloc_setup_type:nnn}
+% \begin{macro}[int]{\@@_setup_type:nnn}
% For each type of register we need to \enquote{counters} that hold the
% last allocated global register, plus a constant for the maximum
% allocation. We also need a sequence to store the \enquote{exceptions}.
+% All of those variables are internal to the module |#1|.
% \begin{macrocode}
-\cs_new_protected:Npn \alloc_setup_type:nnn #1#2#3
+\cs_new_protected:Npn \@@_setup_type:nnn #1#2#3
{
- \tl_new:c { g_ #1 _allocation_tl }
- \tl_gset:cx { g_ #1 _allocation_tl } { \int_eval:n {#2} }
- \tl_const:cx { c_ #1 _allocation_max_tl } { \int_eval:n {#3} }
- \seq_new:c { g_ #1 _allocation_seq }
+ \tl_new:c { g__ #1 _allocation_tl }
+ \tl_gset:cx { g__ #1 _allocation_tl } { \int_eval:n {#2} }
+ \tl_const:cx { c__ #1 _allocation_max_tl } { \int_eval:n {#3} }
+ \seq_new:c { g__ #1 _allocation_seq }
}
% \end{macrocode}
% \end{macro}
@@ -176,44 +184,44 @@
% \end{macro}
%
% \begin{macro}
-% {box_new:N, \dim_new:N, \int_new:N, \muskip_new:N \skip_new:N}
+% {\box_new:N, \dim_new:N, \int_new:N, \muskip_new:N \skip_new:N}
% To get everything to work correctly for inserts, some register types
% need to have their allocators set up \enquote{early}. It therefore
% makes sense to collect most of them together here.
% \begin{macrocode}
\luatex_if_engine:TF
- { \alloc_new:nnnN { box } \c_zero \c_max_register_int \tex_chardef:D }
- { \alloc_new:nnnN { box } \c_zero \c_max_register_int \tex_mathchardef:D }
-\alloc_new:nnnN { dim } \c_zero \c_max_register_int \tex_dimendef:D
-\alloc_new:nnnN { int } { 11 } \c_max_register_int \tex_countdef:D
-\alloc_new:nnnN { muskip } \c_zero \c_max_register_int \tex_muskipdef:D
-\alloc_new:nnnN { skip } \c_zero \c_max_register_int \tex_skipdef:D
+ { \@@_new:nnnN { box } \c_zero \c_max_register_int \tex_chardef:D }
+ { \@@_new:nnnN { box } \c_zero \c_max_register_int \tex_mathchardef:D }
+\@@_new:nnnN { dim } \c_zero \c_max_register_int \tex_dimendef:D
+\@@_new:nnnN { int } { 11 } \c_max_register_int \tex_countdef:D
+\@@_new:nnnN { muskip } \c_zero \c_max_register_int \tex_muskipdef:D
+\@@_new:nnnN { skip } \c_zero \c_max_register_int \tex_skipdef:D
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\insert_new:N}
-% \begin{macro}[aux]{\alloc_reserve_insert:n}
+% \begin{macro}[aux]{\@@_reserve_insert:n}
% For inserts, there is a need to reserve space in various other registers.
% \begin{macrocode}
-\alloc_new:nnnN { insert } { 221 } { 254 } \tex_chardef:D
+\@@_new:nnnN { insert } { 221 } { 254 } \tex_chardef:D
\group_begin:
- \cs_set_protected:Npn \alloc_reserve_insert:n #1
+ \cs_set_protected:Npn \@@_reserve_insert:n #1
{
- \tex_ifnum:D #1 > \c_insert_allocation_max_tl \scan_stop:
+ \tex_ifnum:D #1 > \c__insert_allocation_max_tl \scan_stop:
\exp_after:wN \use_none:n
\tex_else:D
\exp_after:wN \use:n
\tex_fi:D
{
- \seq_put_right:Nn \g_box_allocation_seq {#1}
- \seq_put_right:Nn \g_dim_allocation_seq {#1}
- \seq_put_right:Nn \g_int_allocation_seq {#1}
- \seq_put_right:Nn \g_skip_allocation_seq {#1}
- \exp_args:Nf \alloc_reserve_insert:n
+ \seq_put_right:Nn \g__box_allocation_seq {#1}
+ \seq_put_right:Nn \g__dim_allocation_seq {#1}
+ \seq_put_right:Nn \g__int_allocation_seq {#1}
+ \seq_put_right:Nn \g__skip_allocation_seq {#1}
+ \exp_args:Nf \@@_reserve_insert:n
{ \etex_numexpr:D #1 + 1 \scan_stop: }
}
}
- \alloc_reserve_insert:n { 221 }
+ \@@_reserve_insert:n { 221 }
\group_end:
% \end{macrocode}
% \end{macro}
@@ -222,45 +230,45 @@
% Box $255$ is reserved by \TeX{} for output, so is protected here from
% use by the allocator.
% \begin{macrocode}
-\seq_put_right:Nn \g_box_allocation_seq { 255 }
+\seq_put_right:Nn \g__box_allocation_seq { 255 }
% \end{macrocode}
%
-% \begin{macro}[int]{\alloc_reg:nNN}
+% \begin{macro}[int]{\@@_reg:nNN}
% This internal macro performs the actual allocation.
% \begin{macrocode}
-\cs_new_protected:Npn \alloc_reg:nNN #1#2#3
+\cs_new_protected:Npn \@@_reg:nNN #1#2#3
{
- \chk_if_free_cs:N #3
- \tex_global:D #2 #3 \tl_use:c { g_ #1 _allocation_tl } \scan_stop:
+ \__chk_if_free_cs:N #3
+ \tex_global:D #2 #3 \tl_use:c { g__ #1 _allocation_tl } \scan_stop:
\iow_log:x
{
\token_to_str:N #3 ~=~ #1 ~register~
- \tl_use:c { g_ #1 _allocation_tl }
+ \tl_use:c { g__ #1 _allocation_tl }
}
- \alloc_next:n {#1}
+ \@@_next:n {#1}
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\alloc_next:n}
+% \begin{macro}[aux]{\@@_next:n}
% Finding the next register to use is a question of doing an increment
% then a check: if we run out of registers then it is a fatal error, so
% there is no need to unwind the change. (The check could be done
% first but that needs an additional calculation.) There is a built-in
% loop to handle reserved allocation positions.
% \begin{macrocode}
-\cs_new_protected:Npn \alloc_next:n #1
+\cs_new_protected:Npn \@@_next:n #1
{
- \tl_gset:cx { g_ #1 _allocation_tl }
- { \int_eval:n { \tl_use:c { g_ #1 _allocation_tl } + 1 } }
+ \tl_gset:cx { g__ #1 _allocation_tl }
+ { \int_eval:n { \tl_use:c { g__ #1 _allocation_tl } + 1 } }
\int_compare:nNnTF
- { \tl_use:c { g_ #1 _allocation_tl } }
- > { \tl_use:c { c_ #1 _allocation_max_tl } }
- { \msg_kernel_fatal:nnx { kernel } { out-of-registers } {#1} }
+ { \tl_use:c { g__ #1 _allocation_tl } }
+ > { \tl_use:c { c__ #1 _allocation_max_tl } }
+ { \__msg_kernel_fatal:nnx { kernel } { out-of-registers } {#1} }
{
- \seq_if_in:cxT { g_ #1 _allocation_seq }
- { \tl_use:c { g_ #1 _allocation_tl } }
- { \alloc_next:n {#1} }
+ \seq_if_in:cxT { g__ #1 _allocation_seq }
+ { \tl_use:c { g__ #1 _allocation_tl } }
+ { \@@_next:n {#1} }
}
}
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
index f6be95ab725..549ec6de6f8 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3basics.dtx
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3basics.dtx 3491 2012-03-04 06:13:18Z bruno $
- {L3 Experimental basic definitions}
+\GetIdInfo$Id: l3basics.dtx 3987 2012-07-15 21:57:39Z joseph $
+ {L3 Basic definitions}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -155,36 +155,36 @@
% for the formal parameters (|#1|, |#2|, \ldots).
% \begin{description}
% \item[\texttt{new}]
-% Create a new function with the \texttt{new} primitives,
+% Create a new function with the \texttt{new} scope,
% such as \cs{cs_new:Npn}. The definition is global and will result in
% an error if it is already defined.
% \item[\texttt{set}]
-% Create a new function with the \texttt{set} primitives,
+% Create a new function with the \texttt{set} scope,
% such as \cs{cs_set:Npn}. The definition is restricted to the current
% \TeX{} group and will not result in an error if the function is already
% defined.
% \item[\texttt{gset}]
-% Create a new function with the \texttt{gset} primitives,
+% Create a new function with the \texttt{gset} scope,
% such as \cs{cs_gset:Npn}. The definition is global and
% will not result in an error if the function is already defined.
% \end{description}
%
-% Within each set of primitives there are different ways to define a function.
+% Within each set of scope there are different ways to define a function.
% The differences depend on restrictions on the actual parameters and
% the expandability of the resulting function.
% \begin{description}
% \item[\texttt{nopar}]
-% Create a new function with the \texttt{nopar} primitives,
+% Create a new function with the \texttt{nopar} restriction,
% such as \cs{cs_set_nopar:Npn}. The parameter may not contain
% \cs{par} tokens.
% \item[\texttt{protected}]
-% Create a new function with the \texttt{protected} primitives,
+% Create a new function with the \texttt{protected} restriction,
% such as \cs{cs_set_protected:Npn}. The parameter may contain
% \cs{par} tokens but the function will not expand within an
% \texttt{x}-type expansion.
% \end{description}
%
-% \subsection{Defining new functions using primitive parameter text}
+% \subsection{Defining new functions using parameter text}
%
% \begin{function}{\cs_new:Npn, \cs_new:cpn, \cs_new:Npx, \cs_new:cpx}
% \begin{syntax}
@@ -613,11 +613,11 @@
% \begin{function}
% {\cs_new_eq:NN, \cs_new_eq:Nc, \cs_new_eq:cN, \cs_new_eq:cc}
% \begin{syntax}
-% \cs{cs_new_eq:NN} \meta{cs 1} \meta{cs 2}
-% \cs{cs_new_eq:NN} \meta{cs 1} \meta{token}
+% \cs{cs_new_eq:NN} \meta{cs_1} \meta{cs_2}
+% \cs{cs_new_eq:NN} \meta{cs_1} \meta{token}
% \end{syntax}
-% Globally creates \meta{control sequence 1} and sets it to have the same
-% meaning as \meta{control sequence 2} or <token>.
+% Globally creates \meta{control sequence_1} and sets it to have the same
+% meaning as \meta{control sequence_2} or <token>.
% The second control sequence may
% subsequently be altered without affecting the copy.
% \end{function}
@@ -625,28 +625,28 @@
% \begin{function}
% {\cs_set_eq:NN, \cs_set_eq:Nc, \cs_set_eq:cN, \cs_set_eq:cc}
% \begin{syntax}
-% \cs{cs_set_eq:NN} \meta{cs 1} \meta{cs 2}
-% \cs{cs_set_eq:NN} \meta{cs 1} \meta{token}
+% \cs{cs_set_eq:NN} \meta{cs_1} \meta{cs_2}
+% \cs{cs_set_eq:NN} \meta{cs_1} \meta{token}
% \end{syntax}
-% Sets \meta{control sequence 1} to have the same meaning as
-% \meta{control sequence 2} (or <token>).
+% Sets \meta{control sequence_1} to have the same meaning as
+% \meta{control sequence_2} (or <token>).
% The second control sequence may subsequently be
% altered without affecting the copy. The assignment of a meaning
-% to the \meta{control sequence 1} is restricted to the current
+% to the \meta{control sequence_1} is restricted to the current
% \TeX{} group level.
% \end{function}
%
% \begin{function}
% {\cs_gset_eq:NN, \cs_gset_eq:Nc, \cs_gset_eq:cN, \cs_gset_eq:cc}
% \begin{syntax}
-% \cs{cs_gset_eq:NN} \meta{cs 1} \meta{cs 2}
-% \cs{cs_gset_eq:NN} \meta{cs 1} \meta{token}
+% \cs{cs_gset_eq:NN} \meta{cs_1} \meta{cs_2}
+% \cs{cs_gset_eq:NN} \meta{cs_1} \meta{token}
% \end{syntax}
-% Globally sets \meta{control sequence 1} to have the same meaning as
-% \meta{control sequence 2} (or <token>).
+% Globally sets \meta{control sequence_1} to have the same meaning as
+% \meta{control sequence_2} (or <token>).
% The second control sequence may subsequently be
% altered without affecting the copy. The assignment of a meaning to
-% the \meta{control sequence 1} is \emph{not} restricted to the current
+% the \meta{control sequence_1} is \emph{not} restricted to the current
% \TeX{} group level: the assignment is global.
% \end{function}
%
@@ -938,56 +938,6 @@
% in the input stream for further processing.
% \end{function}
%
-% \subsection{Decomposing control sequences}
-%
-% \begin{function}[EXP]{\cs_get_arg_count_from_signature:N}
-% \begin{syntax}
-% \cs{cs_get_arg_count_from_signature:N} \meta{function}
-% \end{syntax}
-% Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
-% before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
-% The \meta{number} of tokens in the \meta{signature} is then left in
-% the input stream. If there was no \meta{signature} then the result is
-% the marker value $-1$.
-% \end{function}
-%
-% \begin{function}[EXP]{\cs_get_function_name:N}
-% \begin{syntax}
-% \cs{cs_get_function_name:N} \meta{function}
-% \end{syntax}
-% Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
-% before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
-% The \meta{name} is then left in the input stream without the escape
-% character present made up of tokens with category code $12$
-% (other).
-% \end{function}
-%
-% \begin{function}[EXP]{\cs_get_function_signature:N}
-% \begin{syntax}
-% \cs{cs_get_function_signature:N} \meta{function}
-% \end{syntax}
-% Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
-% before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
-% The \meta{signature} is then left in the input stream made up of
-% tokens with category code $12$ (other).
-% \end{function}
-%
-% \begin{function}[EXP]{\cs_split_function:NN}
-% \begin{syntax}
-% \cs{cs_split_function:NN} \meta{function} \meta{processor}
-% \end{syntax}
-% Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
-% before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
-% This information is then placed in the input stream after the
-% \meta{processor} function in three parts: the \meta{name}, the
-% \meta{signature} and a logic token indicating if a colon was found
-% (to differentiate variables from function names). The \meta{name}
-% will not include the escape character, and both the \meta{name} and
-% \meta{signature} are made up of tokens with category code $12$
-% (other). The \meta{processor} should be a function with argument
-% specification \texttt{:nnN} (plus any trailing arguments needed).
-% \end{function}
-%
% \section{Predicates and conditionals}
% \label{sec:predicates}
%
@@ -1031,7 +981,7 @@
% are expandable and have names that end with |_p| in the
% description part. For example,
% \begin{quote}
-% |\cs_if_free_p:N|
+% \cs{cs_if_free_p:N}
% \end{quote}
% would be a predicate function for the same type of test as the
% conditional described above. It would return \enquote{true} if its
@@ -1100,7 +1050,7 @@
% \begin{function}[EXP,pTF]
% {
% \str_if_eq:nn, \str_if_eq:Vn, \str_if_eq:on, \str_if_eq:no,
-% \str_if_eq:nV, \str_if_eq:VV, \str_if_eq:xx
+% \str_if_eq:nV, \str_if_eq:VV
% }
% \begin{syntax}
% \cs{str_if_eq_p:nn} \Arg{tl_1} \Arg{tl_2}
@@ -1110,11 +1060,63 @@
% basis, and is \texttt{true} if the two lists contain the same
% characters in the same order. Thus for example
% \begin{verbatim}
-% \str_if_eq_p:xx { abc } { \tl_to_str:n { abc } }
+% \str_if_eq_p:no { abc } { \tl_to_str:n { abc } }
+% \end{verbatim}
+% is logically \texttt{true}.
+% \end{function}
+%
+% \begin{function}[EXP,pTF, added = 2012-06-05]{\str_if_eq_x:nn}
+% \begin{syntax}
+% \cs{str_if_eq_x_p:nn} \Arg{tl_1} \Arg{tl_2}
+% \cs{str_if_eq_x:nnTF} \Arg{tl_1} \Arg{tl_2} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Compares the full expansion of two \meta{token lists} on a character by
+% character basis, and is \texttt{true} if the two lists contain the same
+% characters in the same order. Thus for example
+% \begin{verbatim}
+% \str_if_eq_x_p:nn { abc } { \tl_to_str:n { abc } }
% \end{verbatim}
-% is logically \texttt{true}. All versions of these functions are fully
-% expandable (including those involving an \texttt{x}-type
-% expansion).
+% is logically \texttt{true}.
+% \end{function}
+%
+% \begin{function}[added = 2012-06-03, EXP]{\str_case:nnn, \str_case:onn}
+% \begin{syntax}
+% \cs{str_case:nnn} \Arg{test string} \\
+% ~~|{| \\
+% ~~~~\Arg{string case_1} \Arg{code case_1} \\
+% ~~~~\Arg{string case_2} \Arg{code case_2} \\
+% ~~~~\ldots \\
+% ~~~~\Arg{string case_n} \Arg{code case_n} \\
+% ~~|}| \\
+% ~~\Arg{else code}
+% \end{syntax}
+% This function compares the \meta{test string} in turn with each
+% of the \meta{string cases}. If the two are equal (as described for
+% \cs{str_if_eq:nnTF} then the
+% associated \meta{code} is left in the input stream. If none of
+% the tests are \texttt{true} then the \texttt{else code} will be
+% left in the input stream.
+% \end{function}
+%
+% \begin{function}[added = 2012-06-05, EXP]{\str_case_x:nnn}
+% \begin{syntax}
+% \cs{str_case_x:nnn} \Arg{test string} \\
+% ~~|{| \\
+% ~~~~\Arg{string case_1} \Arg{code case_1} \\
+% ~~~~\Arg{string case_2} \Arg{code case_2} \\
+% ~~~~\ldots \\
+% ~~~~\Arg{string case_n} \Arg{code case_n} \\
+% ~~|}| \\
+% ~~\Arg{else code}
+% \end{syntax}
+% This function comapres the full expansion of the \meta{test string}
+% in turn with the full expansion of the \meta{string cases}. If the two
+% full expansions are equal (as described for \cs{str_if_eq:nnTF} then the
+% associated \meta{code} is left in the input stream. If none of the tests
+% are \texttt{true} then the \texttt{else code} will be left in the input
+% stream. The \meta{test string} is expanded in each comparison, and must
+% always yield the same result: for example, random numbers should
+% not be used within this string.
% \end{function}
%
% \subsection{Engine-specific conditionals}
@@ -1146,7 +1148,7 @@
% expand whatever comes after them and others don't. Hence the names
% for these underlying functions will often contain a |:w| part but
% higher level functions are often available. See for instance
-% |\int_compare_p:nNn| which is a wrapper for |\if_num:w|.
+% \cs{int_compare_p:nNn} which is a wrapper for \cs{if_int_compare:w}.
%
% Certain conditionals deal with specific data types like boxes and
% fonts and are described there. The ones described below are either
@@ -1167,7 +1169,7 @@
% for more.
% \begin{texnote}
% These are equivalent to their corresponding \TeX\ primitive
-% conditionals; |\reverse_if:N| is \eTeX's |\unless|.
+% conditionals; \cs{reverse_if:N} is \eTeX's \tn{unless}.
% \end{texnote}
% \end{function}
%
@@ -1180,7 +1182,7 @@
% <arg_1> and <arg_2> could be functions, variables, tokens; in all cases the
% \emph{unexpanded} definitions are compared.
% \begin{texnote}
-% This is \TeX{}'s |\ifx|.
+% This is \TeX{}'s \tn{ifx}.
% \end{texnote}
% \end{function}
%
@@ -1223,45 +1225,105 @@
%
% \section{Internal kernel functions}
%
-% \begin{function}{\chk_if_exist_cs:N, \chk_if_exist_cs:c}
+% \begin{function}{\__chk_if_exist_cs:N, \__chk_if_exist_cs:c}
% \begin{syntax}
-% \cs{chk_if_exist_cs:N} \meta{cs}
+% \cs{__chk_if_exist_cs:N} \meta{cs}
% \end{syntax}
% This function checks that \meta{cs} exists according to the
% criteria for \cs{cs_if_exist_p:N}, and if not raises a kernel-level
% error.
% \end{function}
%
-% \begin{function}{\chk_if_free_cs:N, \chk_if_free_cs:c}
+% \begin{function}{\__chk_if_free_cs:N, \__chk_if_free_cs:c}
% \begin{syntax}
-% \cs{chk_if_free_cs:N} \meta{cs}
+% \cs{__chk_if_free_cs:N} \meta{cs}
% \end{syntax}
% This function checks that \meta{cs} is free according to the
% criteria for \cs{cs_if_free_p:N}, and if not raises a kernel-level
% error.
% \end{function}
%
-% \section{Experimental functions}
+% \begin{function}[EXP]{\__cs_count_signature:N, \__cs_count_signature:c}
+% \begin{syntax}
+% \cs{__cs_count_signature:N} \meta{function}
+% \end{syntax}
+% Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
+% before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
+% The \meta{number} of tokens in the \meta{signature} is then left in
+% the input stream. If there was no \meta{signature} then the result is
+% the marker value $-1$.
+% \end{function}
%
-% \begin{function}[EXP,TF,added=2011-10-10]
-% {\cs_if_exist_use:N, \cs_if_exist_use:c}
+% \begin{function}[EXP]{\__cs_split_function:NN}
% \begin{syntax}
-% \cs{cs_if_exist_use:NTF} \meta{control sequence} \Arg{true code} \Arg{false code}
+% \cs{__cs_split_function:NN} \meta{function} \meta{processor}
% \end{syntax}
-% If the \meta{control sequence} exists, leave it in the input stream,
-% followed by the \meta{true code} (unbraced). Otherwise, leave the
-% \meta{false} code in the input stream. For example,
-% \begin{verbatim}
-% \cs_set:Npn \mypkg_use_character:N #1
-% { \cs_if_exist_use:cF { mypkg_#1:n } { \mypkg_default:N #1 } }
-% \end{verbatim}
-% calls the function |\mypkg_#1:n| if it exists, and falls back to
-% a default action otherwise. This could also be done (more slowly)
-% using \cs{prg_case_str:xxn}.
-% \begin{texnote}
-% The \texttt{c} variants do not introduce the \meta{control sequence}
-% in the hash table if it is not there.
-% \end{texnote}
+% Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
+% before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
+% This information is then placed in the input stream after the
+% \meta{processor} function in three parts: the \meta{name}, the
+% \meta{signature} and a logic token indicating if a colon was found
+% (to differentiate variables from function names). The \meta{name}
+% will not include the escape character, and both the \meta{name} and
+% \meta{signature} are made up of tokens with category code $12$
+% (other). The \meta{processor} should be a function with argument
+% specification \texttt{:nnN} (plus any trailing arguments needed).
+% \end{function}
+%
+% \begin{function}[EXP]{\__cs_get_function_name:N}
+% \begin{syntax}
+% \cs{__cs_get_function_name:N} \meta{function}
+% \end{syntax}
+% Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
+% before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
+% The \meta{name} is then left in the input stream without the escape
+% character present made up of tokens with category code $12$
+% (other).
+% \end{function}
+%
+% \begin{function}[EXP]{\__cs_get_function_signature:N}
+% \begin{syntax}
+% \cs{__cs_get_function_signature:N} \meta{function}
+% \end{syntax}
+% Splits the \meta{function} into the \meta{name} (\emph{i.e.}~the part
+% before the colon) and the \meta{signature} (\emph{i.e.}~after the colon).
+% The \meta{signature} is then left in the input stream made up of
+% tokens with category code $12$ (other).
+% \end{function}
+%
+% \begin{function}{\__cs_tmp:w}
+% Function used for various short-term usages, for instance defining
+% functions whose definition involves tokens which are hard to insert
+% normally (spaces, charactes with category other).
+% \end{function}
+%
+% \begin{function}{\__kernel_register_show:N, \__kernel_register_show:c}
+% \begin{syntax}
+% \cs{\__kernel_register_show:N} \meta{register}
+% \end{syntax}
+% Used to show the contents of a \TeX{} register at the terminal, formatted
+% such that internal parts of the mechanism are not visible.
+% \end{function}
+%
+% \begin{function}{\__prg_case_end:nw}
+% \begin{syntax}
+% \cs{__prg_case_end:nw} \Arg{code} \meta{tokens} \cs{q_recursion_stop}
+% \end{syntax}
+% Used to terminate case statements (\cs{int_case:nnn}, \emph{etc.})
+% by removing trailing \meta{tokens} and the end marker
+% \cs{q_recursion_stop}, and inserting the \meta{code} for the successful
+% case.
+% \end{function}
+%
+% \begin{function}{\__str_if_eq_x_return:nn}
+% \begin{syntax}
+% \cs{__str_if_eq_x_return:nn} \Arg{tl_1} \Arg{tl_2}
+% \end{syntax}
+% Compares the full expansion of two \meta{token lists} on a character by
+% character basis, and is \texttt{true} if the two lists contain the same
+% characters in the same order. Either \cs{prg_return_true:} or
+% \cs{prg_return_false:} is then left in the input stream. This is a version
+% of \cs{str_if_eq_x:nn(TF)} coded for speed.
% \end{function}
%
% \end{documentation}
@@ -1278,7 +1340,7 @@
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -1370,11 +1432,11 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[EXP]{\if_int_compare:w, \int_to_roman:w}
+% \begin{macro}[EXP]{\if_int_compare:w, \__int_to_roman:w}
% For integers.
% \begin{macrocode}
\tex_let:D \if_int_compare:w \tex_ifnum:D
-\tex_let:D \int_to_roman:w \tex_romannumeral:D
+\tex_let:D \__int_to_roman:w \tex_romannumeral:D
% \end{macrocode}
% \end{macro}
%
@@ -1385,15 +1447,6 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\tex_global:D, \tex_long:D, \etex_protected:D}
-% Three prefixes for assignments.
-% \begin{macrocode}
-\tex_let:D \tex_global:D \tex_global:D
-\tex_let:D \tex_long:D \tex_long:D
-\tex_let:D \tex_protected:D \etex_protected:D
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}[EXP]{\exp_args:Nc}
% Discussed in \pkg{l3expan}, but needed much earlier.
% \begin{macrocode}
@@ -1403,15 +1456,16 @@
%
% \begin{macro}[EXP]{\token_to_str:c, \cs_meaning:c}
% \begin{macro}{\cs_show:c}
-% A small number of variants by hand. Some of the necessary functions
+% A small number of variants defined by hand.
+% Some of the necessary functions
% (\cs{use_i:nn}, \cs{use_ii:nn}, and \cs{exp_args:NNc}) are not
% defined at that point yet, but will be defined before those variants
% are used. The \cs{cs_meaning:c} command must check for an undefined
% control sequence to avoid defining it mistakenly. The
% \cs{cs_show:c} command is \enquote{protected} because its action is
% not expandable. Also, the conversion of its argument to a control
-% sequence is done within a group to avoid converting it to
-% \tn{relax}.
+% sequence is done within a group to avoid showing \tn{relax} for
+% undefined control sequences.
% \begin{macrocode}
\tex_def:D \token_to_str:c { \exp_args:Nc \token_to_str:N }
\tex_long:D \tex_def:D \cs_meaning:c #1
@@ -1424,7 +1478,7 @@
{ \exp_args:Nc \cs_meaning:N {#1} }
{ \tl_to_str:n {undefined} }
}
-\tex_protected:D \tex_def:D \cs_show:c
+\etex_protected:D \tex_def:D \cs_show:c
{ \group_begin: \exp_args:NNc \group_end: \cs_show:N }
% \end{macrocode}
% \end{macro}
@@ -1434,17 +1488,17 @@
%
% \begin{variable}{\c_minus_one, \c_zero, \c_sixteen}
% \begin{variable}{\c_six, \c_seven, \c_twelve}
-% We need the constants |\c_minus_one| and |\c_sixteen| now for
-% writing information to the log and the terminal and |\c_zero|
+% We need the constants \cs{c_minus_one} and \cs{c_sixteen} now for
+% writing information to the log and the terminal and \cs{c_zero}
% which is used by some functions in the \textsf{l3alloc} module. The
% rest are defined in the \textsf{l3int} module -- at least for the
-% ones that can be defined with |\tex_chardef:D| or
-% |\tex_mathchardef:D|. For other constants the \textsf{l3int} module is
+% ones that can be defined with \cs{tex_chardef:D} or
+% \cs{tex_mathchardef:D}. For other constants the \textsf{l3int} module is
% required but it can't be used until the allocation has been set
% up properly! The actual allocation mechanism is in
% \textsf{l3alloc} and as \TeX{} wants to reserve count registers
% 0--9, the first available one is~10 so we use that for
-% |\c_minus_one|.
+% \cs{c_minus_one}.
% \begin{macrocode}
%<*package>
\tex_let:D \c_minus_one \m@ne
@@ -1453,18 +1507,18 @@
\tex_countdef:D \c_minus_one = 10 ~
\c_minus_one = -1 ~
%</initex>
-\tex_chardef:D \c_sixteen = 16~
-\tex_chardef:D \c_zero = 0~
-\tex_chardef:D \c_six = 6~
-\tex_chardef:D \c_seven = 7~
-\tex_chardef:D \c_twelve = 12~
+\tex_chardef:D \c_sixteen = 16 ~
+\tex_chardef:D \c_zero = 0 ~
+\tex_chardef:D \c_six = 6 ~
+\tex_chardef:D \c_seven = 7 ~
+\tex_chardef:D \c_twelve = 12 ~
% \end{macrocode}
% \end{variable}
% \end{variable}
%
% \begin{variable}{\c_max_register_int}
% This is here as this particular integer is needed both in package
-% mode and to bootstrap \pkg{l3alloc}.
+% mode and to bootstrap \pkg{l3alloc}, and is documented in \pkg{l3int}.
% \begin{macrocode}
\etex_ifdefined:D \luatex_luatexversion:D
\tex_chardef:D \c_max_register_int = 65 535 ~
@@ -1486,24 +1540,24 @@
% \cs_set_protected_nopar:Npn , \cs_set_protected_nopar:Npx ,
% \cs_set_protected:Npn , \cs_set_protected:Npx
% }
-% All assignment functions in \LaTeX3 should be naturally robust;
+% All assignment functions in \LaTeX3 should be naturally protected;
% after all, the \TeX{} primitives for assignments are and it can be
% a cause of problems if others aren't.
% \begin{macrocode}
\tex_let:D \cs_set_nopar:Npn \tex_def:D
\tex_let:D \cs_set_nopar:Npx \tex_edef:D
-\tex_protected:D \cs_set_nopar:Npn \cs_set:Npn
+\etex_protected:D \cs_set_nopar:Npn \cs_set:Npn
{ \tex_long:D \cs_set_nopar:Npn }
-\tex_protected:D \cs_set_nopar:Npn \cs_set:Npx
+\etex_protected:D \cs_set_nopar:Npn \cs_set:Npx
{ \tex_long:D \cs_set_nopar:Npx }
-\tex_protected:D \cs_set_nopar:Npn \cs_set_protected_nopar:Npn
- { \tex_protected:D \cs_set_nopar:Npn }
-\tex_protected:D \cs_set_nopar:Npn \cs_set_protected_nopar:Npx
- { \tex_protected:D \cs_set_nopar:Npx }
+\etex_protected:D \cs_set_nopar:Npn \cs_set_protected_nopar:Npn
+ { \etex_protected:D \cs_set_nopar:Npn }
+\etex_protected:D \cs_set_nopar:Npn \cs_set_protected_nopar:Npx
+ { \etex_protected:D \cs_set_nopar:Npx }
\cs_set_protected_nopar:Npn \cs_set_protected:Npn
- { \tex_protected:D \tex_long:D \cs_set_nopar:Npn }
+ { \etex_protected:D \tex_long:D \cs_set_nopar:Npn }
\cs_set_protected_nopar:Npn \cs_set_protected:Npx
- { \tex_protected:D \tex_long:D \cs_set_nopar:Npx }
+ { \etex_protected:D \tex_long:D \cs_set_nopar:Npx }
% \end{macrocode}
% \end{macro}
%
@@ -1523,13 +1577,13 @@
\cs_set_protected_nopar:Npn \cs_gset:Npx
{ \tex_long:D \cs_gset_nopar:Npx }
\cs_set_protected_nopar:Npn \cs_gset_protected_nopar:Npn
- { \tex_protected:D \cs_gset_nopar:Npn }
+ { \etex_protected:D \cs_gset_nopar:Npn }
\cs_set_protected_nopar:Npn \cs_gset_protected_nopar:Npx
- { \tex_protected:D \cs_gset_nopar:Npx }
+ { \etex_protected:D \cs_gset_nopar:Npx }
\cs_set_protected_nopar:Npn \cs_gset_protected:Npn
- { \tex_protected:D \tex_long:D \cs_gset_nopar:Npn }
+ { \etex_protected:D \tex_long:D \cs_gset_nopar:Npn }
\cs_set_protected_nopar:Npn \cs_gset_protected:Npx
- { \tex_protected:D \tex_long:D \cs_gset_nopar:Npx }
+ { \etex_protected:D \tex_long:D \cs_gset_nopar:Npx }
% \end{macrocode}
% \end{macro}
%
@@ -1544,18 +1598,18 @@
%
% \begin{macro}{\use:x}
% Fully expands its argument and passes it to the input stream. Uses
-% the reserved \cs{l_exp_internal_tl} which will be set up in \pkg{l3expan}.
+% the reserved \cs{l__exp_internal_tl} which will be set up in \pkg{l3expan}.
% \begin{macrocode}
\cs_set_protected:Npn \use:x #1
{
- \cs_set_nopar:Npx \l_exp_internal_tl {#1}
- \l_exp_internal_tl
+ \cs_set_nopar:Npx \l__exp_internal_tl {#1}
+ \l__exp_internal_tl
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[EXP]{\use:n, \use:nn, \use:nnn, \use:nnnn}
-% These macro grabs its arguments and returns it back to the input
+% These macros grab their arguments and returns them back to the input
% (with outer braces removed).
% \begin{macrocode}
\cs_set:Npn \use:n #1 {#1}
@@ -1663,20 +1717,25 @@
% testing and processing must return the \meta{state} this leaves
% \TeX{} in. Therefore, a simple user interface could be something like
% \begin{verbatim}
-% \if_meaning:w #1#2 \prg_return_true: \else:
-% \if_meaning:w #1#3 \prg_return_true: \else:
-% \prg_return_false:
-% \fi: \fi:
+% \if_meaning:w #1#2
+% \prg_return_true:
+% \else:
+% \if_meaning:w #1#3
+% \prg_return_true:
+% \else:
+% \prg_return_false:
+% \fi:
+% \fi:
% \end{verbatim}
% Usually, a \TeX{} programmer would have to insert a number of
-% |\exp_after:wN|s to ensure the state value is returned at exactly
+% \cs{exp_after:wN}s to ensure the state value is returned at exactly
% the point where the last conditional is finished. However, that
% obscures the code and forces the \TeX{} programmer to prove that
% he/she knows the $2^{n}-1$ table. We therefore provide the simpler
% interface.
%
% \begin{macro}[EXP]{\prg_return_true:, \prg_return_false:}
-% The idea here is that \cs{int_to_roman:w} will expand fully any
+% The idea here is that \cs{__int_to_roman:w} will expand fully any
% \cs{else:} and the \cs{fi:} that are waiting to be discarded,
% before reaching the \cs{c_zero} which will leave the expansion null.
% The code can then leave either the first or second argument in the
@@ -1685,9 +1744,9 @@
% to see this.
% \begin{macrocode}
\cs_set_nopar:Npn \prg_return_true:
- { \exp_after:wN \use_i:nn \int_to_roman:w }
+ { \exp_after:wN \use_i:nn \__int_to_roman:w }
\cs_set_nopar:Npn \prg_return_false:
- { \exp_after:wN \use_ii:nn \int_to_roman:w}
+ { \exp_after:wN \use_ii:nn \__int_to_roman:w}
% \end{macrocode}
% An extended state space could be implemented by including a more
% elaborate function in place of \cs{use_i:nn}/\cs{use_ii:nn}. Provided
@@ -1701,29 +1760,29 @@
% \prg_set_protected_conditional:Npnn ,
% \prg_new_protected_conditional:Npnn ,
% }
-% \begin{macro}[aux]{\prg_generate_conditional_parm_aux:NNpnn}
+% \begin{macro}[aux]{\__prg_generate_conditional_parm:nnNpnn}
% The user functions for the types using parameter text from the
% programmer. The various functions only differ by which function is
% used for the assignment. For those |Npnn| type functions, we must
% grab the parameter text, reading everything up to a left brace
% before continuing. Then split the base function into name and
% signature, and feed \Arg{name} \Arg{signature} \meta{boolean}
-% \meta{defining~function} |{parm}| \Arg{parameters} |{TF,...}|
+% \Arg{set~or~new} \Arg{maybe~protected} \Arg{parameters} |{TF,...}|
% \Arg{code} to the auxiliary function responsible for defining all
% conditionals.
% \begin{macrocode}
\cs_set_protected_nopar:Npn \prg_set_conditional:Npnn
- { \prg_generate_conditional_parm_aux:NNpnn \cs_set:Npn }
+ { \__prg_generate_conditional_parm:nnNpnn { set } { } }
\cs_set_protected_nopar:Npn \prg_new_conditional:Npnn
- { \prg_generate_conditional_parm_aux:NNpnn \cs_new:Npn }
+ { \__prg_generate_conditional_parm:nnNpnn { new } { } }
\cs_set_protected_nopar:Npn \prg_set_protected_conditional:Npnn
- { \prg_generate_conditional_parm_aux:NNpnn \cs_set_protected:Npn }
+ { \__prg_generate_conditional_parm:nnNpnn { set } { _protected } }
\cs_set_protected_nopar:Npn \prg_new_protected_conditional:Npnn
- { \prg_generate_conditional_parm_aux:NNpnn \cs_new_protected:Npn }
-\cs_set_protected:Npn \prg_generate_conditional_parm_aux:NNpnn #1#2#3#
+ { \__prg_generate_conditional_parm:nnNpnn { new } { _protected } }
+\cs_set_protected:Npn \__prg_generate_conditional_parm:nnNpnn #1#2#3#4#
{
- \cs_split_function:NN #2 \prg_generate_conditional_aux:nnNNnnnn
- #1 { parm } {#3}
+ \__cs_split_function:NN #3 \__prg_generate_conditional:nnNnnnnn
+ {#1} {#2} {#4}
}
% \end{macrocode}
% \end{macro}
@@ -1736,204 +1795,248 @@
% \prg_set_protected_conditional:Nnn ,
% \prg_new_protected_conditional:Nnn ,
% }
-% \begin{macro}[aux]{\prg_generate_conditional_count_aux:NNnn}
+% \begin{macro}[aux]
+% {
+% \__prg_generate_conditional_count:nnNnn ,
+% \__prg_generate_conditional_count:nnNnnnn
+% }
% The user functions for the types automatically inserting the correct
% parameter text based on the signature. The various functions only
-% differ by which function is used for the assignment. For those |Nnn|
-% type functions, we calculate the number of arguments. Then split the
-% base function into name and signature, and feed \Arg{name}
-% \Arg{signature} \meta{boolean} \meta{defining~function} |{count}|
-% \Arg{arg~count} |{TF,...}| \Arg{code} to the auxiliary function
-% responsible for defining all conditionals.
+% differ by which function is used for the assignment. Split the base
+% function into name and signature. The second auxiliary generates
+% the parameter text from the number of letters in the signature.
+% Then feed \Arg{name} \Arg{signature} \meta{boolean} \Arg{set~or~new}
+% \Arg{maybe~protected} \Arg{parameters} |{TF,...}| \Arg{code} to the
+% auxiliary function responsible for defining all conditionals. If
+% the \meta{signature} has more than $9$ letters, the definition is
+% aborted since \TeX{} macros have at most $9$ arguments. The
+% erroneous case where the function name contains no colon is captured
+% later.
% \begin{macrocode}
\cs_set_protected_nopar:Npn \prg_set_conditional:Nnn
- { \prg_generate_conditional_count_aux:NNnn \cs_set:Npn }
+ { \__prg_generate_conditional_count:nnNnn { set } { } }
\cs_set_protected_nopar:Npn \prg_new_conditional:Nnn
- { \prg_generate_conditional_count_aux:NNnn \cs_new:Npn }
+ { \__prg_generate_conditional_count:nnNnn { new } { } }
\cs_set_protected_nopar:Npn \prg_set_protected_conditional:Nnn
- { \prg_generate_conditional_count_aux:NNnn \cs_set_protected:Npn }
+ { \__prg_generate_conditional_count:nnNnn { set } { _protected } }
\cs_set_protected_nopar:Npn \prg_new_protected_conditional:Nnn
- { \prg_generate_conditional_count_aux:NNnn \cs_new_protected:Npn }
-\cs_set_protected:Npn \prg_generate_conditional_count_aux:NNnn #1#2
+ { \__prg_generate_conditional_count:nnNnn { new } { _protected } }
+\cs_set_protected:Npn \__prg_generate_conditional_count:nnNnn #1#2#3
+ {
+ \__cs_split_function:NN #3 \__prg_generate_conditional_count:nnNnnnn
+ {#1} {#2}
+ }
+\cs_set_protected:Npn \__prg_generate_conditional_count:nnNnnnn #1#2#3#4#5
{
- \exp_args:Nnf \use:n
+ \__cs_parm_from_arg_count:nnF
+ { \__prg_generate_conditional:nnNnnnnn {#1} {#2} #3 {#4} {#5} }
+ { \tl_count:n {#2} }
{
- \cs_split_function:NN #2 \prg_generate_conditional_aux:nnNNnnnn
- #1 { count }
+ \__msg_kernel_error:nnxx { kernel } { bad-number-of-arguments }
+ { \token_to_str:c { #1 : #2 } }
+ { \tl_count:n {#2} }
+ \use_none:nn
}
- { \cs_get_arg_count_from_signature:N #2 }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\prg_set_eq_conditional:NNn,\prg_new_eq_conditional:NNn}
-% The obvious setting-equal functions.
-% \begin{macrocode}
-\cs_set_protected:Npn \prg_set_eq_conditional:NNn #1#2#3
- { \prg_set_eq_conditional_aux:NNNn \cs_set_eq:cc #1#2 {#3} }
-\cs_set_protected:Npn \prg_new_eq_conditional:NNn #1#2#3
- { \prg_set_eq_conditional_aux:NNNn \cs_new_eq:cc #1#2 {#3} }
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}[aux]
% {
-% \prg_generate_conditional_aux:nnNNnnnn,
-% \prg_generate_conditional_aux:nnw
+% \__prg_generate_conditional:nnNnnnnn,
+% \__prg_generate_conditional:nnnnnnw
% }
% The workhorse here is going through a list of desired forms, \emph{i.e.},
% |p|, |TF|, |T| and |F|. The first three arguments come from splitting up
% the base form of the conditional, which gives the name, signature
% and a boolean to signal whether or not there was a colon in the
-% name. For the time being, we do not use this piece of information
-% but could well throw an error. The fourth argument is how to
-% define this function, the fifth is the text |parm| or |count| for
-% which version to use to define the functions, the sixth is the
-% parameters to use (possibly empty) or number of arguments, the
-% seventh is the list of forms to define, the eight is the
+% name. In the absence of a colon, we throw an error and don't define
+% any conditional. The fourth and fifth arguments build up the
+% defining function. The sixth is the parameters to use (possibly
+% empty), the seventh is the list of forms to define, the eigth is the
% replacement text which we will augment when defining the forms.
% \begin{macrocode}
-\cs_set_protected:Npn \prg_generate_conditional_aux:nnNNnnnn #1#2#3#4#5#6#7#8
+\cs_set_protected:Npn \__prg_generate_conditional:nnNnnnnn #1#2#3#4#5#6#7#8
{
- \prg_generate_conditional_aux:nnw {#5}
- {
- #4 {#1} {#2} {#6} {#8}
- }
- #7 , ? , \q_recursion_stop
+ \if_meaning:w \c_true_bool #3
+ \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \use_ii:nn
+ \fi:
+ {
+ \__prg_generate_conditional:nnnnnnw
+ {#4} {#5} {#1} {#2} {#6} {#8}
+ #7 , , \q_recursion_stop
+ }
+ {
+ \__msg_kernel_error:nnx { kernel } { missing-colon }
+ { \token_to_str:c {#1} }
+ }
}
% \end{macrocode}
-% Looping through the list of desired forms. First is the text |parm|
-% or |count|, second is five arguments packed together and third is
-% the form. Use text and form to call the correct type.
+% Looping through the list of desired forms. First are six arguments
+% and seventh is the form. Use the form to call the
+% correct type. If the form does not exist, the \cs{use:c}
+% construction results in \tn{relax}, and the error message is
+% displayed, then \cs{use_none:nnnnnnn} cleans up. Otherwise, the
+% error message is removed by the variant form.
% \begin{macrocode}
-\cs_set_protected:Npn \prg_generate_conditional_aux:nnw #1#2#3 ,
+\cs_set_protected:Npn \__prg_generate_conditional:nnnnnnw #1#2#3#4#5#6#7 ,
{
- \if:w ?#3
+ \if_catcode:w \scan_stop: \etex_detokenize:D {#7} \scan_stop:
\exp_after:wN \use_none_delimit_by_q_recursion_stop:w
\fi:
- \use:c { prg_generate_#3_form_#1:Nnnnn } #2
- \prg_generate_conditional_aux:nnw {#1} {#2}
+ \use:c { __prg_generate_ \etex_detokenize:D {#7} _form:wnnnnnn }
+ \__msg_kernel_error:nnxx
+ { kernel } { conditional-form-unknown }
+ { \tl_to_str:n {#7} } { \token_to_str:c { #3 : #4 } }
+ \use_none:nnnnnnn
+ \q_stop
+ {#1} {#2} {#3} {#4} {#5} {#6}
+ \__prg_generate_conditional:nnnnnnw {#1} {#2} {#3} {#4} {#5} {#6}
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]
% {
-% \prg_generate_p_form_parm:Nnnnn,
-% \prg_generate_TF_form_parm:Nnnnn,
-% \prg_generate_T_form_parm:Nnnnn,
-% \prg_generate_F_form_parm:Nnnnn
+% \__prg_generate_p_form:wnnnnnn,
+% \__prg_generate_TF_form:wnnnnnn,
+% \__prg_generate_T_form:wnnnnnn,
+% \__prg_generate_F_form:wnnnnnn
% }
-% How to generate the various forms. The |parm| types here takes the
-% following arguments: 1: how to define (an N-type), 2: name, 3:
-% signature, 4: parameter text (or empty), 5: replacement. Remember that
-% the logic-returning functions expect two arguments to be present after
-% \cs{c_zero}: notice the construction of the different variants
-% relies on this, and that the |TF| variant will be slightly faster
-% than the |T| version.
-% \begin{macrocode}
-\cs_set_protected:Npn \prg_generate_p_form_parm:Nnnnn #1#2#3#4#5
+% How to generate the various forms. Those functions take the
+% following arguments: 1: \texttt{set} or \texttt{new}, 2: empty or
+% \texttt{\_protected}, 3: function name 4: signature, 5: parameter
+% text (or empty), 6: replacement. Remember that the logic-returning
+% functions expect two arguments to be present after \cs{c_zero}:
+% notice the construction of the different variants relies on this,
+% and that the |TF| variant will be slightly faster than the |T|
+% version. The |p| form is only valid for expandable tests, we check
+% for that by making sure that the second argument is empty.
+% \begin{macrocode}
+\cs_set_protected:Npn \__prg_generate_p_form:wnnnnnn #1 \q_stop #2#3#4#5#6#7
{
- \exp_args:Nc #1 { #2 _p: #3 } #4
+ \if_meaning:w \scan_stop: #3 \scan_stop:
+ \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \use_ii:nn
+ \fi:
{
- #5 \c_zero
- \c_true_bool \c_false_bool
+ \exp_args:Nc \exp_args:Nc { cs_ #2 #3 :Npn } { #4 _p: #5 } #6
+ { #7 \c_zero \c_true_bool \c_false_bool }
}
- }
-\cs_set_protected:Npn \prg_generate_T_form_parm:Nnnnn #1#2#3#4#5
- {
- \exp_args:Nc #1 { #2 : #3 T } #4
{
- #5 \c_zero
- \use:n \use_none:n
+ \__msg_kernel_error:nnx { kernel } { protected-predicate }
+ { \token_to_str:c { #4 _p: #5 } }
}
}
-\cs_set_protected:Npn \prg_generate_F_form_parm:Nnnnn #1#2#3#4#5
+\cs_set_protected:Npn \__prg_generate_T_form:wnnnnnn #1 \q_stop #2#3#4#5#6#7
{
- \exp_args:Nc #1 { #2 : #3 F } #4
- {
- #5 \c_zero
- { }
- }
+ \exp_args:Nc \exp_args:Nc { cs_ #2 #3 :Npn } { #4 : #5 T } #6
+ { #7 \c_zero \use:n \use_none:n }
}
-\cs_set_protected:Npn \prg_generate_TF_form_parm:Nnnnn #1#2#3#4#5
+\cs_set_protected:Npn \__prg_generate_F_form:wnnnnnn #1 \q_stop #2#3#4#5#6#7
{
- \exp_args:Nc #1 { #2 : #3 TF } #4
- { #5 \c_zero }
+ \exp_args:Nc \exp_args:Nc { cs_ #2 #3 :Npn } { #4 : #5 F } #6
+ { #7 \c_zero { } }
+ }
+\cs_set_protected:Npn \__prg_generate_TF_form:wnnnnnn #1 \q_stop #2#3#4#5#6#7
+ {
+ \exp_args:Nc \exp_args:Nc { cs_ #2 #3 :Npn } { #4 : #5 TF } #6
+ { #7 \c_zero }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]
-% {
-% \prg_generate_p_form_count:Nnnnn,
-% \prg_generate_TF_form_count:Nnnnn,
-% \prg_generate_T_form_count:Nnnnn,
-% \prg_generate_F_form_count:Nnnnn
-% }
-% The |count| form is similar, but of course requires a number rather
-% than a primitive argument specification.
+% \begin{macro}{\prg_set_eq_conditional:NNn,\prg_new_eq_conditional:NNn}
+% The setting-equal functions. Split the base function to be copied,
+% and feed a first auxiliary \Arg{name} \Arg{signature} \meta{boolean}
+% \meta{copying~function} \meta{new~function} \Arg{conditions}.
% \begin{macrocode}
-\cs_set_protected:Npn \prg_generate_p_form_count:Nnnnn #1#2#3#4#5
+\cs_set_protected:Npn \prg_set_eq_conditional:NNn #1#2
{
- \cs_generate_from_arg_count:cNnn { #2 _p: #3 } #1 {#4}
- {
- #5 \c_zero
- \c_true_bool \c_false_bool
- }
+ \__cs_split_function:NN #2 \__prg_set_eq_conditional:nnNNNn
+ \cs_set_eq:cc #1
}
-\cs_set_protected:Npn \prg_generate_T_form_count:Nnnnn #1#2#3#4#5
+\cs_set_protected:Npn \prg_new_eq_conditional:NNn #1#2
{
- \cs_generate_from_arg_count:cNnn { #2 : #3 T } #1 {#4}
- {
- #5 \c_zero
- \use:n \use_none:n
- }
- }
-\cs_set_protected:Npn \prg_generate_F_form_count:Nnnnn #1#2#3#4#5
- {
- \cs_generate_from_arg_count:cNnn { #2 : #3 F } #1 {#4}
- {
- #5 \c_zero
- { }
- }
- }
-\cs_set_protected:Npn \prg_generate_TF_form_count:Nnnnn #1#2#3#4#5
- {
- \cs_generate_from_arg_count:cNnn { #2 : #3 TF } #1 {#4}
- { #5 \c_zero }
+ \__cs_split_function:NN #2 \__prg_set_eq_conditional:nnNNNn
+ \cs_new_eq:cc #1
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]
-% {\prg_set_eq_conditional_aux:NNNn, \prg_set_eq_conditional_aux:NNNw}
+% {
+% \__prg_set_eq_conditional:nnNNNn ,
+% \__prg_set_eq_conditional:nnNnnNNw ,
+% \__prg_set_eq_conditional_loop:nnnnNw
+% }
% \begin{macro}[aux, EXP]
% {
-% \prg_conditional_form_p:nnn ,
-% \prg_conditional_form_TF:nnn ,
-% \prg_conditional_form_T:nnn ,
-% \prg_conditional_form_F:nnn ,
+% \__prg_conditional_p_form:nnn ,
+% \__prg_conditional_TF_form:nnn ,
+% \__prg_conditional_T_form:nnn ,
+% \__prg_conditional_F_form:nnn ,
% }
-% Manual clist loop over argument |#4|.
-% \begin{macrocode}
-\cs_set_protected:Npn \prg_set_eq_conditional_aux:NNNn #1#2#3#4
- { \prg_set_eq_conditional_aux:NNNw #1#2#3#4 , ? , \q_recursion_stop }
-\cs_set_protected:Npn \prg_set_eq_conditional_aux:NNNw #1#2#3#4 ,
+% Split the function to be defined, and setup a manual clist loop over
+% argument |#6| of the first auxiliary. The second auxiliary receives
+% twice three arguments coming from splitting the function to be
+% defined and the function to copy. Make sure that both functions
+% contained a colon, otherwise we don't know how to build
+% conditionals, hence abort. Call the looping macro, with arguments
+% \Arg{name_1} \Arg{signature_1} \Arg{name_2} \Arg{signature_2}
+% \meta{copying~function} and followed by the comma list. At each
+% step in the loop, make sure that the conditional form we copy is
+% defined, and copy it, otherwise abort.
+% \begin{macrocode}
+\cs_set_protected:Npn \__prg_set_eq_conditional:nnNNNn #1#2#3#4#5#6
{
- \if:w ? #4 \scan_stop:
+ \__cs_split_function:NN #5 \__prg_set_eq_conditional:nnNnnNNw
+ {#1} {#2} #3 #4
+ #6 , \scan_stop: , \q_recursion_stop
+ }
+\cs_set_protected:Npn \__prg_set_eq_conditional:nnNnnNNw #1#2#3#4#5#6
+ {
+ \if_meaning:w \c_false_bool #3
+ \__msg_kernel_error:nnx { kernel } { missing-colon }
+ { \token_to_str:c {#1} }
+ \exp_after:wN \use_none_delimit_by_q_recursion_stop:w
+ \fi:
+ \if_meaning:w \c_false_bool #6
+ \__msg_kernel_error:nnx { kernel } { missing-colon }
+ { \token_to_str:c {#4} }
\exp_after:wN \use_none_delimit_by_q_recursion_stop:w
\fi:
- #1
- { \exp_args:NNc \cs_split_function:NN #2 { prg_conditional_form_#4:nnn } }
- { \exp_args:NNc \cs_split_function:NN #3 { prg_conditional_form_#4:nnn } }
- \prg_set_eq_conditional_aux:NNNw #1 {#2} {#3}
+ \__prg_set_eq_conditional_loop:nnnnNw {#1} {#2} {#4} {#5}
+ }
+\cs_set_protected:Npn \__prg_set_eq_conditional_loop:nnnnNw #1#2#3#4#5#6 ,
+ {
+ \if_meaning:w \scan_stop: #6 \scan_stop:
+ \exp_after:wN \use_none_delimit_by_q_recursion_stop:w
+ \fi:
+ \cs_if_exist:cTF
+ { \use:c { __prg_conditional_ #6 _form:nn } {#3} {#4} }
+ {
+ #5
+ { \use:c { __prg_conditional_ #6 _form:nn } {#1} {#2} }
+ { \use:c { __prg_conditional_ #6 _form:nn } {#3} {#4} }
+ }
+ {
+ \__msg_kernel_error:nnx { kernel } { command-not-defined }
+ {
+ \token_to_str:c
+ { \use:c { __prg_conditional_ #6 _form:nn } {#3} {#4} }
+ }
+ }
+ \__prg_set_eq_conditional_loop:nnnnNw {#1} {#2} {#3} {#4} #5
}
-\cs_set:Npn \prg_conditional_form_p:nnn #1#2#3 { #1 _p : #2 }
-\cs_set:Npn \prg_conditional_form_TF:nnn #1#2#3 { #1 : #2 TF }
-\cs_set:Npn \prg_conditional_form_T:nnn #1#2#3 { #1 : #2 T }
-\cs_set:Npn \prg_conditional_form_F:nnn #1#2#3 { #1 : #2 F }
+\cs_set:Npn \__prg_conditional_p_form:nn #1#2 { #1 _p : #2 }
+\cs_set:Npn \__prg_conditional_TF_form:nn #1#2 { #1 : #2 TF }
+\cs_set:Npn \__prg_conditional_T_form:nn #1#2 { #1 : #2 T }
+\cs_set:Npn \__prg_conditional_F_form:nn #1#2 { #1 : #2 F }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1941,7 +2044,7 @@
% All that is left is to define the canonical boolean true and false.
% I think Michael originated the idea of expandable boolean tests. At
% first these were supposed to expand into either \texttt{TT} or
-% \texttt{TF} to be tested using |\if:w| but this was later changed to
+% \texttt{TF} to be tested using \cs{if:w} but this was later changed to
% |00| and |01|, so they could be used in logical
% operations. Later again they were changed to being numerical
% constants with values of $1$ for true and $0$ for false. We need
@@ -1950,22 +2053,22 @@
% \begin{variable}{\c_true_bool, \c_false_bool}
% Here are the canonical boolean values.
% \begin{macrocode}
-\tex_chardef:D \c_true_bool = 1~
-\tex_chardef:D \c_false_bool = 0~
+\tex_chardef:D \c_true_bool = 1 ~
+\tex_chardef:D \c_false_bool = 0 ~
% \end{macrocode}
% \end{variable}
%
% \subsection{Dissecting a control sequence}
%
% \begin{macro}[EXP]{\cs_to_str:N}
-% \begin{macro}[aux, EXP]{\cs_to_str_aux:N, \cs_to_str_aux:w}
+% \begin{macro}[aux, EXP]{\__cs_to_str:N, \__cs_to_str:w}
% This converts a control sequence into the character string of its
% name, removing the leading escape character. This turns out to be
% a non-trivial matter as there a different cases:
% \begin{itemize}
% \item The usual case of a printable escape character;
% \item the case of a non-printable escape characters, e.g., when
-% the value of |\tex_escapechar:D| is negative;
+% the value of the \tn{escapechar} is negative;
% \item when the escape character is a space.
% \end{itemize}
% One approach to solve this is to test how many tokens result from
@@ -1979,109 +2082,97 @@
% a little more intricate still. When the escape character is printable,
% \verb*|\token_to_str:N \ | yields the escape character itself and a space.
% The character codes are different, thus the \cs{if:w} test is false,
-% and \TeX{} reads \cs{cs_to_str_aux:N} after turning the following
+% and \TeX{} reads \cs{__cs_to_str:N} after turning the following
% control sequence into a string; this auxiliary removes the escape
-% character, and stops the expansion of the initial \cs{int_to_roman:w}.
+% character, and stops the expansion of the initial \cs{__int_to_roman:w}.
% The second case is that the escape character is not printable. Then
% the \cs{if:w} test is unfinished after reading a the space from
-% \verb*|\token_to_str:N \ |, and the auxiliary \cs{cs_to_str_aux:w}
+% \verb*|\token_to_str:N \ |, and the auxiliary \cs{__cs_to_str:w}
% is expanded, feeding |-| as a second character for the test;
% the test is false, and \TeX{} skips to \cs{fi:}, then performs
-% \cs{token_to_str:N}, and stops the \cs{int_to_roman:w} with \cs{c_zero}.
+% \cs{token_to_str:N}, and stops the \cs{__int_to_roman:w} with \cs{c_zero}.
% The last case is that the escape character is itself a space. In this
-% case, the \cs{if:w} test is true, and the auxiliary \cs{cs_to_str_aux:w}
-% comes into play, inserting |-\int_value:w|, which expands \cs{c_zero}
-% to the character |0|. The initial \cs{int_to_roman:w} then sees
+% case, the \cs{if:w} test is true, and the auxiliary \cs{__cs_to_str:w}
+% comes into play, inserting |-\__int_value:w|, which expands \cs{c_zero}
+% to the character |0|. The initial \cs{__int_to_roman:w} then sees
% |0|, which is not a terminated number, followed by the escape character,
% a space, which is removed, terminating the argument of
-% \cs{int_to_roman:w}.
+% \cs{__int_to_roman:w}.
% In all three cases, \cs{cs_to_str:N} takes two expansion steps
% to be fully expanded.
% \begin{macrocode}
\cs_set_nopar:Npn \cs_to_str:N
{
- \int_to_roman:w
- \if:w \token_to_str:N \ \cs_to_str_aux:w \fi:
- \exp_after:wN \cs_to_str_aux:N \token_to_str:N
+ \__int_to_roman:w
+ \if:w \token_to_str:N \ \__cs_to_str:w \fi:
+ \exp_after:wN \__cs_to_str:N \token_to_str:N
}
-\cs_set:Npn \cs_to_str_aux:N #1 { \c_zero }
-\cs_set:Npn \cs_to_str_aux:w #1 \cs_to_str_aux:N
- { - \int_value:w \fi: \exp_after:wN \c_zero }
+\cs_set:Npn \__cs_to_str:N #1 { \c_zero }
+\cs_set:Npn \__cs_to_str:w #1 \__cs_to_str:N
+ { - \__int_value:w \fi: \exp_after:wN \c_zero }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[EXP]{\cs_split_function:NN}
+% \begin{macro}[EXP, int]{\__cs_split_function:NN}
% \begin{macro}[aux, EXP]
-% {\cs_split_function_aux:w, \cs_split_function_auxii:w}
+% {\__cs_split_function_i:w, \__cs_split_function_ii:w}
% This function takes a function name and splits it into name with
% the escape char removed and argument specification. In addition to
% this, a third argument, a boolean \meta{true} or \meta{false} is
% returned with \meta{true} for when there is a colon in the function
% and \meta{false} if there is not. Lastly, the second argument of
-% \cs{cs_split_function:NN} is supposed to be a function
+% \cs{__cs_split_function:NN} is supposed to be a function
% taking three variables, one for name, one for signature, and one
% for the boolean. For example,
-% |\cs_split_function:NN\foo_bar:cnx\use_i:nnn| as input
-% becomes |\use_i:nnn {foo_bar}{cnx}\c_true_bool|.
-%
-% Can't use a literal |:| because it has the wrong catcode here, so
-% it's transformed from |@| with |\tex_lowercase:D|.
+% |\__cs_split_function:NN \foo_bar:cnx \use_i:nnn| as input
+% becomes |\use_i:nnn {foo_bar} {cnx} \c_true_bool|.
+%
+% We can't use a literal |:| because it has the wrong catcode here, so
+% it's transformed from |@| with \cs{tex_lowercase:D}.
+%
+% First ensure that we actually get a properly evaluated string by
+% expanding \cs{cs_to_str:N} twice. If the function contained a
+% colon, the auxiliary takes as |#1| the function name, delimited by
+% the first colon, then the signature |#2|, delimited by \cs{q_mark},
+% then \cs{c_true_bool} as |#3|, and |#4| cleans up until \cs{q_stop}.
+% Otherwise, the |#1| contains the function name and \cs{q_mark}
+% \cs{c_true_bool}, |#2| is empty, |#3| is \cs{c_false_bool}, and |#4|
+% cleans up. In both cases, |#5| is the \meta{processor}. The second
+% auxiliary trims the trailing \cs{q_mark} from the function name if
+% present (that is, if the original function had no colon).
% \begin{macrocode}
\group_begin:
- \tex_lccode:D `\@ = `\: \scan_stop:
- \tex_catcode:D `\@ = 12~
+\tex_lccode:D `\@ = `\: \scan_stop:
+\tex_catcode:D `\@ = 12 ~
\tex_lowercase:D
{
\group_end:
-% \end{macrocode}
-% First ensure that we actually get a properly evaluated str
-% by expanding \cs{cs_to_str:N} twice. Insert
-% extra colon to catch the error cases.
-% \begin{macrocode}
- \cs_set:Npn \cs_split_function:NN #1#2
+ \cs_set:Npn \__cs_split_function:NN #1
{
\exp_after:wN \exp_after:wN
- \exp_after:wN \cs_split_function_aux:w
- \cs_to_str:N #1 @ a \q_stop #2
- }
-% \end{macrocode}
-% If no colon in the name, |#2| is |a| with catcode 11 and |#3| is
-% empty. If colon in the name, then either |#2| is a colon or the
-% first letter of the signature. The letters here have catcode 12.
-% If a colon was given we need to a) split off the colon and quark at
-% the end and b) ensure we return the name, signature and boolean true
-% We can't use \cs{quark_if_no_value:NTF} yet but this is very safe
-% anyway as all tokens have catcode~12.
-% \begin{macrocode}
- \cs_set:Npn \cs_split_function_aux:w #1 @ #2#3 \q_stop #4
- {
- \if_meaning:w a #2
- \exp_after:wN \use_i:nn
- \else:
- \exp_after:wN\use_ii:nn
- \fi:
- { #4 {#1} { } \c_false_bool }
- { \cs_split_function_auxii:w #2#3 \q_stop #4 {#1} }
+ \exp_after:wN \__cs_split_function_i:w
+ \cs_to_str:N #1 \q_mark \c_true_bool
+ @ \q_mark \c_false_bool
+ \q_stop
}
- \cs_set:Npn \cs_split_function_auxii:w #1 @a \q_stop #2#3
- { #2{#3}{#1}\c_true_bool }
-% \end{macrocode}
-% End of lowercase
-% \begin{macrocode}
+ \cs_set:Npn \__cs_split_function_i:w #1 @ #2 \q_mark #3#4 \q_stop #5
+ { \__cs_split_function_ii:w #5 #1 \q_mark \q_stop {#2} #3 }
+ \cs_set:Npn \__cs_split_function_ii:w #1#2 \q_mark #3 \q_stop
+ { #1 {#2} }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[EXP]{\cs_get_function_name:N, \cs_get_function_signature:N}
-% Now returning the name is trivial: just discard the last two
-% arguments. Similar for signature.
+% \begin{macro}[EXP, int]
+% {\__cs_get_function_name:N, \__cs_get_function_signature:N}
+% Simple wrappers.
% \begin{macrocode}
-\cs_set:Npn \cs_get_function_name:N #1
- { \cs_split_function:NN #1 \use_i:nnn }
-\cs_set:Npn \cs_get_function_signature:N #1
- { \cs_split_function:NN #1 \use_ii:nnn }
+\cs_set:Npn \__cs_get_function_name:N #1
+ { \__cs_split_function:NN #1 \use_i:nnn }
+\cs_set:Npn \__cs_get_function_signature:N #1
+ { \__cs_split_function:NN #1 \use_ii:nnn }
% \end{macrocode}
% \end{macro}
%
@@ -2089,15 +2180,15 @@
%
% A control sequence is said to \emph{exist} (to be used) if has an entry in
% the hash table and its meaning is different from the primitive
-% |\tex_relax:D| token. A control sequence is said to be \emph{free}
+% \tn{relax} token. A control sequence is said to be \emph{free}
% (to be defined) if it does not already exist.
%
% \begin{macro}[pTF, EXP]{\cs_if_exist:N,\cs_if_exist:c}
% Two versions for checking existence. For the |N| form we firstly
-% check for |\scan_stop:| and then if it is in the hash
-% table. There is no problem when inputting something like |\else:|
-% or |\fi:| as \TeX{} will only ever skip input in case the token
-% tested against is |\scan_stop:|.
+% check for \cs{scan_stop:} and then if it is in the hash
+% table. There is no problem when inputting something like \cs{else:}
+% or \cs{fi:} as \TeX{} will only ever skip input in case the token
+% tested against is \cs{scan_stop:}.
% \begin{macrocode}
\prg_set_conditional:Npnn \cs_if_exist:N #1 { p , T , F , TF }
{
@@ -2113,7 +2204,7 @@
}
% \end{macrocode}
% For the |c| form we firstly check if it is in the hash table and
-% then for |\scan_stop:| so that we do not add it to the hash table
+% then for \cs{scan_stop:} so that we do not add it to the hash table
% unless it was already there. Here we have to be careful as the text
% to be skipped if the first test is false may contain tokens that
% disturb the scanner. Therefore, we ensure that the second test is
@@ -2226,14 +2317,14 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}
-% {\msg_kernel_error:nnxx, \msg_kernel_error:nnx, \msg_kernel_error:nn}
+% \begin{macro}[int]
+% {\__msg_kernel_error:nnxx, \__msg_kernel_error:nnx, \__msg_kernel_error:nn}
% If an internal error occurs before \LaTeX3 has loaded \pkg{l3msg} then
% the code should issue a usable if terse error message and halt. This
% can only happen if a coding error is made by the team, so this is
% a reasonable response.
% \begin{macrocode}
-\cs_set_protected:Npn \msg_kernel_error:nnxx #1#2#3#4
+\cs_set_protected:Npn \__msg_kernel_error:nnxx #1#2#3#4
{
\tex_errmessage:D
{
@@ -2245,10 +2336,10 @@
}
\tex_end:D
}
-\cs_set_protected:Npn \msg_kernel_error:nnx #1#2#3
- { \msg_kernel_error:nnxx {#1} {#2} {#3} { } }
-\cs_set_protected:Npn \msg_kernel_error:nn #1#2
- { \msg_kernel_error:nnxx {#1} {#2} { } { } }
+\cs_set_protected:Npn \__msg_kernel_error:nnx #1#2#3
+ { \__msg_kernel_error:nnxx {#1} {#2} {#3} { } }
+\cs_set_protected:Npn \__msg_kernel_error:nn #1#2
+ { \__msg_kernel_error:nnxx {#1} {#2} { } { } }
% \end{macrocode}
% \end{macro}
%
@@ -2256,11 +2347,11 @@
% Another one from \pkg{l3msg} which will be altered later.
% \begin{macrocode}
\cs_set_nopar:Npn \msg_line_context:
- { on~line~\tex_the:D \tex_inputlineno:D }
+ { on~line~ \tex_the:D \tex_inputlineno:D }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\chk_if_free_cs:N, \chk_if_free_cs:c}
+% \begin{macro}[int]{\__chk_if_free_cs:N, \__chk_if_free_cs:c}
% This command is called by \cs{cs_new_nopar:Npn} and \cs{cs_new_eq:NN}
% \emph{etc.}\
% to make sure that the argument sequence is not already in use. If
@@ -2269,46 +2360,46 @@
% issued. We have to make sure we don't put the argument into the
% conditional processing since it may be an |\if...| type function!
% \begin{macrocode}
-\cs_set_protected:Npn \chk_if_free_cs:N #1
+\cs_set_protected:Npn \__chk_if_free_cs:N #1
{
\cs_if_free:NF #1
{
- \msg_kernel_error:nnxx { kernel } { command-already-defined }
+ \__msg_kernel_error:nnxx { kernel } { command-already-defined }
{ \token_to_str:N #1 } { \token_to_meaning:N #1 }
}
}
%<*package>
\tex_ifodd:D \l@expl@log@functions@bool
- \cs_set_protected:Npn \chk_if_free_cs:N #1
+ \cs_set_protected:Npn \__chk_if_free_cs:N #1
{
\cs_if_free:NF #1
{
- \msg_kernel_error:nnxx { kernel } { command-already-defined }
+ \__msg_kernel_error:nnxx { kernel } { command-already-defined }
{ \token_to_str:N #1 } { \token_to_meaning:N #1 }
}
\iow_log:x { Defining~\token_to_str:N #1~ \msg_line_context: }
}
\fi:
%</package>
-\cs_set_protected_nopar:Npn \chk_if_free_cs:c
- { \exp_args:Nc \chk_if_free_cs:N }
+\cs_set_protected_nopar:Npn \__chk_if_free_cs:c
+ { \exp_args:Nc \__chk_if_free_cs:N }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\chk_if_exist_cs:N, \chk_if_exist_cs:c}
-% This function issues a warning message when the control sequence
+% \begin{macro}[int]{\__chk_if_exist_cs:N, \__chk_if_exist_cs:c}
+% This function issues an error message when the control sequence
% in its argument does not exist.
% \begin{macrocode}
-\cs_set_protected:Npn \chk_if_exist_cs:N #1
+\cs_set_protected:Npn \__chk_if_exist_cs:N #1
{
\cs_if_exist:NF #1
{
- \msg_kernel_error:nnxx { kernel } { command-not-defined }
- { \token_to_str:N #1 } { \token_to_meaning:N #1 }
+ \__msg_kernel_error:nnx { kernel } { command-not-defined }
+ { \token_to_str:N #1 }
}
}
-\cs_set_protected_nopar:Npn \chk_if_exist_cs:c
- { \exp_args:Nc \chk_if_exist_cs:N }
+\cs_set_protected_nopar:Npn \__chk_if_exist_cs:c
+ { \exp_args:Nc \__chk_if_exist_cs:N }
% \end{macrocode}
% \end{macro}
%
@@ -2324,22 +2415,22 @@
% Function which check that the control sequence is free before
% defining it.
% \begin{macrocode}
-\cs_set:Npn \cs_tmp:w #1#2
+\cs_set:Npn \__cs_tmp:w #1#2
{
\cs_set_protected:Npn #1 ##1
{
- \chk_if_free_cs:N ##1
+ \__chk_if_free_cs:N ##1
#2 ##1
}
}
-\cs_tmp:w \cs_new_nopar:Npn \cs_gset_nopar:Npn
-\cs_tmp:w \cs_new_nopar:Npx \cs_gset_nopar:Npx
-\cs_tmp:w \cs_new:Npn \cs_gset:Npn
-\cs_tmp:w \cs_new:Npx \cs_gset:Npx
-\cs_tmp:w \cs_new_protected_nopar:Npn \cs_gset_protected_nopar:Npn
-\cs_tmp:w \cs_new_protected_nopar:Npx \cs_gset_protected_nopar:Npx
-\cs_tmp:w \cs_new_protected:Npn \cs_gset_protected:Npn
-\cs_tmp:w \cs_new_protected:Npx \cs_gset_protected:Npx
+\__cs_tmp:w \cs_new_nopar:Npn \cs_gset_nopar:Npn
+\__cs_tmp:w \cs_new_nopar:Npx \cs_gset_nopar:Npx
+\__cs_tmp:w \cs_new:Npn \cs_gset:Npn
+\__cs_tmp:w \cs_new:Npx \cs_gset:Npx
+\__cs_tmp:w \cs_new_protected_nopar:Npn \cs_gset_protected_nopar:Npn
+\__cs_tmp:w \cs_new_protected_nopar:Npx \cs_gset_protected_nopar:Npx
+\__cs_tmp:w \cs_new_protected:Npn \cs_gset_protected:Npn
+\__cs_tmp:w \cs_new_protected:Npx \cs_gset_protected:Npx
% \end{macrocode}
% \end{macro}
%
@@ -2360,14 +2451,14 @@
% \cs{cs_set_nopar:Npn}. This means that there might be a parameter
% string between the two arguments.
% \begin{macrocode}
-\cs_set:Npn \cs_tmp:w #1#2
+\cs_set:Npn \__cs_tmp:w #1#2
{ \cs_new_protected_nopar:Npn #1 { \exp_args:Nc #2 } }
-\cs_tmp:w \cs_set_nopar:cpn \cs_set_nopar:Npn
-\cs_tmp:w \cs_set_nopar:cpx \cs_set_nopar:Npx
-\cs_tmp:w \cs_gset_nopar:cpn \cs_gset_nopar:Npn
-\cs_tmp:w \cs_gset_nopar:cpx \cs_gset_nopar:Npx
-\cs_tmp:w \cs_new_nopar:cpn \cs_new_nopar:Npn
-\cs_tmp:w \cs_new_nopar:cpx \cs_new_nopar:Npx
+\__cs_tmp:w \cs_set_nopar:cpn \cs_set_nopar:Npn
+\__cs_tmp:w \cs_set_nopar:cpx \cs_set_nopar:Npx
+\__cs_tmp:w \cs_gset_nopar:cpn \cs_gset_nopar:Npn
+\__cs_tmp:w \cs_gset_nopar:cpx \cs_gset_nopar:Npx
+\__cs_tmp:w \cs_new_nopar:cpn \cs_new_nopar:Npn
+\__cs_tmp:w \cs_new_nopar:cpx \cs_new_nopar:Npx
% \end{macrocode}
% \end{macro}
%
@@ -2380,12 +2471,12 @@
% Variants of the \cs{cs_set:Npn} versions which make a csname out
% of the first arguments. We may also do this globally.
% \begin{macrocode}
-\cs_tmp:w \cs_set:cpn \cs_set:Npn
-\cs_tmp:w \cs_set:cpx \cs_set:Npx
-\cs_tmp:w \cs_gset:cpn \cs_gset:Npn
-\cs_tmp:w \cs_gset:cpx \cs_gset:Npx
-\cs_tmp:w \cs_new:cpn \cs_new:Npn
-\cs_tmp:w \cs_new:cpx \cs_new:Npx
+\__cs_tmp:w \cs_set:cpn \cs_set:Npn
+\__cs_tmp:w \cs_set:cpx \cs_set:Npx
+\__cs_tmp:w \cs_gset:cpn \cs_gset:Npn
+\__cs_tmp:w \cs_gset:cpx \cs_gset:Npx
+\__cs_tmp:w \cs_new:cpn \cs_new:Npn
+\__cs_tmp:w \cs_new:cpx \cs_new:Npx
% \end{macrocode}
% \end{macro}
%
@@ -2398,12 +2489,12 @@
% Variants of the \cs{cs_set_protected_nopar:Npn} versions which make
% a csname out of the first arguments. We may also do this globally.
% \begin{macrocode}
-\cs_tmp:w \cs_set_protected_nopar:cpn \cs_set_protected_nopar:Npn
-\cs_tmp:w \cs_set_protected_nopar:cpx \cs_set_protected_nopar:Npx
-\cs_tmp:w \cs_gset_protected_nopar:cpn \cs_gset_protected_nopar:Npn
-\cs_tmp:w \cs_gset_protected_nopar:cpx \cs_gset_protected_nopar:Npx
-\cs_tmp:w \cs_new_protected_nopar:cpn \cs_new_protected_nopar:Npn
-\cs_tmp:w \cs_new_protected_nopar:cpx \cs_new_protected_nopar:Npx
+\__cs_tmp:w \cs_set_protected_nopar:cpn \cs_set_protected_nopar:Npn
+\__cs_tmp:w \cs_set_protected_nopar:cpx \cs_set_protected_nopar:Npx
+\__cs_tmp:w \cs_gset_protected_nopar:cpn \cs_gset_protected_nopar:Npn
+\__cs_tmp:w \cs_gset_protected_nopar:cpx \cs_gset_protected_nopar:Npx
+\__cs_tmp:w \cs_new_protected_nopar:cpn \cs_new_protected_nopar:Npn
+\__cs_tmp:w \cs_new_protected_nopar:cpx \cs_new_protected_nopar:Npx
% \end{macrocode}
% \end{macro}
%
@@ -2416,12 +2507,12 @@
% Variants of the \cs{cs_set_protected:Npn} versions which make a csname
% out of the first arguments. We may also do this globally.
% \begin{macrocode}
-\cs_tmp:w \cs_set_protected:cpn \cs_set_protected:Npn
-\cs_tmp:w \cs_set_protected:cpx \cs_set_protected:Npx
-\cs_tmp:w \cs_gset_protected:cpn \cs_gset_protected:Npn
-\cs_tmp:w \cs_gset_protected:cpx \cs_gset_protected:Npx
-\cs_tmp:w \cs_new_protected:cpn \cs_new_protected:Npn
-\cs_tmp:w \cs_new_protected:cpx \cs_new_protected:Npx
+\__cs_tmp:w \cs_set_protected:cpn \cs_set_protected:Npn
+\__cs_tmp:w \cs_set_protected:cpx \cs_set_protected:Npx
+\__cs_tmp:w \cs_gset_protected:cpn \cs_gset_protected:Npn
+\__cs_tmp:w \cs_gset_protected:cpx \cs_gset_protected:Npx
+\__cs_tmp:w \cs_new_protected:cpn \cs_new_protected:Npn
+\__cs_tmp:w \cs_new_protected:cpx \cs_new_protected:Npx
% \end{macrocode}
% \end{macro}
%
@@ -2456,7 +2547,7 @@
\cs_new_protected_nopar:Npn \cs_gset_eq:cc { \exp_args:Ncc \cs_gset_eq:NN }
\cs_new_protected:Npn \cs_new_eq:NN #1
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\tex_global:D \cs_set_eq:NN #1
}
\cs_new_protected_nopar:Npn \cs_new_eq:cN { \exp_args:Nc \cs_new_eq:NN }
@@ -2488,57 +2579,88 @@
% \end{macrocode}
% \end{macro}
%
+% \subsection{Generating parameter text from argument count}
+%
+% \begin{macro}[int]{\__cs_parm_from_arg_count:nnF}
+% \begin{macro}[aux]{\__cs_parm_from_arg_count_test:nnF}
+% \LaTeX3 provides shorthands to define control sequences and
+% conditionals with a simple parameter text, derived directly from the
+% signature, or more generally from knowing the number of arguments,
+% between~$0$ and~$9$. This function expands to its first argument,
+% untouched, followed by a brace group containing the parameter text
+% |{#|$1$\ldots{}|#|$n$|}|, where $n$ is the result of evaluating the
+% second argument (as described in \cs{int_eval:n}). If the second
+% argument gives a result outside the range $[0,9]$, the third
+% argument is returned instead, normally an error message. Some of
+% the functions use here are not defined yet, but will be defined
+% before this function is called.
+% \begin{macrocode}
+\cs_set_protected:Npn \__cs_parm_from_arg_count:nnF #1#2
+ {
+ \exp_args:Nx \__cs_parm_from_arg_count_test:nnF
+ {
+ \exp_after:wN \exp_not:n
+ \if_case:w \__int_eval:w #2 \__int_eval_end:
+ { }
+ \or: { ##1 }
+ \or: { ##1##2 }
+ \or: { ##1##2##3 }
+ \or: { ##1##2##3##4 }
+ \or: { ##1##2##3##4##5 }
+ \or: { ##1##2##3##4##5##6 }
+ \or: { ##1##2##3##4##5##6##7 }
+ \or: { ##1##2##3##4##5##6##7##8 }
+ \or: { ##1##2##3##4##5##6##7##8##9 }
+ \else: { \c_false_bool }
+ \fi:
+ }
+ {#1}
+ }
+\cs_set_protected:Npn \__cs_parm_from_arg_count_test:nnF #1#2
+ {
+ \if_meaning:w \c_false_bool #1
+ \exp_after:wN \use_ii:nn
+ \else:
+ \exp_after:wN \use_i:nn
+ \fi:
+ { #2 {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Defining functions from a given number of arguments}
%
-% \begin{macro}[EXP]{\cs_get_arg_count_from_signature:N}
-% \begin{macro}[aux, EXP]
-% {
-% \cs_get_arg_count_from_signature_aux:nnN,
-% \cs_get_arg_count_from_signature_auxii:w
-% }
-% Counting the number of tokens in the signature, i.e., the number
-% of arguments the function should take. If there is no signature,
-% we return that there is $-1$ arguments to signal an error.
-% Otherwise we insert the string |9876543210| after the signature.
-% If the signature is empty, the number we want is $0$ so we remove
-% the first nine tokens and return the tenth. Similarly, if the
-% signature is |nnn| we want to remove the nine tokens |nnn987654|
-% and return $3$. Therefore, we simply remove the first nine tokens
-% and then return the tenth.
-% \begin{macrocode}
-\cs_new:Npn \cs_get_arg_count_from_signature:N #1
- { \cs_split_function:NN #1 \cs_get_arg_count_from_signature_aux:nnN }
-\cs_new:Npn \cs_get_arg_count_from_signature_aux:nnN #1#2#3
+% \begin{macro}[EXP, int]{\__cs_count_signature:N, \__cs_count_signature:c}
+% \begin{macro}[aux, EXP]{\__cs_count_signature:nnN}
+% Counting the number of tokens in the signature, \emph{i.e.}, the
+% number of arguments the function should take. Since this is not
+% used in any time-critical function, we simply use \cs{tl_count:n} if
+% there is a signature, otherwise $-1$ arguments to signal an error.
+% We need a variant form right away.
+% \begin{macrocode}
+\cs_new:Npn \__cs_count_signature:N #1
+ { \int_eval:n { \__cs_split_function:NN #1 \__cs_count_signature:nnN } }
+\cs_new:Npn \__cs_count_signature:nnN #1#2#3
{
\if_meaning:w \c_true_bool #3
- \exp_after:wN \use_i:nn
+ \tl_count:n {#2}
\else:
- \exp_after:wN\use_ii:nn
+ \c_minus_one
\fi:
- {
- \exp_after:wN \cs_get_arg_count_from_signature_auxii:w
- \use_none:nnnnnnnnn #2 9876543210 \q_stop
- }
- { -1 }
-}
-\cs_new:Npn \cs_get_arg_count_from_signature_auxii:w #1#2 \q_stop {#1}
-% \end{macrocode}
-% A variant form we need right away.
-% \begin{macrocode}
-\cs_new_nopar:Npn \cs_get_arg_count_from_signature:c
- { \exp_args:Nc \cs_get_arg_count_from_signature:N }
+ }
+\cs_new_nopar:Npn \__cs_count_signature:c
+ { \exp_args:Nc \__cs_count_signature:N }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux]
+% \begin{macro}
% {
% \cs_generate_from_arg_count:NNnn,
% \cs_generate_from_arg_count:cNnn,
% \cs_generate_from_arg_count:Ncnn
% }
-% \begin{macro}[aux]{\cs_generate_from_arg_count_error_msg:Nn}
-% \begin{macro}[aux]{\cs_generate_from_arg_count_aux:nwn}
% We provide a constructor function for defining functions with a
% given number of arguments. For this we need to choose the correct
% parameter text and then use that when defining. Since \TeX{}
@@ -2552,27 +2674,13 @@
% \begin{macrocode}
\cs_new_protected:Npn \cs_generate_from_arg_count:NNnn #1#2#3#4
{
- \if_case:w \int_eval:w #3 \int_eval_end:
- \cs_generate_from_arg_count_aux:nwn {}
- \or: \cs_generate_from_arg_count_aux:nwn {##1}
- \or: \cs_generate_from_arg_count_aux:nwn {##1##2}
- \or: \cs_generate_from_arg_count_aux:nwn {##1##2##3}
- \or: \cs_generate_from_arg_count_aux:nwn {##1##2##3##4}
- \or: \cs_generate_from_arg_count_aux:nwn {##1##2##3##4##5}
- \or: \cs_generate_from_arg_count_aux:nwn {##1##2##3##4##5##6}
- \or: \cs_generate_from_arg_count_aux:nwn {##1##2##3##4##5##6##7}
- \or: \cs_generate_from_arg_count_aux:nwn {##1##2##3##4##5##6##7##8}
- \or: \cs_generate_from_arg_count_aux:nwn {##1##2##3##4##5##6##7##8##9}
- \else:
- \cs_generate_from_arg_count_error_msg:Nn #1 {#3}
- \use_i:nnn
- \fi:
- {#2#1}
- {#4}
+ \__cs_parm_from_arg_count:nnF { \use:nnn #2 #1 } {#3}
+ {
+ \__msg_kernel_error:nnxx { kernel } { bad-number-of-arguments }
+ { \token_to_str:N #1 } { \int_eval:n {#3} }
+ }
+ {#4}
}
-\cs_new_protected:Npn
- \cs_generate_from_arg_count_aux:nwn #1 #2 \fi: #3
- { \fi: #3 #1 }
% \end{macrocode}
% A variant form we need right away, plus one which is used elsewhere but
% which is most logically created here.
@@ -2582,17 +2690,6 @@
\cs_new_protected_nopar:Npn \cs_generate_from_arg_count:Ncnn
{ \exp_args:NNc \cs_generate_from_arg_count:NNnn }
% \end{macrocode}
-% The error message. Elsewhere we use the value of $-1$ to signal a
-% missing colon in a function, so provide a hint for help on this.
-% \begin{macrocode}
-\cs_new_protected:Npn \cs_generate_from_arg_count_error_msg:Nn #1#2
- {
- \msg_kernel_error:nnxx { kernel } { bad-number-of-arguments }
- { \token_to_str:N #1 } { \int_eval:n {#2} }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
% \end{macro}
%
% \subsection{Using the signature to define functions}
@@ -2622,7 +2719,7 @@
% \cs_set_protected:Npn \cs_set:Nn #1#2
% {
% \cs_generate_from_arg_count:NNnn #1 \cs_set:Npn
-% { \cs_get_arg_count_from_signature:N #1 } {#2}
+% { \__cs_count_signature:N #1 } {#2}
% }
% \end{verbatim}
% In short, to define \cs{cs_set:Nn} we need just use \cs{cs_set:Npn},
@@ -2630,42 +2727,58 @@
% make it simpler by temporarily defining a function to do this for
% us.
% \begin{macrocode}
-\cs_set:Npn \cs_tmp:w #1#2#3
+\cs_set:Npn \__cs_tmp:w #1#2#3
{
- \cs_new_protected:cpx { cs_ #1 : #2 } ##1##2
+ \cs_new_protected_nopar:cpx { cs_ #1 : #2 }
{
- \exp_not:N \cs_generate_from_arg_count:NNnn ##1
- \exp_after:wN \exp_not:N \cs:w cs_#1 : #3 \cs_end:
- { \exp_not:N \cs_get_arg_count_from_signature:N ##1 }{##2}
+ \exp_not:N \__cs_generate_from_signature:NNn
+ \exp_after:wN \exp_not:N \cs:w cs_ #1 : #3 \cs_end:
+ }
+ }
+\cs_new_protected:Npn \__cs_generate_from_signature:NNn #1#2
+ {
+ \__cs_split_function:NN #2 \__cs_generate_from_signature:nnNNNn
+ #1 #2
+ }
+\cs_new_protected:Npn \__cs_generate_from_signature:nnNNNn #1#2#3#4#5#6
+ {
+ \bool_if:NTF #3
+ {
+ \cs_generate_from_arg_count:NNnn
+ #5 #4 { \tl_count:n {#2} } {#6}
+ }
+ {
+ \__msg_kernel_error:nnx { kernel } { missing-colon }
+ { \token_to_str:N #5 }
}
}
% \end{macrocode}
% Then we define the 24 variants beginning with |N|.
% \begin{macrocode}
-\cs_tmp:w { set } { Nn } { Npn }
-\cs_tmp:w { set } { Nx } { Npx }
-\cs_tmp:w { set_nopar } { Nn } { Npn }
-\cs_tmp:w { set_nopar } { Nx } { Npx }
-\cs_tmp:w { set_protected } { Nn } { Npn }
-\cs_tmp:w { set_protected } { Nx } { Npx }
-\cs_tmp:w { set_protected_nopar } { Nn } { Npn }
-\cs_tmp:w { set_protected_nopar } { Nx } { Npx }
-\cs_tmp:w { gset } { Nn } { Npn }
-\cs_tmp:w { gset } { Nx } { Npx }
-\cs_tmp:w { gset_nopar } { Nn } { Npn }
-\cs_tmp:w { gset_nopar } { Nx } { Npx }
-\cs_tmp:w { gset_protected } { Nn } { Npn }
-\cs_tmp:w { gset_protected } { Nx } { Npx }
-\cs_tmp:w { gset_protected_nopar } { Nn } { Npn }
-\cs_tmp:w { gset_protected_nopar } { Nx } { Npx }
-\cs_tmp:w { new } { Nn } { Npn }
-\cs_tmp:w { new } { Nx } { Npx }
-\cs_tmp:w { new_nopar } { Nn } { Npn }
-\cs_tmp:w { new_nopar } { Nx } { Npx }
-\cs_tmp:w { new_protected } { Nn } { Npn }
-\cs_tmp:w { new_protected } { Nx } { Npx }
-\cs_tmp:w { new_protected_nopar } { Nn } { Npn }
-\cs_tmp:w { new_protected_nopar } { Nx } { Npx }
+\__cs_tmp:w { set } { Nn } { Npn }
+\__cs_tmp:w { set } { Nx } { Npx }
+\__cs_tmp:w { set_nopar } { Nn } { Npn }
+\__cs_tmp:w { set_nopar } { Nx } { Npx }
+\__cs_tmp:w { set_protected } { Nn } { Npn }
+\__cs_tmp:w { set_protected } { Nx } { Npx }
+\__cs_tmp:w { set_protected_nopar } { Nn } { Npn }
+\__cs_tmp:w { set_protected_nopar } { Nx } { Npx }
+\__cs_tmp:w { gset } { Nn } { Npn }
+\__cs_tmp:w { gset } { Nx } { Npx }
+\__cs_tmp:w { gset_nopar } { Nn } { Npn }
+\__cs_tmp:w { gset_nopar } { Nx } { Npx }
+\__cs_tmp:w { gset_protected } { Nn } { Npn }
+\__cs_tmp:w { gset_protected } { Nx } { Npx }
+\__cs_tmp:w { gset_protected_nopar } { Nn } { Npn }
+\__cs_tmp:w { gset_protected_nopar } { Nx } { Npx }
+\__cs_tmp:w { new } { Nn } { Npn }
+\__cs_tmp:w { new } { Nx } { Npx }
+\__cs_tmp:w { new_nopar } { Nn } { Npn }
+\__cs_tmp:w { new_nopar } { Nx } { Npx }
+\__cs_tmp:w { new_protected } { Nn } { Npn }
+\__cs_tmp:w { new_protected } { Nx } { Npx }
+\__cs_tmp:w { new_protected_nopar } { Nn } { Npn }
+\__cs_tmp:w { new_protected_nopar } { Nx } { Npx }
% \end{macrocode}
% \end{macro}
%
@@ -2684,49 +2797,40 @@
% \cs_new_protected:cn , \cs_new_protected:cx ,
% \cs_new_protected_nopar:cn , \cs_new_protected_nopar:cx ,
% }
-% Then something similar for the |c| variants.
-% \begin{verbatim}
-% \cs_set_protected:Npn \cs_set:cn #1#2
-% {
-% \cs_generate_from_arg_count:cNnn {#1} \cs_set:Npn
-% { \cs_get_arg_count_from_signature:c {#1} } {#2}
-% }
-% \end{verbatim}
-% The 24 |c| variants.
+% The 24 |c| variants simply use \cs{exp_args:Nc}.
% \begin{macrocode}
-\cs_set:Npn \cs_tmp:w #1#2#3
+\cs_set:Npn \__cs_tmp:w #1#2
{
- \cs_new_protected:cpx {cs_#1:#2} ##1##2
+ \cs_new_protected_nopar:cpx { cs_ #1 : c #2 }
{
- \exp_not:N \cs_generate_from_arg_count:cNnn {##1}
- \exp_after:wN \exp_not:N \cs:w cs_#1:#3 \cs_end:
- { \exp_not:N \cs_get_arg_count_from_signature:c {##1} } {##2}
+ \exp_not:N \exp_args:Nc
+ \exp_after:wN \exp_not:N \cs:w cs_ #1 : N #2 \cs_end:
}
}
-\cs_tmp:w { set } { cn } { Npn }
-\cs_tmp:w { set } { cx } { Npx }
-\cs_tmp:w { set_nopar } { cn } { Npn }
-\cs_tmp:w { set_nopar } { cx } { Npx }
-\cs_tmp:w { set_protected } { cn } { Npn }
-\cs_tmp:w { set_protected } { cx } { Npx }
-\cs_tmp:w { set_protected_nopar } { cn } { Npn }
-\cs_tmp:w { set_protected_nopar } { cx } { Npx }
-\cs_tmp:w { gset } { cn } { Npn }
-\cs_tmp:w { gset } { cx } { Npx }
-\cs_tmp:w { gset_nopar } { cn } { Npn }
-\cs_tmp:w { gset_nopar } { cx } { Npx }
-\cs_tmp:w { gset_protected } { cn } { Npn }
-\cs_tmp:w { gset_protected } { cx } { Npx }
-\cs_tmp:w { gset_protected_nopar } { cn } { Npn }
-\cs_tmp:w { gset_protected_nopar } { cx } { Npx }
-\cs_tmp:w { new } { cn } { Npn }
-\cs_tmp:w { new } { cx } { Npx }
-\cs_tmp:w { new_nopar } { cn } { Npn }
-\cs_tmp:w { new_nopar } { cx } { Npx }
-\cs_tmp:w { new_protected } { cn } { Npn }
-\cs_tmp:w { new_protected } { cx } { Npx }
-\cs_tmp:w { new_protected_nopar } { cn } { Npn }
-\cs_tmp:w { new_protected_nopar } { cx } { Npx }
+\__cs_tmp:w { set } { n }
+\__cs_tmp:w { set } { x }
+\__cs_tmp:w { set_nopar } { n }
+\__cs_tmp:w { set_nopar } { x }
+\__cs_tmp:w { set_protected } { n }
+\__cs_tmp:w { set_protected } { x }
+\__cs_tmp:w { set_protected_nopar } { n }
+\__cs_tmp:w { set_protected_nopar } { x }
+\__cs_tmp:w { gset } { n }
+\__cs_tmp:w { gset } { x }
+\__cs_tmp:w { gset_nopar } { n }
+\__cs_tmp:w { gset_nopar } { x }
+\__cs_tmp:w { gset_protected } { n }
+\__cs_tmp:w { gset_protected } { x }
+\__cs_tmp:w { gset_protected_nopar } { n }
+\__cs_tmp:w { gset_protected_nopar } { x }
+\__cs_tmp:w { new } { n }
+\__cs_tmp:w { new } { x }
+\__cs_tmp:w { new_nopar } { n }
+\__cs_tmp:w { new_nopar } { x }
+\__cs_tmp:w { new_protected } { n }
+\__cs_tmp:w { new_protected } { x }
+\__cs_tmp:w { new_protected_nopar } { n }
+\__cs_tmp:w { new_protected_nopar } { x }
% \end{macrocode}
% \end{macro}
%
@@ -2758,25 +2862,25 @@
%
% \subsection{Diagnostic wrapper functions}
%
-% \begin{macro}{\kernel_register_show:N, \kernel_register_show:c}
-% Check that the variable, then apply the \tn{showthe} primitive to
+% \begin{macro}[int]{\__kernel_register_show:N, \__kernel_register_show:c}
+% Check that the variable exists, then apply the \tn{showthe} primitive to
% the variable. The odd-looking \cs{use:n} gives a nicer output.
% \begin{macrocode}
-\cs_new:Npn \kernel_register_show:N #1
+\cs_new_protected:Npn \__kernel_register_show:N #1
{
\cs_if_exist:NTF #1
{ \tex_showthe:D \use:n {#1} }
{
- \msg_kernel_error:nnx { kernel } { variable-not-defined }
+ \__msg_kernel_error:nnx { kernel } { variable-not-defined }
{ \token_to_str:N #1 }
}
}
-\cs_new_nopar:Npn \kernel_register_show:c
- { \exp_args:Nc \kernel_register_show:N }
+\cs_new_protected_nopar:Npn \__kernel_register_show:c
+ { \exp_args:Nc \__kernel_register_show:N }
% \end{macrocode}
% \end{macro}
%
-% \subsection{Engine specific definitions}
+% \subsection{Engine specific definitions}
%
% \begin{macro}[pTF, EXP]
% {\xetex_if_engine:, \luatex_if_engine:, \pdftex_if_engine:}
@@ -2831,7 +2935,7 @@
%
% \subsection{String comparisons}
%
-% \begin{macro}[pTF, EXP]{\str_if_eq:nn, \str_if_eq:xx}
+% \begin{macro}[pTF, EXP]{\str_if_eq:nn, \str_if_eq_x:nn}
% Modern engines provide a direct way of comparing two token lists,
% but returning a number. This set of conditionals therefore make life
% a bit clearer. The \texttt{nn} and \texttt{xx} versions are created
@@ -2844,7 +2948,7 @@
= \c_zero
\prg_return_true: \else: \prg_return_false: \fi:
}
-\prg_new_conditional:Npnn \str_if_eq:xx #1#2 { p , T , F , TF }
+\prg_new_conditional:Npnn \str_if_eq_x:nn #1#2 { p , T , F , TF }
{
\if_int_compare:w \pdftex_strcmp:D {#1} {#2} = \c_zero
\prg_return_true: \else: \prg_return_false: \fi:
@@ -2852,20 +2956,83 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[int, EXP]{\__str_if_eq_x_return:nn}
+% It turns out that we often need to compare a token list
+% with the result of applying some function to it, and
+% return with \cs{prg_return_true/false:}. This test is
+% similar to \cs{str_if_eq:nnTF}, but hard-coded for speed.
+% \begin{macrocode}
+\cs_new:Npn \__str_if_eq_x_return:nn #1 #2
+ {
+ \if_int_compare:w \pdftex_strcmp:D {#1} {#2} = \c_zero
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\str_case:nnn, \str_case_x:nnn}
+% \begin{macro}[int, EXP]{\__prg_case_end:nw}
+% \begin{macro}[aux, EXP]
+% {\__str_case:nw, \__str_case_x:nw, \__str_case_end:nw}
+% No calculations for strings, otherwise no surprises.
+% \begin{macrocode}
+\cs_new:Npn \str_case:nnn #1#2#3
+ {
+ \tex_romannumeral:D
+ \__str_case:nw {#1} #2 {#1} {#3} \q_recursion_stop
+ }
+\cs_new:Npn \__str_case:nw #1#2#3
+ {
+ \str_if_eq:nnTF {#1} {#2}
+ { \__str_case_end:nw {#3} }
+ { \__str_case:nw {#1} }
+ }
+\cs_new:Npn \str_case_x:nnn #1#2#3
+ {
+ \tex_romannumeral:D
+ \__str_case_x:nw {#1} #2 {#1} {#3} \q_recursion_stop
+ }
+\cs_new:Npn \__str_case_x:nw #1#2#3
+ {
+ \str_if_eq_x:nnTF {#1} {#2}
+ { \__str_case_end:nw {#3} }
+ { \__str_case_x:nw {#1} }
+ }
+% \end{macrocode}
+% Here, |#1| will be the code needed, |#2| will be any remaining case
+% or cases, and the \cs{c_zero} stops the \tn{romannumeral}.
+% \begin{macrocode}
+\cs_new:Npn \__prg_case_end:nw #1#2 \q_recursion_stop { \c_zero #1 }
+\cs_new_eq:NN \__str_case_end:nw \__prg_case_end:nw
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Breaking out of mapping functions}
%
-% \begin{macro}[EXP]{\prg_break_point:n, \prg_map_break:, \prg_map_break:n}
+% \begin{macro}[EXP]{\__prg_break_point:Nn, \__prg_map_break:Nn}
% In inline mappings, the nesting level must be reset
% at the end of the mapping, even when the user decides
% to break out. This is done by putting the code that
-% must be performed as an argument of \cs{prg_break_point:n}.
+% must be performed as an argument of \cs{__prg_break_point:Nn}.
% The breaking functions are then defined to jump to
-% that point and perform the argument of \cs{prg_break_point:n},
-% before the user's code (if any).
+% that point and perform the argument of \cs{__prg_break_point:Nn},
+% before the user's code (if any). There is a check that we close the
+% correct loop, otherwise we continue breaking.
% \begin{macrocode}
-\cs_new_eq:NN \prg_break_point:n \use:n
-\cs_new:Npn \prg_map_break: #1 \prg_break_point:n #2 { #2 }
-\cs_new:Npn \prg_map_break:n #1 #2 \prg_break_point:n #3 { #3 #1 }
+\cs_new_eq:NN \__prg_break_point:Nn \use_ii:nn
+\cs_new:Npn \__prg_map_break:Nn #1#2#3 \__prg_break_point:Nn #4#5
+ {
+ #5
+ \if_meaning:w #1 #4
+ \exp_after:wN \use_iii:nnn
+ \fi:
+ \__prg_map_break:Nn #1 {#2}
+ }
% \end{macrocode}
% \end{macro}
%
@@ -2963,6 +3130,24 @@
% \end{macrocode}
% \end{macro}
%
+% Deprecated 2012-06-05 for removal after 2012-12-31.
+%
+% \begin{macro}[pTF, EXP]{\str_if_eq:xx}
+% Not really true \texttt{x}-type expansion
+% \begin{macrocode}
+\cs_new_eq:NN \str_if_eq_p:xx \str_if_eq_x_p:nn
+\cs_new_eq:NN \str_if_eq:xxT \str_if_eq_x:nnT
+\cs_new_eq:NN \str_if_eq:xxF \str_if_eq_x:nnF
+\cs_new_eq:NN \str_if_eq:xxTF \str_if_eq_x:nnTF
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\chk_if_free_cs:N}
+% \begin{macrocode}
+\cs_new_eq:NN \chk_if_free_cs:N \__chk_if_free_cs:N
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
index 43b2d11689f..1fb3ac9454f 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3bootstrap.dtx Copyright (C) 2011 The LaTeX3 project
+%% File: l3bootstrap.dtx Copyright (C) 2011-2012 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
@@ -33,22 +33,38 @@
%%
%% -----------------------------------------------------------------------
%
-%<*package>
+%<*driver|package>
+% \begin{macro}{\GetIdInfo}
+% \begin{macro}[aux]{\GetIdInfoAuxI, \GetIdInfoAuxII, \GetIdInfoAuxIII}
+% The idea here is to extract out the information needed from a standard
+% \textsc{svn} \texttt{Id} line, but without a line that will get
+% changed when the file is checked in. Hence the fact that there is
+% not a line which includes both a dollar sign and the \texttt{Id}
+% keyword together!
+% \begin{macrocode}
\protected\def\GetIdInfo
- {
+ {%
\begingroup
- \catcode 32 = 10 \relax
- \GetIdInfoAuxI
+ \catcode 32 = 10 %
+ \GetIdInfoAuxI
}
+% \end{macrocode}
+% A first check for a completely empty \textsc{svn} field. If that is
+% not the case, there is a second case when a file created using
+% \texttt{svn cp} but has not been checked in. That leaves a special
+% marker \texttt{-1} version, which has no further data. Dealing correctly
+% with that is the reason for the space in the line to use
+% \cs{GetIdInforAuxII}.
+% \begin{macrocode}
\protected\def\GetIdInfoAuxI$#1$#2%
- {
+ {%
\def\tempa{#1}%
\def\tempb{Id}%
\ifx\tempa\tempb
\def\tempa
{%
\endgroup
- \def\ExplFileDate{9999/99/99}%
+ \def\ExplFileDate{9999/12/31}%
\def\ExplFileDescription{#2}%
\def\ExplFileName{[unknown name]}%
\def\ExplFileExtension{[unknown extension]}%
@@ -58,34 +74,54 @@
\def\tempa
{%
\endgroup
- \GetIdInfoAuxII$#1${#2}%
+ \def\ExplFileDescription{#2}%
+ \GetIdInfoAuxII$#1 $%
}%
\fi
\tempa
}
-\protected\def\GetIdInfoAuxII$#1 #2.#3 #4 #5 #6 #7 #8$#9%
+% \end{macrocode}
+% Here, |#1| is |Id|, |#2| is the file name, |#3| is the extension,
+% |#4| is the version, |#5| is the check in date and |#6| is the check in
+% time and user, plus some trailing spaces. If |#4| is the marker |-1| value
+% then |#5| and |#6| will be empty.
+% \begin{macrocode}
+\protected\def\GetIdInfoAuxII$#1 #2.#3 #4 #5 #6$%
{%
\def\ExplFileName{#2}%
\def\ExplFileExtension{#3}%
\def\ExplFileVersion{#4}%
- \def\ExplFileDescription{#9}%
- \GetIdInfoAuxIII#5\relax#3\relax#5\relax#6\relax
+ \begingroup
+ \def\tempa{#4}%
+ \def\tempb{-1}%
+ \ifx\tempa\tempb
+ \def\tempa
+ {%
+ \endgroup
+ \def\ExplFileDate{0000/00/00}%
+ }%
+ \else
+ \def\tempa
+ {%
+ \endgroup
+ \GetIdInfoAuxIII$#5$%
+ }%
+ \fi
+ \tempa
}
-\protected\def\GetIdInfoAuxIII#1#2#3#4#5#6\relax
+% \end{macrocode}
+% Convert an \textsc{svn}-style date into a \LaTeX{}-style one.
+% \begin{macrocode}
+\protected\def\GetIdInfoAuxIII$#1-#2-#3$%
{%
- \ifx#5/%
- \expandafter\GetIdInfoAuxCVS
- \else
- \expandafter\GetIdInfoAuxSVN
- \fi
+ \def\ExplFileDate{#1/#2/#3}%
}
-\protected\def\GetIdInfoAuxCVS#1,v\relax#2\relax#3\relax
- {\def\ExplFileDate{#2}}
-\protected\def\GetIdInfoAuxSVN#1\relax#2-#3-#4\relax#5Z\relax
- {\def\ExplFileDate{#2/#3/#4}}
-\GetIdInfo$Id: l3bootstrap.dtx 3110 2011-12-29 14:23:48Z joseph $
- {L3 experimental bootstrap code}
-%</package>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+\GetIdInfo$Id: l3bootstrap.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Bootstrap code}
+%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
\begin{document}
@@ -135,20 +171,7 @@
% and underscore (|_|) are treated as \enquote{letters}, thus allowing
% access to the names of code functions and variables. Within this
% environment, |~| is used to input a space. The \cs{ExplSyntaxOff}
-% reverts to the document category code regim{\'e}.
-% \end{function}
-%
-% \begin{function}{\ExplSyntaxNamesOn, \ExplSyntaxNamesOff}
-% \begin{syntax}
-% \cs{ExplSyntaxNamesOn} \meta{code} \cs{ExplSyntaxNamesOff}
-% \end{syntax}
-% The \cs{ExplSyntaxOn} function switches to a category code
-% regim{\'e} in which the colon (|:|) and underscore (|_|) are treated as
-% \enquote{letters}, thus allowing access to the names of code functions
-% and variables. In contrast to \cs{ExplSyntaxOn}, using
-% \cs{ExplSyntaxNamesOn} does not cause spaces to be ignored.
-% The \cs{ExplSyntaxNamesOff} reverts to the document category code
-% regim{\'e}.
+% reverts to the document category code r{\'e}gime.
% \end{function}
%
% \begin{function}{\ProvidesExplPackage, \ProvidesExplClass, \ProvidesExplFile}
@@ -165,7 +188,7 @@
% \tn{makeatletter} within package and class code.)
% \end{function}
%
-% \begin{function}{\GetIdInfo}
+% \begin{function}[updated = 2012-06-04]{\GetIdInfo}
% \begin{syntax}
% |\RequirePackage{l3names}|
% \cs{GetIdInfo} |$Id:| \meta{SVN info field} |$| \Arg{description}
@@ -189,6 +212,23 @@
% \ProvidesExplPackage{\ExplFileName}
% {\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
% \end{verbatim}
+%
+% \subsection{Internal functions and variables}
+%
+% \begin{function}{\__expl_package_check:}
+% \begin{syntax}
+% \cs{__expl_package_check:}
+% \end{syntax}
+% Used to ensure that all parts of \pkg{expl3} are loaded together
+% (\emph{i.e.}~as part of \pkg{expl3}). Issues an error if a kernel package
+% is loaded independently of the bundle.
+% \end{function}
+%
+% \begin{variable}{\l__kernel_expl_bool}
+% A boolean which records the current code syntax status: \texttt{true} if
+% currently inside a code environment. This variable should only be
+% set by \cs{ExplSyntaxOn}/\cs{ExplSyntaxOff}.
+% \end{variable}
%
% \end{documentation}
%
@@ -198,6 +238,7 @@
%
% \begin{macrocode}
%<*initex|package>
+%<@@=expl>
% \end{macrocode}
%
% \subsection{Format-specific code}
@@ -223,7 +264,7 @@
% \end{macrocode}
%
% For \LuaTeX{} the extra primitives need to be enabled before
-% they can be use. No \tn{ifdefined} yet, so do it the old-fashioned
+% they can be used. No \tn{ifdefined} yet, so do it the old-fashioned
% way. The primitive \tn{strcmp} is simulated using some \Lua{}
% code, which currently has to be applied to every job as the \Lua{}
% code is not part of the format. Thanks to Taco Hoekwater for this
@@ -267,7 +308,7 @@
%</initex>
% \end{macrocode}
%
-% \subsection{Package-specific code}
+% \subsection{Package-specific code part one}
%
% The package starts by identifying itself: the information itself is
% taken from the SVN |Id| string at the start of the source file.
@@ -303,6 +344,64 @@
\fi
%</package>
% \end{macrocode}
+%
+% \subsection{The \tn{pdfstrcmp} primitive in \XeTeX{}}
+%
+% Only \pdfTeX{} has a primitive called \tn{pdfstrcmp}. The \XeTeX{}
+% version is just \tn{strcmp}, so there is some shuffling to do.
+% \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+ \expandafter\ifx\csname pdfstrcmp\endcsname\relax
+ \let\pdfstrcmp\strcmp
+\fi
+% \end{macrocode}
+%
+% \subsection{Engine requirements}
+%
+% The code currently requires functionality equivalent to \tn{pdfstrcmp}
+% in addition to \eTeX{}. The former is therefore used as a test for
+% a suitable engine.
+% \begin{macrocode}
+\begingroup\expandafter\expandafter\expandafter\endgroup
+\expandafter\ifx\csname pdfstrcmp\endcsname\relax
+%<*package>
+ \PackageError{expl3}{Required primitives not found}
+ {%
+ LaTeX3 requires the e-TeX primitives and \string\pdfstrcmp.\MessageBreak
+ \MessageBreak
+ These are available in engine versions:\MessageBreak
+ - pdfTeX 1.30\MessageBreak
+ - XeTeX 0.9994\MessageBreak
+ - LuaTeX 0.40\MessageBreak
+ or later.\MessageBreak
+ \MessageBreak
+ Loading of expl3 will abort!%
+ }
+ \expandafter\endinput
+%</package>
+%<*initex>
+ \newlinechar`\^^J\relax
+ \errhelp{%
+ LaTeX3 requires the e-TeX primitives and \pdfstrcmp.^^J%
+ ^^J%
+ These are available in engine versions:^^J%
+ - pdfTeX 1.30^^J%
+ - XeTeX 0.9994^^J%
+ - LuaTeX 0.40^^J%
+ or later.^^J%
+ ^^J%
+ For pdfTeX and XeTeX the '-etex' command-line switch is also
+ needed.^^J%
+ ^^J%
+ Format building will abort!%
+ }
+ \errmessage{Required primitives not found}%
+ \expandafter\end
+%</initex>
+\fi
+% \end{macrocode}
+%
+% \subsection{Package-specific code part two}
%
% \begin{macro}{\ExplSyntaxOff, \ExplSyntaxOn}
% Experimental syntax switching is set up here for the package-loading
@@ -322,7 +421,7 @@
\catcode 124 = \the\catcode 124\relax
\catcode 126 = \the\catcode 126\relax
\endlinechar = \the\endlinechar\relax
- \chardef\csname\detokenize{l_expl_status_bool}\endcsname = 0 \relax
+ \chardef\csname\detokenize{l__kernel_expl_bool}\endcsname = 0 \relax
}
\protected\edef\ExplSyntaxOn
{
@@ -335,82 +434,24 @@
\catcode 124 = 12 \relax
\catcode 126 = 10 \relax
\endlinechar = 32 \relax
- \chardef\csname\detokenize{l_expl_status_bool}\endcsname = 1 \relax
+ \chardef\csname\detokenize{l__kernel_expl_bool}\endcsname = 1 \relax
}
%</package>
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\l_expl_status_bool}
+% \begin{variable}{\l__kernel_expl_bool}
% The status for experimental code syntax: this is off at present. This
% code is used by both the package and the format.
% \begin{macrocode}
-\expandafter\chardef\csname\detokenize{l_expl_status_bool}\endcsname = 0 \relax
+\expandafter\chardef\csname\detokenize{l__kernel_expl_bool}\endcsname = 0 \relax
% \end{macrocode}
-%\end{macro}
+%\end{variable}
%
% \subsection{Dealing with package-mode meta-data}
%
% \begin{macro}{\GetIdInfo}
-% \begin{macro}[aux]
-% {
-% \GetIdInfoFull, \GetIdInfoAuxI, \GetIdInfoAuxII, \GetIdInfoAuxIII,
-% \GetIdInfoAuxCVS, \GetIdInfoAuxSVN
-% }
-% Functions for collecting up meta-data from the SVN information
-% used by the \LaTeX3 Project.
-% \begin{macrocode}
-%<*package>
-\protected\def\GetIdInfo
- {
- \begingroup
- \catcode 32 = 10 \relax
- \GetIdInfoAuxI
- }
-\protected\def\GetIdInfoAuxI$#1$#2%
- {
- \def\tempa{#1}%
- \def\tempb{Id}%
- \ifx\tempa\tempb
- \def\tempa
- {%
- \endgroup
- \def\ExplFileDate{9999/99/99}%
- \def\ExplFileDescription{#2}%
- \def\ExplFileName{[unknown name]}%
- \def\ExplFileVersion{999}%
- }%
- \else
- \def\tempa
- {%
- \endgroup
- \GetIdInfoAuxII$#1${#2}%
- }%
- \fi
- \tempa
- }
-\protected\def\GetIdInfoAuxII$#1 #2.#3 #4 #5 #6 #7 #8$#9%
- {%
- \def\ExplFileName{#2}%
- \def\ExplFileVersion{#4}%
- \def\ExplFileDescription{#9}%
- \GetIdInfoAuxIII#5\relax#3\relax#5\relax#6\relax
- }
-\protected\def\GetIdInfoAuxIII#1#2#3#4#5#6\relax
- {%
- \ifx#5/%
- \expandafter\GetIdInfoAuxCVS
- \else
- \expandafter\GetIdInfoAuxSVN
- \fi
- }
-\protected\def\GetIdInfoAuxCVS#1,v\relax#2\relax#3\relax
- {\def\ExplFileDate{#2}}
-\protected\def\GetIdInfoAuxSVN#1\relax#2-#3-#4\relax#5Z\relax
- {\def\ExplFileDate{#2/#3/#4}}
-%</package>
-% \end{macrocode}
-% \end{macro}
+% This is implemented right at the start of \texttt{l3bootstrap.dtx}.
% \end{macro}
%
% \begin{macro}{\ProvidesExplPackage, \ProvidesExplClass, \ProvidesExplFile}
@@ -448,16 +489,16 @@
\edef\@pushfilename
{%
\edef\expandafter\noexpand
- \csname\detokenize{l_expl_status_stack_tl}\endcsname
+ \csname\detokenize{l_@@_status_stack_tl}\endcsname
{%
\noexpand\ifodd\expandafter\noexpand
- \csname\detokenize{l_expl_status_bool}\endcsname
+ \csname\detokenize{l__kernel_expl_bool}\endcsname
1%
\noexpand\else
0%
\noexpand\fi
\expandafter\noexpand
- \csname\detokenize{l_expl_status_stack_tl}\endcsname
+ \csname\detokenize{l_@@_status_stack_tl}\endcsname
}%
\ExplSyntaxOff
\unexpanded\expandafter{\@pushfilename}%
@@ -466,14 +507,14 @@
{%
\unexpanded\expandafter{\@popfilename}%
\noexpand\if a\expandafter\noexpand\csname
- \detokenize{l_expl_status_stack_tl}\endcsname a%
+ \detokenize{l_@@_status_stack_tl}\endcsname a%
\ExplSyntaxOff
\noexpand\else
\noexpand\expandafter
\expandafter\noexpand\csname
- \detokenize{expl_status_pop:w}\endcsname
+ \detokenize{@@_status_pop:w}\endcsname
\expandafter\noexpand\csname
- \detokenize{l_expl_status_stack_tl}\endcsname
+ \detokenize{l_@@_status_stack_tl}\endcsname
\noexpand\@nil
\noexpand\fi
}
@@ -481,28 +522,28 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\l_expl_status_stack_tl}
+% \begin{macro}{\l_@@_status_stack_tl}
% As \pkg{expl3} itself cannot be loaded with the code environment
% already active, at the end of the package \cs{ExplSyntaxOff} can
% safely be called.
% \begin{macrocode}
%<*package>
-\@namedef{\detokenize{l_expl_status_stack_tl}}{0}
+\@namedef{\detokenize{l_@@_status_stack_tl}}{0}
%</package>
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\expl_status_pop:w}
+% \begin{macro}[aux]{\@@_status_pop:w}
% The pop auxiliary function removes the first item from the stack,
% saves the rest of the stack and then does the test. As
% \cs{ExplSyntaxOff} is already defined as a protected macro, there
% is no need for \tn{noexpand} here.
% \begin{macrocode}
%<*package>
-\expandafter\edef\csname\detokenize{expl_status_pop:w}\endcsname#1#2\@nil
+\expandafter\edef\csname\detokenize{@@_status_pop:w}\endcsname#1#2\@nil
{%
\def\expandafter\noexpand
- \csname\detokenize{l_expl_status_stack_tl}\endcsname{#2}%
+ \csname\detokenize{l_@@_status_stack_tl}\endcsname{#2}%
\noexpand\ifodd#1\space
\noexpand\expandafter\noexpand\ExplSyntaxOn
\noexpand\else
@@ -513,13 +554,14 @@
% \end{macrocode}
% \end{macro}
%
-% We want the \pkg{expl3} bundle to be loaded \enquote{as one};
-% this command is
-% used to ensure that one of the |l3| packages isn't loaded on its own.
+% \begin{macro}[int]{\__expl_package_check:}
+% We want the \pkg{expl3} bundle to be loaded \enquote{as one};
+% this command is used to ensure that one of the |l3| packages isn't loaded
+% on its own.
% \begin{macrocode}
%<*package>
\expandafter\protected\expandafter\def
- \csname\detokenize{package_check_loaded_expl:}\endcsname
+ \csname\detokenize{__expl_package_check:}\endcsname
{%
\@ifpackageloaded{expl3}
{}
@@ -528,90 +570,16 @@
{Cannot load the expl3 modules separately}
{%
The expl3 modules cannot be loaded separately;\MessageBreak
- please \string\usepackage\string{expl3\string} instead.
+ please \string\usepackage\string{expl3\string} instead.%
}%
}%
}
%</package>
% \end{macrocode}
-%
-% \subsection{The \tn{pdfstrcmp} primitive in \XeTeX{}}
-%
-% Only \pdfTeX{} has a primitive called \tn{pdfstrcmp}. The \XeTeX{}
-% version is just \tn{strcmp}, so there is some shuffling to do.
-% \begin{macrocode}
-\begingroup\expandafter\expandafter\expandafter\endgroup
- \expandafter\ifx\csname pdfstrcmp\endcsname\relax
- \let\pdfstrcmp\strcmp
-\fi
-% \end{macrocode}
-%
-% \subsection{Engine requirements}
-%
-% The code currently requires functionality equivalent to \tn{pdfstrcmp}
-% in addition to \eTeX{}. The former is therefore used as a test for
-% a suitable engine.
-% \begin{macrocode}
-\begingroup\expandafter\expandafter\expandafter\endgroup
-\expandafter\ifx\csname pdfstrcmp\endcsname\relax
-%<*package>
- \PackageError{l3names}{Required primitive not found: \protect\pdfstrcmp}
- {%
- LaTeX3 requires the e-TeX primitives and
- \string\pdfstrcmp.\MessageBreak
- These are available in engine versions: \MessageBreak
- - pdfTeX 1.30 \MessageBreak
- - XeTeX 0.9994 \MessageBreak
- - LuaTeX 0.60 \MessageBreak
- or later. \MessageBreak
- \MessageBreak
- Loading of expl3 will abort!
- }
-%</package>
-%<*initex>
- \newlinechar`\^^J\relax
- \errhelp{%
- LaTeX3 requires the e-TeX primitives and
- \string\pdfstrcmp. ^^J
- These are available in engine versions: ^^J
- - pdfTeX 1.30 ^^J
- - XeTeX 0.9994 ^^J
- - LuaTeX 0.60 ^^J
- or later. ^^J
- For pdfTeX and XeTeX the '-etex' command-line switch is also
- needed.^^J
- ^^J
- Format building will abort!
- }
-%</initex>
- \expandafter\endinput
-\fi
-% \end{macrocode}
+% \end{macro}
%
% \subsection{The \LaTeX3 code environment}
%
-% \begin{macro}{\ExplSyntaxNamesOn, \ExplSyntaxNamesOff}
-% These can be set up early, as they are not used anywhere in the
-% package or format itself. Using an \tn{edef} here makes the
-% definitions that bit clearer later.
-% \begin{macrocode}
-\protected\edef\ExplSyntaxNamesOn
- {%
- \expandafter\noexpand
- \csname\detokenize{char_set_catcode_letter:n}\endcsname{58}%
- \expandafter\noexpand
- \csname\detokenize{char_set_catcode_letter:n}\endcsname{95}%
- }
-\protected\edef\ExplSyntaxNamesOff
- {%
- \expandafter\noexpand
- \csname\detokenize{char_set_catcode_other:n}\endcsname{58}%
- \expandafter\noexpand
- \csname\detokenize{char_set_catcode_math_subscript:n}\endcsname{95}%
- }
-% \end{macrocode}
-% \end{macro}
-%
% The code environment is now set up for the format: the package deals
% with this using \cs{ProvidesExplPackage}.
% \begin{macrocode}
@@ -636,7 +604,7 @@
%<*initex>
\protected \def \ExplSyntaxOn
{
- \bool_if:NF \l_expl_status_bool
+ \bool_if:NF \l__kernel_expl_bool
{
\cs_set_protected_nopar:Npx \ExplSyntaxOff
{
@@ -651,7 +619,7 @@
\char_set_catcode:nn { 126 } { \char_value_catcode:n { 126 } }
\tex_endlinechar:D =
\tex_the:D \tex_endlinechar:D \scan_stop:
- \bool_set_false:N \l_expl_status_bool
+ \bool_set_false:N \l__kernel_expl_bool
\cs_set_protected_nopar:Npn \ExplSyntaxOff { }
}
}
@@ -665,21 +633,47 @@
\char_set_catcode_other:n { 124 } % pipe
\char_set_catcode_space:n { 126 } % tilde
\tex_endlinechar:D = 32 \scan_stop:
- \bool_set_true:N \l_expl_status_bool
+ \bool_set_true:N \l__kernel_expl_bool
}
\protected \def \ExplSyntaxOff { }
%</initex>
% \end{macrocode}
% \end{macro}
%
-% \begin{variable}{\l_expl_status_bool}
+% \begin{variable}{\l__kernel_expl_bool}
% A flag to show the current syntax status.
% \begin{macrocode}
%<*initex>
-\chardef \l_expl_status_bool = 0 ~
+\chardef \l__kernel_expl_bool = 0 ~
%</initex>
% \end{macrocode}
% \end{variable}
+%
+% \subsection{Deprecated functions}
+%
+% Deprecated 2012-06-19 for removal after 2012-12-31.
+%
+% \begin{macro}{\ExplSyntaxNamesOn, \ExplSyntaxNamesOff}
+% These can be set up early, as they are not used anywhere in the
+% package or format itself. Using an \tn{edef} here makes the
+% definitions that bit clearer later.
+% \begin{macrocode}
+\protected\edef\ExplSyntaxNamesOn
+ {%
+ \expandafter\noexpand
+ \csname\detokenize{char_set_catcode_letter:n}\endcsname{58}%
+ \expandafter\noexpand
+ \csname\detokenize{char_set_catcode_letter:n}\endcsname{95}%
+ }
+\protected\edef\ExplSyntaxNamesOff
+ {%
+ \expandafter\noexpand
+ \csname\detokenize{char_set_catcode_other:n}\endcsname{58}%
+ \expandafter\noexpand
+ \csname\detokenize{char_set_catcode_math_subscript:n}\endcsname{95}%
+ }
+% \end{macrocode}
+% \end{macro}
%
% \begin{macrocode}
%</initex|package>
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
index 8ec1f62babe..b578295ac44 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3box.dtx
@@ -35,7 +35,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3box.dtx 3490 2012-03-04 01:00:53Z bruno $
+\GetIdInfo$Id: l3box.dtx 3986 2012-07-15 19:23:51Z joseph $
{L3 Experimental boxes}
%</driver|package>
%<*driver>
@@ -106,9 +106,9 @@
% \box_gset_eq:NN, \box_gset_eq:cN, \box_gset_eq:Nc, \box_gset_eq:cc
% }
% \begin{syntax}
-% \cs{box_set_eq:NN} \meta{box1} \meta{box2}
+% \cs{box_set_eq:NN} \meta{box_1} \meta{box_2}
% \end{syntax}
-% Sets the content of \meta{box1} equal to that of \meta{box2}.
+% Sets the content of \meta{box_1} equal to that of \meta{box_2}.
% \end{function}
%
% \begin{function}
@@ -117,10 +117,10 @@
% \box_set_eq_clear:Nc, \box_set_eq_clear:cc
% }
% \begin{syntax}
-% \cs{box_set_eq_clear:NN} \meta{box1} \meta{box2}
+% \cs{box_set_eq_clear:NN} \meta{box_1} \meta{box_2}
% \end{syntax}
-% Sets the content of \meta{box1} within the current \TeX{} group
-% equal to that of \meta{box2}, then clears \meta{box2} globally.
+% Sets the content of \meta{box_1} within the current \TeX{} group
+% equal to that of \meta{box_2}, then clears \meta{box_2} globally.
% \end{function}
%
% \begin{function}
@@ -129,10 +129,10 @@
% \box_gset_eq_clear:Nc, \box_gset_eq_clear:cc
% }
% \begin{syntax}
-% \cs{box_gset_eq_clear:NN} \meta{box1} \meta{box2}
+% \cs{box_gset_eq_clear:NN} \meta{box_1} \meta{box_2}
% \end{syntax}
-% Sets the content of \meta{box1} equal to that of \meta{box2}, then
-% clears \meta{box2}. These assignments are global.
+% Sets the content of \meta{box_1} equal to that of \meta{box_2}, then
+% clears \meta{box_2}. These assignments are global.
% \end{function}
%
% \begin{function}[EXP, pTF, added=2012-03-03]
@@ -255,153 +255,6 @@
% \Arg{dimension expression}. This is a global assignment.
% \end{function}
%
-% \section{Affine transformations}
-%
-% Affine transformations are changes which (informally) preserve straight
-% lines. Simple translations are affine transformations, but are better handled
-% in \TeX{} by doing the translation first, then inserting an unmodified box.
-% On the other hand, rotation and resizing of boxed material can best be
-% handled by modifying boxes. These transformations are described here.
-%
-% \begin{function}[added = 2011-09-02]{\box_resize:Nnn, \box_resize:cnn}
-% \begin{syntax}
-% \cs{box_resize:Nnn} \meta{box} \Arg{x-size} \Arg{y-size}
-% \end{syntax}
-% Resize the \meta{box} to \meta{x-size} horizontally and \meta{y-size}
-% vertically (both of the sizes are dimension expressions).
-% The \meta{y-size} is the vertical size (height plus depth) of
-% the box. The updated \meta{box} will be an hbox, irrespective of the nature
-% of the \meta{box} before the resizing is applied. Negative sizes will
-% cause the material in the \meta{box} to be reversed in direction, but the
-% reference point of the \meta{box} will be unchanged. The resizing applies
-% within the current \TeX{} group level.
-%
-% \textbf{This function is experimental}
-% \end{function}
-%
-% \begin{function}[added = 2011-09-02, updated = 2011-10-22]
-% {\box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn}
-% \begin{syntax}
-% \cs{box_resize_to_ht_plus_dp:Nn} \meta{box} \Arg{y-size}
-% \end{syntax}
-% Resize the \meta{box} to \meta{y-size} vertically, scaling the horizontal
-% size by the same amount (\meta{y-size} is a dimension expression).
-% The \meta{y-size} is the vertical size (height plus depth) of
-% the box.
-% The updated \meta{box} will be an hbox, irrespective of the nature
-% of the \meta{box} before the resizing is applied. A negative size will
-% cause the material in the \meta{box} to be reversed in direction, but the
-% reference point of the \meta{box} will be unchanged. The resizing applies
-% within the current \TeX{} group level.
-%
-% \textbf{This function is experimental}
-% \end{function}
-%
-% \begin{function}[added = 2011-09-02, updated = 2011-10-22]
-% {\box_resize_to_wd:Nn, \box_resize_to_wd:cn}
-% \begin{syntax}
-% \cs{box_resize_to_wd:Nn} \meta{box} \Arg{x-size}
-% \end{syntax}
-% Resize the \meta{box} to \meta{x-size} horizontally, scaling the vertical
-% size by the same amount (\meta{x-size} is a dimension expression).
-% The updated \meta{box} will be an hbox, irrespective of the nature
-% of the \meta{box} before the resizing is applied. A negative size will
-% cause the material in the \meta{box} to be reversed in direction, but the
-% reference point of the \meta{box} will be unchanged. The resizing applies
-% within the current \TeX{} group level.
-%
-% \textbf{This function is experimental}
-% \end{function}
-%
-% \begin{function}[added = 2011-09-02, updated = 2011-10-22]
-% {\box_rotate:Nn, \box_rotate:cn}
-% \begin{syntax}
-% \cs{box_rotate:Nn} \meta{box} \Arg{angle}
-% \end{syntax}
-% Rotates the \meta{box} by \meta{angle} (in degrees) anti-clockwise about
-% its reference point. The reference point of the updated box will be moved
-% horizontally such that it is at the left side of the smallest rectangle
-% enclosing the rotated material.
-% The updated \meta{box} will be an hbox, irrespective of the nature
-% of the \meta{box} before the rotation is applied. The rotation applies
-% within the current \TeX{} group level.
-%
-% \textbf{This function is experimental}
-% \end{function}
-%
-% \begin{function}[added = 2011-09-02, updated = 2011-10-22]
-% {\box_scale:Nnn, \box_scale:cnn}
-% \begin{syntax}
-% \cs{box_scale:Nnn} \meta{box} \Arg{x-scale} \Arg{y-scale}
-% \end{syntax}
-% Scales the \meta{box} by factors \meta{x-scale} and \meta{y-scale} in
-% the horizontal and vertical directions, respectively (both scales are
-% integer expressions). The updated \meta{box} will be an hbox, irrespective
-% of the nature of the \meta{box} before the scaling is applied. Negative
-% scalings will cause the material in the \meta{box} to be reversed in
-% direction, but the reference point of the \meta{box} will be unchanged.
-% The scaling applies within the current \TeX{} group level.
-%
-% \textbf{This function is experimental}
-% \end{function}
-%
-% \section{Viewing part of a box}
-%
-% \begin{function}[added = 2011-11-13]{\box_clip:N, \box_clip: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} will be an
-% hbox, irrespective of the nature of the \meta{box} before the clipping is
-% applied. The clipping applies within the current \TeX{} group level.
-%
-% \textbf{This function is experimental}
-% \begin{texnote}
-% Clipping is implemented by the driver, and as such the full content of
-% the box is places 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 = 2011-11-13]
-% {\box_trim:Nnnnn, \box_trim:cnnnn}
-% \begin{syntax}
-% \cs{box_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 output of the bounding box will still be displayed in the output
-% unless \cs{box_clip:N} is subsequently applied.
-% The updated \meta{box} will be an
-% hbox, irrespective of the nature of the \meta{box} before the viewport
-% operation is applied. The clipping applies within the current \TeX{}
-% group level.
-%
-% \textbf{This function is experimental}
-% \end{function}
-%
-% \begin{function}[added = 2011-11-13]
-% {\box_viewport:Nnnnn, \box_viewport:cnnnn}
-% \begin{syntax}
-% \cs{box_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 output of the bounding box will
-% still be displayed in the output unless \cs{box_clip:N} is
-% subsequently applied.
-% The updated \meta{box} will be an
-% hbox, irrespective of the nature of the \meta{box} before the viewport
-% operation is applied. The clipping applies within the current \TeX{}
-% group level.
-%
-% \textbf{This function is experimental}
-% \end{function}
-%
% \section{Box conditionals}
%
% \begin{function}[EXP,pTF]{\box_if_empty:N, \box_if_empty:c}
@@ -460,16 +313,45 @@
% code and so should only be used for short-term storage.
% \end{variable}
%
+% \begin{variable}{\g_tmpa_box, \g_tmpb_box}
+% Scratch boxes for global assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
+%
% \section{Viewing box contents}
%
-% \begin{function}{\box_show:N, \box_show:c}
+% \begin{function}[updated = 2012-05-11]{\box_show:N, \box_show:c}
% \begin{syntax}
% \cs{box_show:N} \meta{box}
% \end{syntax}
-% Writes the contents of \meta{box} to the log file.
-% \begin{texnote}
-% This is a wrapper around the \TeX{} primitive \tn{showbox}.
-% \end{texnote}
+% Shows full details of the content of the \meta{box} in the terminal.
+% \end{function}
+%
+% \begin{function}[added = 2012-05-11]{\box_show:Nnn, \box_show:cnn}
+% \begin{syntax}
+% \cs{box_show:Nnn} \meta{box} \meta{intexpr_1} \meta{intexpr_2}
+% \end{syntax}
+% Display the contents of \meta{box} in the terminal, showing the first
+% \meta{intexpr_1} items of the box, and descending into \meta{intexpr_2}
+% group levels.
+% \end{function}
+%
+% \begin{function}[added = 2012-05-11]{\box_log:N, \box_log:c}
+% \begin{syntax}
+% \cs{box_show:N} \meta{box}
+% \end{syntax}
+% Writes full details of the content of the \meta{box} to the log.
+% \end{function}
+%
+% \begin{function}[added = 2012-05-11]{\box_log:Nnn, \box_log:cnn}
+% \begin{syntax}
+% \cs{box_show:Nnn} \meta{box} \meta{intexpr_1} \meta{intexpr_2}
+% \end{syntax}
+% Writes the contents of \meta{box} to the log, showing the first
+% \meta{intexpr_1} items of the box, and descending into \meta{intexpr_2}
+% group levels.
% \end{function}
%
% \section{Horizontal mode boxes}
@@ -671,7 +553,7 @@
% \vbox_gset_end:
% }
% \begin{syntax}
-% \cs{vbox_begin:Nw} \meta{box} \meta{contents} \cs{vbox_set_end:}
+% \cs{vbox_set:Nw} \meta{box} \meta{contents} \cs{vbox_set_end:}
% \end{syntax}
% Typesets the \meta{contents} at natural height and then stores the
% result inside the \meta{box}. In contrast
@@ -682,10 +564,10 @@
%
% \begin{function}[updated = 2011-10-22]{\vbox_set_split_to_ht:NNn}
% \begin{syntax}
-% \cs{vbox_set_split_to_ht:NNn} \meta{box1} \meta{box2} \Arg{dimexpr}
+% \cs{vbox_set_split_to_ht:NNn} \meta{box_1} \meta{box_2} \Arg{dimexpr}
% \end{syntax}
-% Sets \meta{box1} to contain material to the height given by the
-% \meta{dimexpr} by removing content from the top of \meta{box2}
+% Sets \meta{box_1} to contain material to the height given by the
+% \meta{dimexpr} by removing content from the top of \meta{box_2}
% (which must be a vertical box).
% \begin{texnote}
% This is the \TeX{} primitive \tn{vsplit}.
@@ -759,29 +641,6 @@
% \end{texnote}
% \end{function}
%
-% \section{Experimental box functions}
-%
-% \begin{function}[added = 2011-11-21]{\box_show:Nnn, \box_show:cnn}
-% \begin{syntax}
-% \cs{box_show:Nnn} \meta{box} \meta{int 1} \meta{int 2}
-% \end{syntax}
-% Display the contents of \meta{box} in the terminal,
-% showing the first \meta{int 1} items of the box,
-% and descending into \meta{int 1} levels of nesting.
-% \begin{texnote}
-% This is a wrapper around the \TeX{} primitives \tn{showbox},
-% \tn{showboxbreadth} and \tn{showboxdepth}.
-% \end{texnote}
-% \end{function}
-%
-% \begin{function}[added = 2011-11-22]{\box_show_full:N, \box_show_full:c}
-% \begin{syntax}
-% \cs{box_show_full:N} \meta{box}
-% \end{syntax}
-% Display the contents of \meta{box} in the terminal,
-% showing all items in the box.
-% \end{function}
-%
% \end{documentation}
%
% \begin{implementation}
@@ -791,12 +650,16 @@
% \begin{macrocode}
%<*initex|package>
% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=box>
+% \end{macrocode}
%
% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -814,7 +677,7 @@
%<*package>
\cs_new_protected:Npn \box_new:N #1
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\newbox #1
}
%</package>
@@ -863,8 +726,8 @@
{ \tex_setbox:D #1 \tex_copy:D #2 }
\cs_new_protected:Npn \box_gset_eq:NN
{ \tex_global:D \box_set_eq:NN }
-\cs_generate_variant:Nn \box_set_eq:NN { cN , Nc , cc }
-\cs_generate_variant:Nn \box_gset_eq:NN { cN , Nc , cc }
+\cs_generate_variant:Nn \box_set_eq:NN { c , Nc , cc }
+\cs_generate_variant:Nn \box_gset_eq:NN { c , Nc , cc }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -888,8 +751,8 @@
{ \tex_setbox:D #1 \tex_box:D #2 }
\cs_new_protected:Npn \box_gset_eq_clear:NN
{ \tex_global:D \box_set_eq_clear:NN }
-\cs_generate_variant:Nn \box_set_eq_clear:NN { cN , Nc , cc }
-\cs_generate_variant:Nn \box_gset_eq_clear:NN { cN , Nc , cc }
+\cs_generate_variant:Nn \box_set_eq_clear:NN { c , Nc , cc }
+\cs_generate_variant:Nn \box_gset_eq_clear:NN { c , Nc , cc }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -934,11 +797,11 @@
% expandable, so the derived functions are not either.
% \begin{macrocode}
\cs_new_protected:Npn \box_set_dp:Nn #1#2
- { \box_dp:N #1 \dim_eval:w #2 \dim_eval_end: }
+ { \box_dp:N #1 \__dim_eval:w #2 \__dim_eval_end: }
\cs_new_protected:Npn \box_set_ht:Nn #1#2
- { \box_ht:N #1 \dim_eval:w #2 \dim_eval_end: }
+ { \box_ht:N #1 \__dim_eval:w #2 \__dim_eval_end: }
\cs_new_protected:Npn \box_set_wd:Nn #1#2
- { \box_wd:N #1 \dim_eval:w #2 \dim_eval_end: }
+ { \box_wd:N #1 \__dim_eval:w #2 \__dim_eval_end: }
\cs_generate_variant:Nn \box_set_ht:Nn { c }
\cs_generate_variant:Nn \box_set_dp:Nn { c }
\cs_generate_variant:Nn \box_set_wd:Nn { c }
@@ -968,13 +831,13 @@
% Move box material in different directions.
% \begin{macrocode}
\cs_new_protected:Npn \box_move_left:nn #1#2
- { \tex_moveleft:D \dim_eval:w #1 \dim_eval_end: #2 }
+ { \tex_moveleft:D \__dim_eval:w #1 \__dim_eval_end: #2 }
\cs_new_protected:Npn \box_move_right:nn #1#2
- { \tex_moveright:D \dim_eval:w #1 \dim_eval_end: #2 }
+ { \tex_moveright:D \__dim_eval:w #1 \__dim_eval_end: #2 }
\cs_new_protected:Npn \box_move_up:nn #1#2
- { \tex_raise:D \dim_eval:w #1 \dim_eval_end: #2 }
+ { \tex_raise:D \__dim_eval:w #1 \__dim_eval_end: #2 }
\cs_new_protected:Npn \box_move_down:nn #1#2
- { \tex_lower:D \dim_eval:w #1 \dim_eval_end: #2 }
+ { \tex_lower:D \__dim_eval:w #1 \__dim_eval_end: #2 }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1063,7 +926,8 @@
%
% \subsection{Scratch boxes}
%
-% \begin{variable}{\l_tmpa_box, \l_tmpb_box}
+% \begin{variable}{\l_tmpa_box, \l_tmpb_box, \g_tmpa_box, \g_tmpb_box}
+% Reuse the \LaTeXe{} scratch box in package mode.
% \begin{macrocode}
%<*package>
\cs_new_eq:NN \l_tmpa_box \@tempboxa
@@ -1072,52 +936,78 @@
\box_new:N \l_tmpa_box
%</initex>
\box_new:N \l_tmpb_box
+\box_new:N \g_tmpa_box
+\box_new:N \g_tmpb_box
% \end{macrocode}
% \end{variable}
%
% \subsection{Viewing box contents}
+%
+% \TeX{}'s \tn{tex_showbox:D} is not really that helpful in many cases, and
+% it is also inconsistent with other \LaTeX3{} \texttt{show} functions as it
+% does not actually shows material in the terminal. So we provide a richer
+% set of functionality.
%
% \begin{macro}{\box_show:N, \box_show:c}
-% \testfile*
-% Check that the variable exists, then show the contents of the box
-% and write it into the log file. The spurious \cs{use:n} gives
-% a nicer output.
+% \begin{macro}{\box_show:Nnn, \box_show:cnn}
+% Essentially a wrapper around the internal function.
% \begin{macrocode}
\cs_new_protected:Npn \box_show:N #1
+ { \box_show:Nnn #1 \c_max_int \c_max_int }
+\cs_generate_variant:Nn \box_show:N { c }
+\cs_new_protected_nopar:Npn \box_show:Nnn
+ { \@@_show:NNnn \c_one }
+\cs_generate_variant:Nn \box_show:Nnn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\box_log:N, \box_log:c}
+% \begin{macro}{\box_log:Nnn, \box_log:cnn}
+% Getting \TeX{} to write to the log without interruption the run is done by
+% altering the interaction mode. For that, the \eTeX{} extensions are needed.
+% \begin{macrocode}
+\cs_new_protected:Npn \box_log:N #1
+ { \box_log:Nnn #1 \c_max_int \c_max_int }
+\cs_generate_variant:Nn \box_log:N { c }
+\cs_new_protected:Npn \box_log:Nnn #1#2#3
{
- \box_if_exist:NTF #1
- { \tex_showbox:D \use:n {#1} }
+ \use:x
{
- \msg_kernel_error:nnx { kernel } { variable-not-defined }
- { \token_to_str:N #1 }
+ \etex_interactionmode:D \c_zero
+ \@@_show:NNnn \c_zero \exp_not:N #1
+ { \int_eval:n {#2} } { \int_eval:n {#3} }
+ \etex_interactionmode:D
+ = \tex_the:D \etex_interactionmode:D \scan_stop:
}
}
-\cs_generate_variant:Nn \box_show:N { c }
+\cs_generate_variant:Nn \box_log:Nnn { c }
% \end{macrocode}
% \end{macro}
-%
-% \begin{macro}{\box_show:Nnn, \box_show:cnn}
-% \begin{macro}{\box_show_full:N, \box_show_full:c}
-% Show the contents of a box and write it into the log file,
-% after setting the parameters \tn{showboxbreadth} and \tn{showboxdepth}
-% to the values provided by the user.
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_show:NNnn}
+% The internal auxiliary to actually do the output uses a group to deal
+% with breadth and depth values. The \cs{use:n} here gives better output
+% appearance. Setting \tn{tex_tracingonline:D} is used to control what
+% appears in the terminal.
% \begin{macrocode}
-\cs_new_protected:Npn \box_show:Nnn #1#2#3
+\cs_new_protected:Npn \@@_show:NNnn #1#2#3#4
{
\group_begin:
- \int_set:Nn \tex_showboxbreadth:D {#2}
- \int_set:Nn \tex_showboxdepth:D {#3}
- \int_set_eq:NN \tex_tracingonline:D \c_one
- \box_show:N #1
+ \int_set:Nn \tex_showboxbreadth:D {#3}
+ \int_set:Nn \tex_showboxdepth:D {#4}
+ \int_set_eq:NN \tex_tracingonline:D #1
+ \box_if_exist:NTF #2
+ { \tex_showbox:D \use:n {#2} }
+ {
+ \__msg_kernel_error:nnx { kernel } { variable-not-defined }
+ { \token_to_str:N #2 }
+ }
\group_end:
}
-\cs_generate_variant:Nn \box_show:Nnn { c }
-\cs_new_protected:Npn \box_show_full:N #1
- { \box_show:Nnn #1 { \c_max_int } { \c_max_int } }
-\cs_generate_variant:Nn \box_show_full:N { c }
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \subsection{Horizontal mode boxes}
%
@@ -1147,7 +1037,7 @@
% Storing material in a horizontal box with a specified width.
% \begin{macrocode}
\cs_new_protected:Npn \hbox_set_to_wd:Nnn #1#2#3
- { \tex_setbox:D #1 \tex_hbox:D to \dim_eval:w #2 \dim_eval_end: {#3} }
+ { \tex_setbox:D #1 \tex_hbox:D to \__dim_eval:w #2 \__dim_eval_end: {#3} }
\cs_new_protected:Npn \hbox_gset_to_wd:Nnn
{ \tex_global:D \hbox_set_to_wd:Nnn }
\cs_generate_variant:Nn \hbox_set_to_wd:Nnn { c }
@@ -1199,7 +1089,7 @@
% Put a horizontal box directly into the input stream.
% \begin{macrocode}
\cs_new_protected:Npn \hbox_to_wd:nn #1#2
- { \tex_hbox:D to \dim_eval:w #1 \dim_eval_end: {#2} }
+ { \tex_hbox:D to \__dim_eval:w #1 \__dim_eval_end: {#2} }
\cs_new_protected:Npn \hbox_to_zero:n #1 { \tex_hbox:D to \c_zero_skip {#1} }
% \end{macrocode}
% \end{macro}
@@ -1253,7 +1143,7 @@
% Put a vertical box directly into the input stream.
% \begin{macrocode}
\cs_new_protected:Npn \vbox_to_ht:nn #1#2
- { \tex_vbox:D to \dim_eval:w #1 \dim_eval_end: { #2 \par } }
+ { \tex_vbox:D to \__dim_eval:w #1 \__dim_eval_end: { #2 \par } }
\cs_new_protected:Npn \vbox_to_zero:n #1
{ \tex_vbox:D to \c_zero_dim { #1 \par } }
% \end{macrocode}
@@ -1296,7 +1186,7 @@
% Storing material in a vertical box with a specified height.
% \begin{macrocode}
\cs_new_protected:Npn \vbox_set_to_ht:Nnn #1#2#3
- { \tex_setbox:D #1 \tex_vbox:D to \dim_eval:w #2 \dim_eval_end: { #3 \par } }
+ { \tex_setbox:D #1 \tex_vbox:D to \__dim_eval:w #2 \__dim_eval_end: { #3 \par } }
\cs_new_protected:Npn \vbox_gset_to_ht:Nnn
{ \tex_global:D \vbox_set_to_ht:Nnn }
\cs_generate_variant:Nn \vbox_set_to_ht:Nnn { c }
@@ -1366,614 +1256,7 @@
% Splitting a vertical box in two.
% \begin{macrocode}
\cs_new_protected:Npn \vbox_set_split_to_ht:NNn #1#2#3
- { \tex_setbox:D #1 \tex_vsplit:D #2 to \dim_eval:w #3 \dim_eval_end: }
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Affine transformations}
-%
-% \begin{variable}{\l_box_angle_fp}
-% When rotating boxes, the angle itself may be needed by the
-% engine-dependent code. This is done using the \pkg{fp} module so
-% that the value is tidied up properly.
-% \begin{macrocode}
-\fp_new:N \l_box_angle_fp
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_box_cos_fp, \l_box_sin_fp}
-% These are used to hold the calculated sine and cosine values while
-% carrying out a rotation.
-% \begin{macrocode}
-\fp_new:N \l_box_cos_fp
-\fp_new:N \l_box_sin_fp
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}
-% {\l_box_top_dim, \l_box_bottom_dim, \l_box_left_dim, \l_box_right_dim}
-% These are the positions of the four edges of a box before
-% manipulation.
-% \begin{macrocode}
-\dim_new:N \l_box_top_dim
-\dim_new:N \l_box_bottom_dim
-\dim_new:N \l_box_left_dim
-\dim_new:N \l_box_right_dim
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}
-% {
-% \l_box_top_new_dim, \l_box_bottom_new_dim ,
-% \l_box_left_new_dim, \l_box_right_new_dim
-% }
-% These are the positions of the four edges of a box after
-% manipulation.
-% \begin{macrocode}
-\dim_new:N \l_box_top_new_dim
-\dim_new:N \l_box_bottom_new_dim
-\dim_new:N \l_box_left_new_dim
-\dim_new:N \l_box_right_new_dim
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_box_internal_box, \l_box_internal_fp}
-% Scratch space.
-% \begin{macrocode}
-\box_new:N \l_box_internal_box
-\fp_new:N \l_box_internal_fp
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_box_x_fp, \l_box_y_fp, \l_box_x_new_fp, \l_box_y_new_fp}
-% Used as the input and output values for a point when manipulation the
-% location.
-% \begin{macrocode}
-\fp_new:N \l_box_x_fp
-\fp_new:N \l_box_y_fp
-\fp_new:N \l_box_x_new_fp
-\fp_new:N \l_box_y_new_fp
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\box_rotate:Nn}
-% \begin{macro}[aux]{\box_rotate_aux:N}
-% \begin{macro}[aux]{\box_rotate_set_sin_cos:}
-% \begin{macro}[aux]{\box_rotate_x:nnN, \box_rotate_y:nnN}
-% \begin{macro}[aux]
-% {
-% \box_rotate_quadrant_one:, \box_rotate_quadrant_two:,
-% \box_rotate_quadrant_three:, \box_rotate_quadrant_four:
-% }
-% Rotation of a box starts with working out the relevant sine and
-% cosine. There is then a check to avoid doing any real work for the
-% trivial rotation.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_rotate:Nn #1#2
- {
- \hbox_set:Nn #1
- {
- \group_begin:
- \fp_set:Nn \l_box_angle_fp {#2}
- \box_rotate_set_sin_cos:
- \fp_compare:NNNTF \l_box_sin_fp = \c_zero_fp
- {
- \fp_compare:NNNTF \l_box_cos_fp = \c_one_fp
- { \box_use:N #1 }
- { \box_rotate_aux:N #1 }
- }
- { \box_rotate_aux:N #1 }
- \group_end:
- }
- }
-% \end{macrocode}
-% The edges of the box are then recorded: the left edge will
-% always be at zero. Rotation of the four edges then takes place: this is
-% most efficiently done on a quadrant by quadrant basis.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_rotate_aux:N #1
- {
- \dim_set:Nn \l_box_top_dim { \box_ht:N #1 }
- \dim_set:Nn \l_box_bottom_dim { -\box_dp:N #1 }
- \dim_set:Nn \l_box_right_dim { \box_wd:N #1 }
- \dim_zero:N \l_box_left_dim
-% \end{macrocode}
-% The next step is to work out the $x$ and $y$ coordinates of vertices of
-% the rotated box in relation to its original coordinates. The box can be
-% visualized with vertices $B$, $C$, $D$ and $E$ is illustrated
-% (Figure~\ref{fig:rotation}). The vertex $O$ is the reference point on the
-% baseline, and in this implementation is also the centre of rotation.
-% \begin{figure}
-% \centering
-% \setlength{\unitlength}{3pt}^^A
-% \begin{picture}(34,36)(12,44)
-% \thicklines
-% \put(20,52){\dashbox{1}(20,21){}}
-% \put(20,80){\line(0,-1){36}}
-% \put(12,58){\line(1, 0){34}}
-% \put(41,59){A}
-% \put(40,74){B}
-% \put(21,74){C}
-% \put(21,49){D}
-% \put(40,49){E}
-% \put(21,59){O}
-% \end{picture}
-% \caption{Co-ordinates of a box prior to rotation.}
-% \label{fig:rotation}
-% \end{figure}
-% The formulae are, for a point $P$ and angle $\alpha$:
-% \[
-% \begin{array}{l}
-% P'_x = P_x - O_x \\
-% P'_y = P_y - O_y \\
-% P''_x = ( P'_x \cos(\alpha)) - ( P'_y \sin(\alpha) ) \\
-% P''_y = ( P'_x \sin(\alpha)) + ( P'_y \cos(\alpha) ) \\
-% P'''_x = P''_x + O_x + L_x \\
-% P'''_y = P''_y + O_y
-% \end{array}
-% \]
-% The \enquote{extra} horizontal translation $L_x$ at the end is calculated
-% so that the leftmost point of the resulting box has $x$-coordinate $0$.
-% This is desirable as \TeX{} boxes must have the reference point at
-% the left edge of the box. (As $O$ is always $(0,0)$, this part of the
-% calculation is omitted here.)
-% \begin{macrocode}
- \fp_compare:NNNTF \l_box_sin_fp > \c_zero_fp
- {
- \fp_compare:NNNTF \l_box_cos_fp > \c_zero_fp
- { \box_rotate_quadrant_one: }
- { \box_rotate_quadrant_two: }
- }
- {
- \fp_compare:NNNTF \l_box_cos_fp < \c_zero_fp
- { \box_rotate_quadrant_three: }
- { \box_rotate_quadrant_four: }
- }
-% \end{macrocode}
-% The position of the box edges are now known, but the box at this
-% stage be misplaced relative to the current \TeX{} reference point. So the
-% content of the box is moved such that the reference point of the
-% rotated box will be in the same place as the original.
-% \begin{macrocode}
- \hbox_set:Nn \l_box_internal_box { \box_use:N #1 }
- \hbox_set:Nn \l_box_internal_box
- {
- \tex_kern:D -\l_box_left_new_dim
- \hbox:n
- {
- \driver_box_rotate_begin:
- \box_use:N \l_box_internal_box
- \driver_box_rotate_end:
- }
- }
-% \end{macrocode}
-% Tidy up the size of the box so that the material is actually inside
-% the bounding box. The result can then be used to reset the original
-% box.
-% \begin{macrocode}
- \box_set_ht:Nn \l_box_internal_box { \l_box_top_new_dim }
- \box_set_dp:Nn \l_box_internal_box { -\l_box_bottom_new_dim }
- \box_set_wd:Nn \l_box_internal_box
- { \l_box_right_new_dim - \l_box_left_new_dim }
- \box_use:N \l_box_internal_box
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% A simple conversion from degrees to radians followed by calculation
-% of the sine and cosine.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_rotate_set_sin_cos:
- {
- \fp_set_eq:NN \l_box_internal_fp \l_box_angle_fp
- \fp_div:Nn \l_box_internal_fp { 180 }
- \fp_mul:Nn \l_box_internal_fp { \c_pi_fp }
- \fp_sin:Nn \l_box_sin_fp { \l_box_internal_fp }
- \fp_cos:Nn \l_box_cos_fp { \l_box_internal_fp }
- }
-% \end{macrocode}
-% These functions take a general point $(|#1|, |#2|)$ and rotate its
-% location about the origin, using the previously-set sine and cosine
-% values. Each function gives only one component of the location of the
-% updated point. This is because for rotation of a box each step needs
-% only one value, and so performance is gained by avoiding working
-% out both $x'$ and $y'$ at the same time. Contrast this with
-% the equivalent function in the \pkg{l3coffins} module, where both parts
-% are needed.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_rotate_x:nnN #1#2#3
- {
- \fp_set_from_dim:Nn \l_box_x_fp {#1}
- \fp_set_from_dim:Nn \l_box_y_fp {#2}
- \fp_set_eq:NN \l_box_x_new_fp \l_box_x_fp
- \fp_set_eq:NN \l_box_internal_fp \l_box_y_fp
- \fp_mul:Nn \l_box_x_new_fp { \l_box_cos_fp }
- \fp_mul:Nn \l_box_internal_fp { \l_box_sin_fp }
- \fp_sub:Nn \l_box_x_new_fp { \l_box_internal_fp }
- \dim_set:Nn #3 { \fp_to_dim:N \l_box_x_new_fp }
- }
-\cs_new_protected:Npn \box_rotate_y:nnN #1#2#3
- {
- \fp_set_from_dim:Nn \l_box_x_fp {#1}
- \fp_set_from_dim:Nn \l_box_y_fp {#2}
- \fp_set_eq:NN \l_box_y_new_fp \l_box_y_fp
- \fp_set_eq:NN \l_box_internal_fp \l_box_x_fp
- \fp_mul:Nn \l_box_y_new_fp { \l_box_cos_fp }
- \fp_mul:Nn \l_box_internal_fp { \l_box_sin_fp }
- \fp_add:Nn \l_box_y_new_fp { \l_box_internal_fp }
- \dim_set:Nn #3 { \fp_to_dim:N \l_box_y_new_fp }
-}
-% \end{macrocode}
-% Rotation of the edges is done using a different formula for each
-% quadrant. In every case, the top and bottom edges only need the
-% resulting $y$-values, whereas the left and right edges need the
-% $x$-values. Each case is a question of picking out which corner
-% ends up at with the maximum top, bottom, left and right value. Doing
-% this by hand means a lot less calculating and avoids lots of
-% comparisons.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_rotate_quadrant_one:
- {
- \box_rotate_y:nnN \l_box_right_dim \l_box_top_dim
- \l_box_top_new_dim
- \box_rotate_y:nnN \l_box_left_dim \l_box_bottom_dim
- \l_box_bottom_new_dim
- \box_rotate_x:nnN \l_box_left_dim \l_box_top_dim
- \l_box_left_new_dim
- \box_rotate_x:nnN \l_box_right_dim \l_box_bottom_dim
- \l_box_right_new_dim
- }
-\cs_new_protected:Npn \box_rotate_quadrant_two:
- {
- \box_rotate_y:nnN \l_box_right_dim \l_box_bottom_dim
- \l_box_top_new_dim
- \box_rotate_y:nnN \l_box_left_dim \l_box_top_dim
- \l_box_bottom_new_dim
- \box_rotate_x:nnN \l_box_right_dim \l_box_top_dim
- \l_box_left_new_dim
- \box_rotate_x:nnN \l_box_left_dim \l_box_bottom_dim
- \l_box_right_new_dim
- }
-\cs_new_protected:Npn \box_rotate_quadrant_three:
- {
- \box_rotate_y:nnN \l_box_left_dim \l_box_bottom_dim
- \l_box_top_new_dim
- \box_rotate_y:nnN \l_box_right_dim \l_box_top_dim
- \l_box_bottom_new_dim
- \box_rotate_x:nnN \l_box_right_dim \l_box_bottom_dim
- \l_box_left_new_dim
- \box_rotate_x:nnN \l_box_left_dim \l_box_top_dim
- \l_box_right_new_dim
- }
-\cs_new_protected:Npn \box_rotate_quadrant_four:
- {
- \box_rotate_y:nnN \l_box_left_dim \l_box_top_dim
- \l_box_top_new_dim
- \box_rotate_y:nnN \l_box_right_dim \l_box_bottom_dim
- \l_box_bottom_new_dim
- \box_rotate_x:nnN \l_box_left_dim \l_box_bottom_dim
- \l_box_left_new_dim
- \box_rotate_x:nnN \l_box_right_dim \l_box_top_dim
- \l_box_right_new_dim
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{variable}{\l_box_scale_x_fp, \l_box_scale_y_fp}
-% Scaling is potentially-different in the two axes.
-% \begin{macrocode}
-\fp_new:N \l_box_scale_x_fp
-\fp_new:N \l_box_scale_y_fp
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\box_resize:Nnn, \box_resize:cnn}
-% \begin{macro}[aux]{\box_resize_aux:Nnn}
-% Resizing a box starts by working out the various dimensions of the
-% existing box.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_resize:Nnn #1#2#3
- {
- \hbox_set:Nn #1
- {
- \group_begin:
- \dim_set:Nn \l_box_top_dim { \box_ht:N #1 }
- \dim_set:Nn \l_box_bottom_dim { -\box_dp:N #1 }
- \dim_set:Nn \l_box_right_dim { \box_wd:N #1 }
- \dim_zero:N \l_box_left_dim
-% \end{macrocode}
-% The $x$-scaling and resulting box size is easy enough to work
-% out: the dimension is that given as |#2|, and the scale is simply the
-% new width divided by the old one.
-% \begin{macrocode}
- \fp_set_from_dim:Nn \l_box_scale_x_fp {#2}
- \fp_set_from_dim:Nn \l_box_internal_fp { \l_box_right_dim }
- \fp_div:Nn \l_box_scale_x_fp { \l_box_internal_fp }
-% \end{macrocode}
-% The $y$-scaling needs both the height and the depth of the current box.
-% \begin{macrocode}
- \fp_set_from_dim:Nn \l_box_scale_y_fp {#3}
- \fp_set_from_dim:Nn \l_box_internal_fp
- { \l_box_top_dim - \l_box_bottom_dim }
- \fp_div:Nn \l_box_scale_y_fp { \l_box_internal_fp }
-% \end{macrocode}
-% At this stage, check for trivial scaling. If both scalings are unity, then
-% the code does nothing. Otherwise, pass on to the auxiliary function to
-% find the new dimensions.
-% \begin{macrocode}
- \fp_compare:NNNTF \l_box_scale_x_fp = \c_one_fp
- {
- \fp_compare:NNNTF \l_box_scale_y_fp = \c_one_fp
- { \box_use:N #1 }
- { \box_resize_aux:Nnn #1 {#2} {#3} }
- }
- { \box_resize_aux:Nnn #1 {#2} {#3} }
- \group_end:
- }
- }
-\cs_generate_variant:Nn \box_resize:Nnn { c }
-% \end{macrocode}
-% With at least one real scaling to do, the next phase is to find the new
-% edge co-ordinates. In the $x$~direction this is relatively easy: just
-% scale the right edge. This is done using the absolute value of the
-% scale so that the new edge is in the correct place. In the $y$~direction,
-% both dimensions have to be scaled, and this again needs the absolute
-% scale value. Once that is all done, the common resize/rescale code can
-% be employed.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_resize_aux:Nnn #1#2#3
- {
- \dim_compare:nNnTF {#2} > \c_zero_dim
- { \dim_set:Nn \l_box_right_new_dim {#2} }
- { \dim_set:Nn \l_box_right_new_dim { \c_zero_dim - ( #2 ) } }
- \dim_compare:nNnTF {#3} > \c_zero_dim
- {
- \dim_set:Nn \l_box_top_new_dim
- { \fp_use:N \l_box_scale_y_fp \l_box_top_dim }
- \dim_set:Nn \l_box_bottom_new_dim
- { \fp_use:N \l_box_scale_y_fp \l_box_bottom_dim }
- }
- {
- \dim_set:Nn \l_box_top_new_dim
- { - \fp_use:N \l_box_scale_y_fp \l_box_top_dim }
- \dim_set:Nn \l_box_bottom_new_dim
- { - \fp_use:N \l_box_scale_y_fp \l_box_bottom_dim }
- }
- \box_resize_common:N #1
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn}
-% \begin{macro}{\box_resize_to_wd:Nn, \box_resize_to_wd:cn}
-% Scaling to a total height or to a width is a simplified version of the main
-% resizing operation, with the scale simply copied between the two parts. The
-% internal auxiliary is called using the scaling value twice, as the sign for
-% both parts is needed (as this allows the same internal code to be used as
-% for the general case).
-% \begin{macrocode}
-\cs_new_protected:Npn \box_resize_to_ht_plus_dp:Nn #1#2
- {
- \hbox_set:Nn #1
- {
- \group_begin:
- \dim_set:Nn \l_box_top_dim { \box_ht:N #1 }
- \dim_set:Nn \l_box_bottom_dim { -\box_dp:N #1 }
- \dim_set:Nn \l_box_right_dim { \box_wd:N #1 }
- \dim_zero:N \l_box_left_dim
- \fp_set_from_dim:Nn \l_box_scale_y_fp {#2}
- \fp_set_from_dim:Nn \l_box_internal_fp
- { \l_box_top_dim - \l_box_bottom_dim }
- \fp_div:Nn \l_box_scale_y_fp { \l_box_internal_fp }
- \fp_set_eq:NN \l_box_scale_x_fp \l_box_scale_y_fp
- \fp_compare:NNNTF \l_box_scale_y_fp = \c_one_fp
- { \box_use:N #1 }
- { \box_resize_aux:Nnn #1 {#2} {#2} }
- \group_end:
- }
- }
-\cs_generate_variant:Nn \box_resize_to_ht_plus_dp:Nn { c }
-\cs_new_protected:Npn \box_resize_to_wd:Nn #1#2
- {
- \hbox_set:Nn #1
- {
- \group_begin:
- \dim_set:Nn \l_box_top_dim { \box_ht:N #1 }
- \dim_set:Nn \l_box_bottom_dim { -\box_dp:N #1 }
- \dim_set:Nn \l_box_right_dim { \box_wd:N #1 }
- \dim_zero:N \l_box_left_dim
- \fp_set_from_dim:Nn \l_box_scale_x_fp {#2}
- \fp_set_from_dim:Nn \l_box_internal_fp { \l_box_right_dim }
- \fp_div:Nn \l_box_scale_x_fp { \l_box_internal_fp }
- \fp_set_eq:NN \l_box_scale_y_fp \l_box_scale_x_fp
- \fp_compare:NNNTF \l_box_scale_x_fp = \c_one_fp
- { \box_use:N #1 }
- { \box_resize_aux:Nnn #1 {#2} {#2} }
- \group_end:
- }
- }
-\cs_generate_variant:Nn \box_resize_to_wd:Nn { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\box_scale:Nnn, \box_scale:cnn}
-% \begin{macro}[aux]{\box_scale_aux:Nnn}
-% When scaling a box, setting the scaling itself is easy enough. The
-% new dimensions are also relatively easy to find, allowing only for
-% the need to keep them positive in all cases. Once that is done then
-% after a check for the trivial scaling a hand-off can be made to the
-% common code. The dimension scaling operations are carried out using
-% the \TeX{} mechanism as it avoids needing to use \texttt{fp}
-% operations.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_scale:Nnn #1#2#3
- {
- \hbox_set:Nn #1
- {
- \group_begin:
- \fp_set:Nn \l_box_scale_x_fp {#2}
- \fp_set:Nn \l_box_scale_y_fp {#3}
- \dim_set:Nn \l_box_top_dim { \box_ht:N #1 }
- \dim_set:Nn \l_box_bottom_dim { -\box_dp:N #1 }
- \dim_set:Nn \l_box_right_dim { \box_wd:N #1 }
- \dim_zero:N \l_box_left_dim
- \fp_compare:NNNTF \l_box_scale_x_fp = \c_one_fp
- {
- \fp_compare:NNNTF \l_box_scale_y_fp = \c_one_fp
- { \box_use:N #1 }
- { \box_scale_aux:Nnn #1 {#2} {#3} }
- }
- { \box_scale_aux:Nnn #1 {#2} {#3} }
- \group_end:
- }
- }
-\cs_generate_variant:Nn \box_scale:Nnn { c }
-\cs_new_protected:Npn \box_scale_aux:Nnn #1#2#3
- {
- \fp_compare:NNNTF \l_box_scale_y_fp > \c_zero_fp
- {
- \dim_set:Nn \l_box_top_new_dim { #3 \l_box_top_dim }
- \dim_set:Nn \l_box_bottom_new_dim { #3 \l_box_bottom_dim }
- }
- {
- \dim_set:Nn \l_box_top_new_dim { -#3 \l_box_bottom_dim }
- \dim_set:Nn \l_box_bottom_new_dim { -#3 \l_box_top_dim }
- }
- \fp_compare:NNNTF \l_box_scale_x_fp > \c_zero_fp
- { \l_box_right_new_dim #2 \l_box_right_dim }
- { \l_box_right_new_dim -#2 \l_box_right_dim }
- \box_resize_common:N #1
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[int]{\box_resize_common:N}
-% The main resize function places in input into a box which will start
-% of with zero width, and includes the handles for engine rescaling.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_resize_common:N #1
- {
- \hbox_set:Nn \l_box_internal_box
- {
- \driver_box_scale_begin:
- \hbox_overlap_right:n { \box_use:N #1 }
- \driver_box_scale_end:
- }
-% \end{macrocode}
-% The new height and depth can be applied directly.
-% \begin{macrocode}
- \box_set_ht:Nn \l_box_internal_box { \l_box_top_new_dim }
- \box_set_dp:Nn \l_box_internal_box { \l_box_bottom_new_dim }
-% \end{macrocode}
-% Things are not quite as obvious for the width, as the reference point
-% needs to remain unchanged. For positive scaling factors resizing the
-% box is all that is needed. However, for case of a negative scaling
-% the material must be shifted such that the reference point ends up in
-% the right place.
-% \begin{macrocode}
- \fp_compare:NNNTF \l_box_scale_x_fp < \c_zero_fp
- {
- \hbox_to_wd:nn { \l_box_right_new_dim }
- {
- \tex_kern:D \l_box_right_new_dim
- \box_use:N \l_box_internal_box
- \tex_hss:D
- }
- }
- {
- \box_set_wd:Nn \l_box_internal_box { \l_box_right_new_dim }
- \box_use:N \l_box_internal_box
- }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Viewing part of a box}
-%
-% \begin{macro}{\box_clip:N, \box_clip:c}
-% A wrapper around the driver-dependent code.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_clip:N #1
- { \hbox_set:Nn #1 { \driver_box_use_clip:N #1 } }
-\cs_generate_variant:Nn \box_clip:N { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\box_trim:Nnnnn, \box_trim:cnnnn}
-% Trimming from the left- and right-hand edges of the box is easy. The total
-% width is set to remove from the right, and a skip will shift the material
-% to remove from the left.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_trim:Nnnnn #1#2#3#4#5
- {
- \box_set_wd:Nn #1 { \box_wd:N #1 - \dim_eval:n {#4} - \dim_eval:n {#2} }
- \hbox_set:Nn #1
- {
- \skip_horizontal:n { - \dim_eval:n {#2} }
- \box_use:N #1
- }
-% \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.
-% \begin{macrocode}
- \dim_compare:nNnTF { \box_dp:N #1 } > {#3}
- { \box_set_dp:Nn #1 { \box_dp:N #1 - \dim_eval:n {#3} } }
- {
- \hbox_set:Nn #1
- {
- \box_move_down:nn { \dim_eval:n {#3} - \box_dp:N #1 }
- { \box_use:N #1 }
- }
- \box_set_dp:Nn #1 \c_zero_dim
- }
- \dim_compare:nNnTF { \box_ht:N #1 } > {#5}
- { \box_set_ht:Nn #1 { \box_ht:N #1 - \dim_eval:n {#5} } }
- {
- \hbox_set:Nn #1
- {
- \box_move_up:nn { \dim_eval:n {#5} - \box_ht:N #1 }
- { \box_use:N #1 }
- }
- \box_set_ht:Nn #1 \c_zero_dim
- }
- }
-\cs_generate_variant:Nn \box_trim:Nnnnn { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\box_viewport:Nnnnn, \box_viewport:cnnnn}
-% The same general logic as for clipping, but with absolute dimensions.
-% Thus again width is easy and height is harder.
-% \begin{macrocode}
-\cs_new_protected:Npn \box_viewport:Nnnnn #1#2#3#4#5
- {
- \box_set_wd:Nn #1 { \dim_eval:n {#4} - \dim_eval:n {#2} }
- \hbox_set:Nn #1
- {
- \skip_horizontal:n { - \dim_eval:n {#2} }
- \box_use:N #1
- }
- \dim_compare:nNnTF {#3} > \c_zero_dim
- {
- \hbox_set:Nn #1 { \box_move_down:nn {#3} { \box_use:N #1 } }
- \box_set_dp:Nn #1 \c_zero_dim
- }
- { \box_set_dp:Nn #1 { - \dim_eval:n {#3} } }
- \dim_compare:nNnTF {#5} > \c_zero_dim
- { \box_set_ht:Nn #1 {#5} }
- {
- \hbox_set:Nn #1
- { \box_move_up:nn { -\dim_eval:n {#5} } { \box_use:N #1 } }
- \box_set_ht:Nn #1 \c_zero_dim
- }
- }
-\cs_generate_variant:Nn \box_viewport:Nnnnn { c }
+ { \tex_setbox:D #1 \tex_vsplit:D #2 to \__dim_eval:w #3 \__dim_eval_end: }
% \end{macrocode}
% \end{macro}
%
@@ -1982,7 +1265,9 @@
% \begin{variable}{\l_last_box}
% Deprecated 2011-11-13, for removal by 2012-02-28.
% \begin{macrocode}
+%<*deprecated>
\cs_new_eq:NN \l_last_box \tex_lastbox:D
+%</deprecated>
% \end{macrocode}
% \end{variable}
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
new file mode 100644
index 00000000000..8afac7cda1f
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx
@@ -0,0 +1,2828 @@
+% \iffalse meta-comment
+%
+%% File: l3candidates.dtx Copyright(C) 2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver|package>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3candidates.dtx 3633 2012-05-12 20:11:32Z joseph $
+ {L3 Experimental additions to l3kernel}
+%</driver|package>
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \textsf{l3candidates} package\\ Experimental additions to
+% \pkg{l3kernel}^^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 a space in which functions can be added to
+% \pkg{l3kernel} (\pkg{expl3}) while still being experimental. As such, the
+% functions here may not remain in their current form, or indeed at all,
+% in \pkg{l3kernel} in the future. 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.
+%
+% \section{Additions to \pkg{l3basics}}
+%
+% \begin{function}[EXP,TF]{\cs_if_exist_use:N, \cs_if_exist_use:c}
+% \begin{syntax}
+% \cs{cs_if_exist_use:NTF} \meta{control sequence} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{control sequence} exists, leave it in the input stream,
+% followed by the \meta{true code} (unbraced). Otherwise, leave the
+% \meta{false} code in the input stream. For example,
+% \begin{verbatim}
+% \cs_set:Npn \mypkg_use_character:N #1
+% { \cs_if_exist_use:cF { mypkg_#1:n } { \mypkg_default:N #1 } }
+% \end{verbatim}
+% calls the function |\mypkg_#1:n| if it exists, and falls back to
+% a default action otherwise. This could also be done (more slowly)
+% using \cs{str_case_x:nnn}.
+% \begin{texnote}
+% The \texttt{c} variants do not introduce the \meta{control sequence}
+% in the hash table if it is not there.
+% \end{texnote}
+% \end{function}
+%
+% \section{Additions to \pkg{l3box}}
+%
+% \subsection{Affine transformations}
+%
+% Affine transformations are changes which (informally) preserve straight
+% lines. Simple translations are affine transformations, but are better handled
+% in \TeX{} by doing the translation first, then inserting an unmodified box.
+% On the other hand, rotation and resizing of boxed material can best be
+% handled by modifying boxes. These transformations are described here.
+%
+% \begin{function}{\box_resize:Nnn, \box_resize:cnn}
+% \begin{syntax}
+% \cs{box_resize:Nnn} \meta{box} \Arg{x-size} \Arg{y-size}
+% \end{syntax}
+% Resize the \meta{box} to \meta{x-size} horizontally and \meta{y-size}
+% vertically (both of the sizes are dimension expressions).
+% The \meta{y-size} is the vertical size (height plus depth) of
+% the box. The updated \meta{box} will be an hbox, irrespective of the nature
+% of the \meta{box} before the resizing is applied. Negative sizes will
+% cause the material in the \meta{box} to be reversed in direction, but the
+% reference point of the \meta{box} will be unchanged. The resizing applies
+% within the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+% {\box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn}
+% \begin{syntax}
+% \cs{box_resize_to_ht_plus_dp:Nn} \meta{box} \Arg{y-size}
+% \end{syntax}
+% Resize the \meta{box} to \meta{y-size} vertically, scaling the horizontal
+% size by the same amount (\meta{y-size} is a dimension expression).
+% The \meta{y-size} is the vertical size (height plus depth) of
+% the box.
+% The updated \meta{box} will be an hbox, irrespective of the nature
+% of the \meta{box} before the resizing is applied. A negative size will
+% cause the material in the \meta{box} to be reversed in direction, but the
+% reference point of the \meta{box} will be unchanged. The resizing applies
+% within the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}{\box_resize_to_wd:Nn, \box_resize_to_wd:cn}
+% \begin{syntax}
+% \cs{box_resize_to_wd:Nn} \meta{box} \Arg{x-size}
+% \end{syntax}
+% Resize the \meta{box} to \meta{x-size} horizontally, scaling the vertical
+% size by the same amount (\meta{x-size} is a dimension expression).
+% The updated \meta{box} will be an hbox, irrespective of the nature
+% of the \meta{box} before the resizing is applied. A negative size will
+% cause the material in the \meta{box} to be reversed in direction, but the
+% reference point of the \meta{box} will be unchanged. The resizing applies
+% within the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}{\box_rotate:Nn, \box_rotate:cn}
+% \begin{syntax}
+% \cs{box_rotate:Nn} \meta{box} \Arg{angle}
+% \end{syntax}
+% Rotates the \meta{box} by \meta{angle} (in degrees) anti-clockwise about
+% its reference point. The reference point of the updated box will be moved
+% horizontally such that it is at the left side of the smallest rectangle
+% enclosing the rotated material.
+% The updated \meta{box} will be an hbox, irrespective of the nature
+% of the \meta{box} before the rotation is applied. The rotation applies
+% within the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}{\box_scale:Nnn, \box_scale:cnn}
+% \begin{syntax}
+% \cs{box_scale:Nnn} \meta{box} \Arg{x-scale} \Arg{y-scale}
+% \end{syntax}
+% Scales the \meta{box} by factors \meta{x-scale} and \meta{y-scale} in
+% the horizontal and vertical directions, respectively (both scales are
+% integer expressions). The updated \meta{box} will be an hbox, irrespective
+% of the nature of the \meta{box} before the scaling is applied. Negative
+% scalings will cause the material in the \meta{box} to be reversed in
+% direction, but the reference point of the \meta{box} will be unchanged.
+% The scaling applies within the current \TeX{} group level.
+% \end{function}
+%
+% \subsection{Viewing part of a box}
+%
+% \begin{function}{\box_clip:N, \box_clip: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} will be an
+% hbox, irrespective of the nature of the \meta{box} before the clipping is
+% applied. The clipping applies within the current \TeX{} group level.
+%
+% \textbf{These functions require the \LaTeX3 native drivers: they will
+% 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 places 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}{\box_trim:Nnnnn, \box_trim:cnnnn}
+% \begin{syntax}
+% \cs{box_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 output of the bounding box will still be displayed in the output
+% unless \cs{box_clip:N} is subsequently applied.
+% The updated \meta{box} will be an
+% hbox, irrespective of the nature of the \meta{box} before the viewport
+% operation is applied. The adjustment applies within the current \TeX{}
+% group level.
+% \end{function}
+%
+% \begin{function}{\box_viewport:Nnnnn, \box_viewport:cnnnn}
+% \begin{syntax}
+% \cs{box_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 output of the bounding box will
+% still be displayed in the output unless \cs{box_clip:N} is
+% subsequently applied.
+% The updated \meta{box} will be an
+% hbox, irrespective of the nature of the \meta{box} before the viewport
+% operation is applied. The adjustment applies within the current \TeX{}
+% group level.
+% \end{function}
+%
+% \subsection{Internal variables}
+%
+% \begin{variable}{\l__box_angle_fp}
+% The angle through which a box is rotated by \cs{box_rotate:Nn}, given in
+% degrees counter-clockwise. This value is required by the underlying
+% driver code in \pkg{l3driver} to carry out the driver-dependent part
+% of box rotation.
+% \end{variable}
+%
+% \begin{variable}{\l__box_cos_fp, \l__box_sin_fp}
+% The sine and cosine of the angle through which a box is rotated by
+% \cs{box_rotate:Nn}: the values refer to the angle counter-clockwise. These
+% values are required by the underlying driver code in \pkg{l3driver} to
+% carry out the driver-dependent part of box rotation.
+% \end{variable}
+%
+% \begin{variable}{\l__box_scale_x_fp, \l__box_scale_y_fp}
+% The scaling factors by which a box is scaled by \cs{box_scale:Nnn}
+% or \cs{box_resize:Nnn}. These values are required by the underlying
+% driver code in \pkg{l3driver} to carry out the driver-dependent part
+% of box rotation.
+% \end{variable}
+%
+% \begin{variable}{\l__box_internal_box}
+% Box used for affine transformations, which is used to contain rotated
+% material when applying \cs{box_rotate:Nn}. This box must be correctly
+% constructed for the driver-dependent code in \pkg{l3driver} to function
+% correctly.
+% \end{variable}
+%
+% \section{Additions to \pkg{l3clist}}
+%
+% \begin{function}{\clist_item:Nn, \clist_item:cn, \clist_item:nn}
+% \begin{syntax}
+% \cs{clist_item:Nn} \meta{comma list} \Arg{integer expression}
+% \end{syntax}
+% Indexing items in the \meta{comma list} from~$1$ at the top (left), this
+% function will evaluate the \meta{integer expression} and leave the
+% appropriate item from the comma list in the input stream. If the
+% \meta{integer expression} is negative, indexing occurs from the
+% bottom (right) of the comma list. When the \meta{integer expression}
+% is larger than the number of items in the \meta{comma list} (as
+% calculated by \cs{clist_count:N}) then the function will expand to
+% nothing.
+% \begin{texnote}
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the \meta{item}
+% will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}
+% {
+% \clist_set_from_seq:NN, \clist_set_from_seq:cN,
+% \clist_set_from_seq:Nc, \clist_set_from_seq:cc,
+% \clist_gset_from_seq:NN, \clist_gset_from_seq:cN,
+% \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc
+% }
+% \begin{syntax}
+% \cs{clist_set_from_seq:NN} \meta{comma list} \meta{sequence}
+% \end{syntax}
+% Sets the \meta{comma list} to be equal to the content of the
+% \meta{sequence}.
+% Items which contain either spaces or commas are surrounded by braces.
+% \end{function}
+%
+% \begin{function}
+% {
+% \clist_const:Nn, \clist_const:Nx,
+% \clist_const:cn, \clist_const:cx
+% }
+% \begin{syntax}
+% \cs{clist_const:Nn} \meta{clist~var} \Arg{comma list}
+% \end{syntax}
+% Creates a new constant \meta{clist~var} or raises an error
+% if the name is already taken. The value of the
+% \meta{clist~var} will be set globally to the
+% \meta{comma list}.
+% \end{function}
+%
+% \begin{function}[EXP, pTF]{\clist_if_empty:n}
+% \begin{syntax}
+% \cs{clist_if_empty_p:n} \Arg{comma list}
+% \cs{clist_if_empty:nTF} \Arg{comma list} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the \meta{comma list} is empty (containing no items).
+% The rules for space trimming are as for other \texttt{n}-type
+% comma-list functions, hence the comma list |{~,~,,~}| (without
+% outer braces) is empty, while |{~,{},}| (without outer braces)
+% contains one element, which happens to be empty: the comma-list
+% is not empty.
+% \end{function}
+%
+% \begin{function}[EXP, added = 2012-06-26]{\clist_use:Nnnn}
+% \begin{syntax}
+% \cs{clist_use:Nnnn} \meta{clist~var} \Arg{separator~between~two} \Arg{separator~between~more~than~two} \Arg{separator~between~final~two}
+% \end{syntax}
+% Places the contents of the \meta{clist~var} in the input stream,
+% with the appropriate \meta{separator} between the items. Namely, if
+% the comma list has more than $2$ items, the \meta{separator between
+% more than two} is placed between each pair of items except the
+% last, for which the \meta{separator between final two} is used. If
+% the comma list has $2$ items, then they are placed in the input
+% stream separated by the \meta{separator between two}. If the comma
+% list has $1$ item, it is placed in the input stream, and a comma
+% list with no items produces no output. An error will be raised if
+% the variable does not exist or if it is invalid.
+%
+% For example,
+% \begin{verbatim}
+% \clist_set:Nn \l_tmpa_clist { a , b , , c , {de} , f }
+% \clist_use:Nnnn \l_tmpa_clist { ~and~ } { ,~ } { ,~and~ }
+% \end{verbatim}
+% will insert \enquote{\texttt{a, b, c, de, and f}} in the input
+% stream. The first separator argument is not used in this case
+% because the comma list has more than $2$ items.
+% \begin{texnote}
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the \meta{items}
+% will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
+% \section{Additions to \pkg{l3coffins}}
+%
+% \begin{function}{\coffin_resize:Nnn, \coffin_resize:cnn}
+% \begin{syntax}
+% \cs{coffin_resize:Nnn} \meta{coffin} \Arg{width} \Arg{total-height}
+% \end{syntax}
+% Resized the \meta{coffin} to \meta{width} and \meta{total-height},
+% both of which should be given as dimension expressions. These may
+% include the terms \cs{TotalHeight}, \cs{Height}, \cs{Depth} and
+% \cs{Width}, which will evaluate to the appropriate dimensions of
+% the \meta{coffin}.
+% \end{function}
+%
+% \begin{function}{\coffin_rotate:Nn, \coffin_rotate:cn}
+% \begin{syntax}
+% \cs{coffin_rotate:Nn} \meta{coffin} \Arg{angle}
+% \end{syntax}
+% Rotates the \meta{coffin} by the given \meta{angle} (given in
+% degrees counter-clockwise). This process will rotate both the
+% coffin content and poles. Multiple rotations will not result in
+% the bounding box of the coffin growing unnecessarily.
+% \end{function}
+%
+% \begin{function}{\coffin_scale:Nnn, \coffin_scale:cnn}
+% \begin{syntax}
+% \cs{coffin_scale:Nnn} \meta{coffin} \Arg{x-scale} \Arg{y-scale}
+% \end{syntax}
+% Scales the \meta{coffin} by a factors \meta{x-scale} and
+% \meta{y-scale} in the horizontal and vertical directions,
+% respectively. The two scale factors should be given as real numbers.
+% \end{function}
+%
+% \section{Additions to \pkg{l3file}}
+%
+% \begin{function}[added = 2012-02-11]{\ior_map_inline:Nn}
+% \begin{syntax}
+% \cs{ior_map_inline:Nn} \meta{stream} \Arg{inline function}
+% \end{syntax}
+% Applies the \meta{inline function} to \meta{lines} obtained by
+% reading one or more lines (until an equal number of left and right
+% braces are found) from the \meta{stream}. The \meta{inline function}
+% should consist of code which will receive the \meta{line} as |#1|.
+% \end{function}
+%
+% \begin{function}[added = 2012-02-11]{\ior_str_map_inline:Nn}
+% \begin{syntax}
+% \cs{ior_str_map_inline:Nn} \Arg{stream} \Arg{inline function}
+% \end{syntax}
+% Applies the \meta{inline function} to every \meta{line}
+% in the \meta{sream}. The material is read from the \meta{stream}
+% as a series of tokens with category code $12$ (other), with the
+% exception of space characters which are given category code $10$
+% (space). The \meta{inline function} should consist of code which
+% will receive the \meta{line} as |#1|.
+% \end{function}
+%
+% \begin{function}[added = 2012-06-29]{\ior_map_break:}
+% \begin{syntax}
+% \cs{ior_map_break:}
+% \end{syntax}
+% Used to terminate a \cs{ior_map_\ldots} function before all
+% lines from the \meta{stream} have been processed. This will
+% normally take place within a conditional statement, for example
+% \begin{verbatim}
+% \ior_map_inline:Nn \l_my_ior
+% {
+% \str_if_eq:nnTF { #1 } { bingo }
+% { \ior_map_break: }
+% {
+% % Do something useful
+% }
+% }
+% \end{verbatim}
+% Use outside of a \cs{ior_map_\ldots} scenario will lead to low
+% level \TeX{} errors.
+% \begin{texnote}
+% When the mapping is broken, additional tokens may be inserted by the
+% internal macro \cs{__prg_break_point:Nn} before further items are taken
+% from the input stream. This will depend on the design of the mapping
+% function.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2012-06-29]{\ior_map_break:n}
+% \begin{syntax}
+% \cs{ior_map_break:n} \Arg{tokens}
+% \end{syntax}
+% Used to terminate a \cs{ior_map_\ldots} function before all
+% lines in the \meta{stream} have been processed, inserting
+% the \meta{tokens} after the mapping has ended. This will
+% normally take place within a conditional statement, for example
+% \begin{verbatim}
+% \ior_map_inline:Nn \l_my_ior
+% {
+% \str_if_eq:nnTF { #1 } { bingo }
+% { \ior_map_break:n { <tokens> } }
+% {
+% % Do something useful
+% }
+% }
+% \end{verbatim}
+% Use outside of a \cs{ior_map_\ldots} scenario will lead to low
+% level \TeX{} errors.
+% \begin{texnote}
+% When the mapping is broken, additional tokens may be inserted by the
+% internal macro \cs{__prg_break_point:Nn} before the \meta{tokens} are
+% inserted into the input stream.
+% This will depend on the design of the mapping function.
+% \end{texnote}
+% \end{function}
+%
+% \section{Additions to \pkg{l3fp}}
+%
+% \begin{function}
+% {
+% \fp_set_from_dim:Nn, \fp_set_from_dim:cn,
+% \fp_gset_from_dim:Nn, \fp_gset_from_dim:cn
+% }
+% \begin{syntax}
+% \cs{fp_set_from_dim:Nn} \meta{floating point variable} \Arg{dimexpr}
+% \end{syntax}
+% Sets the \meta{floating point variable} to the distance represented
+% by the \meta{dimension expression} in the units points. This means
+% that distances given in other units are first converted to points
+% before being assigned to the \meta{floating point variable}.
+% \end{function}
+%
+% \section{Additions to \pkg{l3prop}}
+%
+% \begin{function}[rEXP]
+% {\prop_map_tokens:Nn, \prop_map_tokens:cn}
+% \begin{syntax}
+% \cs{prop_map_tokens:Nn} \meta{property list} \Arg{code}
+% \end{syntax}
+% Analogue of \cs{prop_map_function:NN} which maps several tokens
+% instead of a single function. The \meta{code} receives each
+% key--value pair in the \meta{property list} as two trailing brace
+% groups. For instance,
+% \begin{verbatim}
+% \prop_map_tokens:Nn \l_my_prop { \str_if_eq:nnT { mykey } }
+% \end{verbatim}
+% will expand to the value corresponding to \texttt{mykey}: for each
+% pair in \cs{l_my_prop} the function \cs{str_if_eq:nnT} receives
+% \texttt{mykey}, the \meta{key} and the \meta{value} as its three
+% arguments. For that specific task, \cs{prop_get:Nn} is faster.
+% \end{function}
+%
+% \begin{function}[EXP]{\prop_get:Nn, \prop_get:cn}
+% \begin{syntax}
+% \cs{prop_get:Nn} \meta{property list} \Arg{key}
+% \end{syntax}
+% Expands to the \meta{value} corresponding to the \meta{key} in
+% the \meta{property list}. If the \meta{key} is missing, this has
+% an empty expansion.
+% \begin{texnote}
+% This function is slower than the non-expandable analogue
+% \cs{prop_get:NnN}.
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the \meta{value}
+% will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
+% \section{Additions to \pkg{l3seq}}
+%
+% \begin{function}[EXP]{\seq_item:Nn, \seq_item:cn}
+% \begin{syntax}
+% \cs{seq_item:Nn} \meta{sequence} \Arg{integer expression}
+% \end{syntax}
+% Indexing items in the \meta{sequence} from~$1$ at the top (left), this
+% function will evaluate the \meta{integer expression} and leave the
+% appropriate item from the sequence in the input stream. If the
+% \meta{integer expression} is negative, indexing occurs from the
+% bottom (right) of the sequence. When the \meta{integer expression}
+% is larger than the number of items in the \meta{sequence} (as
+% calculated by \cs{seq_count:N}) then the function will expand to
+% nothing.
+% \begin{texnote}
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the \meta{item}
+% will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
+% \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} will
+% receive two \texttt{n}-type arguments for each iteration. The mapping
+% will terminate 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_from_clist:NN, \seq_set_from_clist:cN,
+% \seq_set_from_clist:Nc, \seq_set_from_clist:cc,
+% \seq_set_from_clist:Nn, \seq_set_from_clist:cn,
+% \seq_gset_from_clist:NN, \seq_gset_from_clist:cN,
+% \seq_gset_from_clist:Nc, \seq_gset_from_clist:cc,
+% \seq_gset_from_clist:Nn, \seq_gset_from_clist:cn
+% }
+% \begin{syntax}
+% \cs{seq_set_from_clist:NN} \meta{sequence} \meta{comma-list}
+% \end{syntax}
+% Sets the \meta{sequence} within the current \TeX{} group to be equal
+% to the content of the \meta{comma-list}.
+% \end{function}
+%
+% \begin{function}{\seq_reverse:N, \seq_greverse:N}
+% \begin{syntax}
+% \cs{seq_reverse:N} \meta{sequence}
+% \end{syntax}
+% Reverses the order of items in the \meta{sequence}, and
+% assigns the result to \meta{sequence}, locally or globally
+% according to the variant chosen.
+% \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} will
+% receive 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 will lead to low-level \TeX{} errors.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}[added = 2011-12-22]
+% {\seq_set_map:NNn, \seq_gset_map:NNn}
+% \begin{syntax}
+% \cs{seq_set_map:NNn} \meta{sequence_1} \meta{sequence_2} \Arg{inline function}
+% \end{syntax}
+% Applies \meta{inline function} to every \meta{item} stored
+% within the \meta{sequence_2}. The \meta{inline function} should
+% consist of code which will receive the \meta{item} as |#1|.
+% The sequence resulting from \texttt{x}-expanding
+% \meta{inline function} applied to each \meta{item}
+% is assigned to \meta{sequence_1}. As such, the code
+% in \meta{inline function} should be expandable.
+% \begin{texnote}
+% Contrarily to other mapping functions, \cs{seq_map_break:} cannot
+% be used in this function, and will lead to low-level \TeX{} errors.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP, added = 2012-06-26]{\seq_use:Nnnn}
+% \begin{syntax}
+% \cs{seq_use:Nnnn} \meta{seq~var} \Arg{separator~between~two} \Arg{separator~between~more~than~two} \Arg{separator~between~final~two}
+% \end{syntax}
+% Places the contents of the \meta{seq~var} in the input stream, with
+% the appropriate \meta{separator} between the items. Namely, if the
+% sequence has more than $2$ items, the \meta{separator between more
+% than two} is placed between each pair of items except the last,
+% for which the \meta{separator between final two} is used. If the
+% sequence has $2$ items, then they are placed in the input stream
+% separated by the \meta{separator between two}. If the sequence has
+% $1$ item, it is placed in the input stream, and an empty sequence
+% produces no output. An error will be raised if the variable does
+% not exist or if it is invalid.
+%
+% For example,
+% \begin{verbatim}
+% \seq_set_split:Nnn \l_tmpa_seq { | } { a | b | c | {de} | f }
+% \seq_use:Nnnn \l_tmpa_seq { ~and~ } { ,~ } { ,~and~ }
+% \end{verbatim}
+% will insert \enquote{\texttt{a, b, c, de, and f}} in the input
+% stream. The first separator argument is not used in this case
+% because the sequence has more than $2$ items.
+% \begin{texnote}
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the \meta{items}
+% will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
+% \section{Additions to \pkg{l3skip}}
+%
+% \begin{function}{\skip_split_finite_else_action:nnNN}
+% \begin{syntax}
+% \cs{skip_split_finite_else_action:nnNN} \Arg{skipexpr} \Arg{action}
+% ~~\meta{dimen_1} \meta{dimen_2}
+% \end{syntax}
+% Checks if the \meta{skipexpr} contains finite glue. If it does then it
+% assigns
+% \meta{dimen_1} the stretch component and \meta{dimen_2} the shrink
+% component. If
+% it contains infinite glue set \meta{dimen_1} and \meta{dimen_2} to $0$\,pt
+% and place |#2| into the input stream: this is usually an error or
+% warning message of some sort.
+% \end{function}
+%
+% \section{Additions to \pkg{l3tl}}
+%
+% \begin{function}[EXP,pTF]{\tl_if_single_token:n}
+% \begin{syntax}
+% \cs{tl_if_single_token_p:n} \Arg{token list}
+% \cs{tl_if_single_token:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the token list consists of exactly one token, \emph{i.e.}~is
+% either a single space character or a single \enquote{normal} token.
+% Token groups (|{|\ldots|}|) are not single tokens.
+% \end{function}
+%
+% \begin{function}[EXP]{\tl_reverse_tokens:n}
+% \begin{syntax}
+% \cs{tl_reverse_tokens:n} \Arg{tokens}
+% \end{syntax}
+% This function, which works directly on \TeX{} tokens, reverses
+% the order of the \meta{tokens}: the first will be the last and
+% the last will become first. Spaces are preserved. The reversal
+% also operates within brace groups, but the braces themselves
+% are not exchanged, as this would lead to an unbalanced token
+% list. For instance, \cs{tl_reverse_tokens:n} |{a~{b()}}|
+% leaves |{)(b}~a| in the input stream. This function requires
+% two steps of expansion.
+% \begin{texnote}
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the token
+% list will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]{\tl_count_tokens:n}
+% \begin{syntax}
+% \cs{tl_count_tokens:n} \Arg{tokens}
+% \end{syntax}
+% Counts the number of \TeX{} tokens in the \meta{tokens} and leaves
+% this information in the input stream. Every token, including spaces and
+% braces, contributes one to the total; thus for instance, the token count of
+% |a~{bc}| is $6$.
+% This function requires three expansions,
+% giving an \meta{integer denotation}.
+% \end{function}
+%
+% \begin{function}[EXP]{\tl_expandable_uppercase:n,\tl_expandable_lowercase:n}
+% \begin{syntax}
+% \cs{tl_expandable_uppercase:n} \Arg{tokens}
+% \cs{tl_expandable_lowercase:n} \Arg{tokens}
+% \end{syntax}
+% The \cs{tl_expandable_uppercase:n} function works through all of
+% the \meta{tokens}, replacing characters in the range |a|--|z|
+% (with arbitrary category code) by the corresponding letter
+% in the range |A|--|Z|, with category code $11$ (letter). Similarly,
+% \cs{tl_expandable_lowercase:n} replaces characters in the range
+% |A|--|Z| by letters in the range |a|--|z|, and leaves other tokens
+% unchanged. This function requires two steps of expansion.
+% \begin{texnote}
+% Begin-group and end-group characters are normalized and become
+% |{| and |}|, respectively.
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the token
+% list will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]{\tl_item:nn, \tl_item:Nn, \tl_item:cn}
+% \begin{syntax}
+% \cs{tl_item:nn} \Arg{token list} \Arg{integer expression}
+% \end{syntax}
+% Indexing items in the \meta{token list} from~$1$ on the left, this
+% function will evaluate the \meta{integer expression} and leave the
+% appropriate item from the \meta{token list} in the input stream.
+% If the \meta{integer expression} is negative, indexing occurs from
+% the right of the token list, starting at $-1$ for the right-most item.
+% If the index is out of bounds, then thr function expands to nothing.
+% \begin{texnote}
+% The result is returned within the \tn{unexpanded}
+% primitive (\cs{exp_not:n}), which means that the \meta{item}
+% will not expand further when appearing in an \texttt{x}-type
+% argument expansion.
+% \end{texnote}
+% \end{function}
+%
+% \section{Additions to \pkg{l3tokens}}
+%
+% \begin{function}{\char_set_active:Npn, \char_set_active:Npx}
+% \begin{syntax}
+% \cs{char_set_active:Npn} \meta{char} \meta{parameters} \Arg{code}
+% \end{syntax}
+% Makes \meta{char} an active character to expand to \meta{code} as
+% replacement text.
+% Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+% \emph{etc.}) will be replaced by those absorbed. The \meta{char} is
+% made active within the current \TeX{} group level, and the definition
+% is also local.
+% \end{function}
+%
+% \begin{function}{\char_gset_active:Npn, \char_gset_active:Npx}
+% \begin{syntax}
+% \cs{char_gset_active:Npn} \meta{char} \meta{parameters} \Arg{code}
+% \end{syntax}
+% Makes \meta{char} an active character to expand to \meta{code} as
+% replacement text.
+% Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
+% \emph{etc.}) will be replaced by those absorbed. The \meta{char} is
+% made active within the current \TeX{} group level, but the definition
+% is global. This function is therefore suited to cases where an active
+% character definition should be applied only in some context (where the
+% \meta{char} is again made active).
+% \end{function}
+%
+% \begin{function}{\char_set_active_eq:NN}
+% \begin{syntax}
+% \cs{char_set_active_eq:NN} \meta{char} \meta{function}
+% \end{syntax}
+% Makes \meta{char} an active character equivalent in meaning to the
+% \meta{function} (which may itself be an active character). The \meta{char}
+% is made active within the current \TeX{} group level, and the definition
+% is also local.
+% \end{function}
+%
+% \begin{function}{\char_gset_active_eq:NN}
+% \begin{syntax}
+% \cs{char_gset_active_eq:NN} \meta{char} \meta{function}
+% \end{syntax}
+% Makes \meta{char} an active character equivalent in meaning to the
+% \meta{function} (which may itself be an active character). The \meta{char}
+% is made active within the current \TeX{} group level, but the definition
+% is global. This function is therefore suited to cases where an active
+% character definition should be applied only in some context (where the
+% \meta{char} is again made active).
+% \end{function}
+%
+% \begin{function}[TF]{\peek_N_type:}
+% \begin{syntax}
+% \cs{peek_N_type:TF} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the next \meta{token} in the input stream can be safely
+% grabbed as an \texttt{N}-type argument. The test will be \meta{false}
+% if the next \meta{token} is either an explicit or implicit
+% begin-group or end-group token (with any character code), or
+% an explicit or implicit space character (with character code $32$
+% and category code $10$), and \meta{true} in all other cases.
+% Note that a \meta{true} result ensures that the next \meta{token} is
+% a valid \texttt{N}-type argument. However, if the next \meta{token}
+% is for instance \cs{c_space_token}, the test will take the
+% \meta{false} branch, even though the next \meta{token} is in fact
+% a valid \texttt{N}-type argument. The \meta{token} will be left
+% in the input stream after the \meta{true code} or \meta{false code}
+% (as appropriate to the result of the test).
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3candidates} Implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*package>
+\ProvidesExplPackage
+ {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+\__expl_package_check:
+%</package>
+% \end{macrocode}
+%
+% \subsection{Additions to \pkg{l3box}}
+%
+% \begin{macrocode}
+%<@@=box>
+% \end{macrocode}
+%
+% \subsection{Affine transformations}
+%
+% \begin{variable}{\l_@@_angle_fp}
+% When rotating boxes, the angle itself may be needed by the
+% engine-dependent code. This is done using the \pkg{fp} module so
+% that the value is tidied up properly.
+% \begin{macrocode}
+\fp_new:N \l_@@_angle_fp
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_cos_fp, \l_@@_sin_fp}
+% These are used to hold the calculated sine and cosine values while
+% carrying out a rotation.
+% \begin{macrocode}
+\fp_new:N \l_@@_cos_fp
+\fp_new:N \l_@@_sin_fp
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {\l_@@_top_dim, \l_@@_bottom_dim, \l_@@_left_dim, \l_@@_right_dim}
+% These are the positions of the four edges of a box before
+% manipulation.
+% \begin{macrocode}
+\dim_new:N \l_@@_top_dim
+\dim_new:N \l_@@_bottom_dim
+\dim_new:N \l_@@_left_dim
+\dim_new:N \l_@@_right_dim
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}
+% {
+% \l_@@_top_new_dim, \l_@@_bottom_new_dim ,
+% \l_@@_left_new_dim, \l_@@_right_new_dim
+% }
+% These are the positions of the four edges of a box after
+% manipulation.
+% \begin{macrocode}
+\dim_new:N \l_@@_top_new_dim
+\dim_new:N \l_@@_bottom_new_dim
+\dim_new:N \l_@@_left_new_dim
+\dim_new:N \l_@@_right_new_dim
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_internal_box}
+% Scratch space, but also needed by some parts of the driver.
+% \begin{macrocode}
+\box_new:N \l_@@_internal_box
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\box_rotate:Nn}
+% \begin{macro}[aux]{\@@_rotate:N}
+% \begin{macro}[aux]{\@@_rotate_x:nnN, \@@_rotate_y:nnN}
+% \begin{macro}[aux]
+% {
+% \@@_rotate_quadrant_one:, \@@_rotate_quadrant_two:,
+% \@@_rotate_quadrant_three:, \@@_rotate_quadrant_four:
+% }
+% Rotation of a box starts with working out the relevant sine and
+% cosine. The actual rotation is in an auxiliary to keep the flow slightly
+% clearer
+% \begin{macrocode}
+\cs_new_protected:Npn \box_rotate:Nn #1#2
+ {
+ \hbox_set:Nn #1
+ {
+ \group_begin:
+ \fp_set:Nn \l_@@_angle_fp {#2}
+ \fp_set:Nn \l_@@_sin_fp { sin ( \l_@@_angle_fp * deg ) }
+ \fp_set:Nn \l_@@_cos_fp { cos ( \l_@@_angle_fp * deg ) }
+ \@@_rotate:N #1
+ \group_end:
+ }
+ }
+% \end{macrocode}
+% The edges of the box are then recorded: the left edge will
+% always be at zero. Rotation of the four edges then takes place: this is
+% most efficiently done on a quadrant by quadrant basis.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate:N #1
+ {
+ \dim_set:Nn \l_@@_top_dim { \box_ht:N #1 }
+ \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
+ \dim_set:Nn \l_@@_right_dim { \box_wd:N #1 }
+ \dim_zero:N \l_@@_left_dim
+% \end{macrocode}
+% The next step is to work out the $x$ and $y$ coordinates of vertices of
+% the rotated box in relation to its original coordinates. The box can be
+% visualized with vertices $B$, $C$, $D$ and $E$ is illustrated
+% (Figure~\ref{fig:rotation}). The vertex $O$ is the reference point on the
+% baseline, and in this implementation is also the centre of rotation.
+% \begin{figure}
+% \centering
+% \setlength{\unitlength}{3pt}^^A
+% \begin{picture}(34,36)(12,44)
+% \thicklines
+% \put(20,52){\dashbox{1}(20,21){}}
+% \put(20,80){\line(0,-1){36}}
+% \put(12,58){\line(1, 0){34}}
+% \put(41,59){A}
+% \put(40,74){B}
+% \put(21,74){C}
+% \put(21,49){D}
+% \put(40,49){E}
+% \put(21,59){O}
+% \end{picture}
+% \caption{Co-ordinates of a box prior to rotation.}
+% \label{fig:rotation}
+% \end{figure}
+% The formulae are, for a point $P$ and angle $\alpha$:
+% \[
+% \begin{array}{l}
+% P'_x = P_x - O_x \\
+% P'_y = P_y - O_y \\
+% P''_x = ( P'_x \cos(\alpha)) - ( P'_y \sin(\alpha) ) \\
+% P''_y = ( P'_x \sin(\alpha)) + ( P'_y \cos(\alpha) ) \\
+% P'''_x = P''_x + O_x + L_x \\
+% P'''_y = P''_y + O_y
+% \end{array}
+% \]
+% The \enquote{extra} horizontal translation $L_x$ at the end is calculated
+% so that the leftmost point of the resulting box has $x$-coordinate $0$.
+% This is desirable as \TeX{} boxes must have the reference point at
+% the left edge of the box. (As $O$ is always $(0,0)$, this part of the
+% calculation is omitted here.)
+% \begin{macrocode}
+ \fp_compare:nNnTF \l_@@_sin_fp > \c_zero_fp
+ {
+ \fp_compare:nNnTF \l_@@_cos_fp > \c_zero_fp
+ { \@@_rotate_quadrant_one: }
+ { \@@_rotate_quadrant_two: }
+ }
+ {
+ \fp_compare:nNnTF \l_@@_cos_fp < \c_zero_fp
+ { \@@_rotate_quadrant_three: }
+ { \@@_rotate_quadrant_four: }
+ }
+% \end{macrocode}
+% The position of the box edges are now known, but the box at this
+% stage be misplaced relative to the current \TeX{} reference point. So the
+% content of the box is moved such that the reference point of the
+% rotated box will be in the same place as the original.
+% \begin{macrocode}
+ \hbox_set:Nn \l_@@_internal_box { \box_use:N #1 }
+ \hbox_set:Nn \l_@@_internal_box
+ {
+ \tex_kern:D -\l_@@_left_new_dim
+ \hbox:n
+ {
+ \__driver_box_rotate_begin:
+ \box_use:N \l_@@_internal_box
+ \__driver_box_rotate_end:
+ }
+ }
+% \end{macrocode}
+% Tidy up the size of the box so that the material is actually inside
+% the bounding box. The result can then be used to reset the original
+% box.
+% \begin{macrocode}
+ \box_set_ht:Nn \l_@@_internal_box { \l_@@_top_new_dim }
+ \box_set_dp:Nn \l_@@_internal_box { -\l_@@_bottom_new_dim }
+ \box_set_wd:Nn \l_@@_internal_box
+ { \l_@@_right_new_dim - \l_@@_left_new_dim }
+ \box_use:N \l_@@_internal_box
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% These functions take a general point $(|#1|, |#2|)$ and rotate its
+% location about the origin, using the previously-set sine and cosine
+% values. Each function gives only one component of the location of the
+% updated point. This is because for rotation of a box each step needs
+% only one value, and so performance is gained by avoiding working
+% out both $x'$ and $y'$ at the same time. Contrast this with
+% the equivalent function in the \pkg{l3coffins} module, where both parts
+% are needed.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_x:nnN #1#2#3
+ {
+ \dim_set:Nn #3
+ {
+ \fp_to_dim:n
+ {
+ \l_@@_cos_fp * \dim_to_fp:n {#1}
+ - ( \l_@@_sin_fp * \dim_to_fp:n {#2} )
+ }
+ }
+ }
+\cs_new_protected:Npn \@@_rotate_y:nnN #1#2#3
+ {
+ \dim_set:Nn #3
+ {
+ \fp_to_dim:n
+ {
+ \l_@@_sin_fp * \dim_to_fp:n {#1}
+ + \l_@@_cos_fp * \dim_to_fp:n {#2}
+ }
+ }
+ }
+% \end{macrocode}
+% Rotation of the edges is done using a different formula for each
+% quadrant. In every case, the top and bottom edges only need the
+% resulting $y$-values, whereas the left and right edges need the
+% $x$-values. Each case is a question of picking out which corner
+% ends up at with the maximum top, bottom, left and right value. Doing
+% this by hand means a lot less calculating and avoids lots of
+% comparisons.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_quadrant_one:
+ {
+ \@@_rotate_y:nnN \l_@@_right_dim \l_@@_top_dim
+ \l_@@_top_new_dim
+ \@@_rotate_y:nnN \l_@@_left_dim \l_@@_bottom_dim
+ \l_@@_bottom_new_dim
+ \@@_rotate_x:nnN \l_@@_left_dim \l_@@_top_dim
+ \l_@@_left_new_dim
+ \@@_rotate_x:nnN \l_@@_right_dim \l_@@_bottom_dim
+ \l_@@_right_new_dim
+ }
+\cs_new_protected:Npn \@@_rotate_quadrant_two:
+ {
+ \@@_rotate_y:nnN \l_@@_right_dim \l_@@_bottom_dim
+ \l_@@_top_new_dim
+ \@@_rotate_y:nnN \l_@@_left_dim \l_@@_top_dim
+ \l_@@_bottom_new_dim
+ \@@_rotate_x:nnN \l_@@_right_dim \l_@@_top_dim
+ \l_@@_left_new_dim
+ \@@_rotate_x:nnN \l_@@_left_dim \l_@@_bottom_dim
+ \l_@@_right_new_dim
+ }
+\cs_new_protected:Npn \@@_rotate_quadrant_three:
+ {
+ \@@_rotate_y:nnN \l_@@_left_dim \l_@@_bottom_dim
+ \l_@@_top_new_dim
+ \@@_rotate_y:nnN \l_@@_right_dim \l_@@_top_dim
+ \l_@@_bottom_new_dim
+ \@@_rotate_x:nnN \l_@@_right_dim \l_@@_bottom_dim
+ \l_@@_left_new_dim
+ \@@_rotate_x:nnN \l_@@_left_dim \l_@@_top_dim
+ \l_@@_right_new_dim
+ }
+\cs_new_protected:Npn \@@_rotate_quadrant_four:
+ {
+ \@@_rotate_y:nnN \l_@@_left_dim \l_@@_top_dim
+ \l_@@_top_new_dim
+ \@@_rotate_y:nnN \l_@@_right_dim \l_@@_bottom_dim
+ \l_@@_bottom_new_dim
+ \@@_rotate_x:nnN \l_@@_left_dim \l_@@_bottom_dim
+ \l_@@_left_new_dim
+ \@@_rotate_x:nnN \l_@@_right_dim \l_@@_top_dim
+ \l_@@_right_new_dim
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_scale_x_fp, \l_@@_scale_y_fp}
+% Scaling is potentially-different in the two axes.
+% \begin{macrocode}
+\fp_new:N \l_@@_scale_x_fp
+\fp_new:N \l_@@_scale_y_fp
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\box_resize:Nnn, \box_resize:cnn}
+% \begin{macro}[aux]{\@@_resize:Nnn}
+% Resizing a box starts by working out the various dimensions of the
+% existing box.
+% \begin{macrocode}
+\cs_new_protected:Npn \box_resize:Nnn #1#2#3
+ {
+ \hbox_set:Nn #1
+ {
+ \group_begin:
+ \dim_set:Nn \l_@@_top_dim { \box_ht:N #1 }
+ \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
+ \dim_set:Nn \l_@@_right_dim { \box_wd:N #1 }
+ \dim_zero:N \l_@@_left_dim
+% \end{macrocode}
+% The $x$-scaling and resulting box size is easy enough to work
+% out: the dimension is that given as |#2|, and the scale is simply the
+% new width divided by the old one.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_scale_x_fp
+ { \dim_to_fp:n {#2} / ( \dim_to_fp:n \l_@@_right_dim ) }
+% \end{macrocode}
+% The $y$-scaling needs both the height and the depth of the current box.
+% \begin{macrocode}
+ \fp_set:Nn \l_@@_scale_y_fp
+ {
+ \dim_to_fp:n {#3} /
+ ( \dim_to_fp:n { \l_@@_top_dim - \l_@@_bottom_dim } )
+ }
+% \end{macrocode}
+% Hand off to the auxiliary which does the work.
+% \begin{macrocode}
+ \@@_resize:Nnn #1 {#2} {#3}
+ \group_end:
+ }
+ }
+\cs_generate_variant:Nn \box_resize:Nnn { c }
+% \end{macrocode}
+% With at least one real scaling to do, the next phase is to find the new
+% edge co-ordinates. In the $x$~direction this is relatively easy: just
+% scale the right edge. This is done using the absolute value of the
+% scale so that the new edge is in the correct place. In the $y$~direction,
+% both dimensions have to be scaled, and this again needs the absolute
+% scale value. Once that is all done, the common resize/rescale code can
+% be employed.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_resize:Nnn #1#2#3
+ {
+ \dim_compare:nNnTF {#2} > \c_zero_dim
+ { \dim_set:Nn \l_@@_right_new_dim {#2} }
+ { \dim_set:Nn \l_@@_right_new_dim { \c_zero_dim - ( #2 ) } }
+ \dim_compare:nNnTF {#3} > \c_zero_dim
+ {
+ \dim_set:Nn \l_@@_top_new_dim
+ { \fp_use:N \l_@@_scale_y_fp \l_@@_top_dim }
+ \dim_set:Nn \l_@@_bottom_new_dim
+ { \fp_use:N \l_@@_scale_y_fp \l_@@_bottom_dim }
+ }
+ {
+ \dim_set:Nn \l_@@_top_new_dim
+ { - \fp_use:N \l_@@_scale_y_fp \l_@@_top_dim }
+ \dim_set:Nn \l_@@_bottom_new_dim
+ { - \fp_use:N \l_@@_scale_y_fp \l_@@_bottom_dim }
+ }
+ \@@_resize_common:N #1
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\box_resize_to_ht_plus_dp:Nn, \box_resize_to_ht_plus_dp:cn}
+% \begin{macro}{\box_resize_to_wd:Nn, \box_resize_to_wd:cn}
+% Scaling to a total height or to a width is a simplified version of the main
+% resizing operation, with the scale simply copied between the two parts. The
+% internal auxiliary is called using the scaling value twice, as the sign for
+% both parts is needed (as this allows the same internal code to be used as
+% for the general case).
+% \begin{macrocode}
+\cs_new_protected:Npn \box_resize_to_ht_plus_dp:Nn #1#2
+ {
+ \hbox_set:Nn #1
+ {
+ \group_begin:
+ \dim_set:Nn \l_@@_top_dim { \box_ht:N #1 }
+ \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
+ \dim_set:Nn \l_@@_right_dim { \box_wd:N #1 }
+ \dim_zero:N \l_@@_left_dim
+ \fp_set:Nn \l_@@_scale_y_fp
+ {
+ \dim_to_fp:n {#2} /
+ ( \dim_to_fp:n { \l_@@_top_dim - \l_@@_bottom_dim } )
+ }
+ \fp_set_eq:NN \l_@@_scale_x_fp \l_@@_scale_y_fp
+ \@@_resize:Nnn #1 {#2} {#2}
+ \group_end:
+ }
+ }
+\cs_generate_variant:Nn \box_resize_to_ht_plus_dp:Nn { c }
+\cs_new_protected:Npn \box_resize_to_wd:Nn #1#2
+ {
+ \hbox_set:Nn #1
+ {
+ \group_begin:
+ \dim_set:Nn \l_@@_top_dim { \box_ht:N #1 }
+ \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
+ \dim_set:Nn \l_@@_right_dim { \box_wd:N #1 }
+ \dim_zero:N \l_@@_left_dim
+ \fp_set:Nn \l_@@_scale_x_fp
+ { \dim_to_fp:n {#2} / ( \dim_to_fp:n \l_@@_right_dim ) }
+ \fp_set_eq:NN \l_@@_scale_y_fp \l_@@_scale_x_fp
+ \@@_resize:Nnn #1 {#2} {#2}
+ \group_end:
+ }
+ }
+\cs_generate_variant:Nn \box_resize_to_wd:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\box_scale:Nnn, \box_scale:cnn}
+% \begin{macro}[aux]{\@@_scale:Nnn}
+% When scaling a box, setting the scaling itself is easy enough. The
+% new dimensions are also relatively easy to find, allowing only for
+% the need to keep them positive in all cases. Once that is done then
+% after a check for the trivial scaling a hand-off can be made to the
+% common code. The dimension scaling operations are carried out using
+% the \TeX{} mechanism as it avoids needing to use \texttt{fp}
+% operations.
+% \begin{macrocode}
+\cs_new_protected:Npn \box_scale:Nnn #1#2#3
+ {
+ \hbox_set:Nn #1
+ {
+ \group_begin:
+ \fp_set:Nn \l_@@_scale_x_fp {#2}
+ \fp_set:Nn \l_@@_scale_y_fp {#3}
+ \dim_set:Nn \l_@@_top_dim { \box_ht:N #1 }
+ \dim_set:Nn \l_@@_bottom_dim { -\box_dp:N #1 }
+ \dim_set:Nn \l_@@_right_dim { \box_wd:N #1 }
+ \dim_zero:N \l_@@_left_dim
+ \@@_scale:Nnn #1 {#2} {#3}
+ \group_end:
+ }
+ }
+\cs_generate_variant:Nn \box_scale:Nnn { c }
+\cs_new_protected:Npn \@@_scale:Nnn #1#2#3
+ {
+ \fp_compare:nNnTF \l_@@_scale_y_fp > \c_zero_fp
+ {
+ \dim_set:Nn \l_@@_top_new_dim { #3 \l_@@_top_dim }
+ \dim_set:Nn \l_@@_bottom_new_dim { #3 \l_@@_bottom_dim }
+ }
+ {
+ \dim_set:Nn \l_@@_top_new_dim { -#3 \l_@@_bottom_dim }
+ \dim_set:Nn \l_@@_bottom_new_dim { -#3 \l_@@_top_dim }
+ }
+ \fp_compare:nNnTF \l_@@_scale_x_fp > \c_zero_fp
+ { \l_@@_right_new_dim #2 \l_@@_right_dim }
+ { \l_@@_right_new_dim -#2 \l_@@_right_dim }
+ \@@_resize_common:N #1
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_resize_common:N}
+% The main resize function places in input into a box which will start
+% of with zero width, and includes the handles for engine rescaling.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_resize_common:N #1
+ {
+ \hbox_set:Nn \l_@@_internal_box
+ {
+ \__driver_box_scale_begin:
+ \hbox_overlap_right:n { \box_use:N #1 }
+ \__driver_box_scale_end:
+ }
+% \end{macrocode}
+% The new height and depth can be applied directly.
+% \begin{macrocode}
+ \box_set_ht:Nn \l_@@_internal_box { \l_@@_top_new_dim }
+ \box_set_dp:Nn \l_@@_internal_box { \l_@@_bottom_new_dim }
+% \end{macrocode}
+% Things are not quite as obvious for the width, as the reference point
+% needs to remain unchanged. For positive scaling factors resizing the
+% box is all that is needed. However, for case of a negative scaling
+% the material must be shifted such that the reference point ends up in
+% the right place.
+% \begin{macrocode}
+ \fp_compare:nNnTF \l_@@_scale_x_fp < \c_zero_fp
+ {
+ \hbox_to_wd:nn { \l_@@_right_new_dim }
+ {
+ \tex_kern:D \l_@@_right_new_dim
+ \box_use:N \l_@@_internal_box
+ \tex_hss:D
+ }
+ }
+ {
+ \box_set_wd:Nn \l_@@_internal_box { \l_@@_right_new_dim }
+ \box_use:N \l_@@_internal_box
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Viewing part of a box}
+%
+% \begin{macro}{\box_clip:N, \box_clip:c}
+% A wrapper around the driver-dependent code.
+% \begin{macrocode}
+\cs_new_protected:Npn \box_clip:N #1
+ { \hbox_set:Nn #1 { \__driver_box_use_clip:N #1 } }
+\cs_generate_variant:Nn \box_clip:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\box_trim:Nnnnn, \box_trim:cnnnn}
+% Trimming from the left- and right-hand edges of the box is easy. The total
+% width is set to remove from the right, and a skip will shift the material
+% to remove from the left.
+% \begin{macrocode}
+\cs_new_protected:Npn \box_trim:Nnnnn #1#2#3#4#5
+ {
+ \box_set_wd:Nn #1 { \box_wd:N #1 - (#4) - (#2) }
+ \hbox_set:Nn #1
+ {
+ \skip_horizontal:n { - \dim_eval:n {#2} }
+ \box_use:N #1
+ }
+% \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.
+% \begin{macrocode}
+ \dim_compare:nNnTF { \box_dp:N #1 } > {#3}
+ { \box_set_dp:Nn #1 { \box_dp:N #1 - (#3) } }
+ {
+ \hbox_set:Nn #1
+ { \box_move_down:nn { #3 - \box_dp:N #1 } { \box_use:N #1 } }
+ \box_set_dp:Nn #1 \c_zero_dim
+ }
+ \dim_compare:nNnTF { \box_ht:N #1 } > {#5}
+ { \box_set_ht:Nn #1 { \box_ht:N #1 - (#5) } }
+ {
+ \hbox_set:Nn #1
+ { \box_move_up:nn { #5 - \box_ht:N #1 } { \box_use:N #1 } }
+ \box_set_ht:Nn #1 \c_zero_dim
+ }
+ }
+\cs_generate_variant:Nn \box_trim:Nnnnn { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\box_viewport:Nnnnn, \box_viewport:cnnnn}
+% The same general logic as for clipping, but with absolute dimensions.
+% Thus again width is easy and height is harder.
+% \begin{macrocode}
+\cs_new_protected:Npn \box_viewport:Nnnnn #1#2#3#4#5
+ {
+ \box_set_wd:Nn #1 { (#4) - (#2) }
+ \hbox_set:Nn #1
+ {
+ \skip_horizontal:n { - \dim_eval:n {#2} }
+ \box_use:N #1
+ }
+ \dim_compare:nNnTF {#3} > \c_zero_dim
+ {
+ \hbox_set:Nn #1 { \box_move_down:nn {#3} { \box_use:N #1 } }
+ \box_set_dp:Nn #1 \c_zero_dim
+ }
+ { \box_set_dp:Nn #1 { - \dim_eval:n {#3} } }
+ \dim_compare:nNnTF {#5} > \c_zero_dim
+ { \box_set_ht:Nn #1 {#5} }
+ {
+ \hbox_set:Nn #1
+ { \box_move_up:nn { -\dim_eval:n {#5} } { \box_use:N #1 } }
+ \box_set_ht:Nn #1 \c_zero_dim
+ }
+ }
+\cs_generate_variant:Nn \box_viewport:Nnnnn { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Additions to \pkg{l3clist}}
+%
+% \begin{macrocode}
+%<@@=clist>
+% \end{macrocode}
+%
+% \begin{macro}{\clist_item:Nn, \clist_item:cn}
+% \begin{macro}[aux]{\@@_item:nnNn}
+% \begin{macro}[aux]{\@@_item_N_loop:nw}
+% To avoid needing to test the end of the list at each step,
+% we first compute the \meta{length} of the list. If the item number
+% is~$0$, less than $-\meta{length}$, or more than $\meta{length}$,
+% the result is empty. If it is negative, but not less than $-\meta{length}$,
+% add $\meta{length}+1$ to the item number before performing the loop.
+% The loop itself is very simple, return the item if the counter
+% reached~$1$, otherwise, decrease the counter and repeat.
+% \begin{macrocode}
+\cs_new:Npn \clist_item:Nn #1#2
+ {
+ \exp_args:Nfo \@@_item:nnNn
+ { \clist_count:N #1 }
+ #1
+ \@@_item_N_loop:nw
+ {#2}
+ }
+\cs_new:Npn \@@_item:nnNn #1#2#3#4
+ {
+ \int_compare:nNnTF {#4} < \c_zero
+ {
+ \int_compare:nNnTF {#4} < { - #1 }
+ { \use_none_delimit_by_q_stop:w }
+ { \exp_args:Nf #3 { \int_eval:n { #4 + \c_one + #1 } } }
+ }
+ {
+ \int_compare:nNnTF {#4} > {#1}
+ { \use_none_delimit_by_q_stop:w }
+ { #3 {#4} }
+ }
+ { } , #2 , \q_stop
+ }
+\cs_new:Npn \@@_item_N_loop:nw #1 #2,
+ {
+ \int_compare:nNnTF {#1} = \c_zero
+ { \use_i_delimit_by_q_stop:nw { \exp_not:n {#2} } }
+ { \exp_args:Nf \@@_item_N_loop:nw { \int_eval:n { #1 - 1 } } }
+ }
+\cs_generate_variant:Nn \clist_item:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\clist_item:nn}
+% \begin{macro}[aux]{
+% \@@_item_n:nw,
+% \@@_item_n_loop:nw,
+% \@@_item_n_end:n,
+% \@@_item_n_strip:w}
+% This starts in the same way as \cs{clist_item:Nn} by counting the items
+% of the comma list. The final item should be space-trimmed before being
+% brace-stripped, hence we insert a couple of odd-looking
+% \cs{prg_do_nothing:} to avoid losing braces. Blank items are ignored.
+% \begin{macrocode}
+\cs_new:Npn \clist_item:nn #1#2
+ {
+ \exp_args:Nf \@@_item:nnNn
+ { \clist_count:n {#1} }
+ {#1}
+ \@@_item_n:nw
+ {#2}
+ }
+\cs_new:Npn \@@_item_n:nw #1
+ { \@@_item_n_loop:nw {#1} \prg_do_nothing: }
+\cs_new:Npn \@@_item_n_loop:nw #1 #2,
+ {
+ \exp_args:No \tl_if_blank:nTF {#2}
+ { \@@_item_n_loop:nw {#1} \prg_do_nothing: }
+ {
+ \int_compare:nNnTF {#1} = \c_zero
+ { \exp_args:No \@@_item_n_end:n {#2} }
+ {
+ \exp_args:Nf \@@_item_n_loop:nw
+ { \int_eval:n { #1 - 1 } }
+ \prg_do_nothing:
+ }
+ }
+ }
+\cs_new:Npn \@@_item_n_end:n #1 #2 \q_stop
+ {
+ \__tl_trim_spaces:nn { \q_mark #1 }
+ { \exp_last_unbraced:No \@@_item_n_strip:w } ,
+ }
+\cs_new:Npn \@@_item_n_strip:w #1 , { \exp_not:n {#1} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \clist_set_from_seq:NN, \clist_set_from_seq:cN,
+% \clist_set_from_seq:Nc, \clist_set_from_seq:cc
+% }
+% \UnitTested
+% \begin{macro}
+% {
+% \clist_gset_from_seq:NN, \clist_gset_from_seq:cN,
+% \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc
+% }
+% \UnitTested
+% \begin{macro}[aux]{\@@_set_from_seq:NNNN}
+% \begin{macro}[aux]{\@@_wrap_item:n}
+% \begin{macro}[aux]{\@@_set_from_seq:w}
+% Setting a comma list from a comma-separated list is done using a simple
+% mapping. We wrap most items with \cs{exp_not:n}, and a comma. Items which
+% contain a comma or a space are surrounded by an extra set of braces. The
+% first comma must be removed, except in the case of an empty comma-list.
+% \begin{macrocode}
+\cs_new_protected:Npn \clist_set_from_seq:NN
+ { \@@_set_from_seq:NNNN \clist_clear:N \tl_set:Nx }
+\cs_new_protected:Npn \clist_gset_from_seq:NN
+ { \@@_set_from_seq:NNNN \clist_gclear:N \tl_gset:Nx }
+\cs_new_protected:Npn \@@_set_from_seq:NNNN #1#2#3#4
+ {
+ \seq_if_empty:NTF #4
+ { #1 #3 }
+ {
+ #2 #3
+ {
+ \exp_last_unbraced:Nf \use_none:n
+ { \seq_map_function:NN #4 \@@_wrap_item:n }
+ }
+ }
+ }
+\cs_new:Npn \@@_wrap_item:n #1
+ {
+ ,
+ \tl_if_empty:oTF { \@@_set_from_seq:w #1 ~ , #1 ~ }
+ { \exp_not:n {#1} }
+ { \exp_not:n { {#1} } }
+ }
+\cs_new:Npn \@@_set_from_seq:w #1 , #2 ~ { }
+\cs_generate_variant:Nn \clist_set_from_seq:NN { Nc }
+\cs_generate_variant:Nn \clist_set_from_seq:NN { c , cc }
+\cs_generate_variant:Nn \clist_gset_from_seq:NN { Nc }
+\cs_generate_variant:Nn \clist_gset_from_seq:NN { c , cc }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \clist_const:Nn, \clist_const:cn,
+% \clist_const:Nx, \clist_const:cx
+% }
+% Creating and initializing a constant comma list is done in a way
+% similar to \cs{clist_set:Nn} and \cs{clist_gset:Nn}, being careful
+% to strip spaces.
+% \begin{macrocode}
+\cs_new_protected:Npn \clist_const:Nn #1#2
+ { \tl_const:Nx #1 { \@@_trim_spaces:n {#2} } }
+\cs_generate_variant:Nn \clist_const:Nn { c , Nx , cx }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, pTF]{\clist_if_empty:n}
+% \begin{macro}[aux, EXP]{\@@_if_empty_n:w}
+% \begin{macro}[aux, EXP]{\@@_if_empty_n:wNw}
+% As usual, we insert a token (here |?|) before grabbing
+% any argument: this avoids losing braces. The argument
+% of \cs{tl_if_empty:oTF} is empty if |#1| is |?| followed
+% by blank spaces (besides, this particular variant of
+% the emptyness test is optimized). If the item of the
+% comma list is blank, grab the next one. As soon as one
+% item is non-blank, exit: the second auxiliary will grab
+% \cs{prg_return_false:} as |#2|, unless every item in
+% the comma list was blank and the loop actually got broken
+% by the trailing |\q_mark \prg_return_false:| item.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \clist_if_empty:n #1 { p , T , F , TF }
+ {
+ \@@_if_empty_n:w ? #1
+ , \q_mark \prg_return_false:
+ , \q_mark \prg_return_true:
+ \q_stop
+ }
+\cs_new:Npn \@@_if_empty_n:w #1 ,
+ {
+ \tl_if_empty:oTF { \use_none:nn #1 ? }
+ { \@@_if_empty_n:w ? }
+ { \@@_if_empty_n:wNw }
+ }
+\cs_new:Npn \@@_if_empty_n:wNw #1 \q_mark #2#3 \q_stop {#2}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\clist_use:Nnnn}
+% \begin{macro}[EXP, aux]
+% {\@@_use:wwn, \@@_use_ii:nwwwwnwn, \@@_use_iii:nwwn}
+% First check that the variable exists. Then count the items in the
+% comma list. If it has none, output nothing. If it has one item,
+% output that item, brace stripped (note that space-trimming has
+% already been done when the comma list was assigned). If it has two,
+% place the \meta{separator~between~two} in the middle.
+%
+% Otherwise, \cs{@@_use_ii:nwwwwnwn} takes the following arguments; 1:
+% a \meta{separator}, 2, 3, 4: three items from the comma list (or
+% quarks), 5: the rest of the comma list, 6: a \meta{continuation}
+% function (\texttt{use_ii} or \texttt{use_iii} with its
+% \meta{separator} argument), 7: junk, and 8: the temporary result,
+% which is built in a brace group following \cs{q_stop}. The
+% \meta{separator} and the first of the three items are placed in the
+% result, then we use the \meta{continuation}, placing the remaining
+% two items after it. When we begin this loop, the three items really
+% belong to the comma list, the first \cs{q_mark} is taken as a
+% delimiter to the \texttt{use_ii} function, and the continuation is
+% \texttt{use_ii} itself. When we reach the last two items of the
+% original token list, \cs{q_mark} is taken as a third item, and now
+% the seconf \cs{q_mark} serves as a delimiter to \texttt{use_ii},
+% switching to the other \meta{continuation}, \texttt{use_iii}, which
+% uses the \meta{separator between final two}.
+% \begin{macrocode}
+\cs_new:Npn \clist_use:Nnnn #1#2#3#4
+ {
+ \clist_if_exist:NTF #1
+ {
+ \int_case:nnn { \clist_count:N #1 }
+ {
+ { 0 } { }
+ { 1 } { \exp_after:wN \@@_use:wwn #1 , , { } }
+ { 2 } { \exp_after:wN \@@_use:wwn #1 , {#2} }
+ }
+ {
+ \exp_after:wN \@@_use_ii:nwwwwnwn
+ \exp_after:wN { \exp_after:wN } #1 ,
+ \q_mark , { \@@_use_ii:nwwwwnwn {#3} }
+ \q_mark , { \@@_use_iii:nwwn {#4} }
+ \q_stop { }
+ }
+ }
+ { \__msg_kernel_expandable_error:nnn { kernel } { bad-variable } {#1} }
+ }
+\cs_new:Npn \@@_use:wwn #1 , #2 , #3 { \exp_not:n { #1 #3 #2 } }
+\cs_new:Npn \@@_use_ii:nwwwwnwn
+ #1#2 , #3 , #4 , #5 \q_mark , #6#7 \q_stop #8
+ { #6 {#3} , {#4} , #5 \q_mark , {#6} #7 \q_stop { #8 #1 #2 } }
+\cs_new:Npn \@@_use_iii:nwwn #1#2 , #3 \q_stop #4
+ { \exp_not:n { #4 #1 #2 } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Additions to \pkg{l3coffins}}
+%
+% \begin{macrocode}
+%<@@=coffin>
+% \end{macrocode}
+%
+% \subsection{Rotating coffins}
+%
+% \begin{variable}{\l_@@_sin_fp}
+% \begin{variable}{\l_@@_cos_fp}
+% Used for rotations to get the sine and cosine values.
+% \begin{macrocode}
+\fp_new:N \l_@@_sin_fp
+\fp_new:N \l_@@_cos_fp
+% \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_bounding_prop}
+% A property list for the bounding box of a coffin. This is only needed
+% during the rotation, so there is just the one.
+% \begin{macrocode}
+\prop_new:N \l_@@_bounding_prop
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_bounding_shift_dim}
+% The shift of the bounding box of a coffin from the real content.
+% \begin{macrocode}
+\dim_new:N \l_@@_bounding_shift_dim
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_left_corner_dim}
+% \begin{variable}{\l_@@_right_corner_dim}
+% \begin{variable}{\l_@@_bottom_corner_dim}
+% \begin{variable}{\l_@@_top_corner_dim}
+% These are used to hold maxima for the various corner values: these
+% thus define the minimum size of the bounding box after rotation.
+% \begin{macrocode}
+\dim_new:N \l_@@_left_corner_dim
+\dim_new:N \l_@@_right_corner_dim
+\dim_new:N \l_@@_bottom_corner_dim
+\dim_new:N \l_@@_top_corner_dim
+% \end{macrocode}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+% \end{variable}
+%
+% \begin{macro}{\coffin_rotate:Nn, \coffin_rotate:cn}
+% Rotating a coffin requires several steps which can be conveniently
+% run together. The first step is to convert the angle given in degrees
+% to one in radians. This is then used to set \cs{l_@@_sin_fp} and
+% \cs{l_@@_cos_fp}, which are carried through unchanged for the rest
+% of the procedure.
+% \begin{macrocode}
+\cs_new_protected:Npn \coffin_rotate:Nn #1#2
+ {
+ \fp_set:Nn \l_@@_sin_fp { sin ( ( #2 ) * deg ) }
+ \fp_set:Nn \l_@@_cos_fp { cos ( ( #2 ) * deg ) }
+% \end{macrocode}
+% The corners and poles of the coffin can now be rotated around the
+% origin. This is best achieved using mapping functions.
+% \begin{macrocode}
+ \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
+ { \@@_rotate_corner:Nnnn #1 {##1} ##2 }
+ \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop }
+ { \@@_rotate_pole:Nnnnnn #1 {##1} ##2 }
+% \end{macrocode}
+% The bounding box of the coffin needs to be rotated, and to do this
+% the corners have to be found first. They are then rotated in the same
+% way as the corners of the coffin material itself.
+% \begin{macrocode}
+ \@@_set_bounding:N #1
+ \prop_map_inline:Nn \l_@@_bounding_prop
+ { \@@_rotate_bounding:nnn {##1} ##2 }
+% \end{macrocode}
+% At this stage, there needs to be a calculation to find where the
+% corners of the content and the box itself will end up.
+% \begin{macrocode}
+ \@@_find_corner_maxima:N #1
+ \@@_find_bounding_shift:
+ \box_rotate:Nn #1 {#2}
+% \end{macrocode}
+% The correction of the box position itself takes place here. The idea
+% is that the bounding box for a coffin is tight up to the content, and
+% has the reference point at the bottom-left. The $x$-direction is
+% handled by moving the content by the difference in the positions of
+% the bounding box and the content left edge. The $y$-direction is
+% dealt with by moving the box down by any depth it has acquired.
+% \begin{macrocode}
+ \hbox_set:Nn #1
+ {
+ \tex_kern:D \l_@@_bounding_shift_dim
+ \tex_kern:D -\l_@@_left_corner_dim
+ \box_move_down:nn { \l_@@_bottom_corner_dim }
+ { \box_use:N #1 }
+ }
+% \end{macrocode}
+% If there have been any previous rotations then the size of the
+% bounding box will be bigger than the contents. This can be corrected
+% easily by setting the size of the box to the height and width of the
+% content.
+% \begin{macrocode}
+ \box_set_ht:Nn #1
+ { \l_@@_top_corner_dim - \l_@@_bottom_corner_dim }
+ \box_set_dp:Nn #1 { 0 pt }
+ \box_set_wd:Nn #1
+ { \l_@@_right_corner_dim - \l_@@_left_corner_dim }
+% \end{macrocode}
+% The final task is to move the poles and corners such that they are
+% back in alignment with the box reference point.
+% \begin{macrocode}
+ \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
+ { \@@_shift_corner:Nnnn #1 {##1} ##2 }
+ \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop }
+ { \@@_shift_pole:Nnnnnn #1 {##1} ##2 }
+ }
+\cs_generate_variant:Nn \coffin_rotate:Nn { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_set_bounding:N}
+% The bounding box corners for a coffin are easy enough to find: this
+% is the same code as for the corners of the material itself, but
+% using a dedicated property list.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_set_bounding:N #1
+ {
+ \prop_put:Nnx \l_@@_bounding_prop { tl }
+ { { 0 pt } { \dim_use:N \box_ht:N #1 } }
+ \prop_put:Nnx \l_@@_bounding_prop { tr }
+ { { \dim_use:N \box_wd:N #1 } { \dim_use:N \box_ht:N #1 } }
+ \dim_set:Nn \l_@@_internal_dim { - \box_dp:N #1 }
+ \prop_put:Nnx \l_@@_bounding_prop { bl }
+ { { 0 pt } { \dim_use:N \l_@@_internal_dim } }
+ \prop_put:Nnx \l_@@_bounding_prop { br }
+ { { \dim_use:N \box_wd:N #1 } { \dim_use:N \l_@@_internal_dim } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_rotate_bounding:nnn}
+% \begin{macro}{\@@_rotate_corner:Nnnn}
+% Rotating the position of the corner of the coffin is just a case
+% of treating this as a vector from the reference point. The same
+% treatment is used for the corners of the material itself and the
+% bounding box.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_bounding:nnn #1#2#3
+ {
+ \@@_rotate_vector:nnNN {#2} {#3} \l_@@_x_dim \l_@@_y_dim
+ \prop_put:Nnx \l_@@_bounding_prop {#1}
+ { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } }
+ }
+\cs_new_protected:Npn \@@_rotate_corner:Nnnn #1#2#3#4
+ {
+ \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
+ \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } {#2}
+ { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_rotate_pole:Nnnnnn}
+% Rotating a single pole simply means shifting the co-ordinate of
+% the pole and its direction. The rotation here is about the bottom-left
+% corner of the coffin.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_pole:Nnnnnn #1#2#3#4#5#6
+ {
+ \@@_rotate_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
+ \@@_rotate_vector:nnNN {#5} {#6}
+ \l_@@_x_prime_dim \l_@@_y_prime_dim
+ \@@_set_pole:Nnx #1 {#2}
+ {
+ { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim }
+ { \dim_use:N \l_@@_x_prime_dim }
+ { \dim_use:N \l_@@_y_prime_dim }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_rotate_vector:nnNN}
+% A rotation function, which needs only an input vector (as dimensions)
+% and an output space. The values \cs{l_@@_cos_fp} and
+% \cs{l_@@_sin_fp} should previously have been set up correctly.
+% Working this way means that the floating point work is kept to a
+% minimum: for any given rotation the sin and cosine values do no
+% change, after all.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rotate_vector:nnNN #1#2#3#4
+ {
+ \dim_set:Nn #3
+ {
+ \fp_to_dim:n
+ {
+ \dim_to_fp:n {#1} * \l_@@_cos_fp
+ - ( \dim_to_fp:n {#2} * \l_@@_sin_fp )
+ }
+ }
+ \dim_set:Nn #4
+ {
+ \fp_to_dim:n
+ {
+ \dim_to_fp:n {#1} * \l_@@_sin_fp
+ + ( \dim_to_fp:n {#2} * \l_@@_cos_fp )
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_find_corner_maxima:N}
+% \begin{macro}[aux]{\@@_find_corner_maxima_aux:nn}
+% The idea here is to find the extremities of the content of the
+% coffin. This is done by looking for the smallest values for the bottom
+% and left corners, and the largest values for the top and right
+% corners. The values start at the maximum dimensions so that the
+% case where all are positive or all are negative works out correctly.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_find_corner_maxima:N #1
+ {
+ \dim_set:Nn \l_@@_top_corner_dim { -\c_max_dim }
+ \dim_set:Nn \l_@@_right_corner_dim { -\c_max_dim }
+ \dim_set:Nn \l_@@_bottom_corner_dim { \c_max_dim }
+ \dim_set:Nn \l_@@_left_corner_dim { \c_max_dim }
+ \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
+ { \@@_find_corner_maxima_aux:nn ##2 }
+ }
+\cs_new_protected:Npn \@@_find_corner_maxima_aux:nn #1#2
+ {
+ \dim_set_min:Nn \l_@@_left_corner_dim {#1}
+ \dim_set_max:Nn \l_@@_right_corner_dim {#1}
+ \dim_set_min:Nn \l_@@_bottom_corner_dim {#2}
+ \dim_set_max:Nn \l_@@_top_corner_dim {#2}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_find_bounding_shift:}
+% \begin{macro}[aux]{\@@_find_bounding_shift_aux:nn}
+% The approach to finding the shift for the bounding box is similar to
+% that for the corners. However, there is only one value needed here and
+% a fixed input property list, so things are a bit clearer.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_find_bounding_shift:
+ {
+ \dim_set:Nn \l_@@_bounding_shift_dim { \c_max_dim }
+ \prop_map_inline:Nn \l_@@_bounding_prop
+ { \@@_find_bounding_shift_aux:nn ##2 }
+ }
+\cs_new_protected:Npn \@@_find_bounding_shift_aux:nn #1#2
+ { \dim_set_min:Nn \l_@@_bounding_shift_dim {#1} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_shift_corner:Nnnn}
+% \begin{macro}{\@@_shift_pole:Nnnnnn}
+% Shifting the corners and poles of a coffin means subtracting the
+% appropriate values from the $x$- and $y$-components. For
+% the poles, this means that the direction vector is unchanged.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_shift_corner:Nnnn #1#2#3#4
+ {
+ \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _ prop } {#2}
+ {
+ { \dim_eval:n { #3 - \l_@@_left_corner_dim } }
+ { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } }
+ }
+ }
+\cs_new_protected:Npn \@@_shift_pole:Nnnnnn #1#2#3#4#5#6
+ {
+ \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _ prop } {#2}
+ {
+ { \dim_eval:n { #3 - \l_@@_left_corner_dim } }
+ { \dim_eval:n { #4 - \l_@@_bottom_corner_dim } }
+ {#5} {#6}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Resizing coffins}
+%
+% \begin{variable}{\l_@@_scale_x_fp}
+% \begin{variable}{\l_@@_scale_y_fp}
+% Storage for the scaling factors in $x$ and $y$, respectively.
+% \begin{macrocode}
+\fp_new:N \l_@@_scale_x_fp
+\fp_new:N \l_@@_scale_y_fp
+% \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_scaled_total_height_dim}
+% \begin{variable}{\l_@@_scaled_width_dim}
+% When scaling, the values given have to be turned into absolute values.
+% \begin{macrocode}
+\dim_new:N \l_@@_scaled_total_height_dim
+\dim_new:N \l_@@_scaled_width_dim
+% \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \begin{macro}{\coffin_resize:Nnn, \coffin_resize:cnn}
+% Resizing a coffin begins by setting up the user-friendly names for
+% the dimensions of the coffin box. The new sizes are then turned into
+% scale factor. This is the same operation as takes place for the
+% underlying box, but that operation is grouped and so the same
+% calculation is done here.
+% \begin{macrocode}
+\cs_new_protected:Npn \coffin_resize:Nnn #1#2#3
+ {
+ \@@_set_user_dimensions:N #1
+ \box_resize:Nnn #1 {#2} {#3}
+ \fp_set:Nn \l_@@_scale_x_fp
+ { \dim_to_fp:n {#2} / \dim_to_fp:n \Width }
+ \fp_set:Nn \l_@@_scale_y_fp
+ { \dim_to_fp:n {#3} / \dim_to_fp:n \TotalHeight }
+ \@@_resize_common:Nnn #1 {#2} {#3}
+ }
+\cs_generate_variant:Nn \coffin_resize:Nnn { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_resize_common:Nnn}
+% The poles and corners of the coffin are scaled to the appropriate
+% places before actually resizing the underlying box.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_resize_common:Nnn #1#2#3
+ {
+ \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
+ { \@@_scale_corner:Nnnn #1 {##1} ##2 }
+ \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop }
+ { \@@_scale_pole:Nnnnnn #1 {##1} ##2 }
+% \end{macrocode}
+% Negative $x$-scaling values will place the poles in the wrong
+% location: this is corrected here.
+% \begin{macrocode}
+ \fp_compare:nNnT \l_@@_scale_x_fp < \c_zero_fp
+ {
+ \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
+ { \@@_x_shift_corner:Nnnn #1 {##1} ##2 }
+ \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop }
+ { \@@_x_shift_pole:Nnnnnn #1 {##1} ##2 }
+ }
+ \@@_end_user_dimensions:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\coffin_scale:Nnn, \coffin_scale:cnn}
+% For scaling, the opposite calculation is done to find the new
+% dimensions for the coffin. Only the total height is needed, as this
+% is the shift required for corners and poles. The scaling is done
+% the \TeX{} way as this works properly with floating point values
+% without needing to use the \texttt{fp} module.
+% \begin{macrocode}
+\cs_new_protected:Npn \coffin_scale:Nnn #1#2#3
+ {
+ \box_scale:Nnn #1 {#2} {#3}
+ \@@_set_user_dimensions:N #1
+ \fp_set:Nn \l_@@_scale_x_fp {#2}
+ \fp_set:Nn \l_@@_scale_y_fp {#3}
+ \fp_compare:nNnTF \l_@@_scale_y_fp > \c_zero_fp
+ { \l_@@_scaled_total_height_dim #3 \TotalHeight }
+ { \l_@@_scaled_total_height_dim -#3 \TotalHeight }
+ \fp_compare:nNnTF \l_@@_scale_x_fp > \c_zero_fp
+ { \l_@@_scaled_width_dim -#2 \Width }
+ { \l_@@_scaled_width_dim #2 \Width }
+ \@@_resize_common:Nnn #1
+ { \l_@@_scaled_width_dim } { \l_@@_scaled_total_height_dim }
+ }
+\cs_generate_variant:Nn \coffin_scale:Nnn { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_scale_vector:nnNN}
+% This functions scales a vector from the origin using the pre-set scale
+% factors in $x$ and $y$. This is a much less complex operation
+% than rotation, and as a result the code is a lot clearer.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_scale_vector:nnNN #1#2#3#4
+ {
+ \dim_set:Nn #3
+ { \fp_to_dim:n { \dim_to_fp:n {#1} * \l_@@_scale_x_fp } }
+ \dim_set:Nn #4
+ { \fp_to_dim:n { \dim_to_fp:n {#2} * \l_@@_scale_y_fp } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_scale_corner:Nnnn}
+% \begin{macro}{\@@_scale_pole:Nnnnnn}
+% Scaling both corners and poles is a simple calculation using the
+% preceding vector scaling.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_scale_corner:Nnnn #1#2#3#4
+ {
+ \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
+ \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } {#2}
+ { { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim } }
+ }
+\cs_new_protected:Npn \@@_scale_pole:Nnnnnn #1#2#3#4#5#6
+ {
+ \@@_scale_vector:nnNN {#3} {#4} \l_@@_x_dim \l_@@_y_dim
+ \@@_set_pole:Nnx #1 {#2}
+ {
+ { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim }
+ {#5} {#6}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_x_shift_corner:Nnnn}
+% \begin{macro}{\@@_x_shift_pole:Nnnnnn}
+% These functions correct for the $x$ displacement that takes
+% place with a negative horizontal scaling.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_x_shift_corner:Nnnn #1#2#3#4
+ {
+ \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } {#2}
+ {
+ { \dim_eval:n { #3 + \box_wd:N #1 } } {#4}
+ }
+ }
+\cs_new_protected:Npn \@@_x_shift_pole:Nnnnnn #1#2#3#4#5#6
+ {
+ \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } {#2}
+ {
+ { \dim_eval:n #3 + \box_wd:N #1 } {#4}
+ {#5} {#6}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Additions to \pkg{l3file}}
+%
+% \begin{macrocode}
+%<@@=ior>
+% \end{macrocode}
+%
+% \begin{macro}[EXP]{\ior_map_break:, \ior_map_break:n}
+% Usual map breaking functions. Those are not yet in \pkg{l3kernel}
+% proper since the mapping below is the first of its kind.
+% \begin{macrocode}
+\cs_new_nopar:Npn \ior_map_break:
+ { \__prg_map_break:Nn \ior_map_break: { } }
+\cs_new_nopar:Npn \ior_map_break:n
+ { \__prg_map_break:Nn \ior_map_break: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ior_map_inline:Nn, \ior_str_map_inline:Nn}
+% \begin{macro}[aux]{\@@_map_inline:NNn}
+% \begin{macro}[aux]{\@@_map_inline:NNNn}
+% \begin{macro}[aux]{\@@_map_inline_loop:NNN}
+% \begin{variable}{\l_@@_internal_tl}
+% Mapping to an input stream can be done on either a token or a string
+% basis, hence the set up. Within that, there is a check to avoid reading
+% past the end of a file, hence the two applications of \cs{ior_if_eof:N}.
+% This mapping cannot be nested as the stream has only one \enquote{current
+% line}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \ior_map_inline:Nn
+ { \@@_map_inline:NNn \ior_get:NN }
+\cs_new_protected_nopar:Npn \ior_str_map_inline:Nn
+ { \@@_map_inline:NNn \ior_get_str:NN }
+\cs_new_protected_nopar:Npn \@@_map_inline:NNn
+ {
+ \int_gincr:N \g__prg_map_int
+ \exp_args:Nc \@@_map_inline:NNNn
+ { __prg_map_ \int_use:N \g__prg_map_int :n }
+ }
+\cs_new_protected:Npn \@@_map_inline:NNNn #1#2#3#4
+ {
+ \cs_set:Npn #1 ##1 {#4}
+ \ior_if_eof:NF #3 { \@@_map_inline_loop:NNN #1#2#3 }
+ \__prg_break_point:Nn \ior_map_break:
+ { \int_gdecr:N \g__prg_map_int }
+ }
+\cs_new_protected:Npn \@@_map_inline_loop:NNN #1#2#3
+ {
+ #2 #3 \l_@@_internal_tl
+ \ior_if_eof:NF #3
+ {
+ \exp_args:No #1 \l_@@_internal_tl
+ \@@_map_inline_loop:NNN #1#2#3
+ }
+ }
+\tl_new:N \l_@@_internal_tl
+% \end{macrocode}
+% \end{variable}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Additions to \pkg{l3fp}}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \begin{macro}
+% {
+% \fp_set_from_dim:Nn, \fp_set_from_dim:cn,
+% \fp_gset_from_dim:Nn, \fp_gset_from_dim:cn
+% }
+% Use the appropriate function from \pkg{l3fp-convert}.
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_set_from_dim:Nn #1#2
+ { \tl_set:Nx #1 { \dim_to_fp:n {#2} } }
+\cs_new_protected:Npn \fp_gset_from_dim:Nn #1#2
+ { \tl_gset:Nx #1 { \dim_to_fp:n {#2} } }
+\cs_generate_variant:Nn \fp_set_from_dim:Nn { c }
+\cs_generate_variant:Nn \fp_gset_from_dim:Nn { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Additions to \pkg{l3prop}}
+%
+% \begin{macrocode}
+%<@@=prop>
+% \end{macrocode}
+%
+% \begin{macro}[rEXP]{\prop_map_tokens:Nn, \prop_map_tokens:cn}
+% \begin{macro}[aux]{\@@_map_tokens:nwn}
+% The mapping grabs one key--value pair at a time, and stops when
+% reaching the marker key \cs{q_recursion_tail}, which
+% cannot appear in normal keys since those are strings. The odd
+% construction |\use:n {#1}| allows |#1| to contain any token.
+% \begin{macrocode}
+\cs_new:Npn \prop_map_tokens:Nn #1#2
+ {
+ \exp_last_unbraced:Nno \@@_map_tokens:nwn {#2} #1
+ \q_recursion_tail \q__prop { }
+ \__prg_break_point:Nn \prop_map_break: { }
+ }
+\cs_new:Npn \@@_map_tokens:nwn #1 \q__prop #2 \q__prop #3
+ {
+ \__quark_if_recursion_tail_break:NN #2 \prop_map_break:
+ \use:n {#1} {#2} {#3}
+ \@@_map_tokens:nwn {#1}
+ }
+\cs_generate_variant:Nn \prop_map_tokens:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\prop_get:Nn, \prop_get:cn}
+% \begin{macro}[aux]{\@@_get_Nn:nwn}
+% Getting the value corresponding to a key in a property list in an
+% expandable fashion is a simple instance of mapping some tokens.
+% Map the function \cs{prop_get:nnn} which takes as its three
+% arguments the \meta{key} that we are looking for, the current
+% \meta{key} and the current \meta{value}. If the \meta{keys} match,
+% the \meta{value} is returned. If none of the keys match, this expands
+% to nothing.
+% \begin{macrocode}
+\cs_new:Npn \prop_get:Nn #1#2
+ {
+ \exp_last_unbraced:Noo \@@_get_Nn:nwn
+ { \tl_to_str:n {#2} } #1
+ \tl_to_str:n {#2} \q__prop { }
+ \__prg_break_point:
+ }
+\cs_new:Npn \@@_get_Nn:nwn #1 \q__prop #2 \q__prop #3
+ {
+ \str_if_eq_x:nnTF {#1} {#2}
+ { \__prg_break:n { \exp_not:n {#3} } }
+ { \@@_get_Nn:nwn {#1} }
+ }
+\cs_generate_variant:Nn \prop_get:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Additions to \pkg{l3seq}}
+%
+% \begin{macrocode}
+%<@@=seq>
+% \end{macrocode}
+%
+% \begin{macro}{\seq_item:Nn, \seq_item:cn}
+% \begin{macro}[aux]{\@@_item:nnn}
+% The idea here is to find the offset of the item from the left, then use
+% a loop to grab the correct item. If the resulting offset is too large,
+% then the stop code |{ ? \__prg_break: } { }| will be used by the auxiliary,
+% terminating the loop and returning nothing at all.
+% \begin{macrocode}
+\cs_new:Npn \seq_item:Nn #1#2
+ {
+ \exp_last_unbraced:Nfo \@@_item:nnn
+ {
+ \int_eval:n
+ {
+ \int_compare:nNnT {#2} < \c_zero
+ { \seq_count:N #1 + \c_one + }
+ #2
+ }
+ }
+ #1
+ { ? \__prg_break: }
+ { }
+ \__prg_break_point:
+ }
+\cs_new:Npn \@@_item:nnn #1#2#3
+ {
+ \use_none:n #2
+ \int_compare:nNnTF {#1} = \c_one
+ { \__prg_break:n { \exp_not:n {#3} } }
+ { \exp_args:Nf \@@_item:nnn { \int_eval:n { #1 - 1 } } }
+ }
+\cs_generate_variant:Nn \seq_item:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \seq_mapthread_function:NNN, \seq_mapthread_function:NcN,
+% \seq_mapthread_function:cNN, \seq_mapthread_function:ccN
+% }
+% \begin{macro}[aux]{\@@_mapthread_function:NN}
+% \begin{macro}[aux]{\@@_mapthread_function:Nnnwnn}
+% The idea here is to first expand both of the 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 token of |#2| and |#5|, which for items in the sequences
+% will both be \cs{@@_item:n}. The function to be mapped will then be
+% applied to the two entries. When the code hits the end of one of the
+% sequences, the break material will stop 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:NN
+ \exp_after:wN #3
+ \exp_after:wN #1
+ #2
+ { ? \__prg_break: } { }
+ \__prg_break_point:
+ }
+\cs_new:Npn \@@_mapthread_function:NN #1#2
+ {
+ \exp_after:wN \@@_mapthread_function:Nnnwnn
+ \exp_after:wN #1
+ #2
+ { ? \__prg_break: } { }
+ \q_stop
+ }
+\cs_new:Npn \@@_mapthread_function:Nnnwnn #1#2#3#4 \q_stop #5#6
+ {
+ \use_none:n #2
+ \use_none:n #5
+ #1 {#3} {#6}
+ \@@_mapthread_function:Nnnwnn #1 #4 \q_stop
+ }
+\cs_generate_variant:Nn \seq_mapthread_function:NNN { Nc }
+\cs_generate_variant:Nn \seq_mapthread_function:NNN { c , cc }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \seq_set_from_clist:NN, \seq_set_from_clist:cN,
+% \seq_set_from_clist:Nc, \seq_set_from_clist:cc,
+% \seq_set_from_clist:Nn, \seq_set_from_clist:cn
+% }
+% \begin{macro}
+% {
+% \seq_gset_from_clist:NN, \seq_gset_from_clist:cN,
+% \seq_gset_from_clist:Nc, \seq_gset_from_clist:cc,
+% \seq_gset_from_clist:Nn, \seq_gset_from_clist:cn
+% }
+% Setting a sequence from a comma-separated list is done using a simple
+% mapping.
+% \begin{macrocode}
+\cs_new_protected:Npn \seq_set_from_clist:NN #1#2
+ {
+ \tl_set:Nx #1
+ { \clist_map_function:NN #2 \@@_wrap_item:n }
+ }
+\cs_new_protected:Npn \seq_set_from_clist:Nn #1#2
+ {
+ \tl_set:Nx #1
+ { \clist_map_function:nN {#2} \@@_wrap_item:n }
+ }
+\cs_new_protected:Npn \seq_gset_from_clist:NN #1#2
+ {
+ \tl_gset:Nx #1
+ { \clist_map_function:NN #2 \@@_wrap_item:n }
+ }
+\cs_new_protected:Npn \seq_gset_from_clist:Nn #1#2
+ {
+ \tl_gset:Nx #1
+ { \clist_map_function:nN {#2} \@@_wrap_item:n }
+ }
+\cs_generate_variant:Nn \seq_set_from_clist:NN { Nc }
+\cs_generate_variant:Nn \seq_set_from_clist:NN { c , cc }
+\cs_generate_variant:Nn \seq_set_from_clist:Nn { c }
+\cs_generate_variant:Nn \seq_gset_from_clist:NN { Nc }
+\cs_generate_variant:Nn \seq_gset_from_clist:NN { c , cc }
+\cs_generate_variant:Nn \seq_gset_from_clist:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {\seq_reverse:N, \seq_reverse:c, \seq_greverse:N, \seq_greverse:c}
+% \begin{macro}[aux]{\@@_tmp:w}
+% \begin{macro}[aux]{\@@_reverse:NN}
+% \begin{macro}[aux]{\@@_reverse_item:nwn}
+% Previously, \cs{seq_reverse:N} was coded by collecting the items
+% in reverse order after an \cs{exp_stop_f:} marker.
+% \begin{verbatim}
+% \cs_new_protected:Npn \seq_reverse:N #1
+% {
+% \cs_set_eq:NN \@@_item:n \@@_reverse_item:nw
+% \tl_set:Nf #2 { #2 \exp_stop_f: }
+% }
+% \cs_new:Npn \@@_reverse_item:nw #1 #2 \exp_stop_f:
+% {
+% #2 \exp_stop_f:
+% \@@_item:n {#1}
+% }
+% \end{verbatim}
+% At first, this seems optimal, since we can forget about each item
+% as soon as it is placed after \cs{exp_stop_f:}. Unfortunately,
+% \TeX{}'s usual tail recursion does not take place in this case:
+% since the following \cs{@@_reverse_item:nw} only reads
+% tokens until \cs{exp_stop_f:}, and never reads the
+% |\@@_item:n {#1}| left by the previous call, \TeX{} cannot
+% remove that previous call from the stack, and in particular
+% must retain the various macro parameters in memory, until the
+% end of the replacement text is reached. The stack is thus
+% only flushed after all the \cs{@@_reverse_item:nw} are
+% expanded. Keeping track of the arguments of all those calls
+% uses up a memory quadratic in the length of the sequence.
+% \TeX{} can then not cope with more than a few thousand items.
+%
+% Instead, we collect the items in the argument
+% of \cs{exp_not:n}. The previous calls are cleanly removed
+% from the stack, and the memory consumption becomes linear.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_tmp:w { }
+\cs_new_protected_nopar:Npn \seq_reverse:N
+ { \@@_reverse:NN \tl_set:Nx }
+\cs_new_protected_nopar:Npn \seq_greverse:N
+ { \@@_reverse:NN \tl_gset:Nx }
+\cs_new_protected:Npn \@@_reverse:NN #1 #2
+ {
+ \cs_set_eq:NN \@@_tmp:w \@@_item:n
+ \cs_set_eq:NN \@@_item:n \@@_reverse_item:nwn
+ #1 #2 { #2 \exp_not:n { } }
+ \cs_set_eq:NN \@@_item:n \@@_tmp:w
+ }
+\cs_new:Npn \@@_reverse_item:nwn #1 #2 \exp_not:n #3
+ {
+ #2
+ \exp_not:n { \@@_item:n {#1} #3 }
+ }
+\cs_generate_variant:Nn \seq_reverse:N { c }
+\cs_generate_variant:Nn \seq_greverse:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\seq_set_filter:NNn, \seq_gset_filter:NNn}
+% \begin{macro}[aux]{\@@_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_nopar:Npn \seq_set_filter:NNn
+ { \@@_set_filter:NNNn \tl_set:Nx }
+\cs_new_protected_nopar:Npn \seq_gset_filter:NNn
+ { \@@_set_filter:NNNn \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_map:NNn,\seq_gset_map:NNn}
+% \begin{macro}[aux]{\@@_set_map:NNNn}
+% Very similar to \cs{seq_set_filter:NNn}. We could actually
+% merge the two within a single function, but it would have weird
+% semantics.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \seq_set_map:NNn
+ { \@@_set_map:NNNn \tl_set:Nx }
+\cs_new_protected_nopar:Npn \seq_gset_map:NNn
+ { \@@_set_map:NNNn \tl_gset:Nx }
+\cs_new_protected:Npn \@@_set_map:NNNn #1#2#3#4
+ {
+ \@@_push_item_def:n { \exp_not:N \@@_item:n {#4} }
+ #1 #2 { #3 }
+ \@@_pop_item_def:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\seq_use:Nnnn}
+% \begin{macro}[EXP, aux]
+% {\@@_use:NnNnn, \@@_use_ii:nwwwwnwn, \@@_use_iii:nwwn}
+% See \cs{clist_use:Nnnn} for a general explanation. The main
+% difference is that we use \cs{@@_item:n} as a delimiter rather than
+% commas. We also need to add \cs{@@_item:n} at various places.
+% \begin{macrocode}
+\cs_new:Npn \seq_use:Nnnn #1#2#3#4
+ {
+ \seq_if_exist:NTF #1
+ {
+ \int_case:nnn { \seq_count:N #1 }
+ {
+ { 0 } { }
+ { 1 } { \exp_after:wN \@@_use:NnNnn #1 \@@_item:n { } { } }
+ { 2 } { \exp_after:wN \@@_use:NnNnn #1 {#2} }
+ }
+ {
+ \exp_after:wN \@@_use_ii:nwwwwnwn
+ \exp_after:wN { \exp_after:wN } #1 \@@_item:n
+ \q_mark { \@@_use_ii:nwwwwnwn {#3} }
+ \q_mark { \@@_use_iii:nwwn {#4} }
+ \q_stop { }
+ }
+ }
+ { \__msg_kernel_expandable_error:nnn { kernel } { bad-variable } {#1} }
+ }
+\cs_new:Npn \@@_use:NnNnn \@@_item:n #1 \@@_item:n #2#3
+ { \exp_not:n { #1 #3 #2 } }
+\cs_new:Npn \@@_use_ii:nwwwwnwn
+ #1 \@@_item:n #2 \@@_item:n #3 \@@_item:n #4#5
+ \q_mark #6#7 \q_stop #8
+ {
+ #6 \@@_item:n {#3} \@@_item:n {#4} #5
+ \q_mark {#6} #7 \q_stop { #8 #1 #2 }
+ }
+\cs_new:Npn \@@_use_iii:nwwn #1 \@@_item:n #2 #3 \q_stop #4
+ { \exp_not:n { #4 #1 #2 } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Additions to \pkg{l3skip}}
+%
+% \begin{macrocode}
+%<@@=skip>
+% \end{macrocode}
+%
+% \begin{macro}{\skip_split_finite_else_action:nnNN}
+% This macro is useful when performing error checking in certain
+% circumstances. If the \meta{skip} register holds finite glue it sets
+% |#3| and |#4| to the stretch and shrink component, resp. If it holds
+% infinite glue set |#3| and |#4| to zero and issue the special action
+% |#2| which is probably an error message.
+% Assignments are local.
+% \begin{macrocode}
+\cs_new:Npn \skip_split_finite_else_action:nnNN #1#2#3#4
+ {
+ \skip_if_finite:nTF {#1}
+ {
+ #3 = \etex_gluestretch:D #1 \scan_stop:
+ #4 = \etex_glueshrink:D #1 \scan_stop:
+ }
+ {
+ #3 = \c_zero_skip
+ #4 = \c_zero_skip
+ #2
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Additions to \pkg{l3tl}}
+%
+% \begin{macrocode}
+%<@@=tl>
+% \end{macrocode}
+%
+% \begin{macro}[EXP,pTF]{\tl_if_single_token:n}
+% There are four cases: empty token list, token list starting with
+% a normal token, with a brace group, or with a space token.
+% If the token list starts with a normal token, remove it
+% and check for emptyness. Otherwise, compare with a single
+% space, only case where we have a single token.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \tl_if_single_token:n #1 { p , T , F , TF }
+ {
+ \tl_if_head_is_N_type:nTF {#1}
+ { \__str_if_eq_x_return:nn { \exp_not:o { \use_none:n #1 } } { } }
+ { \__str_if_eq_x_return:nn { \exp_not:n {#1} } { ~ } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\tl_reverse_tokens:n}
+% \begin{macro}[EXP,aux]{\@@_reverse_group:nn}
+% The same as \cs{tl_reverse:n} but with recursion within brace groups.
+% \begin{macrocode}
+\cs_new:Npn \tl_reverse_tokens:n #1
+ {
+ \etex_unexpanded:D \exp_after:wN
+ {
+ \tex_romannumeral:D
+ \@@_act:NNNnn
+ \@@_reverse_normal:nN
+ \@@_reverse_group:nn
+ \@@_reverse_space:n
+ { }
+ {#1}
+ }
+ }
+\cs_new:Npn \@@_reverse_group:nn #1
+ {
+ \@@_act_group_recurse:Nnn
+ \@@_act_reverse_output:n
+ { \tl_reverse_tokens:n }
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}[EXP,aux]{\@@_act_group_recurse:Nnn}
+% In many applications of \cs{@@_act:NNNnn}, we need to recursively
+% apply some transformation within brace groups, then output. In this
+% code, |#1| is the output function, |#2| is the transformation,
+% which should expand in two steps, and |#3| is the group.
+% \begin{macrocode}
+\cs_new:Npn \@@_act_group_recurse:Nnn #1#2#3
+ {
+ \exp_args:Nf #1
+ { \exp_after:wN \exp_after:wN \exp_after:wN { #2 {#3} } }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\tl_count_tokens:n}
+% \begin{macro}[EXP,aux]{\@@_act_count_normal:nN,
+% \@@_act_count_group:nn,\@@_act_count_space:n}
+% The token coung is computed through an \cs{int_eval:n} construction.
+% Each \texttt{1+} is output to the \emph{left}, into the integer
+% expression, and the sum is ended by the \cs{c_zero} inserted by
+% \cs{@@_act_end:wn}. Somewhat a hack.
+% \begin{macrocode}
+\cs_new:Npn \tl_count_tokens:n #1
+ {
+ \int_eval:n
+ {
+ \@@_act:NNNnn
+ \@@_act_count_normal:nN
+ \@@_act_count_group:nn
+ \@@_act_count_space:n
+ { }
+ {#1}
+ }
+ }
+\cs_new:Npn \@@_act_count_normal:nN #1 #2 { 1 + }
+\cs_new:Npn \@@_act_count_space:n #1 { 1 + }
+\cs_new:Npn \@@_act_count_group:nn #1 #2
+ { 2 + \tl_count_tokens:n {#2} + }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{variable}{\c_@@_act_uppercase_tl, \c_@@_act_lowercase_tl}
+% These constants contain the correspondance between lowercase
+% and uppercase letters, in the form |aAbBcC...| and |AaBbCc...|
+% respectively.
+% \begin{macrocode}
+\tl_const:Nn \c_@@_act_uppercase_tl
+ {
+ aA bB cC dD eE fF gG hH iI jJ kK lL mM
+ nN oO pP qQ rR sS tT uU vV wW xX yY zZ
+ }
+\tl_const:Nn \c_@@_act_lowercase_tl
+ {
+ Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm
+ Nn Oo Pp Qq Rr Ss Tt Uu Vv Ww Xx Yy Zz
+ }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[EXP]{\tl_expandable_uppercase:n,\tl_expandable_lowercase:n}
+% \begin{macro}[EXP,aux]{\@@_act_case_normal:nN,
+% \@@_act_case_group:nn,\@@_act_case_space:n}
+% The only difference between uppercasing and lowercasing is
+% the table of correspondance that is used. As for other
+% token list actions, we feed \cs{@@_act:NNNnn} three
+% functions, and this time, we use the \meta{parameters}
+% argument to carry which case-changing we are applying.
+% A space is simply output. A normal token is compared
+% to each letter in the alphabet using \cs{str_if_eq:nn}
+% tests, and converted if necessary to upper/lowercase,
+% before being output. For a group, we must perform the
+% conversion within the group (the \cs{exp_after:wN} trigger
+% \tn{romannumeral}, which expands fully to give the
+% converted group), then output.
+% \begin{macrocode}
+\cs_new:Npn \tl_expandable_uppercase:n #1
+ {
+ \etex_unexpanded:D \exp_after:wN
+ {
+ \tex_romannumeral:D
+ \@@_act_case_aux:nn { \c_@@_act_uppercase_tl } {#1}
+ }
+ }
+\cs_new:Npn \tl_expandable_lowercase:n #1
+ {
+ \etex_unexpanded:D \exp_after:wN
+ {
+ \tex_romannumeral:D
+ \@@_act_case_aux:nn { \c_@@_act_lowercase_tl } {#1}
+ }
+ }
+\cs_new:Npn \@@_act_case_aux:nn
+ {
+ \@@_act:NNNnn
+ \@@_act_case_normal:nN
+ \@@_act_case_group:nn
+ \@@_act_case_space:n
+ }
+\cs_new:Npn \@@_act_case_space:n #1 { \@@_act_output:n {~} }
+\cs_new:Npn \@@_act_case_normal:nN #1 #2
+ {
+ \exp_args:Nf \@@_act_output:n
+ {
+ \exp_args:NNo \str_case:nnn #2 {#1}
+ { \exp_stop_f: #2 }
+ }
+ }
+\cs_new:Npn \@@_act_case_group:nn #1 #2
+ {
+ \exp_after:wN \@@_act_output:n \exp_after:wN
+ { \exp_after:wN { \tex_romannumeral:D \@@_act_case_aux:nn {#1} {#2} } }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\tl_item:nn, \tl_item:Nn, \tl_item:cn}
+% \begin{macro}[aux]{\@@_item:nn}
+% The idea here is to find the offset of the item from the left, then use
+% a loop to grab the correct item. If the resulting offset is too large,
+% then \cs{quark_if_recursion_tail_stop:n} terminates the loop, and returns
+% nothing at all.
+% \begin{macrocode}
+\cs_new:Npn \tl_item:nn #1#2
+ {
+ \exp_args:Nf \@@_item:nn
+ {
+ \int_eval:n
+ {
+ \int_compare:nNnT {#2} < \c_zero
+ { \tl_count:n {#1} + \c_one + }
+ #2
+ }
+ }
+ #1
+ \q_recursion_tail
+ \__prg_break_point:
+ }
+\cs_new:Npn \@@_item:nn #1#2
+ {
+ \__quark_if_recursion_tail_break:nN {#2} \__prg_break:
+ \int_compare:nNnTF {#1} = \c_one
+ { \__prg_break:n { \exp_not:n {#2} } }
+ { \exp_args:Nf \@@_item:nn { \int_eval:n { #1 - 1 } } }
+ }
+\cs_new_nopar:Npn \tl_item:Nn { \exp_args:No \tl_item:nn }
+\cs_generate_variant:Nn \tl_item:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Additions to \pkg{l3tokens}}
+%
+% \begin{macrocode}
+%<@@=char>
+% \end{macrocode}
+%
+% \begin{macro}{\char_set_active:Npn,\char_set_active:Npx}
+% \begin{macro}{\char_gset_active:Npn,\char_gset_active:Npx}
+% \begin{macro}{\char_set_active_eq:NN,\char_gset_active_eq:NN}
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_active:N \^^@
+ \cs_set:Npn \char_tmp:NN #1#2
+ {
+ \cs_new:Npn #1 ##1
+ {
+ \char_set_catcode_active:n { `##1 }
+ \group_begin:
+ \char_set_lccode:nn { `\^^@ } { `##1 }
+ \tl_to_lowercase:n { \group_end: #2 ^^@ }
+ }
+ }
+ \char_tmp:NN \char_set_active:Npn \cs_set:Npn
+ \char_tmp:NN \char_set_active:Npx \cs_set:Npx
+ \char_tmp:NN \char_gset_active:Npn \cs_gset:Npn
+ \char_tmp:NN \char_gset_active:Npx \cs_gset:Npx
+ \char_tmp:NN \char_set_active_eq:NN \cs_set_eq:NN
+ \char_tmp:NN \char_gset_active_eq:NN \cs_gset_eq:NN
+\group_end:
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%<@@=peek>
+% \end{macrocode}
+%
+% \begin{macro}[TF]{\peek_N_type:}
+% \begin{macro}{\@@_execute_branches_N_type:}
+% The next token is normal if it is neither a begin-group token,
+% nor an end-group token, nor a charcode-$32$ space token.
+% Note that implicit begin-group tokens, end-group tokens, and
+% spaces are also recognized as non-\texttt{N}-type.
+% Here, there is no \meta{search token}, so we feed a dummy
+% \cs{scan_stop:} to the \cs{peek_token_generic::NN} functions.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_execute_branches_N_type:
+ {
+ \bool_if:nTF
+ {
+ \token_if_eq_catcode_p:NN \l_peek_token \c_group_begin_token ||
+ \token_if_eq_catcode_p:NN \l_peek_token \c_group_end_token ||
+ \token_if_eq_meaning_p:NN \l_peek_token \c_space_token
+ }
+ { \@@_false:w }
+ { \@@_true:w }
+ }
+\cs_new_protected_nopar:Npn \peek_N_type:TF
+ { \@@_token_generic:NNTF \@@_execute_branches_N_type: \scan_stop: }
+\cs_new_protected_nopar:Npn \peek_N_type:T
+ { \@@_token_generic:NNT \@@_execute_branches_N_type: \scan_stop: }
+\cs_new_protected_nopar:Npn \peek_N_type:F
+ { \@@_token_generic:NNF \@@_execute_branches_N_type: \scan_stop: }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
index 31a429e61ef..5fbb63f89d9 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3clist.dtx
@@ -37,8 +37,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3clist.dtx 3490 2012-03-04 01:00:53Z bruno $
- {L3 Experimental comma separated lists}
+\GetIdInfo$Id: l3clist.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Comma separated lists}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -88,7 +88,9 @@
% \end{verbatim}
% will leave \texttt{true} in the input stream. To include an item
% which contains a comma, or starts or ends with a space,
-% surround it with braces.
+% surround it with braces. The sequence data type should be preferred
+% to comma lists if items are to contain |{|, |}|, or |#| (assuming the
+% usual \TeX{} category codes apply).
%
% \section{Creating and initialising comma lists}
%
@@ -118,7 +120,7 @@
% \cs{clist_clear_new:N} \meta{comma list}
% \end{syntax}
% Ensures that the \meta{comma list} exists globally by applying
-% \cs{clsit_new:N} if necessary, then applies \cs{clist_(g)clear:N} to leave
+% \cs{clist_new:N} if necessary, then applies \cs{clist_(g)clear:N} to leave
% the list empty.
% \end{function}
%
@@ -130,10 +132,10 @@
% \clist_gset_eq:Nc, \clist_gset_eq:cc
% }
% \begin{syntax}
-% \cs{clist_set_eq:NN} \meta{comma list1} \meta{comma list2}
+% \cs{clist_set_eq:NN} \meta{comma list_1} \meta{comma list_2}
% \end{syntax}
-% Sets the content of \meta{comma list1} equal to that of
-% \meta{comma list2}.
+% Sets the content of \meta{comma list_1} equal to that of
+% \meta{comma list_2}.
% \end{function}
%
% \begin{function}
@@ -142,11 +144,11 @@
% \clist_gconcat:NNN, \clist_gconcat:ccc
% }
% \begin{syntax}
-% \cs{clist_concat:NNN} \meta{comma list1} \meta{comma list2} \meta{comma list3}
+% \cs{clist_concat:NNN} \meta{comma list_1} \meta{comma list_2} \meta{comma list_3}
% \end{syntax}
-% Concatenates the content of \meta{comma list2} and \meta{comma list3}
-% together and saves the result in \meta{comma list1}. The items in
-% \meta{comma list2} will be placed at the left side of the new comma list.
+% Concatenates the content of \meta{comma list_2} and \meta{comma list_3}
+% together and saves the result in \meta{comma list_1}. The items in
+% \meta{comma list_2} will be placed at the left side of the new comma list.
% \end{function}
%
% \begin{function}[EXP, pTF, added=2012-03-03]
@@ -173,7 +175,7 @@
% \clist_gset:co, \clist_gset:cx
% }
% \begin{syntax}
-% \cs{clist_set:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}|
+% \cs{clist_set:Nn} \meta{comma list} |{|\meta{item_1},\ldots{},\meta{item_n}|}|
% \end{syntax}
% Sets \meta{comma list} to contain the \meta{items},
% removing any previous content from the variable.
@@ -192,7 +194,7 @@
% \clist_gput_left:co, \clist_gput_left:cx
% }
% \begin{syntax}
-% \cs{clist_put_left:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}|
+% \cs{clist_put_left:Nn} \meta{comma list} |{|\meta{item_1},\ldots{},\meta{item_n}|}|
% \end{syntax}
% Appends the \meta{items} to the left of the \meta{comma list}.
% Spaces are removed from both sides of each item.
@@ -210,22 +212,12 @@
% \clist_gput_right:co, \clist_gput_right:cx
% }
% \begin{syntax}
-% \cs{clist_put_right:Nn} \meta{comma list} |{|\meta{item1},\ldots{},\meta{item$_n$}|}|
+% \cs{clist_put_right:Nn} \meta{comma list} |{|\meta{item_1},\ldots{},\meta{item_n}|}|
% \end{syntax}
% Appends the \meta{items} to the right of the \meta{comma list}.
% Spaces are removed from both sides of each item.
% \end{function}
%
-% \section{Using comma lists}
-%
-% \begin{function}[EXP]{\clist_use:N, \clist_use:c}
-% \begin{syntax}
-% \cs{clist_use:N} \meta{comma list}
-% \end{syntax}
-% Places the \meta{comma list} directly into the input stream,
-% including the commas, thus treating it as a \meta{token list}.
-% \end{function}
-%
% \section{Modifying comma lists}
%
% While comma lists are normally used as ordered lists, it may be
@@ -281,17 +273,6 @@
% Tests if the \meta{comma list} is empty (containing no items).
% \end{function}
%
-% \begin{function}[EXP,pTF]
-% {\clist_if_eq:NN, \clist_if_eq:Nc, \clist_if_eq:cN, \clist_if_eq:cc}
-% \begin{syntax}
-% \cs{clist_if_eq_p:NN} \meta{clist_1} \meta{clist_2}
-% \cs{clist_if_eq:NNTF} \meta{clist_1} \meta{clist_2} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Compares the content of two \meta{comma lists} and
-% is logically \texttt{true} if the two contain the same list of
-% entries in the same order.
-% \end{function}
-%
% \begin{function}[updated = 2011-09-06, TF]
% {
% \clist_if_in:Nn, \clist_if_in:NV, \clist_if_in:No,
@@ -326,16 +307,16 @@
% If the result of trimming spaces is empty, the item is ignored.
% Otherwise, if the item is surrounded by braces, one set is removed,
% and the result is passed to the mapped function. Thus, if your
-% comma list that is being mapped is \verb*|{a , {b }, ,{}, {c},}|
+% comma list that is being mapped is \verb*|{a , {{b} }, ,{}, {c},}|
% then the arguments passed to the mapped function are
-% `\verb*|a|', `\verb*|{b }|', an empty argument, and `\verb*|c|'.
+% `\verb*|a|', `\verb*|{b} |', an empty argument, and `\verb*|c|'.
%
% When the comma list is given as an \texttt{N}-type argument, spaces
% have already been trimmed on input, and items are simply stripped
% of one set of braces if any. This case is more efficient than using
% \texttt{n}-type comma lists.
%
-% \begin{function}[rEXP]
+% \begin{function}[rEXP, updated = 2012-06-29]
% {\clist_map_function:NN, \clist_map_function:cN, \clist_map_function:nN}
% \begin{syntax}
% \cs{clist_map_function:NN} \meta{comma list} \meta{function}
@@ -348,7 +329,7 @@
% One mapping may be nested inside another.
% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {\clist_map_inline:Nn, \clist_map_inline:cn, \clist_map_inline:nn}
% \begin{syntax}
% \cs{clist_map_inline:Nn} \meta{comma list} \Arg{inline function}
@@ -360,7 +341,7 @@
% are returned from left to right.
% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {\clist_map_variable:NNn, \clist_map_variable:cNn, \clist_map_variable:nNn}
% \begin{syntax}
% \cs{clist_map_variable:NNn} \meta{comma list} \meta{tl~var.} \Arg{function using tl~var.}
@@ -373,7 +354,7 @@
% are returned from left to right.
% \end{function}
%
-% \begin{function}[rEXP]{\clist_map_break:}
+% \begin{function}[rEXP, updated = 2012-06-29]{\clist_map_break:}
% \begin{syntax}
% \cs{clist_map_break:}
% \end{syntax}
@@ -394,13 +375,13 @@
% level \TeX{} errors.
% \begin{texnote}
% When the mapping is broken, additional tokens may be inserted by the
-% internal macro \cs{prg_break_point:n} before further items are taken
+% internal macro \cs{__prg_break_point:Nn} before further items are taken
% from the input stream. This will depend on the design of the mapping
% function.
% \end{texnote}
% \end{function}
%
-% \begin{function}[rEXP]{\clist_map_break:n}
+% \begin{function}[updated = 2012-06-29, rEXP]{\clist_map_break:n}
% \begin{syntax}
% \cs{clist_map_break:n} \Arg{tokens}
% \end{syntax}
@@ -422,12 +403,23 @@
% level \TeX{} errors.
% \begin{texnote}
% When the mapping is broken, additional tokens may be inserted by the
-% internal macro \cs{prg_break_point:n} before the \meta{tokens} are
+% internal macro \cs{__prg_break_point:Nn} before the \meta{tokens} are
% inserted into the input stream.
% This will depend on the design of the mapping function.
% \end{texnote}
% \end{function}
%
+% \begin{function}[EXP, added = 2012-07-13]
+% {\clist_count:N, \clist_count:c, \clist_count:n}
+% \begin{syntax}
+% \cs{clist_count:N} \meta{comma list}
+% \end{syntax}
+% Leaves the number of items in the \meta{comma list} in the input
+% stream as an \meta{integer denotation}. The total number of items
+% in a \meta{comma list} will include those which are duplicates,
+% \emph{i.e.}~every item in a \meta{comma list} is unique.
+% \end{function}
+%
% \section{Comma lists as stacks}
%
% Comma lists can be used as stacks, where data is pushed to and popped
@@ -437,22 +429,28 @@
% in the previous section: a comma list should either be used as an
% ordered data type or as a stack, but not in both ways.
%
-% \begin{function}{\clist_get:NN, \clist_get:cN}
+% \begin{function}[updated = 2012-05-14]{\clist_get:NN, \clist_get:cN}
% \begin{syntax}
% \cs{clist_get:NN} \meta{comma list} \meta{token list variable}
% \end{syntax}
% Stores the left-most item from a \meta{comma list} in the
% \meta{token list variable} without removing it from the
% \meta{comma list}. The \meta{token list variable} is assigned locally.
+% If the \meta{comma list} is empty the \meta{token list variable} will
+% contain the marker value \cs{q_no_value}.
% \end{function}
%
-% \begin{function}{\clist_get:NN, \clist_get:cN}
+% \begin{function}[TF, added = 2012-05-14]{\clist_get:NN, \clist_get:cN}
% \begin{syntax}
-% \cs{clist_get:NN} \meta{comma list} \meta{token list variable}
+% \cs{clist_get:NNTF} \meta{comma list} \meta{token list variable} \Arg{true code} \Arg{false code}
% \end{syntax}
-% Stores the right-most item from a \meta{comma list} in the
-% \meta{token list variable} without removing it from the
-% \meta{comma list}. The \meta{token list variable} is assigned locally.
+% If the \meta{comma list} is empty, leaves the \meta{false code} in the
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{comma list} is non-empty, stores the top item from the
+% \meta{comma list} in the \meta{token list variable} without removing it
+% from the \meta{comma list}. The \meta{token list variable} is assigned
+% locally.
% \end{function}
%
% \begin{function}[updated = 2011-09-06]{\clist_pop:NN, \clist_pop:cN}
@@ -476,6 +474,32 @@
% the \meta{token list variable} is local.
% \end{function}
%
+% \begin{function}[TF, added = 2012-05-14]{\clist_pop:NN, \clist_pop:cN}
+% \begin{syntax}
+% \cs{clist_pop:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{comma list} is empty, leaves the \meta{false code} in the
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{comma list} is non-empty, pops the top item from the
+% \meta{comma list} in the \meta{token list variable}, \emph{i.e.}~removes
+% the item from the \meta{comma list}. Both the \meta{comma list} and the
+% \meta{token list variable} are assigned locally.
+% \end{function}
+%
+% \begin{function}[TF, added = 2012-05-14]{\clist_gpop:NN, \clist_gpop:cN}
+% \begin{syntax}
+% \cs{clist_gpop:NNTF} \meta{comma list} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{comma list} is empty, leaves the \meta{false code} in the
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{comma list} is non-empty, pops the top item from the
+% \meta{comma list} in the \meta{token list variable}, \emph{i.e.}~removes
+% the item from the \meta{comma list}. The \meta{comma list} is modified
+% globally, while the \meta{token list variable} is assigned locally.
+% \end{function}
+%
% \begin{function}
% {
% \clist_push:Nn, \clist_push:NV, \clist_push:No, \clist_push:Nx,
@@ -506,7 +530,11 @@
% Displays the entries in the comma list in the terminal.
% \end{function}
%
-% \section{Scratch comma lists}
+% \section{Constant and scratch comma lists}
+%
+% \begin{variable}[added = 2012-07-02]{\c_empty_clist}
+% Constant that is always empty.
+% \end{variable}
%
% \begin{variable}[added = 2011-09-06]{\l_tmpa_clist, \l_tmpb_clist}
% Scratch comma lists for local assignment. These are never used by
@@ -522,97 +550,6 @@
% code and so should only be used for short-term storage.
% \end{variable}
%
-% \section{Experimental comma list functions}
-%
-% This section contains functions which may or may not be retained, depending
-% on how useful they are found to be.
-%
-% \begin{function}[added = 2011-06-25, updated = 2011-09-06, EXP]
-% {\clist_length:N, \clist_length:c, \clist_length:n}
-% \begin{syntax}
-% \cs{clist_length:N} \meta{comma list}
-% \end{syntax}
-% Leaves the number of items in the \meta{comma list} in the input
-% stream as an \meta{integer denotation}. The total number of items
-% in a \meta{comma list} will include those which are duplicates,
-% \emph{i.e.}~every item in a \meta{comma list} is unique.
-% \end{function}
-%
-% \begin{function}[updated = 2012-01-08, EXP]
-% {\clist_item:Nn, \clist_item:cn, \clist_item:nn}
-% \begin{syntax}
-% \cs{clist_item:Nn} \meta{comma list} \Arg{integer expression}
-% \end{syntax}
-% Indexing items in the \meta{comma list} from $0$ at the top (left), this
-% function will evaluate the \meta{integer expression} and leave the
-% appropriate item from the comma list in the input stream. If the
-% \meta{integer expression} is negative, indexing occurs from the
-% bottom (right) of the comma list. When the \meta{integer expression}
-% is larger than the number of items in the \meta{comma list} (as
-% calculated by \cs{clist_length:N}) then the function will expand to
-% nothing.
-% \begin{texnote}
-% The result is returned within the \tn{unexpanded}
-% primitive (\cs{exp_not:n}), which means that the \meta{item}
-% will not expand further when appearing in an x-type
-% argument expansion.
-% \end{texnote}
-% \end{function}
-%
-% \begin{function}[updated = 2011-08-31]
-% {
-% \clist_set_from_seq:NN, \clist_set_from_seq:cN,
-% \clist_set_from_seq:Nc, \clist_set_from_seq:cc,
-% \clist_gset_from_seq:NN, \clist_gset_from_seq:cN,
-% \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc
-% }
-% \begin{syntax}
-% \cs{clist_set_from_seq:NN} \meta{comma list} \meta{sequence}
-% \end{syntax}
-% Sets the \meta{comma list} to be equal to the content of the
-% \meta{sequence}.
-% Items which contain either spaces or commas are surrounded by braces.
-% \end{function}
-%
-% \begin{function}[added = 2011-11-26]
-% {
-% \clist_const:Nn, \clist_const:Nx,
-% \clist_const:cn, \clist_const:cx
-% }
-% \begin{syntax}
-% \cs{clist_const:Nn} \meta{clist~var} \Arg{comma list}
-% \end{syntax}
-% Creates a new constant \meta{clist~var} or raises an error
-% if the name is already taken. The value of the
-% \meta{clist~var} will be set globally to the
-% \meta{comma list}.
-% \end{function}
-%
-% \begin{function}[EXP, pTF, added = 2011-12-07]{\clist_if_empty:n}
-% \begin{syntax}
-% \cs{clist_if_empty_p:n} \Arg{comma list}
-% \cs{clist_if_empty:nTF} \Arg{comma list} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Tests if the \meta{comma list} is empty (containing no items).
-% The rules for space trimming are as for other \texttt{n}-type
-% comma-list functions, hence the comma list |{~,~,,~}| (without
-% outer braces) is empty, while |{~,{},}| (without outer braces)
-% contains one element, which happens to be empty: the comma-list
-% is not empty.
-% \end{function}
-%
-% \section{Internal comma-list functions}
-%
-% \begin{function}[added = 2011-07-09, rEXP]{\clist_trim_spaces:n}
-% \begin{syntax}
-% \cs{clist_trim_spaces:n} \Arg{comma list}
-% \end{syntax}
-% Removes leading and trailing spaces from each \meta{item} in the
-% \meta{comma list}, leaving the resulting modified list in the
-% input stream. This is used by the functions which add data
-% into a comma list.
-% \end{function}
-%
% \end{documentation}
%
% \begin{implementation}
@@ -626,25 +563,36 @@
% \end{macrocode}
%
% \begin{macrocode}
+%<@@=clist>
+% \end{macrocode}
+%
+% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
-% \begin{variable}{\l_clist_internal_clist}
+% \begin{variable}{\c_empty_clist}
+% An empty comma list is simply an empty token list.
+% \begin{macrocode}
+\cs_new_eq:NN \c_empty_clist \c_empty_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_internal_clist}
% Scratch space for various internal uses. This comma list variable
% cannot be declared as such because it comes before \cs{clist_new:N}
% \begin{macrocode}
-\tl_new:N \l_clist_internal_clist
+\tl_new:N \l_@@_internal_clist
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}[aux]{\clist_tmp:w}
+% \begin{macro}[aux]{\@@_tmp:w}
% A temporary function for various purposes.
% \begin{macrocode}
-\cs_new_protected:Npn \clist_tmp:w { }
+\cs_new_protected:Npn \@@_tmp:w { }
% \end{macrocode}
% \end{macro}
%
@@ -714,16 +662,16 @@
% \UnitTested
% \begin{macro}{\clist_gconcat:NNN, \clist_gconcat:ccc}
% \UnitTested
-% \begin{macro}[aux]{\clist_concat_aux:NNNN}
-% Concatenating sequences is not quite as easy as it seems, as
+% \begin{macro}[aux]{\@@_concat:NNNN}
+% Concatenating comma lists is not quite as easy as it seems, as
% there needs to be the correct addition of a comma to the output. So
% a little work to do.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \clist_concat:NNN
- { \clist_concat_aux:NNNN \tl_set:Nx }
+ { \@@_concat:NNNN \tl_set:Nx }
\cs_new_protected_nopar:Npn \clist_gconcat:NNN
- { \clist_concat_aux:NNNN \tl_gset:Nx }
-\cs_new_protected:Npn \clist_concat_aux:NNNN #1#2#3#4
+ { \@@_concat:NNNN \tl_gset:Nx }
+\cs_new_protected:Npn \@@_concat:NNNN #1#2#3#4
{
#1 #2
{
@@ -755,73 +703,58 @@
%
% \subsection{Removing spaces around items}
%
-% \begin{macro}[int,EXP]{\clist_trim_spaces_generic:nw}
-% \begin{macro}[aux]{\clist_trim_spaces_generic_aux:w}
-% \begin{macro}[aux]{\clist_trim_spaces_generic_aux_ii:nn}
-% Used as `\cs{clist_trim_spaces_generic:nw} \Arg{code}
-% \cs{q_mark} \meta{item} |,|' (including the comma).
+% \begin{macro}[int,EXP]{\@@_trim_spaces_generic:nw}
+% \begin{macro}[aux]{\@@_trim_spaces_generic:nn}
+% \begin{syntax}
+% \cs{@@_trim_spaces_generic:nw} \Arg{code} \cs{q_mark} \meta{item} |,|
+% \end{syntax}
% This expands to the \meta{code}, followed by a brace group
-% containing the \meta{item}, with leading and trailing spaces removed.
-% The calling function is responsible for inserting \cs{q_mark}
-% in front of the \meta{item}, as well as testing for the end of the list.
-% See \cs{tl_trim_spaces:n} for a partial explanation of what
-% is happening here. We changed \cs{tl_trim_spaces_aux_iv:w}
-% into \cs{clist_trim_spaces_generic_aux:w} compared to
-% \cs{tl_trim_spaces:n}, and dropped a \cs{q_mark}, which is
-% already included in the argument |##2|.
+% containing the \meta{item}, with leading and trailing spaces
+% removed. The calling function is responsible for inserting
+% \cs{q_mark} in front of the \meta{item}, as well as testing for the
+% end of the list. We reuse a \pkg{l3tl} internal function, whose
+% first argument must start with \cs{q_mark}. That trims the item
+% |#2|, then feeds the result (after having to do an \texttt{o}-type
+% expansion) to \cs{@@_trim_spaces_generic:nn} which places the
+% \meta{code} in front of the \meta{trimmed item}.
% \begin{macrocode}
-\cs_set:Npn \clist_tmp:w #1
+\cs_new:Npn \@@_trim_spaces_generic:nw #1#2 ,
{
- \cs_new:Npn \clist_trim_spaces_generic:nw ##1 ##2 ,
- {
- \tl_trim_spaces_aux_i:w
- ##2
- \q_nil
- \q_mark #1 { }
- \q_mark \tl_trim_spaces_aux_ii:w
- \tl_trim_spaces_aux_iii:w
- #1 \q_nil
- \clist_trim_spaces_generic_aux:w
- \q_stop
- {##1}
- }
+ \__tl_trim_spaces:nn {#2}
+ { \exp_args:No \@@_trim_spaces_generic:nn } {#1}
}
-\clist_tmp:w {~}
-\cs_new:Npn \clist_trim_spaces_generic_aux:w #1 \q_nil #2 \q_stop
- { \exp_args:No \clist_trim_spaces_generic_aux_ii:nn { \use_none:n #1 } }
-\cs_new:Npn \clist_trim_spaces_generic_aux_ii:nn #1 #2 { #2 {#1} }
+\cs_new:Npn \@@_trim_spaces_generic:nn #1#2 { #2 {#1} }
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
%
-% \begin{macro}[int,rEXP]{\clist_trim_spaces:n}
-% \begin{macro}[aux]{\clist_trim_spaces_aux:nn}
-% The first argument of \cs{clist_trim_spaces_aux:nn} is initially empty,
+% \begin{macro}[int,rEXP]{\@@_trim_spaces:n}
+% \begin{macro}[aux]{\@@_trim_spaces_ii:nn}
+% The first argument of \cs{@@_trim_spaces_ii:nn} is initially empty,
% and later a comma, namely, as soon as we have added an item to the
% resulting list. The auxiliary tests for the end of the list,
% and also prevents empty arguments from finding their way into the
% output.
% \begin{macrocode}
-\cs_new:Npn \clist_trim_spaces:n #1
+\cs_new:Npn \@@_trim_spaces:n #1
{
- \clist_trim_spaces_generic:nw
- { \clist_trim_spaces_aux:nn { } }
+ \@@_trim_spaces_generic:nw
+ { \@@_trim_spaces_ii:nn { } }
\q_mark #1 ,
\q_recursion_tail, \q_recursion_stop
}
-\cs_new:Npn \clist_trim_spaces_aux:nn #1 #2
+\cs_new:Npn \@@_trim_spaces_ii:nn #1 #2
{
\quark_if_recursion_tail_stop:n {#2}
\tl_if_empty:nTF {#2}
{
- \clist_trim_spaces_generic:nw
- { \clist_trim_spaces_aux:nn {#1} } \q_mark
+ \@@_trim_spaces_generic:nw
+ { \@@_trim_spaces_ii:nn {#1} } \q_mark
}
{
#1 \exp_not:n {#2}
- \clist_trim_spaces_generic:nw
- { \clist_trim_spaces_aux:nn { , } } \q_mark
+ \@@_trim_spaces_generic:nw
+ { \@@_trim_spaces_ii:nn { , } } \q_mark
}
}
% \end{macrocode}
@@ -846,9 +779,9 @@
% }
% \begin{macrocode}
\cs_new_protected:Npn \clist_set:Nn #1#2
- { \tl_set:Nx #1 { \clist_trim_spaces:n {#2} } }
+ { \tl_set:Nx #1 { \@@_trim_spaces:n {#2} } }
\cs_new_protected:Npn \clist_gset:Nn #1#2
- { \tl_gset:Nx #1 { \clist_trim_spaces:n {#2} } }
+ { \tl_gset:Nx #1 { \@@_trim_spaces:n {#2} } }
\cs_generate_variant:Nn \clist_set:Nn { NV , No , Nx , c , cV , co , cx }
\cs_generate_variant:Nn \clist_gset:Nn { NV , No , Nx , c , cV , co , cx }
% \end{macrocode}
@@ -871,18 +804,18 @@
% \clist_gput_left:co, \clist_gput_left:cx
% }
% \UnitTested
-% \begin{macro}[aux]{\clist_put_left_aux:NNNn}
+% \begin{macro}[aux]{\@@_put_left:NNNn}
% Comma lists cannot hold empty values: there are therefore a couple
% of sanity checks to avoid accumulating commas.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \clist_put_left:Nn
- { \clist_put_left_aux:NNNn \clist_concat:NNN \clist_set:Nn }
+ { \@@_put_left:NNNn \clist_concat:NNN \clist_set:Nn }
\cs_new_protected_nopar:Npn \clist_gput_left:Nn
- { \clist_put_left_aux:NNNn \clist_gconcat:NNN \clist_set:Nn }
-\cs_new_protected:Npn \clist_put_left_aux:NNNn #1#2#3#4
+ { \@@_put_left:NNNn \clist_gconcat:NNN \clist_set:Nn }
+\cs_new_protected:Npn \@@_put_left:NNNn #1#2#3#4
{
- #2 \l_clist_internal_clist {#4}
- #1 #3 \l_clist_internal_clist #3
+ #2 \l_@@_internal_clist {#4}
+ #1 #3 \l_@@_internal_clist #3
}
\cs_generate_variant:Nn \clist_put_left:Nn { NV , No , Nx }
\cs_generate_variant:Nn \clist_put_left:Nn { c , cV , co , cx }
@@ -909,16 +842,16 @@
% \clist_gput_right:co, \clist_gput_right:cx
% }
% \UnitTested
-% \begin{macro}[aux]{\clist_put_right_aux:NNNn}
+% \begin{macro}[aux]{\@@_put_right:NNNn}
% \begin{macrocode}
\cs_new_protected_nopar:Npn \clist_put_right:Nn
- { \clist_put_right_aux:NNNn \clist_concat:NNN \clist_set:Nn }
+ { \@@_put_right:NNNn \clist_concat:NNN \clist_set:Nn }
\cs_new_protected_nopar:Npn \clist_gput_right:Nn
- { \clist_put_right_aux:NNNn \clist_gconcat:NNN \clist_gset:Nn }
-\cs_new_protected:Npn \clist_put_right_aux:NNNn #1#2#3#4
+ { \@@_put_right:NNNn \clist_gconcat:NNN \clist_gset:Nn }
+\cs_new_protected:Npn \@@_put_right:NNNn #1#2#3#4
{
- #2 \l_clist_internal_clist {#4}
- #1 #3 #3 \l_clist_internal_clist
+ #2 \l_@@_internal_clist {#4}
+ #1 #3 #3 \l_@@_internal_clist
}
\cs_generate_variant:Nn \clist_put_right:Nn { NV , No , Nx }
\cs_generate_variant:Nn \clist_put_right:Nn { c , cV , co , cx }
@@ -933,13 +866,19 @@
%
% \begin{macro}{\clist_get:NN, \clist_get:cN}
% \UnitTested
-% \begin{macro}[aux]{\clist_get_aux:wN}
+% \begin{macro}[aux]{\@@_get:wN}
% Getting an item from the left of a comma list is pretty easy: just
% trim off the first item using the comma.
% \begin{macrocode}
\cs_new_protected:Npn \clist_get:NN #1#2
- { \exp_after:wN \clist_get_aux:wN #1 , \q_stop #2 }
-\cs_new_protected:Npn \clist_get_aux:wN #1 , #2 \q_stop #3
+ {
+ \if_meaning:w #1 \c_empty_clist
+ \tl_set:Nn #2 { \q_no_value }
+ \else:
+ \exp_after:wN \@@_get:wN #1 , \q_stop #2
+ \fi:
+ }
+\cs_new_protected:Npn \@@_get:wN #1 , #2 \q_stop #3
{ \tl_set:Nn #3 {#1} }
\cs_generate_variant:Nn \clist_get:NN { c }
% \end{macrocode}
@@ -951,28 +890,39 @@
% \begin{macro}{\clist_gpop:NN, \clist_gpop:cN}
% \UnitTested
% \begin{macro}[aux]
-% {\clist_pop_aux:NNN, \clist_pop_aux:NwNNN, \clist_pop_aux:wNN}
-% The aim here is to get the popped item as |#1| in the auxiliary, with
-% |#2| containing either the remainder of the list \emph{or} \cs{q_nil}
-% if there were insufficient items. That keeps the number of auxiliary
-% functions down.
+% {\@@_pop:NNN, \@@_pop:wwNNN, \@@_pop:wN}
+% An empty clist leads to \cs{q_no_value}, otherwise grab until the
+% first comma and assign to the variable. The second argument of
+% \cs{@@_pop:wwNNN} is a comma list ending in a comma and
+% \cs{q_mark}, unless the original clist contained exactly one item:
+% then the argument is just \cs{q_mark}. The next auxiliary picks
+% either \cs{exp_not:n} or \cs{use_none:n} as |#2|, ensuring that the
+% result can safely be an empty comma list.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \clist_pop:NN
- { \clist_pop_aux:NNN \tl_set:Nf }
+ { \@@_pop:NNN \tl_set:Nx }
\cs_new_protected_nopar:Npn \clist_gpop:NN
- { \clist_pop_aux:NNN \tl_gset:Nf }
-\cs_new_protected:Npn \clist_pop_aux:NNN #1#2#3
+ { \@@_pop:NNN \tl_gset:Nx }
+\cs_new_protected:Npn \@@_pop:NNN #1#2#3
{
- \exp_after:wN \clist_pop_aux:wNNN #2 , \q_nil \q_stop #1#2#3
+ \if_meaning:w #2 \c_empty_clist
+ \tl_set:Nn #3 { \q_no_value }
+ \else:
+ \exp_after:wN \@@_pop:wwNNN #2 , \q_mark \q_stop #1#2#3
+ \fi:
}
-\cs_new_protected:Npn \clist_pop_aux:wNNN #1 , #2 \q_stop #3#4#5
+\cs_new_protected:Npn \@@_pop:wwNNN #1 , #2 \q_stop #3#4#5
{
\tl_set:Nn #5 {#1}
- \quark_if_nil:nTF {#2}
- { #3 #4 { } }
- { #3 #4 { \clist_pop_aux:w \exp_stop_f: #2 } }
+ #3 #4
+ {
+ \@@_pop:wN \prg_do_nothing:
+ #2 \exp_not:o
+ , \q_mark \use_none:n
+ \q_stop
+ }
}
-\cs_new_protected:Npn \clist_pop_aux:w #1 , \q_nil {#1}
+\cs_new:Npn \@@_pop:wN #1 , \q_mark #2 #3 \q_stop { #2 {#1} }
\cs_generate_variant:Nn \clist_pop:NN { c }
\cs_generate_variant:Nn \clist_gpop:NN { c }
% \end{macrocode}
@@ -980,6 +930,49 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}[TF]{\clist_get:NN, \clist_get:cN}
+% \begin{macro}[TF]{\clist_pop:NN, \clist_pop:cN}
+% \begin{macro}[TF]{\clist_gpop:NN, \clist_gpop:cN}
+% \begin{macro}[aux]{\@@_pop_TF:NNN}
+% The same, as branching code: very similar to the above.
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn \clist_get:NN #1#2 { T , F , TF }
+ {
+ \if_meaning:w #1 \c_empty_clist
+ \prg_return_false:
+ \else:
+ \exp_after:wN \@@_get:wN #1 , \q_stop #2
+ \prg_return_true:
+ \fi:
+ }
+\cs_generate_variant:Nn \clist_get:NNT { c }
+\cs_generate_variant:Nn \clist_get:NNF { c }
+\cs_generate_variant:Nn \clist_get:NNTF { c }
+\prg_new_protected_conditional:Npnn \clist_pop:NN #1#2 { T , F , TF }
+ { \@@_pop_TF:NNN \tl_set:Nx #1 #2 }
+\prg_new_protected_conditional:Npnn \clist_gpop:NN #1#2 { T , F , TF }
+ { \@@_pop_TF:NNN \tl_gset:Nx #1 #2 }
+\cs_new_protected:Npn \@@_pop_TF:NNN #1#2#3
+ {
+ \if_meaning:w #2 \c_empty_clist
+ \prg_return_false:
+ \else:
+ \exp_after:wN \@@_pop:wwNNN #2 , \q_mark \q_stop #1#2#3
+ \prg_return_true:
+ \fi:
+ }
+\cs_generate_variant:Nn \clist_pop:NNT { c }
+\cs_generate_variant:Nn \clist_pop:NNF { c }
+\cs_generate_variant:Nn \clist_pop:NNTF { c }
+\cs_generate_variant:Nn \clist_gpop:NNT { c }
+\cs_generate_variant:Nn \clist_gpop:NNF { c }
+\cs_generate_variant:Nn \clist_gpop:NNTF { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}{
% \clist_push:Nn, \clist_push:NV, \clist_push:No, \clist_push:Nx,
% \clist_push:cn, \clist_push:cV, \clist_push:co, \clist_push:cx
@@ -990,7 +983,7 @@
% \clist_gpush:cn, \clist_gpush:cV, \clist_gpush:co, \clist_gpush:cx
% }
% \UnitTested
-% Pushing to a sequence is the same as adding on the left.
+% Pushing to a comma list is the same as adding on the left.
% \begin{macrocode}
\cs_new_eq:NN \clist_push:Nn \clist_put_left:Nn
\cs_new_eq:NN \clist_push:NV \clist_put_left:NV
@@ -1012,23 +1005,12 @@
% \end{macro}
% \end{macro}
%
-% \subsection{Using comma lists}
-%
-% \begin{macro}{\clist_use:N, \clist_use:c}
-% \UnitTested
-% The approach is the same as for \cs{tl_use:N}.
-% \begin{macrocode}
-\cs_new_eq:NN \clist_use:N \tl_use:N
-\cs_new_eq:NN \clist_use:c \tl_use:c
-% \end{macrocode}
-% \end{macro}
-%
% \subsection{Modifying comma lists}
%
-% \begin{variable}{\l_clist_internal_remove_clist}
+% \begin{variable}{\l_@@_internal_remove_clist}
% An internal comma list for the removal routines.
% \begin{macrocode}
-\clist_new:N \l_clist_internal_remove_clist
+\clist_new:N \l_@@_internal_remove_clist
% \end{macrocode}
% \end{variable}
%
@@ -1036,22 +1018,22 @@
% \UnitTested
% \begin{macro}{\clist_gremove_duplicates:N, \clist_gremove_duplicates:c}
% \UnitTested
-% \begin{macro}[aux]{\clist_remove_duplicates_aux:NN}
+% \begin{macro}[aux]{\@@_remove_duplicates:NN}
% Removing duplicates means making a new list then copying it.
% \begin{macrocode}
\cs_new_protected:Npn \clist_remove_duplicates:N
- { \clist_remove_duplicates_aux:NN \clist_set_eq:NN }
+ { \@@_remove_duplicates:NN \clist_set_eq:NN }
\cs_new_protected:Npn \clist_gremove_duplicates:N
- { \clist_remove_duplicates_aux:NN \clist_gset_eq:NN }
-\cs_new_protected:Npn \clist_remove_duplicates_aux:NN #1#2
+ { \@@_remove_duplicates:NN \clist_gset_eq:NN }
+\cs_new_protected:Npn \@@_remove_duplicates:NN #1#2
{
- \clist_clear:N \l_clist_internal_remove_clist
+ \clist_clear:N \l_@@_internal_remove_clist
\clist_map_inline:Nn #2
{
- \clist_if_in:NnF \l_clist_internal_remove_clist {##1}
- { \clist_put_right:Nn \l_clist_internal_remove_clist {##1} }
+ \clist_if_in:NnF \l_@@_internal_remove_clist {##1}
+ { \clist_put_right:Nn \l_@@_internal_remove_clist {##1} }
}
- #1 #2 \l_clist_internal_remove_clist
+ #1 #2 \l_@@_internal_remove_clist
}
\cs_generate_variant:Nn \clist_remove_duplicates:N { c }
\cs_generate_variant:Nn \clist_gremove_duplicates:N { c }
@@ -1064,21 +1046,21 @@
% \UnitTested
% \begin{macro}{\clist_gremove_all:Nn, \clist_gremove_all:cn}
% \UnitTested
-% \begin{macro}[aux]{\clist_remove_all_aux:NNn}
-% \begin{macro}[aux]{\clist_remove_all_aux:w}
-% \begin{macro}[aux]{\clist_remove_all_aux:}
+% \begin{macro}[aux]{\@@_remove_all:NNn}
+% \begin{macro}[aux]{\@@_remove_all:w}
+% \begin{macro}[aux]{\@@_remove_all:}
% The method used here is very similar to \cs{tl_replace_all:Nnn}.
% Build a function delimited by the \meta{item} that should be removed,
% surrounded with commas, and call that function followed by
% the expanded comma list, and another copy of the \meta{item}.
% The loop is controlled by the argument grabbed by
-% \cs{clist_remove_all_aux:w}: when the item was found,
+% \cs{@@_remove_all:w}: when the item was found,
% the \cs{q_mark} delimiter used is the one inserted by
-% \cs{clist_tmp:w}, and \cs{use_none_delimit_by_q_stop:w}
+% \cs{@@_tmp:w}, and \cs{use_none_delimit_by_q_stop:w}
% is deleted. At the end, the final \meta{item} is
-% grabbed, and the argument of \cs{clist_tmp:w} contains
-% \cs{q_mark}: in that case, \cs{clist_remove_all_aux:w}
-% removes the second \cs{q_mark} (inserted by \cs{clist_tmp:w}),
+% grabbed, and the argument of \cs{@@_tmp:w} contains
+% \cs{q_mark}: in that case, \cs{@@_remove_all:w}
+% removes the second \cs{q_mark} (inserted by \cs{@@_tmp:w}),
% and lets \cs{use_none_delimit_by_q_stop:w} act.
%
% No brace is lost because items are always grabbed with a leading comma.
@@ -1090,20 +1072,20 @@
% the second step removes it.
% \begin{macrocode}
\cs_new_protected:Npn \clist_remove_all:Nn
- { \clist_remove_all_aux:NNn \tl_set:Nx }
+ { \@@_remove_all:NNn \tl_set:Nx }
\cs_new_protected:Npn \clist_gremove_all:Nn
- { \clist_remove_all_aux:NNn \tl_gset:Nx }
-\cs_new_protected:Npn \clist_remove_all_aux:NNn #1#2#3
+ { \@@_remove_all:NNn \tl_gset:Nx }
+\cs_new_protected:Npn \@@_remove_all:NNn #1#2#3
{
- \cs_set:Npn \clist_tmp:w ##1 , #3 ,
+ \cs_set:Npn \@@_tmp:w ##1 , #3 ,
{
##1
, \q_mark , \use_none_delimit_by_q_stop:w ,
- \clist_remove_all_aux:
+ \@@_remove_all:
}
#1 #2
{
- \exp_after:wN \clist_remove_all_aux:
+ \exp_after:wN \@@_remove_all:
#2 , \q_mark , #3 , \q_stop
}
\clist_if_empty:NF #2
@@ -1115,9 +1097,9 @@
}
}
}
-\cs_new:Npn \clist_remove_all_aux:
- { \exp_after:wN \clist_remove_all_aux:w \clist_tmp:w , }
-\cs_new:Npn \clist_remove_all_aux:w #1 , \q_mark , #2 , { \exp_not:n {#1} }
+\cs_new:Npn \@@_remove_all:
+ { \exp_after:wN \@@_remove_all:w \@@_tmp:w , }
+\cs_new:Npn \@@_remove_all:w #1 , \q_mark , #2 , { \exp_not:n {#1} }
\cs_generate_variant:Nn \clist_remove_all:Nn { c }
\cs_generate_variant:Nn \clist_gremove_all:Nn { c }
% \end{macrocode}
@@ -1138,43 +1120,31 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[pTF]
-% {\clist_if_eq:NN, \clist_if_eq:Nc, \clist_if_eq:cN, \clist_if_eq:cc}
-% \UnitTested
-% Simple copies from the token list variable material.
-% \begin{macrocode}
-\prg_new_eq_conditional:NNn \clist_if_eq:NN \tl_if_eq:NN { p , T , F , TF }
-\prg_new_eq_conditional:NNn \clist_if_eq:Nc \tl_if_eq:Nc { p , T , F , TF }
-\prg_new_eq_conditional:NNn \clist_if_eq:cN \tl_if_eq:cN { p , T , F , TF }
-\prg_new_eq_conditional:NNn \clist_if_eq:cc \tl_if_eq:cc { p , T , F , TF }
-% \end{macrocode}
-% \end{macro}
-%
% \begin{macro}[TF]
% {
% \clist_if_in:Nn, \clist_if_in:NV, \clist_if_in:No,
% \clist_if_in:cn, \clist_if_in:cV, \clist_if_in:co,
% \clist_if_in:nn, \clist_if_in:nV, \clist_if_in:no
% }
-% \begin{macro}[aux]{\clist_if_in_return:nn}
+% \begin{macro}[aux]{\@@_if_in_return:nn}
% \UnitTested
% See description of the \cs{tl_if_in:Nn} function for details.
% We simply surround the comma list, and the item, with commas.
% \begin{macrocode}
\prg_new_protected_conditional:Npnn \clist_if_in:Nn #1#2 { T , F , TF }
{
- \exp_args:No \clist_if_in_return:nn #1 {#2}
+ \exp_args:No \@@_if_in_return:nn #1 {#2}
}
\prg_new_protected_conditional:Npnn \clist_if_in:nn #1#2 { T , F , TF }
{
- \clist_set:Nn \l_clist_internal_clist {#1}
- \exp_args:No \clist_if_in_return:nn \l_clist_internal_clist {#2}
+ \clist_set:Nn \l_@@_internal_clist {#1}
+ \exp_args:No \@@_if_in_return:nn \l_@@_internal_clist {#2}
}
-\cs_new_protected:Npn \clist_if_in_return:nn #1#2
+\cs_new_protected:Npn \@@_if_in_return:nn #1#2
{
- \cs_set:Npn \clist_tmp:w ##1 ,#2, { }
+ \cs_set:Npn \@@_tmp:w ##1 ,#2, { }
\tl_if_empty:oTF
- { \clist_tmp:w ,#1, {} {} ,#2, }
+ { \@@_tmp:w ,#1, {} {} ,#2, }
{ \prg_return_false: } { \prg_return_true: }
}
\cs_generate_variant:Nn \clist_if_in:NnT { NV , No }
@@ -1194,28 +1164,28 @@
%
% \begin{macro}{\clist_map_function:NN, \clist_map_function:cN}
% \UnitTested
-% \begin{macro}[aux]{\clist_map_function_aux:Nw}
+% \begin{macro}[aux]{\@@_map_function:Nw}
% If the variable is empty, the mapping is skipped (otherwise,
% that comma-list would be seen as consisting of one empty item).
% Then loop over the comma-list, grabbing one comma-delimited
% item at a time. The end is marked by \cs{q_recursion_tail}.
-% The auxiliary function \cs{clist_map_function_aux:Nw} is used
+% The auxiliary function \cs{@@_map_function:Nw} is used
% directly in \cs{clist_map_inline:Nn}. Change with care.
% \begin{macrocode}
\cs_new:Npn \clist_map_function:NN #1#2
{
\clist_if_empty:NF #1
{
- \exp_last_unbraced:NNo \clist_map_function_aux:Nw #2 #1
+ \exp_last_unbraced:NNo \@@_map_function:Nw #2 #1
, \q_recursion_tail ,
- \prg_break_point:n { }
+ \__prg_break_point:Nn \clist_map_break: { }
}
}
-\cs_new:Npn \clist_map_function_aux:Nw #1#2 ,
+\cs_new:Npn \@@_map_function:Nw #1#2 ,
{
- \quark_if_recursion_tail_break:n {#2}
+ \__quark_if_recursion_tail_break:nN {#2} \clist_map_break:
#1 {#2}
- \clist_map_function_aux:Nw #1
+ \@@_map_function:Nw #1
}
\cs_generate_variant:Nn \clist_map_function:NN { c }
% \end{macrocode}
@@ -1224,31 +1194,31 @@
%
% \begin{macro}{\clist_map_function:nN}
% \UnitTested
-% \begin{macro}[aux]{\clist_map_function_n_aux:Nn}
-% \begin{macro}{\clist_map_aux_unbrace:Nw}
+% \begin{macro}[aux]{\@@_map_function_n:Nn}
+% \begin{macro}[aux]{\@@_map_unbrace:Nw}
% The \texttt{n}-type mapping function is a bit more awkward,
-% since spaces mustbe trimmed from each item.
-% Space trimming is again based on \cs{clist_trim_spaces_generic:nw}.
-% The auxiliary \cs{clist_map_function_n_aux:Nn} receives
+% since spaces must be trimmed from each item.
+% Space trimming is again based on \cs{@@_trim_spaces_generic:nw}.
+% The auxiliary \cs{@@_map_function_n:Nn} receives
% as arguments the function, and the result of removing leading
% and trailing spaces from the item which lies until the next comma.
% Empty items are ignored, then one level of braces is removed
-% by \cs{clist_map_aux_unbrace:Nw}.
+% by \cs{@@_map_unbrace:Nw}.
% \begin{macrocode}
\cs_new:Npn \clist_map_function:nN #1#2
{
- \clist_trim_spaces_generic:nw { \clist_map_function_n_aux:Nn #2 }
+ \@@_trim_spaces_generic:nw { \@@_map_function_n:Nn #2 }
\q_mark #1, \q_recursion_tail,
- \prg_break_point:n { }
+ \__prg_break_point:Nn \clist_map_break: { }
}
-\cs_new:Npn \clist_map_function_n_aux:Nn #1 #2
+\cs_new:Npn \@@_map_function_n:Nn #1 #2
{
- \quark_if_recursion_tail_break:n {#2}
- \tl_if_empty:nF {#2} { \clist_map_aux_unbrace:Nw #1 #2, }
- \clist_trim_spaces_generic:nw { \clist_map_function_n_aux:Nn #1 }
+ \__quark_if_recursion_tail_break:nN {#2} \clist_map_break:
+ \tl_if_empty:nF {#2} { \@@_map_unbrace:Nw #1 #2, }
+ \@@_trim_spaces_generic:nw { \@@_map_function_n:Nn #1 }
\q_mark
}
-\cs_new:Npn \clist_map_aux_unbrace:Nw #1 #2, { #1 {#2} }
+\cs_new:Npn \@@_map_unbrace:Nw #1 #2, { #1 {#2} }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1274,18 +1244,19 @@
{
\clist_if_empty:NF #1
{
- \int_gincr:N \g_prg_map_int
- \cs_gset:cpn { clist_map_ \int_use:N \g_prg_map_int :n } ##1 {#2}
- \exp_last_unbraced:Nco \clist_map_function_aux:Nw
- { clist_map_ \int_use:N \g_prg_map_int :n }
+ \int_gincr:N \g__prg_map_int
+ \cs_gset:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2}
+ \exp_last_unbraced:Nco \@@_map_function:Nw
+ { __prg_map_ \int_use:N \g__prg_map_int :w }
#1 , \q_recursion_tail ,
- \prg_break_point:n { \int_gdecr:N \g_prg_map_int }
+ \__prg_break_point:Nn \clist_map_break:
+ { \int_gdecr:N \g__prg_map_int }
}
}
\cs_new_protected:Npn \clist_map_inline:nn #1
{
- \clist_set:Nn \l_clist_internal_clist {#1}
- \clist_map_inline:Nn \l_clist_internal_clist
+ \clist_set:Nn \l_@@_internal_clist {#1}
+ \clist_map_inline:Nn \l_@@_internal_clist
}
\cs_generate_variant:Nn \clist_map_inline:Nn { c }
% \end{macrocode}
@@ -1295,7 +1266,7 @@
% \begin{macro}{\clist_map_variable:NNn, \clist_map_variable:cNn}
% \UnitTested
% \begin{macro}{\clist_map_variable:nNn}
-% \begin{macro}[aux]{\clist_map_variable_aux:Nnw}
+% \begin{macro}[aux]{\@@_map_variable:Nnw}
% As for other comma-list mappings, filter out the case of
% an empty list. Same approach as \cs{clist_map_function:Nn},
% additionally we store each item in the given variable.
@@ -1307,23 +1278,23 @@
\clist_if_empty:NF #1
{
\exp_args:Nno \use:nn
- { \clist_map_variable_aux:Nnw #2 {#3} }
+ { \@@_map_variable:Nnw #2 {#3} }
#1
, \q_recursion_tail , \q_recursion_stop
- \prg_break_point:n { }
+ \__prg_break_point:Nn \clist_map_break: { }
}
}
\cs_new_protected:Npn \clist_map_variable:nNn #1
{
- \clist_set:Nn \l_clist_internal_clist {#1}
- \clist_map_variable:NNn \l_clist_internal_clist
+ \clist_set:Nn \l_@@_internal_clist {#1}
+ \clist_map_variable:NNn \l_@@_internal_clist
}
-\cs_new_protected:Npn \clist_map_variable_aux:Nnw #1#2#3,
+\cs_new_protected:Npn \@@_map_variable:Nnw #1#2#3,
{
\tl_set:Nn #1 {#3}
\quark_if_recursion_tail_stop:N #1
\use:n {#2}
- \clist_map_variable_aux:Nnw #1 {#2}
+ \@@_map_variable:Nnw #1 {#2}
}
\cs_generate_variant:Nn \clist_map_variable:NNn { c }
% \end{macrocode}
@@ -1331,293 +1302,99 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\clist_map_break:}
-% \begin{macro}{\clist_map_break:n}
-% The break statements are simply copies.
+% \begin{macro}{\clist_map_break:, \clist_map_break:n}
+% The break statements use the general \cs{__prg_map_break:Nn} mechanism.
% \begin{macrocode}
-\cs_new_eq:NN \clist_map_break: \prg_map_break:
-\cs_new_eq:NN \clist_map_break:n \prg_map_break:n
+\cs_new_nopar:Npn \clist_map_break:
+ { \__prg_map_break:Nn \clist_map_break: { } }
+\cs_new_nopar:Npn \clist_map_break:n
+ { \__prg_map_break:Nn \clist_map_break: }
% \end{macrocode}
% \end{macro}
-% \end{macro}
-%
-% \subsection{Viewing comma lists}
-%
-% \begin{macro}{\clist_show:N, \clist_show:c}
-% \begin{macro}{\clist_show:n}
-% Apply the general \cs{msg_aux_show:Nnx}. In the case
-% of an \texttt{n}-type comma-list, first store it
-% in a scratch variable, then show that variable,
-% omitting its name from the $4$-th argument.
-% \begin{macrocode}
-\cs_new_protected:Npn \clist_show:N #1
- {
- \msg_aux_show:Nnx
- #1
- { clist }
- { \clist_map_function:NN #1 \msg_aux_show:n }
- }
-\cs_new_protected:Npn \clist_show:n #1
- {
- \clist_set:Nn \l_clist_internal_clist {#1}
- \msg_aux_show:Nnx
- \l_clist_internal_clist
- { clist }
- { \clist_map_function:NN \l_clist_internal_clist \msg_aux_show:n }
- }
-\cs_generate_variant:Nn \clist_show:N { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Scratch comma lists}
-%
-% \begin{variable}{\l_tmpa_clist, \l_tmpb_clist}
-% \begin{variable}{\g_tmpa_clist, \g_tmpb_clist}
-% Temporary comma list variables.
-% \begin{macrocode}
-\clist_new:N \l_tmpa_clist
-\clist_new:N \l_tmpb_clist
-\clist_new:N \g_tmpa_clist
-\clist_new:N \g_tmpb_clist
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-%
-% \subsection{Experimental functions}
-%
-% \begin{macro}{\clist_length:N, \clist_length:c}
-% \begin{macro}{\clist_length:n}
-% \begin{macro}[aux]{\clist_length_aux:w}
+%
+% \begin{macro}{\clist_count:N, \clist_count:c, \clist_count:n}
+% \begin{macro}[aux]{\@@_count:n}
+% \begin{macro}[aux]{\@@_count:w}
% Counting the items in a comma list is done using the same approach as for
-% other length functions: turn each entry into a \texttt{+1} then use
+% other token count functions: turn each entry into a \texttt{+1} then use
% integer evaluation to actually do the mathematics.
% In the case of an \texttt{n}-type comma-list, we could of course use
% \cs{clist_map_function:nN}, but that is very slow, because it carefully
% removes spaces. Instead, we loop manually, and skip blank items
% (but not |{}|, hence the extra spaces).
% \begin{macrocode}
-\cs_new:Npn \clist_length:N #1
+\cs_new:Npn \clist_count:N #1
{
\int_eval:n
{
0
- \clist_map_function:NN #1 \clist_length_aux:n
+ \clist_map_function:NN #1 \@@_count:n
}
}
-\cs_new:Npn \clist_length_aux:n #1 { +1 }
-\cs_new:Npx \clist_length:n #1
+\cs_generate_variant:Nn \clist_count:N { c }
+\cs_new:Npx \clist_count:n #1
{
\exp_not:N \int_eval:n
{
0
- \exp_not:N \clist_length_n_aux:w \c_space_tl
+ \exp_not:N \@@_count:w \c_space_tl
#1 \exp_not:n { , \q_recursion_tail , \q_recursion_stop }
}
}
-\cs_new:Npx \clist_length_n_aux:w #1 ,
+\cs_new:Npn \@@_count:n #1 { + \c_one }
+\cs_new:Npx \@@_count:w #1 ,
{
\exp_not:n { \exp_args:Nf \quark_if_recursion_tail_stop:n } {#1}
\exp_not:N \tl_if_blank:nF {#1} { + \c_one }
- \exp_not:N \clist_length_n_aux:w \c_space_tl
+ \exp_not:N \@@_count:w \c_space_tl
}
-\cs_generate_variant:Nn \clist_length:N { c }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\clist_item:Nn, \clist_item:cn}
-% \begin{macro}[aux]{\clist_item_aux:nnNn}
-% \begin{macro}[aux]{\clist_item_N_loop:nw}
-% To avoid needing to test the end of the list at each step,
-% we first compute the \meta{length} of the list. If the item number
-% is less than $-\meta{length}$ or more than $\meta{length}-1$,
-% the result is empty. If it is negative, but not less than $-\meta{length}$,
-% add the \meta{length} to the item number before performing the loop.
-% The loop itself is very simple, return the item if the counter
-% reached zero, otherwise, decrease the counter and repeat.
-% \begin{macrocode}
-\cs_new:Npn \clist_item:Nn #1#2
- {
- \exp_args:Nfo \clist_item_aux:nnNn
- { \clist_length:N #1 }
- #1
- \clist_item_N_loop:nw
- {#2}
- }
-\cs_new:Npn \clist_item_aux:nnNn #1#2#3#4
- {
- \int_compare:nNnTF {#4} < \c_zero
- {
- \int_compare:nNnTF {#4} < { - #1 }
- { \use_none_delimit_by_q_stop:w }
- { \exp_args:Nf #3 { \int_eval:n { #4 + #1 } } }
- }
- {
- \int_compare:nNnTF {#4} < {#1}
- { #3 {#4} }
- { \use_none_delimit_by_q_stop:w }
- }
- #2, \q_stop
- }
-\cs_new:Npn \clist_item_N_loop:nw #1 #2,
- {
- \int_compare:nNnTF {#1} = \c_zero
- { \use_i_delimit_by_q_stop:nw { \exp_not:n {#2} } }
- { \exp_args:Nf \clist_item_N_loop:nw { \int_eval:n { #1 - 1 } } }
- }
-\cs_generate_variant:Nn \clist_item:Nn { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\clist_item:nn}
-% \begin{macro}[aux]{
-% \clist_item_n_aux:nw,
-% \clist_item_n_loop:nw,
-% \clist_item_n_end:n,
-% \clist_item_n_strip:w}
-% This starts in the same way as \cs{clist_item:Nn} by checking the length
-% of the comma list. The final item should be space-trimmed before being
-% brace-stripped, hence we insert a couple of odd-looking
-% \cs{prg_do_nothing:} to avoid losing braces. Blank items are ignored.
-% \begin{macrocode}
-\cs_new:Npn \clist_item:nn #1#2
- {
- \exp_args:Nf \clist_item_aux:nnNn
- { \clist_length:n {#1} }
- {#1}
- \clist_item_n_aux:nw
- {#2}
- }
-\cs_new:Npn \clist_item_n_aux:nw #1
- { \clist_item_n_loop:nw {#1} \prg_do_nothing: }
-\cs_new:Npn \clist_item_n_loop:nw #1 #2,
- {
- \exp_args:No \tl_if_blank:nTF {#2}
- { \clist_item_n_loop:nw {#1} \prg_do_nothing: }
- {
- \int_compare:nNnTF {#1} = \c_zero
- { \exp_args:No \clist_item_n_end:n {#2} }
- {
- \exp_args:Nf \clist_item_n_loop:nw
- { \int_eval:n { #1 - 1 } }
- \prg_do_nothing:
- }
- }
- }
-\cs_new:Npn \clist_item_n_end:n #1 #2 \q_stop
- {
- \exp_after:wN \exp_after:wN \exp_after:wN \clist_item_n_strip:w
- \tl_trim_spaces:n {#1} ,
- }
-\cs_new:Npn \clist_item_n_strip:w #1 , { \exp_not:n {#1} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
+% \subsection{Viewing comma lists}
%
-% \begin{macro}
-% {
-% \clist_set_from_seq:NN, \clist_set_from_seq:cN,
-% \clist_set_from_seq:Nc, \clist_set_from_seq:cc
-% }
-% \UnitTested
-% \begin{macro}
-% {
-% \clist_gset_from_seq:NN, \clist_gset_from_seq:cN,
-% \clist_gset_from_seq:Nc, \clist_gset_from_seq:cc
-% }
-% \UnitTested
-% \begin{macro}[aux]{\clist_set_from_seq_aux:NNNN}
-% \begin{macro}[aux]{\clist_wrap_item:n}
-% Setting a comma list from a comma-separated list is done using a simple
-% mapping. We wrap most items with \cs{exp_not:n}, and a comma. Items which
-% contain a comma or a space are surrounded by an extra set of braces. The
-% first comma must be removed, except in the case of an empty comma-list.
+% \begin{macro}{\clist_show:N, \clist_show:c}
+% \begin{macro}{\clist_show:n}
+% Apply the general \cs{__msg_show_variable:Nnn}. In the case
+% of an \texttt{n}-type comma-list, first store it
+% in a scratch variable, then show that variable,
+% omitting its name from the $4$-th argument.
% \begin{macrocode}
-\cs_new_protected:Npn \clist_set_from_seq:NN
- { \clist_set_from_seq_aux:NNNN \clist_clear:N \tl_set:Nx }
-\cs_new_protected:Npn \clist_gset_from_seq:NN
- { \clist_set_from_seq_aux:NNNN \clist_gclear:N \tl_gset:Nx }
-\cs_new_protected:Npn \clist_set_from_seq_aux:NNNN #1#2#3#4
+\cs_new_protected:Npn \clist_show:N #1
{
- \seq_if_empty:NTF #4
- { #1 #3 }
- {
- #2 #3
- {
- \exp_last_unbraced:Nf \use_none:n
- { \seq_map_function:NN #4 \clist_wrap_item:n }
- }
- }
+ \__msg_show_variable:Nnn
+ #1
+ { clist }
+ { \clist_map_function:NN #1 \__msg_show_item:n }
}
-\cs_new:Npn \clist_wrap_item:n #1
+\cs_new_protected:Npn \clist_show:n #1
{
- ,
- \tl_if_empty:oTF { \clist_set_from_seq_aux:w #1 ~ , #1 ~ }
- { \exp_not:n {#1} }
- { \exp_not:n { {#1} } }
+ \clist_set:Nn \l_@@_internal_clist {#1}
+ \__msg_show_variable:Nnn
+ \l_@@_internal_clist
+ { clist }
+ { \clist_map_function:NN \l_@@_internal_clist \__msg_show_item:n }
}
-\cs_new:Npn \clist_set_from_seq_aux:w #1 , #2 ~ { }
-\cs_generate_variant:Nn \clist_set_from_seq:NN { Nc }
-\cs_generate_variant:Nn \clist_set_from_seq:NN { c , cc }
-\cs_generate_variant:Nn \clist_gset_from_seq:NN { Nc }
-\cs_generate_variant:Nn \clist_gset_from_seq:NN { c , cc }
+\cs_generate_variant:Nn \clist_show:N { c }
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
%
-% \begin{macro}
-% {
-% \clist_const:Nn, \clist_const:cn,
-% \clist_const:Nx, \clist_const:cx
-% }
-% Creating and initializing a constant comma list is done in a way
-% similar to \cs{clist_set:Nn} and \cs{clist_gset:Nn}, being careful
-% to strip spaces.
-% \begin{macrocode}
-\cs_new_protected:Npn \clist_const:Nn #1#2
- { \tl_const:Nx #1 { \clist_trim_spaces:n {#2} } }
-\cs_generate_variant:Nn \clist_const:Nn { c , Nx , cx }
-% \end{macrocode}
-% \end{macro}
+% \subsection{Scratch comma lists}
%
-% \begin{macro}[EXP, pTF]{\clist_if_empty:n}
-% \begin{macro}[aux, EXP]{\clist_if_empty_n_aux:w}
-% \begin{macro}[aux, EXP]{\clist_if_empty_n_aux:wNw}
-% As usual, we insert a token (here |?|) before grabbing
-% any argument: this avoids losing braces. The argument
-% of \cs{tl_if_empty:oTF} is empty if |#1| is |?| followed
-% by blank spaces (besides, this particular variant of
-% the emptyness test is optimized). If the item of the
-% comma list is blank, grab the next one. As soon as one
-% item is non-blank, exit: the second auxiliary will grab
-% \cs{prg_return_false:} as |#2|, unless every item in
-% the comma list was blank and the loop actually got broken
-% by the trailing |\q_mark \prg_return_false:| item.
+% \begin{variable}{\l_tmpa_clist, \l_tmpb_clist}
+% \begin{variable}{\g_tmpa_clist, \g_tmpb_clist}
+% Temporary comma list variables.
% \begin{macrocode}
-\prg_new_conditional:Npnn \clist_if_empty:n #1 { p , T , F , TF }
- {
- \clist_if_empty_n_aux:w ? #1
- , \q_mark \prg_return_false:
- , \q_mark \prg_return_true:
- \q_stop
- }
-\cs_new:Npn \clist_if_empty_n_aux:w #1 ,
- {
- \tl_if_empty:oTF { \use_none:nn #1 ? }
- { \clist_if_empty_n_aux:w ? }
- { \clist_if_empty_n_aux:wNw }
- }
-\cs_new:Npn \clist_if_empty_n_aux:wNw #1 \q_mark #2#3 \q_stop {#2}
+\clist_new:N \l_tmpa_clist
+\clist_new:N \l_tmpb_clist
+\clist_new:N \g_tmpa_clist
+\clist_new:N \g_tmpb_clist
% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+% \end{variable}
+% \end{variable}
%
% \subsection{Deprecated interfaces}
%
@@ -1664,7 +1441,7 @@
% }
% Since clist items are now always stripped from their surrounding
% spaces, it is redundant to provide these functions.
-% The \cs{clist_trim_spaces:n} function is now internal,
+% The \cs{@@_trim_spaces:n} function is now internal,
% deprecated for use outside the kernel.
% \begin{macrocode}
%<*deprecated>
@@ -1676,6 +1453,38 @@
% \end{macrocode}
% \end{macro}
%
+% Deprecated on 2012-05-10, for removal by 2012-08-31.
+%
+% \begin{macro}[pTF]
+% {\clist_if_eq:NN, \clist_if_eq:Nc, \clist_if_eq:cN, \clist_if_eq:cc}
+% Simple copies from the token list variable material.
+% \begin{macrocode}
+\prg_new_eq_conditional:NNn \clist__if_eq:NN \tl_if_eq:NN { p , T , F , TF }
+\prg_new_eq_conditional:NNn \clist_if_eq:Nc \tl_if_eq:Nc { p , T , F , TF }
+\prg_new_eq_conditional:NNn \clist_if_eq:cN \tl_if_eq:cN { p , T , F , TF }
+\prg_new_eq_conditional:NNn \clist_if_eq:cc \tl_if_eq:cc { p , T , F , TF }
+% \end{macrocode}
+% \end{macro}
+%
+% Deprecated 2012-05-13 for removal by 2012-11-31.
+%
+% \begin{macro}{\clist_length:N, \clist_length:c, \clist_length:n}
+% \begin{macrocode}
+\cs_new_eq:NN \clist_length:N \clist_count:N
+\cs_new_eq:NN \clist_length:n \clist_count:c
+\cs_new_eq:NN \clist_length:c \clist_count:n
+% \end{macrocode}
+% \end{macro}
+%
+% Deprecated 2012-05-19 for removal by 2012-11-31.
+%
+% \begin{macro}{\clist_use:N, \clist_use:c}
+% \begin{macrocode}
+\cs_new_eq:NN \clist_use:N \tl_use:N
+\cs_new_eq:NN \clist_use:c \tl_use:c
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
index 54575bde8ce..b4242b6d8ed 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3coffins.dtx
@@ -36,8 +36,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3coffins.dtx 3482 2012-03-03 18:48:06Z bruno $
- {L3 Experimental coffin code layer}
+\GetIdInfo$Id: l3coffins.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Coffin code layer}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -94,10 +94,19 @@
% \begin{function}[added = 2011-08-17]
% {\coffin_set_eq:NN, \coffin_set_eq:Nc, \coffin_set_eq:cN, \coffin_set_eq:cc}
% \begin{syntax}
-% \cs{coffin_set_eq:NN} \meta{coffin1} \meta{coffin2}
+% \cs{coffin_set_eq:NN} \meta{coffin_1} \meta{coffin_2}
% \end{syntax}
-% Sets both the content and poles of \meta{coffin1} equal to those
-% of \meta{coffin2} within the current \TeX\ group level.
+% Sets both the content and poles of \meta{coffin_1} equal to those
+% of \meta{coffin_2} within the current \TeX\ group level.
+% \end{function}
+%
+% \begin{function}[EXP, pTF, added = 2012-06-20]
+% {\coffin_if_exist:N, \coffin_if_exist:c}
+% \begin{syntax}
+% \cs{coffin_if_exist_p:N} \meta{box}
+% \cs{coffin_if_exist:NTF} \meta{box} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests whether the \meta{coffin} is currently defined.
% \end{function}
%
% \section{Setting coffin content and poles}
@@ -127,7 +136,7 @@
% environment in a coffin.
% \end{function}
%
-% \begin{function}[added = 2011-08-17, updated = 2011-09-03]
+% \begin{function}[added = 2011-08-17, updated = 2012-05-22]
% {\vcoffin_set:Nnn, \vcoffin_set:cnn}
% \begin{syntax}
% \cs{vcoffin_set:Nnn} \meta{coffin} \Arg{width} \Arg{material}
@@ -138,7 +147,7 @@
% size of the typeset material.
% \end{function}
%
-% \begin{function}[added = 2011-09-10]
+% \begin{function}[added = 2011-09-10, updated = 2012-05-22]
% {\vcoffin_set:Nnw, \vcoffin_set:cnw, \vcoffin_set_end:}
% \begin{syntax}
% \cs{vcoffin_set:Nnw} \meta{coffin} \Arg{width} \meta{material} \cs{vcoffin_set_end:}
@@ -180,42 +189,6 @@
% the \meta{coffin}.
% \end{function}
%
-% \section{Coffin transformations}
-%
-% \begin{function}[added = 2011-09-02]{\coffin_resize:Nnn, \coffin_resize:cnn}
-% \begin{syntax}
-% \cs{coffin_resize:Nnn} \meta{coffin} \Arg{width} \Arg{total-height}
-% \end{syntax}
-% Resized the \meta{coffin} to \meta{width} and \meta{total-height},
-% both of which should be given as dimension expressions. These may
-% include the terms \cs{TotalHeight}, \cs{Height}, \cs{Depth} and
-% \cs{Width}, which will evaluate to the appropriate dimensions of
-% the \meta{coffin}.
-%
-% \textbf{This function is experimental.}
-% \end{function}
-%
-% \begin{function}[added = 2011-09-02]{\coffin_rotate:Nn, \coffin_rotate:cn}
-% \begin{syntax}
-% \cs{coffin_rotate:Nn} \meta{coffin} \Arg{angle}
-% \end{syntax}
-% Rotates the \meta{coffin} by the given \meta{angle} (given in
-% degrees counter-clockwise). This process will rotate both the
-% coffin content and poles. Multiple rotations will not result in
-% the bounding box of the coffin growing unnecessarily.
-% \end{function}
-%
-% \begin{function}[added = 2011-09-02]{\coffin_scale:Nnn, \coffin_scale:cnn}
-% \begin{syntax}
-% \cs{coffin_scale:Nnn} \meta{coffin} \Arg{x-scale} \Arg{y-scale}
-% \end{syntax}
-% Scales the \meta{coffin} by a factors \meta{x-scale} and
-% \meta{y-scale} in the horizontal and vertical directions,
-% respectively. The two scale factors should be given as real numbers.
-%
-% \textbf{This function is experimental.}
-% \end{function}
-%
% \section{Joining and using coffins}
%
% \begin{function}
@@ -225,19 +198,19 @@
% }
% \begin{syntax}
% \cs{coffin_attach:NnnNnnnn}
-% ~~\meta{coffin1} \Arg{coffin1-pole1} \Arg{coffin1-pole2}
-% ~~\meta{coffin2} \Arg{coffin2-pole1} \Arg{coffin2-pole2}
+% ~~\meta{coffin_1} \Arg{coffin_1-pole_1} \Arg{coffin_1-pole_2}
+% ~~\meta{coffin_2} \Arg{coffin_2-pole_1} \Arg{coffin_2-pole_2}
% ~~\Arg{x-offset} \Arg{y-offset}
% \end{syntax}
% This function attaches <coffin_2> to <coffin_1> such that the bounding box
-% of \meta{coffin1} is not altered, \emph{i.e.}~\meta{coffin2} can
+% of \meta{coffin_1} is not altered, \emph{i.e.}~\meta{coffin_2} can
% protrude outside of the bounding box of the coffin. The alignment
-% is carried out by first calculating \meta{handle1}, the
-% point of intersection of \meta{coffin1-pole1} and
-% \meta{coffin1-pole2}, and \meta{handle2}, the point of intersection
-% of \meta{coffin2-pole1} and \meta{coffin2-pole2}. \meta{coffin2} is
-% then attached to \meta{coffin1} such that the relationship between
-% \meta{handle1} and \meta{handle2} is described by the \meta{x-offset}
+% is carried out by first calculating \meta{handle_1}, the
+% point of intersection of \meta{coffin_1-pole_1} and
+% \meta{coffin_1-pole_2}, and \meta{handle_2}, the point of intersection
+% of \meta{coffin_2-pole_1} and \meta{coffin_2-pole_2}. \meta{coffin_2} is
+% then attached to \meta{coffin_1} such that the relationship between
+% \meta{handle_1} and \meta{handle_2} is described by the \meta{x-offset}
% and \meta{y-offset}. The two offsets should be given as dimension
% expressions.
% \end{function}
@@ -249,19 +222,19 @@
% }
% \begin{syntax}
% \cs{coffin_join:NnnNnnnn}
-% ~~\meta{coffin1} \Arg{coffin1-pole1} \Arg{coffin1-pole2}
-% ~~\meta{coffin2} \Arg{coffin2-pole1} \Arg{coffin2-pole2}
+% ~~\meta{coffin_1} \Arg{coffin_1-pole_1} \Arg{coffin_1-pole_2}
+% ~~\meta{coffin_2} \Arg{coffin_2-pole_1} \Arg{coffin_2-pole_2}
% ~~\Arg{x-offset} \Arg{y-offset}
% \end{syntax}
% This function joins <coffin_2> to <coffin_1> such that the bounding box
-% of \meta{coffin1} may expand. The new bounding
+% of \meta{coffin_1} may expand. The new bounding
% box will cover the area containing the bounding boxes of the two
% original coffins. The alignment is carried out by first calculating
-% \meta{handle1}, the point of intersection of \meta{coffin1-pole1} and
-% \meta{coffin1-pole2}, and \meta{handle2}, the point of intersection
-% of \meta{coffin2-pole1} and \meta{coffin2-pole2}. \meta{coffin2} is
-% then attached to \meta{coffin1} such that the relationship between
-% \meta{handle1} and \meta{handle2} is described by the \meta{x-offset}
+% \meta{handle_1}, the point of intersection of \meta{coffin_1-pole_1} and
+% \meta{coffin_1-pole_2}, and \meta{handle_2}, the point of intersection
+% of \meta{coffin_2-pole_1} and \meta{coffin_2-pole_2}. \meta{coffin_2} is
+% then attached to \meta{coffin_1} such that the relationship between
+% \meta{handle_1} and \meta{handle_2} is described by the \meta{x-offset}
% and \meta{y-offset}. The two offsets should be given as dimension
% expressions.
% \end{function}
@@ -272,7 +245,7 @@
% ~~\Arg{x-offset} \Arg{y-offset}
% \end{syntax}
% Typesetting is carried out by first calculating \meta{handle}, the
-% point of intersection of \meta{pole1} and \meta{pole2}. The coffin
+% point of intersection of \meta{pole_1} and \meta{pole_2}. The coffin
% is then typeset such that the relationship between the current
% reference point in the document and the \meta{handle} is described
% by the \meta{x-offset} and \meta{y-offset}. The two offsets should
@@ -310,7 +283,7 @@
% \section{Coffin diagnostics}
%
% \begin{function}[updated = 2011-09-02]
-% {\coffin_display_handles:cn, \coffin_display_handles:cn}
+% {\coffin_display_handles:Nn, \coffin_display_handles:cn}
% \begin{syntax}
% \cs{coffin_display_handles:Nn} \meta{coffin} \Arg{colour}
% \end{syntax}
@@ -329,8 +302,8 @@
% \cs{coffin_mark_handle:Nnnn} \meta{coffin} \Arg{pole_1} \Arg{pole_2} \Arg{colour}
% \end{syntax}
% This function first calculates the \meta{handle} for the
-% \meta{coffin} as defined by the intersection of \meta{pole1} and
-% \meta{pole2}. It then marks the position of the \meta{handle}
+% \meta{coffin} as defined by the intersection of \meta{pole_1} and
+% \meta{pole_2}. It then marks the position of the \meta{handle}
% on the \meta{coffin}. The \meta{handle} will be labelled as part of
% this process: the location of the \meta{handle} and the label are
% both printed in the \meta{colour} specified.
@@ -353,6 +326,19 @@
% the later, rather than the absolute values, which determines the
% direction of the pole.
% \end{function}
+%
+% \subsection{Constants and variables}
+%
+% \begin{variable}{\c_empty_coffin}
+% A permanently empty coffin.
+% \end{variable}
+%
+% \begin{variable}[added = 2012-06-19]{\l_tmpa_coffin, \l_tmpb_coffin}
+% Scratch coffins for local assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
%
% \end{documentation}
%
@@ -363,183 +349,148 @@
% \begin{macrocode}
%<*initex|package>
% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=coffin>
+% \end{macrocode}
%
% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
% \subsection{Coffins: data structures and general variables}
%
-% \begin{variable}{\l_coffin_internal_box}
-% \begin{variable}{\l_coffin_internal_dim}
-% \begin{variable}{\l_coffin_internal_fp}
-% \begin{variable}{\l_coffin_internal_tl}
+% \begin{variable}{\l_@@_internal_box}
+% \begin{variable}{\l_@@_internal_dim}
+% \begin{variable}{\l_@@_internal_tl}
% Scratch variables.
% \begin{macrocode}
-\box_new:N \l_coffin_internal_box
-\dim_new:N \l_coffin_internal_dim
-\fp_new:N \l_coffin_internal_fp
-\tl_new:N \l_coffin_internal_tl
+\box_new:N \l_@@_internal_box
+\dim_new:N \l_@@_internal_dim
+\tl_new:N \l_@@_internal_tl
% \end{macrocode}
% \end{variable}
% \end{variable}
% \end{variable}
-% \end{variable}
%
-% \begin{variable}{\c_coffin_corners_prop}
+% \begin{variable}{\c_@@_corners_prop}
% The \enquote{corners}; of a coffin define the real content, as
% opposed to the \TeX{} bounding box. They all start off in the same
% place, of course.
% \begin{macrocode}
-\prop_new:N \c_coffin_corners_prop
-\prop_put:Nnn \c_coffin_corners_prop { tl } { { 0 pt } { 0 pt } }
-\prop_put:Nnn \c_coffin_corners_prop { tr } { { 0 pt } { 0 pt } }
-\prop_put:Nnn \c_coffin_corners_prop { bl } { { 0 pt } { 0 pt } }
-\prop_put:Nnn \c_coffin_corners_prop { br } { { 0 pt } { 0 pt } }
+\prop_new:N \c_@@_corners_prop
+\prop_put:Nnn \c_@@_corners_prop { tl } { { 0 pt } { 0 pt } }
+\prop_put:Nnn \c_@@_corners_prop { tr } { { 0 pt } { 0 pt } }
+\prop_put:Nnn \c_@@_corners_prop { bl } { { 0 pt } { 0 pt } }
+\prop_put:Nnn \c_@@_corners_prop { br } { { 0 pt } { 0 pt } }
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\c_coffin_poles_prop}
+% \begin{variable}{\c_@@_poles_prop}
% Pole positions are given for horizontal, vertical and reference-point
% based values.
% \begin{macrocode}
-\prop_new:N \c_coffin_poles_prop
-\tl_set:Nn \l_coffin_internal_tl { { 0 pt } { 0 pt } { 0 pt } { 1000 pt } }
-\prop_put:Nno \c_coffin_poles_prop { l } { \l_coffin_internal_tl }
-\prop_put:Nno \c_coffin_poles_prop { hc } { \l_coffin_internal_tl }
-\prop_put:Nno \c_coffin_poles_prop { r } { \l_coffin_internal_tl }
-\tl_set:Nn \l_coffin_internal_tl { { 0 pt } { 0 pt } { 1000 pt } { 0 pt } }
-\prop_put:Nno \c_coffin_poles_prop { b } { \l_coffin_internal_tl }
-\prop_put:Nno \c_coffin_poles_prop { vc } { \l_coffin_internal_tl }
-\prop_put:Nno \c_coffin_poles_prop { t } { \l_coffin_internal_tl }
-\prop_put:Nno \c_coffin_poles_prop { B } { \l_coffin_internal_tl }
-\prop_put:Nno \c_coffin_poles_prop { H } { \l_coffin_internal_tl }
-\prop_put:Nno \c_coffin_poles_prop { T } { \l_coffin_internal_tl }
+\prop_new:N \c_@@_poles_prop
+\tl_set:Nn \l_@@_internal_tl { { 0 pt } { 0 pt } { 0 pt } { 1000 pt } }
+\prop_put:Nno \c_@@_poles_prop { l } { \l_@@_internal_tl }
+\prop_put:Nno \c_@@_poles_prop { hc } { \l_@@_internal_tl }
+\prop_put:Nno \c_@@_poles_prop { r } { \l_@@_internal_tl }
+\tl_set:Nn \l_@@_internal_tl { { 0 pt } { 0 pt } { 1000 pt } { 0 pt } }
+\prop_put:Nno \c_@@_poles_prop { b } { \l_@@_internal_tl }
+\prop_put:Nno \c_@@_poles_prop { vc } { \l_@@_internal_tl }
+\prop_put:Nno \c_@@_poles_prop { t } { \l_@@_internal_tl }
+\prop_put:Nno \c_@@_poles_prop { B } { \l_@@_internal_tl }
+\prop_put:Nno \c_@@_poles_prop { H } { \l_@@_internal_tl }
+\prop_put:Nno \c_@@_poles_prop { T } { \l_@@_internal_tl }
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_coffin_calc_a_fp}
-% \begin{variable}{\l_coffin_calc_b_fp}
-% \begin{variable}{\l_coffin_calc_c_fp}
-% \begin{variable}{\l_coffin_calc_d_fp}
-% \begin{variable}{\l_coffin_calc_result_fp}
-% Used for calculations of intersections and in other internal places.
+% \begin{variable}{\l_@@_slope_x_fp}
+% \begin{variable}{\l_@@_slope_y_fp}
+% Used for calculations of intersections.
% \begin{macrocode}
-\fp_new:N \l_coffin_calc_a_fp
-\fp_new:N \l_coffin_calc_b_fp
-\fp_new:N \l_coffin_calc_c_fp
-\fp_new:N \l_coffin_calc_d_fp
-\fp_new:N \l_coffin_calc_result_fp
+\fp_new:N \l_@@_slope_x_fp
+\fp_new:N \l_@@_slope_y_fp
% \end{macrocode}
% \end{variable}
% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
%
-% \begin{variable}{\l_coffin_error_bool}
+% \begin{variable}{\l_@@_error_bool}
% For propagating errors so that parts of the code can work around them.
% \begin{macrocode}
-\bool_new:N \l_coffin_error_bool
+\bool_new:N \l_@@_error_bool
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_coffin_offset_x_dim}
-% \begin{variable}{\l_coffin_offset_y_dim}
+% \begin{variable}{\l_@@_offset_x_dim}
+% \begin{variable}{\l_@@_offset_y_dim}
% The offset between two sets of coffin handles when typesetting. These
% values are corrected from those requested in an alignment for the
% positions of the handles.
% \begin{macrocode}
-\dim_new:N \l_coffin_offset_x_dim
-\dim_new:N \l_coffin_offset_y_dim
+\dim_new:N \l_@@_offset_x_dim
+\dim_new:N \l_@@_offset_y_dim
% \end{macrocode}
% \end{variable}
% \end{variable}
%
-% \begin{variable}{\l_coffin_pole_a_tl}
-% \begin{variable}{\l_coffin_pole_b_tl}
+% \begin{variable}{\l_@@_pole_a_tl}
+% \begin{variable}{\l_@@_pole_b_tl}
% Needed for finding the intersection of two poles.
% \begin{macrocode}
-\tl_new:N \l_coffin_pole_a_tl
-\tl_new:N \l_coffin_pole_b_tl
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\l_coffin_sin_fp}
-% \begin{variable}{\l_coffin_cos_fp}
-% Used for rotations to get the sine and cosine values.
-% \begin{macrocode}
-\fp_new:N \l_coffin_sin_fp
-\fp_new:N \l_coffin_cos_fp
+\tl_new:N \l_@@_pole_a_tl
+\tl_new:N \l_@@_pole_b_tl
% \end{macrocode}
% \end{variable}
% \end{variable}
%
-% \begin{variable}{\l_coffin_x_dim}
-% \begin{variable}{\l_coffin_y_dim}
-% \begin{variable}{\l_coffin_x_prime_dim}
-% \begin{variable}{\l_coffin_y_prime_dim}
+% \begin{variable}{\l_@@_x_dim}
+% \begin{variable}{\l_@@_y_dim}
+% \begin{variable}{\l_@@_x_prime_dim}
+% \begin{variable}{\l_@@_y_prime_dim}
% For calculating intersections and so forth.
% \begin{macrocode}
-\dim_new:N \l_coffin_x_dim
-\dim_new:N \l_coffin_y_dim
-\dim_new:N \l_coffin_x_prime_dim
-\dim_new:N \l_coffin_y_prime_dim
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\l_coffin_x_fp}
-% \begin{variable}{\l_coffin_y_fp}
-% \begin{variable}{\l_coffin_x_prime_fp}
-% \begin{variable}{\l_coffin_y_prime_fp}
-% Used for calculations where there are clear $x$- and
-% $y$-components, for example during vector rotation.
-% \begin{macrocode}
-\fp_new:N \l_coffin_x_fp
-\fp_new:N \l_coffin_y_fp
-\fp_new:N \l_coffin_x_prime_fp
-\fp_new:N \l_coffin_y_prime_fp
+\dim_new:N \l_@@_x_dim
+\dim_new:N \l_@@_y_dim
+\dim_new:N \l_@@_x_prime_dim
+\dim_new:N \l_@@_y_prime_dim
% \end{macrocode}
% \end{variable}
% \end{variable}
% \end{variable}
% \end{variable}
%
-% \begin{variable}{\l_coffin_Depth_dim}
-% \begin{variable}{\l_coffin_Height_dim}
-% \begin{variable}{\l_coffin_TotalHeight_dim}
-% \begin{variable}{\l_coffin_Width_dim}
+% \begin{variable}{\l_@@_Depth_dim}
+% \begin{variable}{\l_@@_Height_dim}
+% \begin{variable}{\l_@@_TotalHeight_dim}
+% \begin{variable}{\l_@@_Width_dim}
% Dimensions for the various parts of a coffin.
% \begin{macrocode}
-\dim_new:N \l_coffin_Depth_dim
-\dim_new:N \l_coffin_Height_dim
-\dim_new:N \l_coffin_TotalHeight_dim
-\dim_new:N \l_coffin_Width_dim
+\dim_new:N \l_@@_Depth_dim
+\dim_new:N \l_@@_Height_dim
+\dim_new:N \l_@@_TotalHeight_dim
+\dim_new:N \l_@@_Width_dim
% \end{macrocode}
% \end{variable}
% \end{variable}
% \end{variable}
% \end{variable}
%
-% \begin{macro}{\coffin_saved_Depth:}
-% \begin{macro}{\coffin_saved_Height:}
-% \begin{macro}{\coffin_saved_TotalHeight:}
-% \begin{macro}{\coffin_saved_Width:}
+% \begin{macro}{\@@_saved_Depth:}
+% \begin{macro}{\@@_saved_Height:}
+% \begin{macro}{\@@_saved_TotalHeight:}
+% \begin{macro}{\@@_saved_Width:}
% Used to save the meaning of \cs{Depth}, \cs{Height}, \cs{TotalHeight}
% and \cs{Width}.
% \begin{macrocode}
-\cs_new_nopar:Npn \coffin_saved_Depth: { }
-\cs_new_nopar:Npn \coffin_saved_Height: { }
-\cs_new_nopar:Npn \coffin_saved_TotalHeight: { }
-\cs_new_nopar:Npn \coffin_saved_Width: { }
+\cs_new_nopar:Npn \@@_saved_Depth: { }
+\cs_new_nopar:Npn \@@_saved_Height: { }
+\cs_new_nopar:Npn \@@_saved_TotalHeight: { }
+\cs_new_nopar:Npn \@@_saved_Width: { }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -552,25 +503,40 @@
% placing material in them. This all relies on the following data
% structures.
%
-% \begin{macro}{\coffin_if_exist:NT}
+% \begin{macro}[EXP, pTF]{\coffin_if_exist:N, \coffin_if_exist:c}
% Several of the higher-level coffin functions will give multiple
% errors if the coffin does not exist. A cleaner way to handle this
% is provided here: both the box and the coffin structure are
% checked.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_if_exist:NT #1#2
+\prg_new_conditional:Npnn \coffin_if_exist:N #1 { p , T , F , TF }
{
\cs_if_exist:NTF #1
{
- \cs_if_exist:cTF { l_coffin_poles_ \int_value:w #1 _prop }
- { #2 }
- {
- \msg_kernel_error:nnx { coffins } { unknown-coffin }
- { \token_to_str:N #1 }
- }
+ \cs_if_exist:cTF { l_@@_poles_ \__int_value:w #1 _prop }
+ { \prg_return_true: }
+ { \prg_return_false: }
}
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \coffin_if_exist_p:N { c }
+\cs_generate_variant:Nn \coffin_if_exist:NT { c }
+\cs_generate_variant:Nn \coffin_if_exist:NF { c }
+\cs_generate_variant:Nn \coffin_if_exist:NTF { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_if_exist:NT}
+% Several of the higher-level coffin functions will give multiple
+% errors if the coffin does not exist. So a wrapper is provided to deal
+% with this correctly, issuing an error on erroneous use.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_if_exist:NT #1#2
+ {
+ \coffin_if_exist:NTF #1
+ { #2 }
{
- \msg_kernel_error:nnx { coffins } { unknown-coffin }
+ \__msg_kernel_error:nnx { kernel } { unknown-coffin }
{ \token_to_str:N #1 }
}
}
@@ -583,10 +549,10 @@
% \begin{macrocode}
\cs_new_protected:Npn \coffin_clear:N #1
{
- \coffin_if_exist:NT #1
+ \@@_if_exist:NT #1
{
\box_clear:N #1
- \coffin_reset_structure:N #1
+ \@@_reset_structure:N #1
}
}
\cs_generate_variant:Nn \coffin_clear:N { c }
@@ -603,12 +569,12 @@
\cs_new_protected:Npn \coffin_new:N #1
{
\box_new:N #1
- \prop_clear_new:c { l_coffin_corners_ \int_value:w #1 _prop }
- \prop_clear_new:c { l_coffin_poles_ \int_value:w #1 _prop }
- \prop_gset_eq:cN { l_coffin_corners_ \int_value:w #1 _prop }
- \c_coffin_corners_prop
- \prop_gset_eq:cN { l_coffin_poles_ \int_value:w #1 _prop }
- \c_coffin_poles_prop
+ \prop_clear_new:c { l_@@_corners_ \__int_value:w #1 _prop }
+ \prop_clear_new:c { l_@@_poles_ \__int_value:w #1 _prop }
+ \prop_gset_eq:cN { l_@@_corners_ \__int_value:w #1 _prop }
+ \c_@@_corners_prop
+ \prop_gset_eq:cN { l_@@_poles_ \__int_value:w #1 _prop }
+ \c_@@_poles_prop
}
\cs_generate_variant:Nn \coffin_new:N { c }
% \end{macrocode}
@@ -620,7 +586,7 @@
% \begin{macrocode}
\cs_new_protected:Npn \hcoffin_set:Nn #1#2
{
- \coffin_if_exist:NT #1
+ \@@_if_exist:NT #1
{
\hbox_set:Nn #1
{
@@ -629,9 +595,9 @@
#2
\color_group_end:
}
- \coffin_reset_structure:N #1
- \coffin_update_poles:N #1
- \coffin_update_corners:N #1
+ \@@_reset_structure:N #1
+ \@@_update_poles:N #1
+ \@@_update_corners:N #1
}
}
\cs_generate_variant:Nn \hcoffin_set:Nn { c }
@@ -642,32 +608,38 @@
% Setting vertical coffins is more complex. First, the material is
% typeset with a given width. The default handles and poles are set as
% for a horizontal coffin, before finding the top baseline using a
-% temporary box.
+% temporary box. No \cs{color_ensure_current:} here as that would add a
+% whatsit to the start of the vertical box and mess up the location of the
+% \texttt{T}~pole (see \emph{\TeX{} by Topic} for discussion of the
+% \tn{vtop} primitive, used to do the measuring).
% \begin{macrocode}
\cs_new_protected:Npn \vcoffin_set:Nnn #1#2#3
{
- \coffin_if_exist:NT #1
+ \@@_if_exist:NT #1
{
\vbox_set:Nn #1
{
\dim_set:Nn \tex_hsize:D {#2}
+%<*package>
+ \dim_set_eq:NN \linewidth \tex_hsize:D
+ \dim_set_eq:NN \columnwidth \tex_hsize:D
+%</package>
\color_group_begin:
- \color_ensure_current:
#3
\color_group_end:
}
- \coffin_reset_structure:N #1
- \coffin_update_poles:N #1
- \coffin_update_corners:N #1
- \vbox_set_top:Nn \l_coffin_internal_box { \vbox_unpack:N #1 }
- \coffin_set_pole:Nnx #1 { T }
+ \@@_reset_structure:N #1
+ \@@_update_poles:N #1
+ \@@_update_corners:N #1
+ \vbox_set_top:Nn \l_@@_internal_box { \vbox_unpack:N #1 }
+ \@@_set_pole:Nnx #1 { T }
{
{ 0 pt }
- { \dim_eval:n { \box_ht:N #1 - \box_ht:N \l_coffin_internal_box } }
+ { \dim_eval:n { \box_ht:N #1 - \box_ht:N \l_@@_internal_box } }
{ 1000 pt }
{ 0 pt }
}
- \box_clear:N \l_coffin_internal_box
+ \box_clear:N \l_@@_internal_box
}
}
\cs_generate_variant:Nn \vcoffin_set:Nnn { c }
@@ -681,16 +653,16 @@
% \begin{macrocode}
\cs_new_protected:Npn \hcoffin_set:Nw #1
{
- \coffin_if_exist:NT #1
+ \@@_if_exist:NT #1
{
\hbox_set:Nw #1 \color_group_begin: \color_ensure_current:
\cs_set_protected_nopar:Npn \hcoffin_set_end:
{
\color_group_end:
\hbox_set_end:
- \coffin_reset_structure:N #1
- \coffin_update_poles:N #1
- \coffin_update_corners:N #1
+ \@@_reset_structure:N #1
+ \@@_update_poles:N #1
+ \@@_update_corners:N #1
}
}
}
@@ -706,29 +678,33 @@
% \begin{macrocode}
\cs_new_protected:Npn \vcoffin_set:Nnw #1#2
{
- \coffin_if_exist:NT #1
+ \@@_if_exist:NT #1
{
\vbox_set:Nw #1
\dim_set:Nn \tex_hsize:D {#2}
+%<*package>
+ \dim_set_eq:NN \linewidth \tex_hsize:D
+ \dim_set_eq:NN \columnwidth \tex_hsize:D
+%</package>
\color_group_begin: \color_ensure_current:
\cs_set_protected:Npn \vcoffin_set_end:
{
\color_group_end:
\vbox_set_end:
- \coffin_reset_structure:N #1
- \coffin_update_poles:N #1
- \coffin_update_corners:N #1
- \vbox_set_top:Nn \l_coffin_internal_box { \vbox_unpack:N #1 }
- \coffin_set_pole:Nnx #1 { T }
+ \@@_reset_structure:N #1
+ \@@_update_poles:N #1
+ \@@_update_corners:N #1
+ \vbox_set_top:Nn \l_@@_internal_box { \vbox_unpack:N #1 }
+ \@@_set_pole:Nnx #1 { T }
{
{ 0 pt }
{
- \dim_eval:n { \box_ht:N #1 - \box_ht:N \l_coffin_internal_box }
+ \dim_eval:n { \box_ht:N #1 - \box_ht:N \l_@@_internal_box }
}
{ 1000 pt }
{ 0 pt }
}
- \box_clear:N \l_coffin_internal_box
+ \box_clear:N \l_@@_internal_box
}
}
}
@@ -747,10 +723,10 @@
% \begin{macrocode}
\cs_new_protected:Npn \coffin_set_eq:NN #1#2
{
- \coffin_if_exist:NT #1
+ \@@_if_exist:NT #1
{
\box_set_eq:NN #1 #2
- \coffin_set_eq_structure:NN #1 #2
+ \@@_set_eq_structure:NN #1 #2
}
}
\cs_generate_variant:Nn \coffin_set_eq:NN { c , Nc , cc }
@@ -758,20 +734,28 @@
% \end{macro}
%
% \begin{variable}{\c_empty_coffin}
-% \begin{variable}{\l_coffin_aligned_coffin}
-% \begin{variable}{\l_coffin_aligned_internal_coffin}
+% \begin{variable}{\l_@@_aligned_coffin}
+% \begin{variable}{\l_@@_aligned_internal_coffin}
% Special coffins: these cannot be set up earlier as they need
% \cs{coffin_new:N}. The empty coffin is set as a box as the full
% coffin-setting system needs some material which is not yet available.
% \begin{macrocode}
\coffin_new:N \c_empty_coffin
\hbox_set:Nn \c_empty_coffin { }
-\coffin_new:N \l_coffin_aligned_coffin
-\coffin_new:N \l_coffin_aligned_internal_coffin
+\coffin_new:N \l_@@_aligned_coffin
+\coffin_new:N \l_@@_aligned_internal_coffin
% \end{macrocode}
% \end{variable}
% \end{variable}
% \end{variable}
+%
+% \begin{variable}{\l_tmpa_coffin, \l_tmpb_coffin}
+% The usual scratch space.
+% \begin{macrocode}
+\coffin_new:N \l_tmpa_coffin
+\coffin_new:N \l_tmpb_coffin
+% \end{macrocode}
+% \end{variable}
%
% \subsection{Measuring coffins}
%
@@ -794,16 +778,16 @@
%
% \subsection{Coffins: handle and pole management}
%
-% \begin{macro}{\coffin_get_pole:NnN}
+% \begin{macro}{\@@_get_pole:NnN}
% A simple wrapper around the recovery of a coffin pole, with some
% error checking and recovery built-in.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_get_pole:NnN #1#2#3
+\cs_new_protected:Npn \@@_get_pole:NnN #1#2#3
{
\prop_get:cnNF
- { l_coffin_poles_ \int_value:w #1 _prop } {#2} #3
+ { l_@@_poles_ \__int_value:w #1 _prop } {#2} #3
{
- \msg_kernel_error:nnxx { coffins } { unknown-coffin-pole }
+ \__msg_kernel_error:nnxx { kernel } { unknown-coffin-pole }
{#2} { \token_to_str:N #1 }
\tl_set:Nn #3 { { 0 pt } { 0 pt } { 0 pt } { 0 pt } }
}
@@ -811,42 +795,42 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\coffin_reset_structure:N}
+% \begin{macro}{\@@_reset_structure:N}
% Resetting the structure is a simple copy job.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_reset_structure:N #1
+\cs_new_protected:Npn \@@_reset_structure:N #1
{
- \prop_set_eq:cN { l_coffin_corners_ \int_value:w #1 _prop }
- \c_coffin_corners_prop
- \prop_set_eq:cN { l_coffin_poles_ \int_value:w #1 _prop }
- \c_coffin_poles_prop
+ \prop_set_eq:cN { l_@@_corners_ \__int_value:w #1 _prop }
+ \c_@@_corners_prop
+ \prop_set_eq:cN { l_@@_poles_ \__int_value:w #1 _prop }
+ \c_@@_poles_prop
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\coffin_set_eq_structure:NN,\coffin_gset_eq_structure:NN}
+% \begin{macro}{\@@_set_eq_structure:NN,\@@_gset_eq_structure:NN}
% Setting coffin structures equal simply means copying the property
% list.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_set_eq_structure:NN #1#2
+\cs_new_protected:Npn \@@_set_eq_structure:NN #1#2
{
- \prop_set_eq:cc { l_coffin_corners_ \int_value:w #1 _prop }
- { l_coffin_corners_ \int_value:w #2 _prop }
- \prop_set_eq:cc { l_coffin_poles_ \int_value:w #1 _prop }
- { l_coffin_poles_ \int_value:w #2 _prop }
+ \prop_set_eq:cc { l_@@_corners_ \__int_value:w #1 _prop }
+ { l_@@_corners_ \__int_value:w #2 _prop }
+ \prop_set_eq:cc { l_@@_poles_ \__int_value:w #1 _prop }
+ { l_@@_poles_ \__int_value:w #2 _prop }
}
-\cs_new_protected:Npn \coffin_gset_eq_structure:NN #1#2
+\cs_new_protected:Npn \@@_gset_eq_structure:NN #1#2
{
- \prop_gset_eq:cc { l_coffin_corners_ \int_value:w #1 _prop }
- { l_coffin_corners_ \int_value:w #2 _prop }
- \prop_gset_eq:cc { l_coffin_poles_ \int_value:w #1 _prop }
- { l_coffin_poles_ \int_value:w #2 _prop }
+ \prop_gset_eq:cc { l_@@_corners_ \__int_value:w #1 _prop }
+ { l_@@_corners_ \__int_value:w #2 _prop }
+ \prop_gset_eq:cc { l_@@_poles_ \__int_value:w #1 _prop }
+ { l_@@_poles_ \__int_value:w #2 _prop }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\coffin_set_user_dimensions:N}
-% \begin{macro}{\coffin_end_user_dimensions:}
+% \begin{macro}{\@@_set_user_dimensions:N}
+% \begin{macro}{\@@_end_user_dimensions:}
% \begin{macro}{\Depth}
% \begin{macro}{\Height}
% \begin{macro}{\TotalHeight}
@@ -854,27 +838,27 @@
% These make design-level names for the dimensions of a coffin easy to
% get at.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_set_user_dimensions:N #1
+\cs_new_protected:Npn \@@_set_user_dimensions:N #1
{
- \cs_set_eq:NN \coffin_saved_Height: \Height
- \cs_set_eq:NN \coffin_saved_Depth: \Depth
- \cs_set_eq:NN \coffin_saved_TotalHeight: \TotalHeight
- \cs_set_eq:NN \coffin_saved_Width: \Width
- \cs_set_eq:NN \Height \l_coffin_Height_dim
- \cs_set_eq:NN \Depth \l_coffin_Depth_dim
- \cs_set_eq:NN \TotalHeight \l_coffin_TotalHeight_dim
- \cs_set_eq:NN \Width \l_coffin_Width_dim
+ \cs_set_eq:NN \@@_saved_Height: \Height
+ \cs_set_eq:NN \@@_saved_Depth: \Depth
+ \cs_set_eq:NN \@@_saved_TotalHeight: \TotalHeight
+ \cs_set_eq:NN \@@_saved_Width: \Width
+ \cs_set_eq:NN \Height \l_@@_Height_dim
+ \cs_set_eq:NN \Depth \l_@@_Depth_dim
+ \cs_set_eq:NN \TotalHeight \l_@@_TotalHeight_dim
+ \cs_set_eq:NN \Width \l_@@_Width_dim
\dim_set:Nn \Height { \box_ht:N #1 }
\dim_set:Nn \Depth { \box_dp:N #1 }
\dim_set:Nn \TotalHeight { \box_ht:N #1 + \box_dp:N #1 }
\dim_set:Nn \Width { \box_wd:N #1 }
}
-\cs_new_protected_nopar:Npn \coffin_end_user_dimensions:
+\cs_new_protected_nopar:Npn \@@_end_user_dimensions:
{
- \cs_set_eq:NN \Height \coffin_saved_Height:
- \cs_set_eq:NN \Depth \coffin_saved_Depth:
- \cs_set_eq:NN \TotalHeight \coffin_saved_TotalHeight:
- \cs_set_eq:NN \Width \coffin_saved_Width:
+ \cs_set_eq:NN \Height \@@_saved_Height:
+ \cs_set_eq:NN \Depth \@@_saved_Depth:
+ \cs_set_eq:NN \TotalHeight \@@_saved_TotalHeight:
+ \cs_set_eq:NN \Width \@@_saved_Width:
}
% \end{macrocode}
% \end{macro}
@@ -887,7 +871,7 @@
% \begin{macro}
% {\coffin_set_horizontal_pole:Nnn, \coffin_set_horizontal_pole:cnn}
% \begin{macro}{\coffin_set_vertical_pole:Nnn,\coffin_set_vertical_pole:cnn}
-% \begin{macro}{\coffin_set_pole:Nnn, \coffin_set_pole:Nnx}
+% \begin{macro}{\@@_set_pole:Nnn, \@@_set_pole:Nnx}
% Setting the pole of a coffin at the user/designer level requires a
% bit more care. The idea here is to provide a reasonable interface to
% the system, then to do the setting with full expansion. The
@@ -895,93 +879,93 @@
% \begin{macrocode}
\cs_new_protected:Npn \coffin_set_horizontal_pole:Nnn #1#2#3
{
- \coffin_if_exist:NT #1
+ \@@_if_exist:NT #1
{
- \coffin_set_user_dimensions:N #1
- \coffin_set_pole:Nnx #1 {#2}
+ \@@_set_user_dimensions:N #1
+ \@@_set_pole:Nnx #1 {#2}
{
{ 0 pt } { \dim_eval:n {#3} }
{ 1000 pt } { 0 pt }
}
- \coffin_end_user_dimensions:
+ \@@_end_user_dimensions:
}
}
\cs_new_protected:Npn \coffin_set_vertical_pole:Nnn #1#2#3
{
- \coffin_if_exist:NT #1
+ \@@_if_exist:NT #1
{
- \coffin_set_user_dimensions:N #1
- \coffin_set_pole:Nnx #1 {#2}
+ \@@_set_user_dimensions:N #1
+ \@@_set_pole:Nnx #1 {#2}
{
{ \dim_eval:n {#3} } { 0 pt }
{ 0 pt } { 1000 pt }
}
- \coffin_end_user_dimensions:
+ \@@_end_user_dimensions:
}
}
-\cs_new_protected:Npn \coffin_set_pole:Nnn #1#2#3
- { \prop_put:cnn { l_coffin_poles_ \int_value:w #1 _prop } {#2} {#3} }
+\cs_new_protected:Npn \@@_set_pole:Nnn #1#2#3
+ { \prop_put:cnn { l_@@_poles_ \__int_value:w #1 _prop } {#2} {#3} }
\cs_generate_variant:Nn \coffin_set_horizontal_pole:Nnn { c }
\cs_generate_variant:Nn \coffin_set_vertical_pole:Nnn { c }
-\cs_generate_variant:Nn \coffin_set_pole:Nnn { Nnx }
+\cs_generate_variant:Nn \@@_set_pole:Nnn { Nnx }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\coffin_update_corners:N}
+% \begin{macro}{\@@_update_corners:N}
% Updating the corners of a coffin is straight-forward as at this stage
% there can be no rotation. So the corners of the content are just those
% of the underlying \TeX{} box.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_update_corners:N #1
+\cs_new_protected:Npn \@@_update_corners:N #1
{
- \prop_put:cnx { l_coffin_corners_ \int_value:w #1 _prop } { tl }
+ \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } { tl }
{ { 0 pt } { \dim_use:N \box_ht:N #1 } }
- \prop_put:cnx { l_coffin_corners_ \int_value:w #1 _prop } { tr }
+ \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } { tr }
{ { \dim_use:N \box_wd:N #1 } { \dim_use:N \box_ht:N #1 } }
- \prop_put:cnx { l_coffin_corners_ \int_value:w #1 _prop } { bl }
+ \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } { bl }
{ { 0 pt } { \dim_eval:n { - \box_dp:N #1 } } }
- \prop_put:cnx { l_coffin_corners_ \int_value:w #1 _prop } { br }
+ \prop_put:cnx { l_@@_corners_ \__int_value:w #1 _prop } { br }
{ { \dim_use:N \box_wd:N #1 } { \dim_eval:n { - \box_dp:N #1 } } }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\coffin_update_poles:N}
+% \begin{macro}{\@@_update_poles:N}
% This function is called when a coffin is set, and updates the poles to
% reflect the nature of size of the box. Thus this function only alters
% poles where the default position is dependent on the size of the box.
% It also does not set poles which are relevant only to vertical
% coffins.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_update_poles:N #1
+\cs_new_protected:Npn \@@_update_poles:N #1
{
- \prop_put:cnx { l_coffin_poles_ \int_value:w #1 _prop } { hc }
+ \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { hc }
{
{ \dim_eval:n { 0.5 \box_wd:N #1 } }
{ 0 pt } { 0 pt } { 1000 pt }
}
- \prop_put:cnx { l_coffin_poles_ \int_value:w #1 _prop } { r }
+ \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { r }
{
{ \dim_use:N \box_wd:N #1 }
{ 0 pt } { 0 pt } { 1000 pt }
}
- \prop_put:cnx { l_coffin_poles_ \int_value:w #1 _prop } { vc }
+ \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { vc }
{
{ 0 pt }
{ \dim_eval:n { ( \box_ht:N #1 - \box_dp:N #1 ) / 2 } }
{ 1000 pt }
{ 0 pt }
}
- \prop_put:cnx { l_coffin_poles_ \int_value:w #1 _prop } { t }
+ \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { t }
{
{ 0 pt }
{ \dim_use:N \box_ht:N #1 }
{ 1000 pt }
{ 0 pt }
}
- \prop_put:cnx { l_coffin_poles_ \int_value:w #1 _prop } { b }
+ \prop_put:cnx { l_@@_poles_ \__int_value:w #1 _prop } { b }
{
{ 0 pt }
{ \dim_eval:n { - \box_dp:N #1 } }
@@ -994,27 +978,27 @@
%
% \subsection{Coffins: calculation of pole intersections}
%
-% \begin{macro}{\coffin_calculate_intersection:Nnn}
-% \begin{macro}[aux]{\coffin_calculate_intersection:nnnnnnnn}
-% \begin{macro}[aux]{\coffin_calculate_intersection_aux:nnnnnN}
+% \begin{macro}{\@@_calculate_intersection:Nnn}
+% \begin{macro}[aux]{\@@_calculate_intersection:nnnnnnnn}
+% \begin{macro}[aux]{\@@_calculate_intersection_aux:nnnnnN}
% The lead off in finding intersections is to recover the two poles
% and then hand off to the auxiliary for the actual calculation. There
% may of course not be an intersection, for which an error trap is
% needed.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_calculate_intersection:Nnn #1#2#3
+\cs_new_protected:Npn \@@_calculate_intersection:Nnn #1#2#3
{
- \coffin_get_pole:NnN #1 {#2} \l_coffin_pole_a_tl
- \coffin_get_pole:NnN #1 {#3} \l_coffin_pole_b_tl
- \bool_set_false:N \l_coffin_error_bool
+ \@@_get_pole:NnN #1 {#2} \l_@@_pole_a_tl
+ \@@_get_pole:NnN #1 {#3} \l_@@_pole_b_tl
+ \bool_set_false:N \l_@@_error_bool
\exp_last_two_unbraced:Noo
- \coffin_calculate_intersection:nnnnnnnn
- \l_coffin_pole_a_tl \l_coffin_pole_b_tl
- \bool_if:NT \l_coffin_error_bool
+ \@@_calculate_intersection:nnnnnnnn
+ \l_@@_pole_a_tl \l_@@_pole_b_tl
+ \bool_if:NT \l_@@_error_bool
{
- \msg_kernel_error:nn { coffins } { no-pole-intersection }
- \dim_zero:N \l_coffin_x_dim
- \dim_zero:N \l_coffin_y_dim
+ \__msg_kernel_error:nn { kernel } { no-pole-intersection }
+ \dim_zero:N \l_@@_x_dim
+ \dim_zero:N \l_@@_y_dim
}
}
% \end{macrocode}
@@ -1029,7 +1013,7 @@
% is either horizontal or vertical then one or more of $c$, $d$,
% $c'$ and $d'$ will be zero and a special case is needed.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_calculate_intersection:nnnnnnnn
+\cs_new_protected:Npn \@@_calculate_intersection:nnnnnnnn
#1#2#3#4#5#6#7#8
{
\dim_compare:nNnTF {#3} = { \c_zero_dim }
@@ -1039,9 +1023,9 @@
% second pole: if it is also vertical then there is an error.
% \begin{macrocode}
{
- \dim_set:Nn \l_coffin_x_dim {#1}
+ \dim_set:Nn \l_@@_x_dim {#1}
\dim_compare:nNnTF {#7} = \c_zero_dim
- { \bool_set_true:N \l_coffin_error_bool }
+ { \bool_set_true:N \l_@@_error_bool }
% \end{macrocode}
% The second pole may still be horizontal, in which case the
% $y$-component of the intersection will be $b'$. If not,
@@ -1053,10 +1037,10 @@
% \begin{macrocode}
{
\dim_compare:nNnTF {#8} = \c_zero_dim
- { \dim_set:Nn \l_coffin_y_dim {#6} }
+ { \dim_set:Nn \l_@@_y_dim {#6} }
{
- \coffin_calculate_intersection_aux:nnnnnN
- {#1} {#5} {#6} {#7} {#8} \l_coffin_y_dim
+ \@@_calculate_intersection_aux:nnnnnN
+ {#1} {#5} {#6} {#7} {#8} \l_@@_y_dim
}
}
}
@@ -1068,12 +1052,12 @@
{
\dim_compare:nNnTF {#4} = \c_zero_dim
{
- \dim_set:Nn \l_coffin_y_dim {#2}
+ \dim_set:Nn \l_@@_y_dim {#2}
\dim_compare:nNnTF {#8} = { \c_zero_dim }
- { \bool_set_true:N \l_coffin_error_bool }
+ { \bool_set_true:N \l_@@_error_bool }
{
\dim_compare:nNnTF {#7} = \c_zero_dim
- { \dim_set:Nn \l_coffin_x_dim {#5} }
+ { \dim_set:Nn \l_@@_x_dim {#5} }
% \end{macrocode}
% The formula for the case where the second pole is neither horizontal
% nor vertical is
@@ -1083,8 +1067,8 @@
% which is again handled by the same auxiliary.
% \begin{macrocode}
{
- \coffin_calculate_intersection_aux:nnnnnN
- {#2} {#6} {#5} {#8} {#7} \l_coffin_x_dim
+ \@@_calculate_intersection_aux:nnnnnN
+ {#2} {#6} {#5} {#8} {#7} \l_@@_x_dim
}
}
}
@@ -1097,32 +1081,30 @@
{
\dim_compare:nNnTF {#7} = \c_zero_dim
{
- \dim_set:Nn \l_coffin_x_dim {#5}
- \coffin_calculate_intersection_aux:nnnnnN
- {#5} {#1} {#2} {#3} {#4} \l_coffin_y_dim
+ \dim_set:Nn \l_@@_x_dim {#5}
+ \@@_calculate_intersection_aux:nnnnnN
+ {#5} {#1} {#2} {#3} {#4} \l_@@_y_dim
}
{
\dim_compare:nNnTF {#8} = \c_zero_dim
{
- \dim_set:Nn \l_coffin_x_dim {#6}
- \coffin_calculate_intersection_aux:nnnnnN
- {#6} {#2} {#1} {#4} {#3} \l_coffin_x_dim
+ \dim_set:Nn \l_@@_x_dim {#6}
+ \@@_calculate_intersection_aux:nnnnnN
+ {#6} {#2} {#1} {#4} {#3} \l_@@_x_dim
}
% \end{macrocode}
% If none of the special cases apply then there is still a need to
% check that there is a unique intersection between the two pole. This
% is the case if they have different slopes.
% \begin{macrocode}
- {
- \fp_set_from_dim:Nn \l_coffin_calc_a_fp {#3}
- \fp_set_from_dim:Nn \l_coffin_calc_b_fp {#4}
- \fp_set_from_dim:Nn \l_coffin_calc_c_fp {#7}
- \fp_set_from_dim:Nn \l_coffin_calc_d_fp {#8}
- \fp_div:Nn \l_coffin_calc_b_fp \l_coffin_calc_a_fp
- \fp_div:Nn \l_coffin_calc_d_fp \l_coffin_calc_c_fp
+ {
+ \fp_set:Nn \l_@@_slope_x_fp
+ { \dim_to_fp:n {#4} / \dim_to_fp:n {#3} }
+ \fp_set:Nn \l_@@_slope_y_fp
+ { \dim_to_fp:n {#8} / \dim_to_fp:n {#7} }
\fp_compare:nNnTF
- \l_coffin_calc_b_fp = \l_coffin_calc_d_fp
- { \bool_set_true:N \l_coffin_error_bool }
+ \l_@@_slope_x_fp = \l_@@_slope_y_fp
+ { \bool_set_true:N \l_@@_error_bool }
% \end{macrocode}
% All of the tests pass, so there is the full complexity of the
% calculation:
@@ -1137,29 +1119,23 @@
% $x$-position.
% \begin{macrocode}
{
- \fp_set_from_dim:Nn \l_coffin_calc_result_fp {#6}
- \fp_set_from_dim:Nn \l_coffin_calc_a_fp {#2}
- \fp_sub:Nn \l_coffin_calc_result_fp
- { \l_coffin_calc_a_fp }
- \fp_set_from_dim:Nn \l_coffin_calc_a_fp {#1}
- \fp_mul:Nn \l_coffin_calc_a_fp
- { \l_coffin_calc_b_fp }
- \fp_add:Nn \l_coffin_calc_result_fp
- { \l_coffin_calc_a_fp }
- \fp_set_from_dim:Nn \l_coffin_calc_a_fp {#5}
- \fp_mul:Nn \l_coffin_calc_a_fp
- { \l_coffin_calc_d_fp }
- \fp_sub:Nn \l_coffin_calc_result_fp
- { \l_coffin_calc_a_fp }
- \fp_sub:Nn \l_coffin_calc_b_fp
- { \l_coffin_calc_d_fp }
- \fp_div:Nn \l_coffin_calc_result_fp
- { \l_coffin_calc_b_fp }
- \dim_set:Nn \l_coffin_x_dim
- { \fp_to_dim:N \l_coffin_calc_result_fp }
- \coffin_calculate_intersection_aux:nnnnnN
- { \l_coffin_x_dim }
- {#5} {#6} {#8} {#7} \l_coffin_y_dim
+ \dim_set:Nn \l_@@_x_dim
+ {
+ \fp_to_dim:n
+ {
+ (
+ \dim_to_fp:n {#1} * \l_@@_slope_x_fp
+ - ( \dim_to_fp:n {#5} * \l_@@_slope_y_fp )
+ - \dim_to_fp:n {#2}
+ + \dim_to_fp:n {#6}
+ )
+ /
+ ( \l_@@_slope_x_fp - \l_@@_slope_y_fp )
+ }
+ }
+ \@@_calculate_intersection_aux:nnnnnN
+ { \l_@@_x_dim }
+ {#5} {#6} {#8} {#7} \l_@@_y_dim
}
}
}
@@ -1170,24 +1146,23 @@
% The formula for finding the intersection point is in most cases the
% same. The formula here is
% \[
-% \#6 = \frac{\#5}{\#4} \left ( \#1 - \#2 \right ) + \#3
+% \#6 = \#4 \cdot \left( \frac { \#1 - \#2 } { \#5 } \right)\#3
% \]
% Thus |#4| and |#5| should be the directions of the pole while
% |#2| and |#3| are co-ordinates.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_calculate_intersection_aux:nnnnnN
- #1#2#3#4#5#6
+\cs_new_protected:Npn \@@_calculate_intersection_aux:nnnnnN #1#2#3#4#5#6
{
- \fp_set_from_dim:Nn \l_coffin_calc_result_fp {#1}
- \fp_set_from_dim:Nn \l_coffin_calc_a_fp {#2}
- \fp_set_from_dim:Nn \l_coffin_calc_b_fp {#3}
- \fp_set_from_dim:Nn \l_coffin_calc_c_fp {#4}
- \fp_set_from_dim:Nn \l_coffin_calc_d_fp {#5}
- \fp_sub:Nn \l_coffin_calc_result_fp { \l_coffin_calc_a_fp }
- \fp_div:Nn \l_coffin_calc_result_fp { \l_coffin_calc_d_fp }
- \fp_mul:Nn \l_coffin_calc_result_fp { \l_coffin_calc_c_fp }
- \fp_add:Nn \l_coffin_calc_result_fp { \l_coffin_calc_b_fp }
- \dim_set:Nn #6 { \fp_to_dim:N \l_coffin_calc_result_fp }
+ \dim_set:Nn #6
+ {
+ \fp_to_dim:n
+ {
+ \dim_to_fp:n {#4} *
+ ( \dim_to_fp:n {#1} - \dim_to_fp:n {#2} ) /
+ \dim_to_fp:n {#5}
+ + \dim_to_fp:n {#3}
+ }
+ }
}
% \end{macrocode}
% \end{macro}
@@ -1209,8 +1184,8 @@
% \begin{macrocode}
\cs_new_protected:Npn \coffin_join:NnnNnnnn #1#2#3#4#5#6#7#8
{
- \coffin_align:NnnNnnnnN
- #1 {#2} {#3} #4 {#5} {#6} {#7} {#8} \l_coffin_aligned_coffin
+ \@@_align:NnnNnnnnN
+ #1 {#2} {#3} #4 {#5} {#6} {#7} {#8} \l_@@_aligned_coffin
% \end{macrocode}
% Correct the placement of the reference point. If the $x$-offset
% is negative then the reference point of the second box is to the left
@@ -1219,46 +1194,46 @@
% than the sum of the $x$-offset and the width of the second box.
% So a second kern may be needed.
% \begin{macrocode}
- \hbox_set:Nn \l_coffin_aligned_coffin
+ \hbox_set:Nn \l_@@_aligned_coffin
{
- \dim_compare:nNnT { \l_coffin_offset_x_dim } < \c_zero_dim
- { \tex_kern:D -\l_coffin_offset_x_dim }
- \hbox_unpack:N \l_coffin_aligned_coffin
- \dim_set:Nn \l_coffin_internal_dim
- { \l_coffin_offset_x_dim - \box_wd:N #1 + \box_wd:N #4 }
- \dim_compare:nNnT \l_coffin_internal_dim < \c_zero_dim
- { \tex_kern:D -\l_coffin_internal_dim }
+ \dim_compare:nNnT { \l_@@_offset_x_dim } < \c_zero_dim
+ { \tex_kern:D -\l_@@_offset_x_dim }
+ \hbox_unpack:N \l_@@_aligned_coffin
+ \dim_set:Nn \l_@@_internal_dim
+ { \l_@@_offset_x_dim - \box_wd:N #1 + \box_wd:N #4 }
+ \dim_compare:nNnT \l_@@_internal_dim < \c_zero_dim
+ { \tex_kern:D -\l_@@_internal_dim }
}
% \end{macrocode}
% The coffin structure is reset, and the corners are cleared: only
% those from the two parent coffins are needed.
% \begin{macrocode}
- \coffin_reset_structure:N \l_coffin_aligned_coffin
+ \@@_reset_structure:N \l_@@_aligned_coffin
\prop_clear:c
- { l_coffin_corners_ \int_value:w \l_coffin_aligned_coffin _ prop }
- \coffin_update_poles:N \l_coffin_aligned_coffin
+ { l_@@_corners_ \__int_value:w \l_@@_aligned_coffin _ prop }
+ \@@_update_poles:N \l_@@_aligned_coffin
% \end{macrocode}
% The structures of the parent coffins are now transferred to the new
% coffin, which requires that the appropriate offsets are applied. That
% will then depend on whether any shift was needed.
% \begin{macrocode}
- \dim_compare:nNnTF \l_coffin_offset_x_dim < \c_zero_dim
+ \dim_compare:nNnTF \l_@@_offset_x_dim < \c_zero_dim
{
- \coffin_offset_poles:Nnn #1 { -\l_coffin_offset_x_dim } { 0 pt }
- \coffin_offset_poles:Nnn #4 { 0 pt } { \l_coffin_offset_y_dim }
- \coffin_offset_corners:Nnn #1 { -\l_coffin_offset_x_dim } { 0 pt }
- \coffin_offset_corners:Nnn #4 { 0 pt } { \l_coffin_offset_y_dim }
+ \@@_offset_poles:Nnn #1 { -\l_@@_offset_x_dim } { 0 pt }
+ \@@_offset_poles:Nnn #4 { 0 pt } { \l_@@_offset_y_dim }
+ \@@_offset_corners:Nnn #1 { -\l_@@_offset_x_dim } { 0 pt }
+ \@@_offset_corners:Nnn #4 { 0 pt } { \l_@@_offset_y_dim }
}
{
- \coffin_offset_poles:Nnn #1 { 0 pt } { 0 pt }
- \coffin_offset_poles:Nnn #4
- { \l_coffin_offset_x_dim } { \l_coffin_offset_y_dim }
- \coffin_offset_corners:Nnn #1 { 0 pt } { 0 pt }
- \coffin_offset_corners:Nnn #4
- { \l_coffin_offset_x_dim } { \l_coffin_offset_y_dim }
+ \@@_offset_poles:Nnn #1 { 0 pt } { 0 pt }
+ \@@_offset_poles:Nnn #4
+ { \l_@@_offset_x_dim } { \l_@@_offset_y_dim }
+ \@@_offset_corners:Nnn #1 { 0 pt } { 0 pt }
+ \@@_offset_corners:Nnn #4
+ { \l_@@_offset_x_dim } { \l_@@_offset_y_dim }
}
- \coffin_update_vertical_poles:NNN #1 #4 \l_coffin_aligned_coffin
- \coffin_set_eq:NN #1 \l_coffin_aligned_coffin
+ \@@_update_vertical_poles:NNN #1 #4 \l_@@_aligned_coffin
+ \coffin_set_eq:NN #1 \l_@@_aligned_coffin
}
\cs_generate_variant:Nn \coffin_join:NnnNnnnn { c , Nnnc , cnnc }
% \end{macrocode}
@@ -1278,37 +1253,37 @@
% \begin{macrocode}
\cs_new_protected:Npn \coffin_attach:NnnNnnnn #1#2#3#4#5#6#7#8
{
- \coffin_align:NnnNnnnnN
- #1 {#2} {#3} #4 {#5} {#6} {#7} {#8} \l_coffin_aligned_coffin
- \box_set_ht:Nn \l_coffin_aligned_coffin { \box_ht:N #1 }
- \box_set_dp:Nn \l_coffin_aligned_coffin { \box_dp:N #1 }
- \box_set_wd:Nn \l_coffin_aligned_coffin { \box_wd:N #1 }
- \coffin_reset_structure:N \l_coffin_aligned_coffin
+ \@@_align:NnnNnnnnN
+ #1 {#2} {#3} #4 {#5} {#6} {#7} {#8} \l_@@_aligned_coffin
+ \box_set_ht:Nn \l_@@_aligned_coffin { \box_ht:N #1 }
+ \box_set_dp:Nn \l_@@_aligned_coffin { \box_dp:N #1 }
+ \box_set_wd:Nn \l_@@_aligned_coffin { \box_wd:N #1 }
+ \@@_reset_structure:N \l_@@_aligned_coffin
\prop_set_eq:cc
- { l_coffin_corners_ \int_value:w \l_coffin_aligned_coffin _prop }
- { l_coffin_corners_ \int_value:w #1 _prop }
- \coffin_update_poles:N \l_coffin_aligned_coffin
- \coffin_offset_poles:Nnn #1 { 0 pt } { 0 pt }
- \coffin_offset_poles:Nnn #4
- { \l_coffin_offset_x_dim } { \l_coffin_offset_y_dim }
- \coffin_update_vertical_poles:NNN #1 #4 \l_coffin_aligned_coffin
- \coffin_set_eq:NN #1 \l_coffin_aligned_coffin
+ { l_@@_corners_ \__int_value:w \l_@@_aligned_coffin _prop }
+ { l_@@_corners_ \__int_value:w #1 _prop }
+ \@@_update_poles:N \l_@@_aligned_coffin
+ \@@_offset_poles:Nnn #1 { 0 pt } { 0 pt }
+ \@@_offset_poles:Nnn #4
+ { \l_@@_offset_x_dim } { \l_@@_offset_y_dim }
+ \@@_update_vertical_poles:NNN #1 #4 \l_@@_aligned_coffin
+ \coffin_set_eq:NN #1 \l_@@_aligned_coffin
}
\cs_new_protected:Npn \coffin_attach_mark:NnnNnnnn #1#2#3#4#5#6#7#8
{
- \coffin_align:NnnNnnnnN
- #1 {#2} {#3} #4 {#5} {#6} {#7} {#8} \l_coffin_aligned_coffin
- \box_set_ht:Nn \l_coffin_aligned_coffin { \box_ht:N #1 }
- \box_set_dp:Nn \l_coffin_aligned_coffin { \box_dp:N #1 }
- \box_set_wd:Nn \l_coffin_aligned_coffin { \box_wd:N #1 }
- \box_set_eq:NN #1 \l_coffin_aligned_coffin
+ \@@_align:NnnNnnnnN
+ #1 {#2} {#3} #4 {#5} {#6} {#7} {#8} \l_@@_aligned_coffin
+ \box_set_ht:Nn \l_@@_aligned_coffin { \box_ht:N #1 }
+ \box_set_dp:Nn \l_@@_aligned_coffin { \box_dp:N #1 }
+ \box_set_wd:Nn \l_@@_aligned_coffin { \box_wd:N #1 }
+ \box_set_eq:NN #1 \l_@@_aligned_coffin
}
\cs_generate_variant:Nn \coffin_attach:NnnNnnnn { c , Nnnc , cnnc }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\coffin_align:NnnNnnnnN}
+% \begin{macro}{\@@_align:NnnNnnnnN}
% The internal function aligns the two coffins into a third one, but
% performs no corrections on the resulting coffin poles. The process
% begins by finding the points of intersection for the poles for each
@@ -1319,30 +1294,30 @@
% input coffins. The default poles are then set up, but the final result
% will depend on how the bounding box is being handled.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_align:NnnNnnnnN #1#2#3#4#5#6#7#8#9
+\cs_new_protected:Npn \@@_align:NnnNnnnnN #1#2#3#4#5#6#7#8#9
{
- \coffin_calculate_intersection:Nnn #4 {#5} {#6}
- \dim_set:Nn \l_coffin_x_prime_dim { \l_coffin_x_dim }
- \dim_set:Nn \l_coffin_y_prime_dim { \l_coffin_y_dim }
- \coffin_calculate_intersection:Nnn #1 {#2} {#3}
- \dim_set:Nn \l_coffin_offset_x_dim
- { \l_coffin_x_dim - \l_coffin_x_prime_dim + #7 }
- \dim_set:Nn \l_coffin_offset_y_dim
- { \l_coffin_y_dim - \l_coffin_y_prime_dim + #8 }
- \hbox_set:Nn \l_coffin_aligned_internal_coffin
+ \@@_calculate_intersection:Nnn #4 {#5} {#6}
+ \dim_set:Nn \l_@@_x_prime_dim { \l_@@_x_dim }
+ \dim_set:Nn \l_@@_y_prime_dim { \l_@@_y_dim }
+ \@@_calculate_intersection:Nnn #1 {#2} {#3}
+ \dim_set:Nn \l_@@_offset_x_dim
+ { \l_@@_x_dim - \l_@@_x_prime_dim + #7 }
+ \dim_set:Nn \l_@@_offset_y_dim
+ { \l_@@_y_dim - \l_@@_y_prime_dim + #8 }
+ \hbox_set:Nn \l_@@_aligned_internal_coffin
{
\box_use:N #1
\tex_kern:D -\box_wd:N #1
- \tex_kern:D \l_coffin_offset_x_dim
- \box_move_up:nn { \l_coffin_offset_y_dim } { \box_use:N #4 }
+ \tex_kern:D \l_@@_offset_x_dim
+ \box_move_up:nn { \l_@@_offset_y_dim } { \box_use:N #4 }
}
- \coffin_set_eq:NN #9 \l_coffin_aligned_internal_coffin
+ \coffin_set_eq:NN #9 \l_@@_aligned_internal_coffin
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\coffin_offset_poles:Nnn}
-% \begin{macro}[aux]{\coffin_offset_pole:Nnnnnnn}
+% \begin{macro}{\@@_offset_poles:Nnn}
+% \begin{macro}[aux]{\@@_offset_pole:Nnnnnnn}
% Transferring structures from one coffin to another requires that the
% positions are updated by the offset between the two coffins. This is
% done by mapping to the property list of the source coffins, moving
@@ -1353,22 +1328,22 @@
% or handle names, and that multiple alignments do not result in a
% whole set of values.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_offset_poles:Nnn #1#2#3
+\cs_new_protected:Npn \@@_offset_poles:Nnn #1#2#3
{
- \prop_map_inline:cn { l_coffin_poles_ \int_value:w #1 _prop }
- { \coffin_offset_pole:Nnnnnnn #1 {##1} ##2 {#2} {#3} }
+ \prop_map_inline:cn { l_@@_poles_ \__int_value:w #1 _prop }
+ { \@@_offset_pole:Nnnnnnn #1 {##1} ##2 {#2} {#3} }
}
-\cs_new_protected:Npn \coffin_offset_pole:Nnnnnnn #1#2#3#4#5#6#7#8
+\cs_new_protected:Npn \@@_offset_pole:Nnnnnnn #1#2#3#4#5#6#7#8
{
- \dim_set:Nn \l_coffin_x_dim { #3 + #7 }
- \dim_set:Nn \l_coffin_y_dim { #4 + #8 }
+ \dim_set:Nn \l_@@_x_dim { #3 + #7 }
+ \dim_set:Nn \l_@@_y_dim { #4 + #8 }
\tl_if_in:nnTF {#2} { - }
- { \tl_set:Nn \l_coffin_internal_tl { {#2} } }
- { \tl_set:Nn \l_coffin_internal_tl { { #1 - #2 } } }
- \exp_last_unbraced:NNo \coffin_set_pole:Nnx \l_coffin_aligned_coffin
- { \l_coffin_internal_tl }
+ { \tl_set:Nn \l_@@_internal_tl { {#2} } }
+ { \tl_set:Nn \l_@@_internal_tl { { #1 - #2 } } }
+ \exp_last_unbraced:NNo \@@_set_pole:Nnx \l_@@_aligned_coffin
+ { \l_@@_internal_tl }
{
- { \dim_use:N \l_coffin_x_dim } { \dim_use:N \l_coffin_y_dim }
+ { \dim_use:N \l_@@_x_dim } { \dim_use:N \l_@@_y_dim }
{#5} {#6}
}
}
@@ -1376,21 +1351,21 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\coffin_offset_corners:Nnn}
-% \begin{macro}[aux]{\coffin_offset_corners:Nnnnn}
+% \begin{macro}{\@@_offset_corners:Nnn}
+% \begin{macro}[aux]{\@@_offset_corner:Nnnnn}
% Saving the offset corners of a coffin is very similar, except that
% there is no need to worry about naming: every corner can be saved
% here as order is unimportant.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_offset_corners:Nnn #1#2#3
+\cs_new_protected:Npn \@@_offset_corners:Nnn #1#2#3
{
- \prop_map_inline:cn { l_coffin_corners_ \int_value:w #1 _prop }
- { \coffin_offset_corner:Nnnnn #1 {##1} ##2 {#2} {#3} }
+ \prop_map_inline:cn { l_@@_corners_ \__int_value:w #1 _prop }
+ { \@@_offset_corner:Nnnnn #1 {##1} ##2 {#2} {#3} }
}
-\cs_new_protected:Npn \coffin_offset_corner:Nnnnn #1#2#3#4#5#6
+\cs_new_protected:Npn \@@_offset_corner:Nnnnn #1#2#3#4#5#6
{
\prop_put:cnx
- { l_coffin_corners_ \int_value:w \l_coffin_aligned_coffin _prop }
+ { l_@@_corners_ \__int_value:w \l_@@_aligned_coffin _prop }
{ #1 - #2 }
{
{ \dim_eval:n { #3 + #5 } }
@@ -1401,46 +1376,46 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\coffin_update_vertical_poles:NNN}
-% \begin{macro}[aux]{\coffin_update_T:nnnnnnnnN}
-% \begin{macro}[aux]{\coffin_update_B:nnnnnnnnN}
+% \begin{macro}{\@@_update_vertical_poles:NNN}
+% \begin{macro}[aux]{\@@_update_T:nnnnnnnnN}
+% \begin{macro}[aux]{\@@_update_B:nnnnnnnnN}
% The \texttt{T} and \texttt{B} poles will need to be recalculated
% after alignment. These functions find the larger absolute value for
% the poles, but this is of course only logical when the poles are
% horizontal.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_update_vertical_poles:NNN #1#2#3
+\cs_new_protected:Npn \@@_update_vertical_poles:NNN #1#2#3
{
- \coffin_get_pole:NnN #3 { #1 -T } \l_coffin_pole_a_tl
- \coffin_get_pole:NnN #3 { #2 -T } \l_coffin_pole_b_tl
- \exp_last_two_unbraced:Noo \coffin_update_T:nnnnnnnnN
- \l_coffin_pole_a_tl \l_coffin_pole_b_tl #3
- \coffin_get_pole:NnN #3 { #1 -B } \l_coffin_pole_a_tl
- \coffin_get_pole:NnN #3 { #2 -B } \l_coffin_pole_b_tl
- \exp_last_two_unbraced:Noo \coffin_update_B:nnnnnnnnN
- \l_coffin_pole_a_tl \l_coffin_pole_b_tl #3
+ \@@_get_pole:NnN #3 { #1 -T } \l_@@_pole_a_tl
+ \@@_get_pole:NnN #3 { #2 -T } \l_@@_pole_b_tl
+ \exp_last_two_unbraced:Noo \@@_update_T:nnnnnnnnN
+ \l_@@_pole_a_tl \l_@@_pole_b_tl #3
+ \@@_get_pole:NnN #3 { #1 -B } \l_@@_pole_a_tl
+ \@@_get_pole:NnN #3 { #2 -B } \l_@@_pole_b_tl
+ \exp_last_two_unbraced:Noo \@@_update_B:nnnnnnnnN
+ \l_@@_pole_a_tl \l_@@_pole_b_tl #3
}
-\cs_new_protected:Npn \coffin_update_T:nnnnnnnnN #1#2#3#4#5#6#7#8#9
+\cs_new_protected:Npn \@@_update_T:nnnnnnnnN #1#2#3#4#5#6#7#8#9
{
\dim_compare:nNnTF {#2} < {#6}
{
- \coffin_set_pole:Nnx #9 { T }
+ \@@_set_pole:Nnx #9 { T }
{ { 0 pt } {#6} { 1000 pt } { 0 pt } }
}
{
- \coffin_set_pole:Nnx #9 { T }
+ \@@_set_pole:Nnx #9 { T }
{ { 0 pt } {#2} { 1000 pt } { 0 pt } }
}
}
-\cs_new_protected:Npn \coffin_update_B:nnnnnnnnN #1#2#3#4#5#6#7#8#9
+\cs_new_protected:Npn \@@_update_B:nnnnnnnnN #1#2#3#4#5#6#7#8#9
{
\dim_compare:nNnTF {#2} < {#6}
{
- \coffin_set_pole:Nnx #9 { B }
+ \@@_set_pole:Nnx #9 { B }
{ { 0 pt } {#2} { 1000 pt } { 0 pt } }
}
{
- \coffin_set_pole:Nnx #9 { B }
+ \@@_set_pole:Nnx #9 { B }
{ { 0 pt } {#6} { 1000 pt } { 0 pt } }
}
}
@@ -1456,556 +1431,120 @@
% \begin{macrocode}
\cs_new_protected:Npn \coffin_typeset:Nnnnn #1#2#3#4#5
{
- \coffin_align:NnnNnnnnN \c_empty_coffin { H } { l }
- #1 {#2} {#3} {#4} {#5} \l_coffin_aligned_coffin
+ \@@_align:NnnNnnnnN \c_empty_coffin { H } { l }
+ #1 {#2} {#3} {#4} {#5} \l_@@_aligned_coffin
\hbox_unpack:N \c_empty_box
- \box_use:N \l_coffin_aligned_coffin
+ \box_use:N \l_@@_aligned_coffin
}
\cs_generate_variant:Nn \coffin_typeset:Nnnnn { c }
% \end{macrocode}
% \end{macro}
%
-% \subsection{Rotating coffins}
-%
-% \begin{variable}{\l_coffin_bounding_prop}
-% A property list for the bounding box of a coffin. This is only needed
-% during the rotation, so there is just the one.
-% \begin{macrocode}
-\prop_new:N \l_coffin_bounding_prop
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_coffin_bounding_shift_dim}
-% The shift of the bounding box of a coffin from the real content.
-% \begin{macrocode}
-\dim_new:N \l_coffin_bounding_shift_dim
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_coffin_left_corner_dim}
-% \begin{variable}{\l_coffin_right_corner_dim}
-% \begin{variable}{\l_coffin_bottom_corner_dim}
-% \begin{variable}{\l_coffin_top_corner_dim}
-% These are used to hold maxima for the various corner values: these
-% thus define the minimum size of the bounding box after rotation.
-% \begin{macrocode}
-\dim_new:N \l_coffin_left_corner_dim
-\dim_new:N \l_coffin_right_corner_dim
-\dim_new:N \l_coffin_bottom_corner_dim
-\dim_new:N \l_coffin_top_corner_dim
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{macro}{\coffin_rotate:Nn, \coffin_rotate:cn}
-% Rotating a coffin requires several steps which can be conveniently
-% run together. The first step is to convert the angle given in degrees
-% to one in radians. This is then used to set \cs{l_coffin_sin_fp} and
-% \cs{l_coffin_cos_fp}, which are carried through unchanged for the rest
-% of the procedure.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_rotate:Nn #1#2
- {
- \fp_set:Nn \l_coffin_internal_fp {#2}
- \fp_div:Nn \l_coffin_internal_fp { 180 }
- \fp_mul:Nn \l_coffin_internal_fp { \c_pi_fp }
- \fp_sin:Nn \l_coffin_sin_fp { \l_coffin_internal_fp }
- \fp_cos:Nn \l_coffin_cos_fp { \l_coffin_internal_fp }
-% \end{macrocode}
-% The corners and poles of the coffin can now be rotated around the
-% origin. This is best achieved using mapping functions.
-% \begin{macrocode}
- \prop_map_inline:cn { l_coffin_corners_ \int_value:w #1 _prop }
- { \coffin_rotate_corner:Nnnn #1 {##1} ##2 }
- \prop_map_inline:cn { l_coffin_poles_ \int_value:w #1 _prop }
- { \coffin_rotate_pole:Nnnnnn #1 {##1} ##2 }
-% \end{macrocode}
-% The bounding box of the coffin needs to be rotated, and to do this
-% the corners have to be found first. They are then rotated in the same
-% way as the corners of the coffin material itself.
-% \begin{macrocode}
- \coffin_set_bounding:N #1
- \prop_map_inline:Nn \l_coffin_bounding_prop
- { \coffin_rotate_bounding:nnn {##1} ##2 }
-% \end{macrocode}
-% At this stage, there needs to be a calculation to find where the
-% corners of the content and the box itself will end up.
-% \begin{macrocode}
- \coffin_find_corner_maxima:N #1
- \coffin_find_bounding_shift:
- \box_rotate:Nn #1 {#2}
-% \end{macrocode}
-% The correction of the box position itself takes place here. The idea
-% is that the bounding box for a coffin is tight up to the content, and
-% has the reference point at the bottom-left. The $x$-direction is
-% handled by moving the content by the difference in the positions of
-% the bounding box and the content left edge. The $y$-direction is
-% dealt with by moving the box down by any depth it has acquired.
-% \begin{macrocode}
- \hbox_set:Nn #1
- {
- \tex_kern:D \l_coffin_bounding_shift_dim
- \tex_kern:D -\l_coffin_left_corner_dim
- \box_move_down:nn { \l_coffin_bottom_corner_dim }
- { \box_use:N #1 }
- }
-% \end{macrocode}
-% If there have been any previous rotations then the size of the
-% bounding box will be bigger than the contents. This can be corrected
-% easily by setting the size of the box to the height and width of the
-% content.
-% \begin{macrocode}
- \box_set_ht:Nn #1
- { \l_coffin_top_corner_dim - \l_coffin_bottom_corner_dim }
- \box_set_dp:Nn #1 { 0 pt }
- \box_set_wd:Nn #1
- { \l_coffin_right_corner_dim - \l_coffin_left_corner_dim }
-% \end{macrocode}
-% The final task is to move the poles and corners such that they are
-% back in alignment with the box reference point.
-% \begin{macrocode}
- \prop_map_inline:cn { l_coffin_corners_ \int_value:w #1 _prop }
- { \coffin_shift_corner:Nnnn #1 {##1} ##2 }
- \prop_map_inline:cn { l_coffin_poles_ \int_value:w #1 _prop }
- { \coffin_shift_pole:Nnnnnn #1 {##1} ##2 }
- }
-\cs_generate_variant:Nn \coffin_rotate:Nn { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\coffin_set_bounding:N}
-% The bounding box corners for a coffin are easy enough to find: this
-% is the same code as for the corners of the material itself, but
-% using a dedicated property list.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_set_bounding:N #1
- {
- \prop_put:Nnx \l_coffin_bounding_prop { tl }
- { { 0 pt } { \dim_use:N \box_ht:N #1 } }
- \prop_put:Nnx \l_coffin_bounding_prop { tr }
- { { \dim_use:N \box_wd:N #1 } { \dim_use:N \box_ht:N #1 } }
- \dim_set:Nn \l_coffin_internal_dim { - \box_dp:N #1 }
- \prop_put:Nnx \l_coffin_bounding_prop { bl }
- { { 0 pt } { \dim_use:N \l_coffin_internal_dim } }
- \prop_put:Nnx \l_coffin_bounding_prop { br }
- { { \dim_use:N \box_wd:N #1 } { \dim_use:N \l_coffin_internal_dim } }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\coffin_rotate_bounding:nnn}
-% \begin{macro}{\coffin_rotate_corner:Nnnn}
-% Rotating the position of the corner of the coffin is just a case
-% of treating this as a vector from the reference point. The same
-% treatment is used for the corners of the material itself and the
-% bounding box.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_rotate_bounding:nnn #1#2#3
- {
- \coffin_rotate_vector:nnNN {#2} {#3} \l_coffin_x_dim \l_coffin_y_dim
- \prop_put:Nnx \l_coffin_bounding_prop {#1}
- { { \dim_use:N \l_coffin_x_dim } { \dim_use:N \l_coffin_y_dim } }
- }
-\cs_new_protected:Npn \coffin_rotate_corner:Nnnn #1#2#3#4
- {
- \coffin_rotate_vector:nnNN {#3} {#4} \l_coffin_x_dim \l_coffin_y_dim
- \prop_put:cnx { l_coffin_corners_ \int_value:w #1 _prop } {#2}
- { { \dim_use:N \l_coffin_x_dim } { \dim_use:N \l_coffin_y_dim } }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\coffin_rotate_pole:Nnnnnn}
-% Rotating a single pole simply means shifting the co-ordinate of
-% the pole and its direction. The rotation here is about the bottom-left
-% corner of the coffin.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_rotate_pole:Nnnnnn #1#2#3#4#5#6
- {
- \coffin_rotate_vector:nnNN {#3} {#4} \l_coffin_x_dim \l_coffin_y_dim
- \coffin_rotate_vector:nnNN {#5} {#6}
- \l_coffin_x_prime_dim \l_coffin_y_prime_dim
- \coffin_set_pole:Nnx #1 {#2}
- {
- { \dim_use:N \l_coffin_x_dim } { \dim_use:N \l_coffin_y_dim }
- { \dim_use:N \l_coffin_x_prime_dim }
- { \dim_use:N \l_coffin_y_prime_dim }
- }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\coffin_rotate_vector:nnNN}
-% A rotation function, which needs only an input vector (as dimensions)
-% and an output space. The values \cs{l_coffin_cos_fp} and
-% \cs{l_coffin_sin_fp} should previously have been set up correctly.
-% Working this way means that the floating point work is kept to a
-% minimum: for any given rotation the sin and cosine values do no
-% change, after all.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_rotate_vector:nnNN #1#2#3#4
- {
- \fp_set_from_dim:Nn \l_coffin_x_fp {#1}
- \fp_set_from_dim:Nn \l_coffin_y_fp {#2}
- \fp_set_eq:NN \l_coffin_x_prime_fp \l_coffin_x_fp
- \fp_set_eq:NN \l_coffin_internal_fp \l_coffin_y_fp
- \fp_mul:Nn \l_coffin_x_prime_fp { \l_coffin_cos_fp }
- \fp_mul:Nn \l_coffin_internal_fp { \l_coffin_sin_fp }
- \fp_sub:Nn \l_coffin_x_prime_fp { \l_coffin_internal_fp }
- \fp_set_eq:NN \l_coffin_y_prime_fp \l_coffin_y_fp
- \fp_set_eq:NN \l_coffin_internal_fp \l_coffin_x_fp
- \fp_mul:Nn \l_coffin_y_prime_fp { \l_coffin_cos_fp }
- \fp_mul:Nn \l_coffin_internal_fp { \l_coffin_sin_fp }
- \fp_add:Nn \l_coffin_y_prime_fp { \l_coffin_internal_fp }
- \dim_set:Nn #3 { \fp_to_dim:N \l_coffin_x_prime_fp }
- \dim_set:Nn #4 { \fp_to_dim:N \l_coffin_y_prime_fp }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\coffin_find_corner_maxima:N}
-% \begin{macro}[aux]{\coffin_find_corner_maxima_aux:nn}
-% The idea here is to find the extremities of the content of the
-% coffin. This is done by looking for the smallest values for the bottom
-% and left corners, and the largest values for the top and right
-% corners. The values start at the maximum dimensions so that the
-% case where all are positive or all are negative works out correctly.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_find_corner_maxima:N #1
- {
- \dim_set:Nn \l_coffin_top_corner_dim { -\c_max_dim }
- \dim_set:Nn \l_coffin_right_corner_dim { -\c_max_dim }
- \dim_set:Nn \l_coffin_bottom_corner_dim { \c_max_dim }
- \dim_set:Nn \l_coffin_left_corner_dim { \c_max_dim }
- \prop_map_inline:cn { l_coffin_corners_ \int_value:w #1 _prop }
- { \coffin_find_corner_maxima_aux:nn ##2 }
- }
-\cs_new_protected:Npn \coffin_find_corner_maxima_aux:nn #1#2
- {
- \dim_set_min:Nn \l_coffin_left_corner_dim {#1}
- \dim_set_max:Nn \l_coffin_right_corner_dim {#1}
- \dim_set_min:Nn \l_coffin_bottom_corner_dim {#2}
- \dim_set_max:Nn \l_coffin_top_corner_dim {#2}
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\coffin_find_bounding_shift:}
-% \begin{macro}[aux]{\coffin_find_bounding_shift_aux:nn}
-% The approach to finding the shift for the bounding box is similar to
-% that for the corners. However, there is only one value needed here and
-% a fixed input property list, so things are a bit clearer.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \coffin_find_bounding_shift:
- {
- \dim_set:Nn \l_coffin_bounding_shift_dim { \c_max_dim }
- \prop_map_inline:Nn \l_coffin_bounding_prop
- { \coffin_find_bounding_shift_aux:nn ##2 }
- }
-\cs_new_protected:Npn \coffin_find_bounding_shift_aux:nn #1#2
- { \dim_set_min:Nn \l_coffin_bounding_shift_dim {#1} }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\coffin_shift_corner:Nnnn}
-% \begin{macro}{\coffin_shift_pole:Nnnnnn}
-% Shifting the corners and poles of a coffin means subtracting the
-% appropriate values from the $x$- and $y$-components. For
-% the poles, this means that the direction vector is unchanged.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_shift_corner:Nnnn #1#2#3#4
- {
- \prop_put:cnx { l_coffin_corners_ \int_value:w #1 _ prop } {#2}
- {
- { \dim_eval:n { #3 - \l_coffin_left_corner_dim } }
- { \dim_eval:n { #4 - \l_coffin_bottom_corner_dim } }
- }
- }
-\cs_new_protected:Npn \coffin_shift_pole:Nnnnnn #1#2#3#4#5#6
- {
- \prop_put:cnx { l_coffin_poles_ \int_value:w #1 _ prop } {#2}
- {
- { \dim_eval:n { #3 - \l_coffin_left_corner_dim } }
- { \dim_eval:n { #4 - \l_coffin_bottom_corner_dim } }
- {#5} {#6}
- }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Resizing coffins}
-%
-% \begin{variable}{\l_coffin_scale_x_fp}
-% \begin{variable}{\l_coffin_scale_y_fp}
-% Storage for the scaling factors in $x$ and $y$, respectively.
-% \begin{macrocode}
-\fp_new:N \l_coffin_scale_x_fp
-\fp_new:N \l_coffin_scale_y_fp
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\l_coffin_scaled_total_height_dim}
-% \begin{variable}{\l_coffin_scaled_width_dim}
-% When scaling, the values given have to be turned into absolute values.
-% \begin{macrocode}
-\dim_new:N \l_coffin_scaled_total_height_dim
-\dim_new:N \l_coffin_scaled_width_dim
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-%
-% \begin{macro}{\coffin_resize:Nnn, \coffin_resize:cnn}
-% Resizing a coffin begins by setting up the user-friendly names for
-% the dimensions of the coffin box. The new sizes are then turned into
-% scale factor. This is the same operation as takes place for the
-% underlying box, but that operation is grouped and so the same
-% calculation is done here.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_resize:Nnn #1#2#3
- {
- \coffin_set_user_dimensions:N #1
- \box_resize:Nnn #1 {#2} {#3}
- \fp_set_from_dim:Nn \l_coffin_scale_x_fp {#2}
- \fp_set_from_dim:Nn \l_coffin_internal_fp { \Width }
- \fp_div:Nn \l_coffin_scale_x_fp { \l_coffin_internal_fp }
- \fp_set_from_dim:Nn \l_coffin_scale_y_fp {#3}
- \fp_set_from_dim:Nn \l_coffin_internal_fp { \TotalHeight }
- \fp_div:Nn \l_coffin_scale_y_fp { \l_coffin_internal_fp }
- \coffin_resize_common:Nnn #1 {#2} {#3}
- }
-\cs_generate_variant:Nn \coffin_resize:Nnn { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\coffin_resize_common:Nnn}
-% The poles and corners of the coffin are scaled to the appropriate
-% places before actually resizing the underlying box.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_resize_common:Nnn #1#2#3
- {
- \prop_map_inline:cn { l_coffin_corners_ \int_value:w #1 _prop }
- { \coffin_scale_corner:Nnnn #1 {##1} ##2 }
- \prop_map_inline:cn { l_coffin_poles_ \int_value:w #1 _prop }
- { \coffin_scale_pole:Nnnnnn #1 {##1} ##2 }
-% \end{macrocode}
-% Negative $x$-scaling values will place the poles in the wrong
-% location: this is corrected here.
-% \begin{macrocode}
- \fp_compare:NNNT \l_coffin_scale_x_fp < \c_zero_fp
- {
- \prop_map_inline:cn { l_coffin_corners_ \int_value:w #1 _prop }
- { \coffin_x_shift_corner:Nnnn #1 {##1} ##2 }
- \prop_map_inline:cn { l_coffin_poles_ \int_value:w #1 _prop }
- { \coffin_x_shift_pole:Nnnnnn #1 {##1} ##2 }
- }
- \coffin_end_user_dimensions:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\coffin_scale:Nnn, \coffin_scale:cnn}
-% For scaling, the opposite calculation is done to find the new
-% dimensions for the coffin. Only the total height is needed, as this
-% is the shift required for corners and poles. The scaling is done
-% the \TeX{} way as this works properly with floating point values
-% without needing to use the \texttt{fp} module.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_scale:Nnn #1#2#3
- {
- \box_scale:Nnn #1 {#2} {#3}
- \coffin_set_user_dimensions:N #1
- \fp_set:Nn \l_coffin_scale_x_fp {#2}
- \fp_set:Nn \l_coffin_scale_y_fp {#3}
- \fp_compare:NNNTF \l_coffin_scale_y_fp > \c_zero_fp
- { \l_coffin_scaled_total_height_dim #3 \TotalHeight }
- { \l_coffin_scaled_total_height_dim -#3 \TotalHeight }
- \fp_compare:NNNTF \l_coffin_scale_x_fp > \c_zero_fp
- { \l_coffin_scaled_width_dim -#2 \Width }
- { \l_coffin_scaled_width_dim #2 \Width }
- \coffin_resize_common:Nnn #1
- { \l_coffin_scaled_width_dim } { \l_coffin_scaled_total_height_dim }
- }
-\cs_generate_variant:Nn \coffin_scale:Nnn { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\coffin_scale_vector:nnNN}
-% This functions scales a vector from the origin using the pre-set scale
-% factors in $x$ and $y$. This is a much less complex operation
-% than rotation, and as a result the code is a lot clearer.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_scale_vector:nnNN #1#2#3#4
- {
- \fp_set_from_dim:Nn \l_coffin_internal_fp {#1}
- \fp_mul:Nn \l_coffin_internal_fp { \l_coffin_scale_x_fp }
- \dim_set:Nn #3 { \fp_to_dim:N \l_coffin_internal_fp }
- \fp_set_from_dim:Nn \l_coffin_internal_fp {#2}
- \fp_mul:Nn \l_coffin_internal_fp { \l_coffin_scale_y_fp }
- \dim_set:Nn #4 { \fp_to_dim:N \l_coffin_internal_fp }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\coffin_scale_corner:Nnnn}
-% \begin{macro}{\coffin_scale_pole:Nnnnnn}
-% Scaling both corners and poles is a simple calculation using the
-% preceding vector scaling.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_scale_corner:Nnnn #1#2#3#4
- {
- \coffin_scale_vector:nnNN {#3} {#4} \l_coffin_x_dim \l_coffin_y_dim
- \prop_put:cnx { l_coffin_corners_ \int_value:w #1 _prop } {#2}
- { { \dim_use:N \l_coffin_x_dim } { \dim_use:N \l_coffin_y_dim } }
- }
-\cs_new_protected:Npn \coffin_scale_pole:Nnnnnn #1#2#3#4#5#6
- {
- \coffin_scale_vector:nnNN {#3} {#4} \l_coffin_x_dim \l_coffin_y_dim
- \coffin_set_pole:Nnx #1 {#2}
- {
- { \dim_use:N \l_coffin_x_dim } { \dim_use:N \l_coffin_y_dim }
- {#5} {#6}
- }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\coffin_x_shift_corner:Nnnn}
-% \begin{macro}{\coffin_x_shift_pole:Nnnnnn}
-% These functions correct for the $x$ displacement that takes
-% place with a negative horizontal scaling.
-% \begin{macrocode}
-\cs_new_protected:Npn \coffin_x_shift_corner:Nnnn #1#2#3#4
- {
- \prop_put:cnx { l_coffin_corners_ \int_value:w #1 _prop } {#2}
- {
- { \dim_eval:n { #3 + \box_wd:N #1 } } {#4}
- }
- }
-\cs_new_protected:Npn \coffin_x_shift_pole:Nnnnnn #1#2#3#4#5#6
- {
- \prop_put:cnx { l_coffin_poles_ \int_value:w #1 _prop } {#2}
- {
- { \dim_eval:n #3 + \box_wd:N #1 } {#4}
- {#5} {#6}
- }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
% \subsection{Coffin diagnostics}
%
-% \begin{variable}{\l_coffin_display_coffin}
-% \begin{variable}{\l_coffin_display_coord_coffin}
-% \begin{variable}{\l_coffin_display_pole_coffin}
+% \begin{variable}{\l_@@_display_coffin}
+% \begin{variable}{\l_@@_display_coord_coffin}
+% \begin{variable}{\l_@@_display_pole_coffin}
% Used for printing coffins with data structures attached.
% \begin{macrocode}
-\coffin_new:N \l_coffin_display_coffin
-\coffin_new:N \l_coffin_display_coord_coffin
-\coffin_new:N \l_coffin_display_pole_coffin
+\coffin_new:N \l_@@_display_coffin
+\coffin_new:N \l_@@_display_coord_coffin
+\coffin_new:N \l_@@_display_pole_coffin
% \end{macrocode}
% \end{variable}
% \end{variable}
% \end{variable}
%
-% \begin{variable}{\l_coffin_display_handles_prop}
+% \begin{variable}{\l_@@_display_handles_prop}
% This property list is used to print coffin handles at suitable
% positions. The offsets are expressed as multiples of the basic offset
% value, which therefore acts as a scale-factor.
% \begin{macrocode}
-\prop_new:N \l_coffin_display_handles_prop
-\prop_put:Nnn \l_coffin_display_handles_prop { tl }
+\prop_new:N \l_@@_display_handles_prop
+\prop_put:Nnn \l_@@_display_handles_prop { tl }
{ { b } { r } { -1 } { 1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { thc }
+\prop_put:Nnn \l_@@_display_handles_prop { thc }
{ { b } { hc } { 0 } { 1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { tr }
+\prop_put:Nnn \l_@@_display_handles_prop { tr }
{ { b } { l } { 1 } { 1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { vcl }
+\prop_put:Nnn \l_@@_display_handles_prop { vcl }
{ { vc } { r } { -1 } { 0 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { vchc }
+\prop_put:Nnn \l_@@_display_handles_prop { vchc }
{ { vc } { hc } { 0 } { 0 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { vcr }
+\prop_put:Nnn \l_@@_display_handles_prop { vcr }
{ { vc } { l } { 1 } { 0 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { bl }
+\prop_put:Nnn \l_@@_display_handles_prop { bl }
{ { t } { r } { -1 } { -1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { bhc }
+\prop_put:Nnn \l_@@_display_handles_prop { bhc }
{ { t } { hc } { 0 } { -1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { br }
+\prop_put:Nnn \l_@@_display_handles_prop { br }
{ { t } { l } { 1 } { -1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { Tl }
+\prop_put:Nnn \l_@@_display_handles_prop { Tl }
{ { t } { r } { -1 } { -1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { Thc }
+\prop_put:Nnn \l_@@_display_handles_prop { Thc }
{ { t } { hc } { 0 } { -1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { Tr }
+\prop_put:Nnn \l_@@_display_handles_prop { Tr }
{ { t } { l } { 1 } { -1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { Hl }
+\prop_put:Nnn \l_@@_display_handles_prop { Hl }
{ { vc } { r } { -1 } { 1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { Hhc }
+\prop_put:Nnn \l_@@_display_handles_prop { Hhc }
{ { vc } { hc } { 0 } { 1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { Hr }
+\prop_put:Nnn \l_@@_display_handles_prop { Hr }
{ { vc } { l } { 1 } { 1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { Bl }
+\prop_put:Nnn \l_@@_display_handles_prop { Bl }
{ { b } { r } { -1 } { -1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { Bhc }
+\prop_put:Nnn \l_@@_display_handles_prop { Bhc }
{ { b } { hc } { 0 } { -1 } }
-\prop_put:Nnn \l_coffin_display_handles_prop { Br }
+\prop_put:Nnn \l_@@_display_handles_prop { Br }
{ { b } { l } { 1 } { -1 } }
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_coffin_display_offset_dim}
+% \begin{variable}{\l_@@_display_offset_dim}
% The standard offset for the label from the handle position when
% displaying handles.
% \begin{macrocode}
-\dim_new:N \l_coffin_display_offset_dim
-\dim_set:Nn \l_coffin_display_offset_dim { 2 pt }
+\dim_new:N \l_@@_display_offset_dim
+\dim_set:Nn \l_@@_display_offset_dim { 2 pt }
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_coffin_display_x_dim}
-% \begin{variable}{\l_coffin_display_y_dim}
+% \begin{variable}{\l_@@_display_x_dim}
+% \begin{variable}{\l_@@_display_y_dim}
% As the intersections of poles have to be calculated to find which
% ones to print, there is a need to avoid repetition. This is done
% by saving the intersection into two dedicated values.
% \begin{macrocode}
-\dim_new:N \l_coffin_display_x_dim
-\dim_new:N \l_coffin_display_y_dim
+\dim_new:N \l_@@_display_x_dim
+\dim_new:N \l_@@_display_y_dim
% \end{macrocode}
% \end{variable}
% \end{variable}
%
-% \begin{variable}{\l_coffin_display_poles_prop}
+% \begin{variable}{\l_@@_display_poles_prop}
% A property list for printing poles: various things need to be deleted
% from this to get a \enquote{nice} output.
% \begin{macrocode}
-\prop_new:N \l_coffin_display_poles_prop
+\prop_new:N \l_@@_display_poles_prop
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_coffin_display_font_tl}
+% \begin{variable}{\l_@@_display_font_tl}
% Stores the settings used to print coffin data: this keeps things
% flexible.
% \begin{macrocode}
-\tl_new:N \l_coffin_display_font_tl
+\tl_new:N \l_@@_display_font_tl
%<*initex>
-\tl_set:Nn \l_coffin_display_font_tl { } % TODO
+\tl_set:Nn \l_@@_display_font_tl { } % TODO
%</initex>
%<*package>
-\tl_set:Nn \l_coffin_display_font_tl { \sffamily \tiny }
+\tl_set:Nn \l_@@_display_font_tl { \sffamily \tiny }
%</package>
% \end{macrocode}
% \end{variable}
%
% \begin{macro}{\coffin_mark_handle:Nnnn, \coffin_mark_handle:cnnn}
-% \begin{macro}[aux]{\coffin_mark_handle_aux:nnnnNnn}
+% \begin{macro}[aux]{\@@_mark_handle_aux:nnnnNnn}
% Marking a single handle is relatively easy. The standard attachment
% function is used, meaning that there are two calculations for the
% location. However, this is likely to be okay given the load expected.
@@ -2014,7 +1553,7 @@
% \begin{macrocode}
\cs_new_protected:Npn \coffin_mark_handle:Nnnn #1#2#3#4
{
- \hcoffin_set:Nn \l_coffin_display_pole_coffin
+ \hcoffin_set:Nn \l_@@_display_pole_coffin
{
%<*initex>
\hbox:n { \tex_vrule:D width 1 pt height 1 pt \scan_stop: } % TODO
@@ -2025,8 +1564,8 @@
%</package>
}
\coffin_attach_mark:NnnNnnnn #1 {#2} {#3}
- \l_coffin_display_pole_coffin { hc } { vc } { 0 pt } { 0 pt }
- \hcoffin_set:Nn \l_coffin_display_coord_coffin
+ \l_@@_display_pole_coffin { hc } { vc } { 0 pt } { 0 pt }
+ \hcoffin_set:Nn \l_@@_display_coord_coffin
{
%<*initex>
% TODO
@@ -2034,37 +1573,37 @@
%<*package>
\color {#4}
%</package>
- \l_coffin_display_font_tl
+ \l_@@_display_font_tl
( \tl_to_str:n { #2 , #3 } )
}
- \prop_get:NnN \l_coffin_display_handles_prop
- { #2 #3 } \l_coffin_internal_tl
- \quark_if_no_value:NTF \l_coffin_internal_tl
+ \prop_get:NnN \l_@@_display_handles_prop
+ { #2 #3 } \l_@@_internal_tl
+ \quark_if_no_value:NTF \l_@@_internal_tl
{
- \prop_get:NnN \l_coffin_display_handles_prop
- { #3 #2 } \l_coffin_internal_tl
- \quark_if_no_value:NTF \l_coffin_internal_tl
+ \prop_get:NnN \l_@@_display_handles_prop
+ { #3 #2 } \l_@@_internal_tl
+ \quark_if_no_value:NTF \l_@@_internal_tl
{
\coffin_attach_mark:NnnNnnnn #1 {#2} {#3}
- \l_coffin_display_coord_coffin { l } { vc }
+ \l_@@_display_coord_coffin { l } { vc }
{ 1 pt } { 0 pt }
}
{
- \exp_last_unbraced:No \coffin_mark_handle_aux:nnnnNnn
- \l_coffin_internal_tl #1 {#2} {#3}
+ \exp_last_unbraced:No \@@_mark_handle_aux:nnnnNnn
+ \l_@@_internal_tl #1 {#2} {#3}
}
}
{
- \exp_last_unbraced:No \coffin_mark_handle_aux:nnnnNnn
- \l_coffin_internal_tl #1 {#2} {#3}
+ \exp_last_unbraced:No \@@_mark_handle_aux:nnnnNnn
+ \l_@@_internal_tl #1 {#2} {#3}
}
}
-\cs_new_protected:Npn \coffin_mark_handle_aux:nnnnNnn #1#2#3#4#5#6#7
+\cs_new_protected:Npn \@@_mark_handle_aux:nnnnNnn #1#2#3#4#5#6#7
{
\coffin_attach_mark:NnnNnnnn #5 {#6} {#7}
- \l_coffin_display_coord_coffin {#1} {#2}
- { #3 \l_coffin_display_offset_dim }
- { #4 \l_coffin_display_offset_dim }
+ \l_@@_display_coord_coffin {#1} {#2}
+ { #3 \l_@@_display_offset_dim }
+ { #4 \l_@@_display_offset_dim }
}
\cs_generate_variant:Nn \coffin_mark_handle:Nnnn { c }
% \end{macrocode}
@@ -2072,9 +1611,9 @@
% \end{macro}
%
% \begin{macro}{\coffin_display_handles:Nn, \coffin_display_handles:cn}
-% \begin{macro}[aux]{\coffin_display_handles_aux:nnnnnn}
-% \begin{macro}[aux]{\coffin_display_handles_aux:nnnn}
-% \begin{macro}[aux]{\coffin_display_attach:Nnnnn}
+% \begin{macro}[aux]{\@@_display_handles_aux:nnnnnn}
+% \begin{macro}[aux]{\@@_display_handles_aux:nnnn}
+% \begin{macro}[aux]{\@@_display_attach:Nnnnn}
% Printing the poles starts by removing any duplicates, for which the
% \texttt{H} poles is used as the definitive version for the baseline
% and bottom. Two loops are then used to find the combinations of
@@ -2083,7 +1622,7 @@
% \begin{macrocode}
\cs_new_protected:Npn \coffin_display_handles:Nn #1#2
{
- \hcoffin_set:Nn \l_coffin_display_pole_coffin
+ \hcoffin_set:Nn \l_@@_display_pole_coffin
{
%<*initex>
\hbox:n { \tex_vrule:D width 1 pt height 1 pt \scan_stop: } % TODO
@@ -2093,22 +1632,22 @@
\rule { 1 pt } { 1 pt }
%</package>
}
- \prop_set_eq:Nc \l_coffin_display_poles_prop
- { l_coffin_poles_ \int_value:w #1 _prop }
- \coffin_get_pole:NnN #1 { H } \l_coffin_pole_a_tl
- \coffin_get_pole:NnN #1 { T } \l_coffin_pole_b_tl
- \tl_if_eq:NNT \l_coffin_pole_a_tl \l_coffin_pole_b_tl
- { \prop_del:Nn \l_coffin_display_poles_prop { T } }
- \coffin_get_pole:NnN #1 { B } \l_coffin_pole_b_tl
- \tl_if_eq:NNT \l_coffin_pole_a_tl \l_coffin_pole_b_tl
- { \prop_del:Nn \l_coffin_display_poles_prop { B } }
- \coffin_set_eq:NN \l_coffin_display_coffin #1
- \prop_map_inline:Nn \l_coffin_display_poles_prop
+ \prop_set_eq:Nc \l_@@_display_poles_prop
+ { l_@@_poles_ \__int_value:w #1 _prop }
+ \@@_get_pole:NnN #1 { H } \l_@@_pole_a_tl
+ \@@_get_pole:NnN #1 { T } \l_@@_pole_b_tl
+ \tl_if_eq:NNT \l_@@_pole_a_tl \l_@@_pole_b_tl
+ { \prop_remove:Nn \l_@@_display_poles_prop { T } }
+ \@@_get_pole:NnN #1 { B } \l_@@_pole_b_tl
+ \tl_if_eq:NNT \l_@@_pole_a_tl \l_@@_pole_b_tl
+ { \prop_remove:Nn \l_@@_display_poles_prop { B } }
+ \coffin_set_eq:NN \l_@@_display_coffin #1
+ \prop_map_inline:Nn \l_@@_display_poles_prop
{
- \prop_del:Nn \l_coffin_display_poles_prop {##1}
- \coffin_display_handles_aux:nnnnnn {##1} ##2 {#2}
+ \prop_remove:Nn \l_@@_display_poles_prop {##1}
+ \@@_display_handles_aux:nnnnnn {##1} ##2 {#2}
}
- \box_use:N \l_coffin_display_coffin
+ \box_use:N \l_@@_display_coffin
}
% \end{macrocode}
% For each pole there is a check for an intersection, which here does
@@ -2116,20 +1655,20 @@
% and used to align the pole coffin with the main coffin for output.
% The positions are recovered from the preset list if available.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_display_handles_aux:nnnnnn #1#2#3#4#5#6
+\cs_new_protected:Npn \@@_display_handles_aux:nnnnnn #1#2#3#4#5#6
{
- \prop_map_inline:Nn \l_coffin_display_poles_prop
+ \prop_map_inline:Nn \l_@@_display_poles_prop
{
- \bool_set_false:N \l_coffin_error_bool
- \coffin_calculate_intersection:nnnnnnnn {#2} {#3} {#4} {#5} ##2
- \bool_if:NF \l_coffin_error_bool
+ \bool_set_false:N \l_@@_error_bool
+ \@@_calculate_intersection:nnnnnnnn {#2} {#3} {#4} {#5} ##2
+ \bool_if:NF \l_@@_error_bool
{
- \dim_set:Nn \l_coffin_display_x_dim { \l_coffin_x_dim }
- \dim_set:Nn \l_coffin_display_y_dim { \l_coffin_y_dim }
- \coffin_display_attach:Nnnnn
- \l_coffin_display_pole_coffin { hc } { vc }
+ \dim_set:Nn \l_@@_display_x_dim { \l_@@_x_dim }
+ \dim_set:Nn \l_@@_display_y_dim { \l_@@_y_dim }
+ \@@_display_attach:Nnnnn
+ \l_@@_display_pole_coffin { hc } { vc }
{ 0 pt } { 0 pt }
- \hcoffin_set:Nn \l_coffin_display_coord_coffin
+ \hcoffin_set:Nn \l_@@_display_coord_coffin
{
%<*initex>
% TODO
@@ -2137,40 +1676,40 @@
%<*package>
\color {#6}
%</package>
- \l_coffin_display_font_tl
+ \l_@@_display_font_tl
( \tl_to_str:n { #1 , ##1 } )
}
- \prop_get:NnN \l_coffin_display_handles_prop
- { #1 ##1 } \l_coffin_internal_tl
- \quark_if_no_value:NTF \l_coffin_internal_tl
+ \prop_get:NnN \l_@@_display_handles_prop
+ { #1 ##1 } \l_@@_internal_tl
+ \quark_if_no_value:NTF \l_@@_internal_tl
{
- \prop_get:NnN \l_coffin_display_handles_prop
- { ##1 #1 } \l_coffin_internal_tl
- \quark_if_no_value:NTF \l_coffin_internal_tl
+ \prop_get:NnN \l_@@_display_handles_prop
+ { ##1 #1 } \l_@@_internal_tl
+ \quark_if_no_value:NTF \l_@@_internal_tl
{
- \coffin_display_attach:Nnnnn
- \l_coffin_display_coord_coffin { l } { vc }
+ \@@_display_attach:Nnnnn
+ \l_@@_display_coord_coffin { l } { vc }
{ 1 pt } { 0 pt }
}
{
\exp_last_unbraced:No
- \coffin_display_handles_aux:nnnn
- \l_coffin_internal_tl
+ \@@_display_handles_aux:nnnn
+ \l_@@_internal_tl
}
}
{
- \exp_last_unbraced:No \coffin_display_handles_aux:nnnn
- \l_coffin_internal_tl
+ \exp_last_unbraced:No \@@_display_handles_aux:nnnn
+ \l_@@_internal_tl
}
}
}
}
-\cs_new_protected:Npn \coffin_display_handles_aux:nnnn #1#2#3#4
+\cs_new_protected:Npn \@@_display_handles_aux:nnnn #1#2#3#4
{
- \coffin_display_attach:Nnnnn
- \l_coffin_display_coord_coffin {#1} {#2}
- { #3 \l_coffin_display_offset_dim }
- { #4 \l_coffin_display_offset_dim }
+ \@@_display_attach:Nnnnn
+ \l_@@_display_coord_coffin {#1} {#2}
+ { #3 \l_@@_display_offset_dim }
+ { #4 \l_@@_display_offset_dim }
}
\cs_generate_variant:Nn \coffin_display_handles:Nn { c }
% \end{macrocode}
@@ -2179,29 +1718,29 @@
% and stored for the display coffin the code simply uses it directly,
% with no calculation.
% \begin{macrocode}
-\cs_new_protected:Npn \coffin_display_attach:Nnnnn #1#2#3#4#5
+\cs_new_protected:Npn \@@_display_attach:Nnnnn #1#2#3#4#5
{
- \coffin_calculate_intersection:Nnn #1 {#2} {#3}
- \dim_set:Nn \l_coffin_x_prime_dim { \l_coffin_x_dim }
- \dim_set:Nn \l_coffin_y_prime_dim { \l_coffin_y_dim }
- \dim_set:Nn \l_coffin_offset_x_dim
- { \l_coffin_display_x_dim - \l_coffin_x_prime_dim + #4 }
- \dim_set:Nn \l_coffin_offset_y_dim
- { \l_coffin_display_y_dim - \l_coffin_y_prime_dim + #5 }
- \hbox_set:Nn \l_coffin_aligned_coffin
+ \@@_calculate_intersection:Nnn #1 {#2} {#3}
+ \dim_set:Nn \l_@@_x_prime_dim { \l_@@_x_dim }
+ \dim_set:Nn \l_@@_y_prime_dim { \l_@@_y_dim }
+ \dim_set:Nn \l_@@_offset_x_dim
+ { \l_@@_display_x_dim - \l_@@_x_prime_dim + #4 }
+ \dim_set:Nn \l_@@_offset_y_dim
+ { \l_@@_display_y_dim - \l_@@_y_prime_dim + #5 }
+ \hbox_set:Nn \l_@@_aligned_coffin
{
- \box_use:N \l_coffin_display_coffin
- \tex_kern:D -\box_wd:N \l_coffin_display_coffin
- \tex_kern:D \l_coffin_offset_x_dim
- \box_move_up:nn { \l_coffin_offset_y_dim } { \box_use:N #1 }
+ \box_use:N \l_@@_display_coffin
+ \tex_kern:D -\box_wd:N \l_@@_display_coffin
+ \tex_kern:D \l_@@_offset_x_dim
+ \box_move_up:nn { \l_@@_offset_y_dim } { \box_use:N #1 }
}
- \box_set_ht:Nn \l_coffin_aligned_coffin
- { \box_ht:N \l_coffin_display_coffin }
- \box_set_dp:Nn \l_coffin_aligned_coffin
- { \box_dp:N \l_coffin_display_coffin }
- \box_set_wd:Nn \l_coffin_aligned_coffin
- { \box_wd:N \l_coffin_display_coffin }
- \box_set_eq:NN \l_coffin_display_coffin \l_coffin_aligned_coffin
+ \box_set_ht:Nn \l_@@_aligned_coffin
+ { \box_ht:N \l_@@_display_coffin }
+ \box_set_dp:Nn \l_@@_aligned_coffin
+ { \box_dp:N \l_@@_display_coffin }
+ \box_set_wd:Nn \l_@@_aligned_coffin
+ { \box_wd:N \l_@@_display_coffin }
+ \box_set_eq:NN \l_@@_display_coffin \l_@@_aligned_coffin
}
% \end{macrocode}
% \end{macro}
@@ -2216,13 +1755,13 @@
% \begin{macrocode}
\cs_new_protected:Npn \coffin_show_structure:N #1
{
- \coffin_if_exist:NT #1
+ \@@_if_exist:NT #1
{
- \msg_aux_show:Nnx #1 { coffins }
+ \__msg_show_variable:Nnn #1 { coffins }
{
\prop_map_function:cN
- { l_coffin_poles_ \int_value:w #1 _prop }
- \msg_aux_show_unbraced:nn
+ { l_@@_poles_ \__int_value:w #1 _prop }
+ \__msg_show_item_unbraced:nn
}
}
}
@@ -2233,7 +1772,7 @@
% \subsection{Messages}
%
% \begin{macrocode}
-\msg_kernel_new:nnnn { coffins } { no-pole-intersection }
+\__msg_kernel_new:nnnn { kernel } { no-pole-intersection }
{ No~intersection~between~coffin~poles. }
{
\c_msg_coding_error_text_tl
@@ -2241,17 +1780,17 @@
but~they~do~not~have~a~unique~meeting~point:~
the~value~(0~pt,~0~pt)~will~be~used.
}
-\msg_kernel_new:nnnn { coffins } { unknown-coffin }
+\__msg_kernel_new:nnnn { kernel } { unknown-coffin }
{ Unknown~coffin~'#1'. }
{ The~coffin~'#1'~was~never~defined. }
-\msg_kernel_new:nnnn { coffins } { unknown-coffin-pole }
+\__msg_kernel_new:nnnn { kernel } { unknown-coffin-pole }
{ Pole~'#1'~unknown~for~coffin~'#2'. }
{
\c_msg_coding_error_text_tl
LaTeX~was~asked~to~find~a~typesetting~pole~for~a~coffin,~
but~either~the~coffin~does~not~exist~or~the~pole~name~is~wrong.
}
-\msg_kernel_new:nnn { coffins } { show }
+\__msg_kernel_new:nnn { kernel } { show-coffins }
{
Size~of~coffin~\token_to_str:N #1 : \\
> ~ ht~=~\dim_use:N \box_ht:N #1 \\
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
index 2089859d4e3..e8aa1f5d050 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3color.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3color.dtx Copyright(C) 2011 The LaTeX3 Project
+%% File: l3color.dtx Copyright(C) 2011,2012 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
@@ -36,7 +36,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3color.dtx 2776 2011-09-07 18:33:19Z joseph $
+\GetIdInfo$Id: l3color.dtx 3986 2012-07-15 19:23:51Z joseph $
{L3 Experimental colour support}
%</driver|package>
%<*driver>
@@ -111,7 +111,7 @@
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -135,10 +135,27 @@
% \begin{macrocode}
%<*initex>
\cs_new_protected_nopar:Npn \color_ensure_current:
- { \driver_color_ensure_current: }
+ { \__driver_color_ensure_current: }
%</initex>
+% \end{macrocode}
+% In package mode, the driver code may not be loaded. To keep down
+% dependencies, if there is no driver code available and no \cs{set@color}
+% then colour is not in use and this function can be a no-op.
+% \begin{macrocode}
%<*package>
-\cs_new_protected_nopar:Npn \color_ensure_current: { \set@color }
+\cs_new_protected_nopar:Npn \color_ensure_current: { }
+\AtBeginDocument
+ {
+ \cs_if_exist:NTF \__driver_color_ensure_current:
+ {
+ \cs_set_protected_nopar:Npn \color_ensure_current:
+ { \__driver_color_ensure_current: }
+ }
+ {
+ \cs_if_exist:NT \set@color
+ { \cs_set_protected_nopar:Npn \color_ensure_current: { \set@color } }
+ }
+ }
%</package>
% \end{macrocode}
% \end{macro}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
index 8eec496836e..137d75f056f 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3doc.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3doc.dtx Copyright (C) 1990-2011 The LaTeX3 project
+%% File: l3doc.dtx Copyright (C) 1990-2012 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
@@ -55,7 +55,7 @@ Do not distribute a modified version of this file.
% stop docstrip adding \endinput
\postamble
\endpostamble
-\generate{\file{l3doc.cls}{\from{l3doc.dtx}{class}}}
+\generate{\file{l3doc.cls}{\from{l3doc.dtx}{class,cfg}}}
\generate{\file{l3doc.ist}{\from{l3doc.dtx}{docist}}}
\ifx\fmtname\nameofplainTeX
\expandafter\endbatchfile
@@ -64,10 +64,6 @@ Do not distribute a modified version of this file.
\fi
%</driver>
%
-%<*driver|class>
-\RequirePackage{expl3,xparse,calc}
-%</driver|class>
-%
% Need to protect the file metadata for any modules that load l3doc.
% This is restored after "\ProvideExplClass" below.
% \begin{macrocode}
@@ -78,7 +74,11 @@ Do not distribute a modified version of this file.
% \end{macrocode}
%
%<*driver|class>
-\GetIdInfo$Id: l3doc.dtx 3491 2012-03-04 06:13:18Z bruno $
+\RequirePackage{expl3,xparse,calc}
+%</driver|class>
+%
+%<*driver|class>
+\GetIdInfo$Id: l3doc.dtx 3989 2012-07-16 01:15:43Z bruno $
{L3 Experimental documentation class}
%</driver|class>
%
@@ -265,7 +265,7 @@ Do not distribute a modified version of this file.
% when the DTX file is "\DocInput"; use "\DisableDocumentation"/"\DisableImplementation"
% to omit the contents of those environments.
%
-% Note that \cmd\DocInput\ now takes comma-separated arguments, and \cmd\DocInputAgain\
+% Note that "\DocInput" now takes comma-separated arguments, and "\DocInputAgain"
% can be used to re-input all DTX files previously input in this way.
%
% \subsection{Describing functions in the documentation}
@@ -463,16 +463,6 @@ Do not distribute a modified version of this file.
%<*class>
% \end{macrocode}
%
-% The Guilty Parties.
-% \begin{macrocode}
-\cs_new_nopar:Npn\Team{%
- The~\LaTeX3~Project\thanks{%
- Frank~Mittelbach,~Denys~Duchier,~Chris~Rowley,~
- Rainer~Sch\"opf,~Johannes~Braams,~Michael~Downes,~
- David~Carlisle,~Alan~Jeffrey,~Morten~H\o{}gholm,~Thomas~Lotze,~
- Javier~Bezos,~Will~Robertson,~Joseph~Wright,~Bruno~Le~Floch}}
-% \end{macrocode}
-%
% \subsection{Variables}
%
% \begin{macrocode}
@@ -518,6 +508,19 @@ Do not distribute a modified version of this file.
\bool_new:N \g_doc_checktest_bool
% \end{macrocode}
%
+% Temporaries:
+% \begin{macrocode}
+\seq_new:N \g_doc_tmpa_seq
+\tl_new:N \l_doc_tmpa_tl
+\tl_new:N \l_doc_tmpb_tl
+\int_new:N \l_doc_tmpa_int
+% \end{macrocode}
+%
+% Other:
+% \begin{macrocode}
+\bool_new:N \l_doc_tested_bool
+% \end{macrocode}
+%
% \subsection{expl3 extras}
%
% \begin{macro}
@@ -526,18 +529,20 @@ Do not distribute a modified version of this file.
% \coffin_gset_eq:cN, \coffin_gset_eq:cc
% }
% Setting two coffins equal is just a wrapper around other functions.
+% Slightly naughty use of an internal coffin function here, but \ldots
% \begin{macrocode}
\cs_set_protected_nopar:Npn \coffin_gset_eq:NN #1#2
{
\coffin_if_exist:NT #1
{
\box_gset_eq:NN #1 #2
- \coffin_gset_eq_structure:NN #1 #2
+ \__coffin_gset_eq_structure:NN #1 #2
}
}
\cs_generate_variant:Nn \coffin_gset_eq:NN { c , Nc , cc }
% \end{macrocode}
% \end{macro}
+%
%
% \subsection{Options and configuration}
%
@@ -571,16 +576,18 @@ Do not distribute a modified version of this file.
\ExecuteOptions{full,a4paper,nocheck,nochecktest,lm-default}
% \end{macrocode}
%
-% Input a local configuration file, if it exists.
+% Input a local configuration file, if it exists, with a message to the console that this has happened. Since we distribute a cfg file with the class, this should usually always be true. Therefore, check for \cs{ExplMakeTitle} (defined in `our' cfg file) and only output the informational message if it's not found.
%
% \begin{macrocode}
-\InputIfFileExists{l3doc.cfg}
+\msg_new:nnn {l3doc} {input-cfg}
{
- \typeout{*************************************^^J
- *~Local~config~file~l3doc.cfg~used ^^J
- *************************************}
+ Local~config~file~l3doc.cfg~loaded.
+ }
+\file_if_exist:nT {l3doc.cfg}
+ {
+ \file_input:n {l3doc.cfg}
+ \msg_info:nn {l3doc} {input-cfg}
}
- { \@input{l3doc.ltx} }
% \end{macrocode}
%
% \begin{macrocode}
@@ -597,6 +604,7 @@ Do not distribute a modified version of this file.
{
array,
alphalph,
+ amsmath,
booktabs,
color,
colortbl,
@@ -679,9 +687,9 @@ Do not distribute a modified version of this file.
% \begin{macrocode}
\setcounter{StandardModuleDepth}{1}
\@addtoreset{CodelineNo}{part}
-\cs_set_nopar:Npn \theCodelineNo {
- \textcolor[gray]{0.5}{ \sffamily\tiny\arabic{CodelineNo} }
-}
+\tl_replace_once:Nnn \theCodelineNo
+ { \HDorg@theCodelineNo }
+ { \textcolor[gray]{0.5} { \sffamily\tiny\arabic{CodelineNo} } }
% \end{macrocode}
%
%
@@ -762,13 +770,29 @@ Do not distribute a modified version of this file.
% \end{macrocode}
%
% \begin{macro}{\cmd,\cs}
-% |\cmd{\foo}| Prints |\foo| verbatim. It may be used inside moving
-% arguments. |\cs{foo}| also prints |\foo|, for those who prefer that
-% syntax.
-% \begin{macrocode}
-\cs_set_nopar:Npn \cmd #1 { \cs{\expandafter\cmd@to@cs\string#1} }
-\cs_set_nopar:Npn \cmd@to@cs #1#2 { \char\number`#2\relax }
-\DeclareRobustCommand \cs [1] { \texttt { \char`\\ #1 } }
+% |\cmd{\foo}| Prints |\foo| verbatim. It may be used inside moving
+% arguments. |\cs{foo}| also prints |\foo|, for those who prefer that
+% syntax. There is a bit of shuffling around to make sure that |_|
+% has the catcode that \cs{doc_replace_at_at:N} expects, without
+% rescanning the whole argument. For that we store in
+% \cs{l_doc_tmpb_tl} a single underscore with the current catcode,
+% then replace all such underscores by letter underscores in |#1|
+% (stored in the |tmpa| token list). After calling
+% \cs{doc_replace_at_at:N}, we replace the underscores back to their
+% old meaning before using the token list.
+% \begin{macrocode}
+\cs_set_nopar:Npn \cmd #1 { \cs{\expandafter \doc_cmd_to_cs:w \string#1} }
+\cs_set_nopar:Npn \doc_cmd_to_cs:w #1#2 { \char\number`#2\relax }
+\DeclareRobustCommand \cs [1]
+ {
+ \tl_set_rescan:Nnn \l_doc_tmpb_tl { } { _ }
+ \tl_set:Nn \l_doc_tmpa_tl {#1}
+ \tl_replace_all:NVn \l_doc_tmpa_tl \l_doc_tmpb_tl { _ }
+ \doc_replace_at_at:N \l_doc_tmpa_tl
+ \tl_replace_all:NnV \l_doc_tmpa_tl { _ } \l_doc_tmpb_tl
+ \texttt { \char`\\ \tl_use:N \l_doc_tmpa_tl}
+ }
+\cs_generate_variant:Nn \tl_replace_all:Nnn { NV , NnV }
% \end{macrocode}
% \end{macro}
%
@@ -823,7 +847,7 @@ Do not distribute a modified version of this file.
% \begin{macro}{\DisableDocumentation,\DisableImplementation}
% \begin{macrocode}
\cs_new:Npn \doc_implementation: {
- \cs_set:Npn \variable {\macro[var]}
+ \DeclareDocumentCommand {\variable} { O{} } { \doc_macro:n { var , ##1 } }
\cs_set_eq:NN \endvariable \endmacro
}
\cs_new:Npn \doc_docu: {
@@ -931,8 +955,9 @@ Do not distribute a modified version of this file.
\char_set_catcode_ignore:N \ % space
\char_set_catcode_ignore:N \^^M
\char_set_catcode_ignore:N \^^I
-
- \function_aux:n
+ \exp_after:wN
+ \group_end:
+ \function_aux:n
}
{
\vcoffin_set_end:
@@ -989,8 +1014,6 @@ Do not distribute a modified version of this file.
% \begin{macrocode}
\cs_set_nopar:Npn \function_aux:n #1 {
- \group_end:
-
\tl_set:Nn \l_doc_function_input_tl {#1}
\dim_zero:N \l_doc_trial_width_dim
@@ -1027,7 +1050,7 @@ Do not distribute a modified version of this file.
% about the functions being typeset and their variants.
% The property list uses a specific format: the keys contained are the function `names' (stripped of signature) with values specified by a comma-separated list containing two brace groups per item:
% \begin{center}
-% "> {my_function} => { {" \meta{Nargs 1} "}{" \meta{sig.\ 1} "} , {" \meta{Nargs 2} "}{" \meta{sig.\ 2} "} , ... }"
+% |> {my_function} => {| \Arg{Nargs_1} \Arg{sig_1} |,| \Arg{Nargs_2} \Arg{sig_2} |, ... }|
% \end{center}
% This somewhat arcane syntax is chosen to distinguish between all variants of control sequence that may be being documented here. (With or without \textsf{expl3} function syntax.)
% \begin{macrocode}
@@ -1048,22 +1071,22 @@ Do not distribute a modified version of this file.
% finally, for regular old csnames:
\exp_args:NNf \prop_get:NnNTF
\l_doc_functions_block_prop
- { \cs_get_function_name:N #1 } \l_doc_tmp_tl
+ { \__cs_get_function_name:N #1 } \l_doc_tmpb_tl
{
\prop_put:Nxx \l_doc_functions_block_prop
- { \cs_get_function_name:N #1 }
+ { \__cs_get_function_name:N #1 }
{
- \l_doc_tmp_tl ,
- {\cs_get_arg_count_from_signature:N #1}
- {\cs_get_function_signature:N #1}
+ \l_doc_tmpb_tl ,
+ {\__cs_count_signature:N #1}
+ {\__cs_get_function_signature:N #1}
}
}
{
\prop_put:Nxx \l_doc_functions_block_prop
- { \cs_get_function_name:N #1 }
+ { \__cs_get_function_name:N #1 }
{
- {\cs_get_arg_count_from_signature:N #1}
- {\cs_get_function_signature:N #1}
+ {\__cs_count_signature:N #1}
+ {\__cs_get_function_signature:N #1}
}
}
}
@@ -1072,7 +1095,7 @@ Do not distribute a modified version of this file.
{
% for now don't bother splitting into variants:
\tl_gclear:N \l_doc_function_name_prefix_tl
- \prop_put:Nxx \l_doc_functions_block_prop { #1 } { {-1} {} }
+ \prop_put:Nxx \l_doc_functions_block_prop { \tl_to_str:n {#1} } { {-1} {} }
}
}
@@ -1091,13 +1114,13 @@ Do not distribute a modified version of this file.
\cs_new:Nn \doc_typeset_functions:nn
{
\clist_gset:Nn \l_doc_variants_clist {#2}
- \clist_gpop:NN \l_doc_variants_clist \l_doc_tmp_tl
+ \clist_gpop:NN \l_doc_variants_clist \l_doc_tmpb_tl
\exp_args:Nc \doc_typeset_functions_aux:N
{
#1
- \int_compare:nT { \exp_after:wN \use_i:nn \l_doc_tmp_tl > -1 } {:}
- \int_compare:nT { \exp_after:wN \use_i:nn \l_doc_tmp_tl > 0 }
- { \exp_after:wN \use_ii:nn \l_doc_tmp_tl }
+ \int_compare:nT { \exp_after:wN \use_i:nn \l_doc_tmpb_tl > -1 } {:}
+ \int_compare:nT { \exp_after:wN \use_i:nn \l_doc_tmpb_tl > 0 }
+ { \exp_after:wN \use_ii:nn \l_doc_tmpb_tl }
}
\\
}
@@ -1105,18 +1128,22 @@ Do not distribute a modified version of this file.
\cs_new_nopar:Nn \doc_typeset_functions_aux:N
{
\bool_if:NT \l_doc_meta_pTF_bool {
+ \tl_set:Nx \l_doc_pTF_name_tl
+ { \l_doc_function_name_prefix_tl \doc_predicate_from_base:N #1 }
+ \doc_special_main_index:o { \l_doc_pTF_name_tl }
+ \seq_gput_right:Nx \g_doc_functions_seq
+ { \tl_to_str:N \l_doc_pTF_name_tl }
\tl_set:Nx \l_doc_pTF_name_tl { \doc_predicate_from_base:N #1 }
- \doc_special_main_index:o { \tl_to_str:N \l_doc_pTF_name_tl }
- \seq_gput_right:Nx \g_doc_functions_seq { \l_doc_function_name_prefix_tl \l_doc_pTF_name_tl }
}
- \bool_if:NTF \l_doc_meta_TF_bool {
- \doc_special_main_index:o { \token_to_str:N #1 TF }
- \seq_gput_right:Nx \g_doc_functions_seq { \token_to_str:N #1 TF }
- }{
- \doc_special_main_index:o { \token_to_str:N #1 }
- \seq_gput_right:Nx \g_doc_functions_seq { \tl_to_str:n {#1} }
- }
+ \tl_set:Nx \l_doc_tmpa_tl
+ {
+ \l_doc_function_name_prefix_tl
+ \cs_to_str:N #1
+ \bool_if:NT \l_doc_meta_TF_bool { \tl_to_str:n {TF} }
+ }
+ \doc_special_main_index:o { \l_doc_tmpa_tl }
+ \seq_gput_right:No \g_doc_functions_seq { \l_doc_tmpa_tl }
\bool_if:NTF \l_doc_meta_pTF_bool {
@@ -1139,24 +1166,19 @@ Do not distribute a modified version of this file.
% \begin{macro}[internal]{\doc_typeset_function_block:N}
% \begin{macrocode}
\cs_set_nopar:Nn \doc_typeset_function_block:N {
- \tl_gset:Nx \l_doc_function_name_tl { \cs_get_function_name:N #1 }
- \tl_gset:Nx \l_doc_function_sig_tl { \cs_get_function_signature:N #1 }
+ \tl_gset:Nx \l_doc_function_name_tl { \__cs_get_function_name:N #1 }
+ \tl_gset:Nx \l_doc_function_sig_tl { \__cs_get_function_signature:N #1 }
\tl_gset:Nx \g_doc_macro_tl { \l_doc_function_name_prefix_tl \l_doc_function_name_tl }
\doc_typeset_function_basename:N #1
\bool_if:NT \l_doc_meta_TF_bool { \doc_typeset_TF: }
\doc_typeset_expandability:
\clist_if_empty:NF \l_doc_variants_clist { \doc_typeset_variants: }
- \bool_if:NT \g_doc_full_bool { \doc_label_function: }
+ \bool_if:NT \g_doc_full_bool { \doc_label_function:N #1 }
}
\cs_set:Nn \doc_typeset_function_basename:N
- {
- \g_doc_macro_tl
- \int_compare:nT { \cs_get_arg_count_from_signature:N #1 > -1 } { : }
- \int_compare:nT { \cs_get_arg_count_from_signature:N #1 > 0 }
- { \l_doc_function_sig_tl }
- }
+ { \l_doc_function_name_prefix_tl \cs_to_str:N #1 }
\cs_set:Nn \doc_typeset_expandability:
{
&
@@ -1173,12 +1195,12 @@ Do not distribute a modified version of this file.
{
\\
\doc_typeset_aux:n \g_doc_macro_tl :
- \int_compare:nTF { \clist_length:N \l_doc_variants_clist == 1 }
+ \int_compare:nTF { \clist_count:N \l_doc_variants_clist == 1 }
{ \exp_after:wN \use_ii:nn \l_doc_variants_clist }
{
\textrm(
- \clist_pop:NN \l_doc_variants_clist \l_doc_tmp_tl
- \exp_after:wN \use_ii:nn \l_doc_tmp_tl
+ \clist_pop:NN \l_doc_variants_clist \l_doc_tmpb_tl
+ \exp_after:wN \use_ii:nn \l_doc_tmpb_tl
\clist_map_inline:Nn \l_doc_variants_clist {\textrm| \use_ii:nn ##1}
\textrm)
}
@@ -1193,15 +1215,12 @@ Do not distribute a modified version of this file.
\hyperlink{rexpstar} {\ding{73}} % hollow star
}
}
-\cs_set:Nn \doc_label_function:
+\cs_set:Nn \doc_label_function:N
{
- \exp_args:NNf \tl_replace_all:Nnn \g_doc_macro_tl {\token_to_str:N _} {/}
- \exp_args:NNf \tl_replace_all:Nnn \g_doc_macro_tl {\@backslashchar} {}
- \exp_args:Nx \label
- {
- doc/function//\g_doc_macro_tl
- \tl_if_empty:NF \l_doc_function_sig_tl { : \l_doc_function_sig_tl }
- }
+ \tl_set:Nx \l_doc_tmpa_tl { \l_doc_function_name_prefix_tl \cs_to_str:N #1 }
+ \exp_args:NNf \tl_replace_all:Nnn \l_doc_tmpa_tl {\token_to_str:N _} {/}
+ \exp_args:NNf \tl_remove_all:Nn \l_doc_tmpa_tl {\@backslashchar}
+ \exp_args:Nx \label {doc/function//\l_doc_tmpa_tl}
}
% \end{macrocode}
% \end{macro}
@@ -1339,11 +1358,14 @@ Do not distribute a modified version of this file.
{ \bool_set_true:N \l_doc_macro_TF_bool } ,
pTF .code:n =
{ \bool_set_true:N \l_doc_macro_pTF_bool } ,
+ tested .code:n =
+ { } ,
}
% \end{macrocode}
%
% \begin{macrocode}
-\renewcommand \macro [1][] {
+\RenewDocumentCommand { \macro } { O{} } { \doc_macro:n {#1} }
+\cs_new_protected:Npn \doc_macro:n #1 {
\int_compare:nNnTF \currentgrouplevel=2
{ \int_gzero:N \g_doc_nested_macro_int }
@@ -1412,7 +1434,7 @@ Do not distribute a modified version of this file.
% \begin{macrocode}
\cs_set:Nn \doc_predicate_from_base:N
{
- \cs_get_function_name:N #1 _p: \cs_get_function_signature:N #1
+ \__cs_get_function_name:N #1 _p: \__cs_get_function_signature:N #1
}
\cs_set:Npn \doc_predicate_from_base:w #1 : #2 \q_nil
{
@@ -1427,10 +1449,15 @@ Do not distribute a modified version of this file.
% \begin{arguments}
% \item Macro/function/whatever name; input has already been sanitised.
% \end{arguments}
+% \cs{l_doc_at_replaced_macro_tl} stores the macro name after
+% replacement of |@@|.
% \begin{macrocode}
+\tl_new:N \l_doc_at_replaced_macro_tl
\cs_set_nopar:Npn \doc_macro_single:n #1 {
\int_incr:N \l_doc_macro_int
- \tl_set:Nx \saved@macroname { \token_to_str:N #1 }
+ \tl_set:Nx \l_doc_at_replaced_macro_tl { \token_to_str:N #1 }
+ \doc_replace_at_at:N \l_doc_at_replaced_macro_tl
+ \tl_set_eq:NN \saved@macroname \l_doc_at_replaced_macro_tl
\topsep\MacroTopsep
\trivlist
\cs_set_nopar:Npn \makelabel ##1 { \llap{##1} }
@@ -1457,33 +1484,33 @@ Do not distribute a modified version of this file.
}
\bool_if:NF \l_doc_macro_aux_bool {
- \tl_gset:Nx \l_doc_macro_tl { \tl_to_str:n {#1} }
+ \tl_gset:Nx \l_doc_macro_tl { \tl_to_str:N \l_doc_at_replaced_macro_tl }
\exp_args:NNf \tl_greplace_all:Nnn \l_doc_macro_tl {\token_to_str:N _} {/}
\exp_args:NNf \tl_greplace_all:Nnn \l_doc_macro_tl {\@backslashchar} {}
}
\use:x {
\exp_not:N \item [ \exp_not:N \doc_print_macroname:n {
- \tl_to_str:n {#1}
+ \tl_to_str:N \l_doc_at_replaced_macro_tl
}]
}
\global\advance \c@CodelineNo \@ne
\bool_if:NF \l_doc_macro_aux_bool {
\bool_if:NTF \l_doc_macro_TF_bool {
- \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n { #1 TF } }
- \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n { #1 T } }
- \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n { #1 F } }
+ \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_doc_at_replaced_macro_tl \tl_to_str:n {TF} }
+ \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_doc_at_replaced_macro_tl \tl_to_str:n {T } }
+ \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_doc_at_replaced_macro_tl \tl_to_str:n { F} }
}{
- \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:n {#1} }
+ \seq_gput_right:Nx \g_doc_macros_seq { \tl_to_str:N \l_doc_at_replaced_macro_tl }
}
}
\bool_if:NTF \l_doc_macro_TF_bool {
- \SpecialMainIndex{#1 TF}\nobreak
- \DoNotIndex{#1 TF}
+ \exp_args:Nx \SpecialMainIndex{ \tl_to_str:N \l_doc_at_replaced_macro_tl TF}\nobreak
+ \exp_args:Nx \DoNotIndex{ \tl_to_str:N \l_doc_at_replaced_macro_tl TF}
}{
- \SpecialMainIndex{#1}\nobreak
- \DoNotIndex{#1}
+ \exp_args:Nx \SpecialMainIndex{ \tl_to_str:N \l_doc_at_replaced_macro_tl }\nobreak
+ \exp_args:Nx \DoNotIndex{ \tl_to_str:N \l_doc_at_replaced_macro_tl }
}
\global\advance \c@CodelineNo \m@ne
@@ -1496,7 +1523,8 @@ Do not distribute a modified version of this file.
\tl_clear:N \l_doc_macro_tl
\cs_set_nopar:Npn \doc_print_macroname:n #1 {
\strut
- \int_compare:nTF { \tl_length:n {#1} <= 28 }
+ \HD@target
+ \int_compare:nTF { \tl_count:n {#1} <= 28 }
{ \MacroFont } { \MacroLongFont }
% INEFFICIENT: (!)
@@ -1581,15 +1609,16 @@ Do not distribute a modified version of this file.
% \end{macro}
%
% \begin{macro}{\TestMissing}
+% Note: There \cs{l_doc_macro_input_clist} may contain unconverted |@@|.
% \begin{macrocode}
\cs_generate_variant:Nn \prop_gput:Nnn {NVx}
\DeclareDocumentCommand \TestMissing {m} {
\prop_if_in:NVTF \g_doc_missing_tests_prop \l_doc_macro_input_clist
{
- \prop_get:NVN \g_doc_missing_tests_prop \l_doc_macro_input_clist \l_tmpa_tl
+ \prop_get:NVN \g_doc_missing_tests_prop \l_doc_macro_input_clist \l_doc_tmpa_tl
\prop_gput:NVx \g_doc_missing_tests_prop \l_doc_macro_input_clist
{
- *~ \l_tmpa_tl
+ *~ \l_doc_tmpa_tl
^^J \exp_not:n {\space\space\space\space\space\space}
*~ #1
}
@@ -1599,11 +1628,45 @@ Do not distribute a modified version of this file.
% \end{macrocode}
% \end{macro}
%
+% \begin{variable}{\g_doc_module_name_tl}
+% \begin{macro}[int]{\doc_replace_at_at:N}
+% \begin{macrocode}
+\tl_new:N \g_doc_module_name_tl
+\cs_new_protected:Npn \doc_replace_at_at:N #1 {
+ \tl_if_empty:NF \g_doc_module_name_tl
+ {
+ \tl_replace_all:Non #1 { \token_to_str:N @ } { @ }
+ \tl_replace_all:Non #1 { \token_to_str:N _ } { _ }
+ \tl_replace_all:Nox #1 { _@@ } { __ \g_doc_module_name_tl }
+ \tl_replace_all:Nox #1 { @@ } { __ \g_doc_module_name_tl }
+ }
+}
+\cs_generate_variant:Nn \tl_replace_all:Nnn { Non, Nox }
+% \end{macrocode}
+% \end{macro}
+% \end{variable}
+%
% \begin{macro}{\endmacro}
+% The \cs{doc_endmacro_wrap_each:N} puts each item of the sequence |#1|
+% in \cs{texttt} font and with a trailing TF if needed. This should
+% go inline in the definition of \cs{endmacro}, but somehow the |#|
+% doesn't go through some \LaTeXe{} internals.
% \begin{macrocode}
-\cs_set:Nn \doc_macro_wrap:n
+\cs_new_protected:Nn \doc_endmacro_build_seq:N
+ {
+ \seq_gclear:N #1
+ \clist_map_inline:Nn \l_doc_macro_input_clist
+ {
+ \tl_set:Nn \l_doc_tmpa_tl {##1}
+ \doc_replace_at_at:N \l_doc_tmpa_tl
+ \seq_gput_right:No #1 { \l_doc_tmpa_tl }
+ }
+ }
+\cs_set_protected:Nn \doc_endmacro_wrap_each:N
{
- #1 \bool_if:NT \l_doc_macro_TF_bool {TF}
+ \bool_if:NTF \l_doc_macro_TF_bool
+ { \seq_gset_map:NNn #1 #1 { \exp_not:N \texttt { ##1 TF } } }
+ { \seq_gset_map:NNn #1 #1 { \exp_not:N \texttt { ##1 } } }
}
\cs_set:Nn \doc_texttt_comma:n {\,,~\texttt{#1}}
\cs_set:Npn \endmacro {
@@ -1611,29 +1674,14 @@ Do not distribute a modified version of this file.
{
\par\nobreak\noindent{\footnotesize(\emph{
End~ definition~ for~
- \prg_case_int:nnn { \clist_length:N \l_doc_macro_input_clist }
- {
- {1} { \texttt{ \doc_macro_wrap:n { \clist_use:N \l_doc_macro_input_clist } }. }
- {2}
+ \doc_endmacro_build_seq:N \g_doc_tmpa_seq
+ \doc_endmacro_wrap_each:N \g_doc_tmpa_seq
+ \int_compare:nTF { \seq_count:N \g_doc_tmpa_seq <= 3 }
{
- \tl_set:Nx \l_clist_first_tl { \clist_item:Nn \l_doc_macro_input_clist {0} }
- \tl_set:Nx \l_clist_last_tl { \clist_item:Nn \l_doc_macro_input_clist {1} }
- \texttt{\doc_macro_wrap:n\l_clist_first_tl}\,~ and~ \texttt{\doc_macro_wrap:n\l_clist_last_tl}\,.
+ \seq_use:Nnnn \g_doc_tmpa_seq
+ { \,~and~ } { \,,~ } { \,,~and~ }
}
- {3}
- {
- \tl_set:Nx \l_clist_first_tl { \clist_item:Nn \l_doc_macro_input_clist {0} }
- \tl_set:Nx \l_clist_mid_tl { \clist_item:Nn \l_doc_macro_input_clist {1} }
- \tl_set:Nx \l_clist_last_tl { \clist_item:Nn \l_doc_macro_input_clist {2} }
- \texttt{\doc_macro_wrap:n\l_clist_first_tl}\,,~
- \texttt{\doc_macro_wrap:n\l_clist_mid_tl}\,,~
- and~ \texttt{\doc_macro_wrap:n\l_clist_last_tl}\,.
- }
- }
- {
- \tl_set:Nx \l_clist_first_tl { \clist_item:Nn \l_doc_macro_input_clist {0} }
- \texttt{\doc_macro_wrap:n\l_clist_first_tl}\,~and~others.
- }
+ { \seq_item:Nn \g_doc_tmpa_seq {1}\,~and~others. }
\bool_if:nT {
!\l_doc_macro_aux_bool &&
!\l_doc_macro_internal_bool &&
@@ -1656,7 +1704,7 @@ Do not distribute a modified version of this file.
{
\seq_gput_right:Nx \g_doc_not_tested_seq
{
- \l_doc_macro_input_clist
+ \seq_use:Nnnn \g_doc_tmpa_seq { , } { , } { , }
\bool_if:NT \l_doc_macro_pTF_bool {~(pTF)}
\bool_if:NT \l_doc_macro_TF_bool {~(TF)}
}
@@ -1665,6 +1713,70 @@ Do not distribute a modified version of this file.
% \end{macrocode}
% \end{macro}
%
+% \begin{environment}{macrocode}
+% \begin{macro}[aux]{\doc_xmacro_code:n}
+% Hook into the \texttt{macrocode} environment in a dirty way:
+% \cs{xmacro@code} is responsible for grabbing (and tokenizing) the
+% body of the environment. Redefine it to pass what it grabs to
+% \cs{doc_xparse_code:n}. This new macro replaces all |@@| by the
+% appropriate module name. One exceptional case is the
+% |<@@=|\meta{module}|>| lines themselves, where |@@| should not be
+% modified. Actually, we search for such lines, to set the module
+% name automatically. We need to be careful: no |<@@=| should appear
+% as such in the code below since \pkg{l3doc} is also typeset using
+% this code.
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_escape:N \/
+ \char_set_catcode_other:N \^^A
+ \char_set_catcode_active:N \^^S
+ \char_set_catcode_active:N \^^B
+ \char_set_catcode_other:N \^^L
+ \char_set_catcode_other:N \^^R
+ \char_set_lccode:nn { `\^^A } { `\% }
+ \char_set_lccode:nn { `\^^S } { `\ }
+ \char_set_lccode:nn { `\^^B } { `\\ }
+ \char_set_lccode:nn { `\^^L } { `\{ }
+ \char_set_lccode:nn { `\^^R } { `\} }
+ \tl_to_lowercase:n
+ {
+ \group_end:
+ \cs_set_protected:Npn \xmacro@code
+ #1 ^^A ^^S^^S^^S^^S ^^Bend ^^Lmacrocode^^R
+ { \doc_xmacro_code:n {#1} /end{macrocode} }
+ }
+\group_begin:
+ \char_set_catcode_active:N \<
+ \char_set_catcode_active:N \>
+ \cs_new_protected:Npn \doc_xmacro_code:n #1
+ {
+ \tl_if_in:nnTF {#1} { < @ @ = }
+ { \doc_xmacro_code:w #1 \q_stop }
+ {
+ \tl_set:Nn \l_doc_tmpa_tl {#1}
+ \doc_replace_at_at:N \l_doc_tmpa_tl
+ \tl_use:N \l_doc_tmpa_tl
+ }
+ }
+ \cs_new_protected:Npn \doc_xmacro_code:w #1 < @ @ = #2 > #3 \q_stop
+ {
+ \tl_set:Nn \l_doc_tmpa_tl {#1}
+ \doc_replace_at_at:N \l_doc_tmpa_tl
+
+ \tl_gset:Nn \g_doc_module_name_tl {#2}
+ \tl_put_right:Nn \l_doc_tmpa_tl { < @ @ = #2 > }
+
+ \tl_set:Nn \l_doc_tmpb_tl {#3}
+ \doc_replace_at_at:N \l_doc_tmpb_tl
+ \tl_put_right:No \l_doc_tmpa_tl { \l_doc_tmpb_tl }
+
+ \tl_use:N \l_doc_tmpa_tl
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+% \end{environment}
+%
% \begin{macro}{\DescribeOption}
% For describing package options. Due to Joseph Wright.
% Name/usage might change soon.
@@ -1987,40 +2099,44 @@ Do not distribute a modified version of this file.
% Print all defined and documented macros/functions.
%
% \begin{macrocode}
-\iow_open:Nn \g_write_func_stream { \jobname.cmds }
+\iow_new:N \g_doc_func_iow
% \end{macrocode}
%
% \begin{macrocode}
\cs_new_nopar:Npn \doc_show_functions_defined: {
\bool_if:nT { \g_doc_implementation_bool && \g_doc_checkfunc_bool } {
\typeout{ ======================================== ^^J }
+ \iow_open:Nn \g_doc_func_iow { \c_job_name_tl .cmds }
- \tl_clear:N \l_tmpa_tl
+ \tl_clear:N \l_doc_tmpa_tl
\seq_map_inline:Nn \g_doc_functions_seq {
\seq_if_in:NnT \g_doc_macros_seq {##1} {
- \tl_put_right:Nn \l_tmpa_tl { ##1 ^^J }
- \iow_now:Nn \g_write_func_stream { ##1 }
+ \tl_put_right:Nn \l_doc_tmpa_tl { ##1 ^^J }
+ \iow_now:Nn \g_doc_func_iow { > ~ ##1 }
}
}
- \iow_close:N \g_write_func_stream
+
\doc_functions_typeout:n {
Functions~both~documented~and~defined:^^J (In~order~of~being~documented)
}
\seq_map_inline:Nn \g_doc_functions_seq {
\seq_if_in:NnF \g_doc_macros_seq {##1} {
- \tl_put_right:Nn \l_tmpa_tl { ##1 ^^J }
+ \tl_put_right:Nn \l_doc_tmpa_tl { ##1 ^^J }
+ \iow_now:Nn \g_doc_func_iow { ! ~ ##1}
}
}
\doc_functions_typeout:n { Functions~documented~but~not~defined: }
\seq_map_inline:Nn \g_doc_macros_seq {
\seq_if_in:NnF \g_doc_functions_seq {##1} {
- \tl_put_right:Nn \l_tmpa_tl { ##1 ^^J }
+ \tl_put_right:Nn \l_doc_tmpa_tl { ##1 ^^J }
+ \iow_now:Nn \g_doc_func_iow { ? ~ ##1}
}
}
\doc_functions_typeout:n { Functions~defined~but~not~documented: }
+ \iow_close:N \g_doc_func_iow
\typeout{ ======================================== }
}
}
@@ -2029,12 +2145,12 @@ Do not distribute a modified version of this file.
%
% \begin{macrocode}
\cs_set_nopar:Npn \doc_functions_typeout:n #1 {
- \tl_if_empty:NF \l_tmpa_tl {
+ \tl_if_empty:NF \l_doc_tmpa_tl {
\typeout{
-------------------------------------- ^^J #1 ^^J
- -------------------------------------- ^^J \l_tmpa_tl
+ -------------------------------------- ^^J \l_doc_tmpa_tl
}
- \tl_clear:N \l_tmpa_tl
+ \tl_clear:N \l_doc_tmpa_tl
}
}
% \end{macrocode}
@@ -2046,23 +2162,23 @@ Do not distribute a modified version of this file.
\bool_if:nT { !(\seq_if_empty_p:N \g_doc_not_tested_seq) ||
!(\prop_if_empty_p:N \g_doc_missing_tests_prop) }
{
- \tl_clear:N \l_tmpa_tl
+ \tl_clear:N \l_doc_tmpa_tl
\prop_if_empty:NF \g_doc_missing_tests_prop
{
- \tl_put_right:Nn \l_tmpa_tl
+ \tl_put_right:Nn \l_doc_tmpa_tl
{
^^J^^JThe~ following~ macro(s)~ have~ incomplete~ tests:^^J
}
\prop_map_inline:Nn \g_doc_missing_tests_prop
{
- \tl_put_right:Nn \l_tmpa_tl
+ \tl_put_right:Nn \l_doc_tmpa_tl
{^^J\space\space\space\space ##1
^^J\space\space\space\space\space\space ##2}
}
}
\seq_if_empty:NF \g_doc_not_tested_seq
{
- \tl_put_right:Nn \l_tmpa_tl
+ \tl_put_right:Nn \l_doc_tmpa_tl
{
^^J^^J
The~ following~ macro(s)~ do~ not~ have~ any~ tests:^^J
@@ -2071,12 +2187,12 @@ Do not distribute a modified version of this file.
{
\clist_map_inline:nn {##1}
{
- \tl_put_right:Nn \l_tmpa_tl {^^J\space\space\space\space ####1}
+ \tl_put_right:Nn \l_doc_tmpa_tl {^^J\space\space\space\space ####1}
}
}
\int_set:Nn \l_tmpa_int {\etex_interactionmode:D}
\errorstopmode
- \ClassError{l3doc}{\l_tmpa_tl}{}
+ \ClassError{l3doc}{\l_doc_tmpa_tl}{}
\int_set:Nn \etex_interactionmode:D {\l_tmpa_int}
}
}
@@ -2111,39 +2227,31 @@ Do not distribute a modified version of this file.
% \end{macrocode}
%
%
-% \begin{macro}{\doc_special_main_index:n,\doc_special_main_index:o,\hdpgindex}
+% \begin{macro}{\doc_special_main_index:n,\doc_special_main_index:o, \doc_special_main_index:x}
% Heiko's replacement to play nicely with |hypdoc|:
% \begin{macrocode}
\cs_set_nopar:Npn \doc_special_main_index:n #1 {
+ \HD@target
\index{
\@gobble#1
\actualchar
\string\verb\quotechar*\verbatimchar#1\verbatimchar
\encapchar
- hdpgindex{\thepage}{usage}
- }
-}
-\cs_set_nopar:Npn \doc_special_main_index:o { \exp_args:No \doc_special_main_index:n }
-% \end{macrocode}
-% \begin{macrocode}
-\cs_set_nopar:Npn \hdpgindex #1#2#3 {
- \csname\ifx\\#2\\relax\else#2\fi\endcsname{
- \hyperlink{page.#1}{#3}
+ hdclindex{\the\c@HD@hypercount}{usage}
}
}
+\cs_generate_variant:Nn \doc_special_main_index:n { o , x }
% \end{macrocode}
% \end{macro}
%
% \begin{macrocode}
-\g@addto@macro \PrintIndex { \AtEndDocument{ \typeout{^^J
- ========================================^^J
- Generate~the~index~by~executing^^J
- \c_space_tl \c_space_tl \c_space_tl \c_space_tl
- makeindex~-s~l3doc.ist~-o~\jobname.ind~\jobname.idx^^J
- ========================================^^J
- }}
-}
+\msg_new:nnn {l3doc} {print-index-howto}
+ {
+ Generate~the~index~by~executing\\
+ \iow_indent:n { makeindex~-s~l3doc.ist~-o~\c_job_name_tl .ind~\c_job_name_tl .idx }
+ }
+\tl_gput_right:Nn \PrintIndex { \AtEndDocument{ \msg_info:nn {l3doc} {print-index-howto} } }
% \end{macrocode}
%
% \subsection{Change history}
@@ -2160,14 +2268,12 @@ Do not distribute a modified version of this file.
% \end{macrocode}
%
% \begin{macrocode}
-\g@addto@macro \PrintChanges { \AtEndDocument{ \typeout{^^J
- ========================================^^J
- Generate~the~change~list~by~executing^^J
- \c_space_tl \c_space_tl \c_space_tl \c_space_tl
- makeindex~-s~gglo.ist~~-o~\jobname.gls~\jobname.glo^^J
- ========================================^^J
- }}
-}
+\msg_new:nnn {l3doc} {print-changes-howto}
+ {
+ Generate~the~change~list~by~executing\\
+ \iow_indent:n { makeindex~-s~gglo.ist~-o~\c_job_name_tl .gls~\c_job_name_tl .glo }
+ }
+\tl_gput_right:Nn \PrintChanges { \AtEndDocument{ \msg_info:nn {l3doc} {print-changes-howto} } }
% \end{macrocode}
%
%^^A The standard \changes command modified slightly to better cope with
@@ -2190,7 +2296,7 @@ Do not distribute a modified version of this file.
%^^A :\levelchar #3}}%
%^^A \@tempa\endgroup\@esphack}
%
-% \subsection{cfg}
+% \subsection{Default configuration}
%
% \begin{macrocode}
\bool_if:NTF \g_doc_full_bool {
@@ -2210,6 +2316,79 @@ Do not distribute a modified version of this file.
%</class>
% \end{macrocode}
%
+% \subsection{Internal macros for \LaTeX3 sources}
+%
+% These definitions are only used by the \LaTeX3 documentation;
+% they are not necessary for third-party users of l3doc.
+% In time this will be broken into a separate package that is specifically
+% loaded in the various expl3 modules, etc.
+%
+% \begin{macrocode}
+%<*cfg>
+% \end{macrocode}
+%
+% The Guilty Parties.
+% \begin{macrocode}
+\cs_new_nopar:Npn\Team{%
+ The~\LaTeX3~Project\thanks{%
+ Frank~Mittelbach,~Denys~Duchier,~Chris~Rowley,~
+ Rainer~Sch\"opf,~Johannes~Braams,~Michael~Downes,~
+ David~Carlisle,~Alan~Jeffrey,~Morten~H\o{}gholm,~Thomas~Lotze,~
+ Javier~Bezos,~Will~Robertson,~Joseph~Wright,~Bruno~Le~Floch}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\NewDocumentCommand{\ExplMakeTitle}{mm}
+ {
+ \title
+ {
+ The~\pkg{#1}~package \\ #2
+ \thanks{This~file~describes~v\ExplFileVersion,~
+ last~revised~\ExplFileDate.}
+ }
+ \author{The~\LaTeX3~Project\thanks{E-mail:~
+ \href{mailto:latex-l@listserv.uni-heidelberg.de}
+ {latex-l@listserv.uni-heidelberg.de}}}
+ \date{Released~\ExplFileDate}
+ \maketitle
+ }
+% \end{macrocode}
+%
+% \subsection{Text extras}
+%
+% \begin{macrocode}
+\DeclareDocumentCommand\ie{}{\emph{i.e.}}
+\DeclareDocumentCommand\eg{}{\emph{e.g.}}
+\DeclareDocumentCommand\Ie{}{\emph{I.e.}}
+\DeclareDocumentCommand\Eg{}{\emph{E.g.}}
+% \end{macrocode}
+%
+% \subsection{Math extras}
+%
+% For \pkg{l3fp}.
+%
+% \begin{macrocode}
+\AtBeginDocument
+ {
+ \clist_map_inline:nn
+ {
+ asin, acos, atan, acot,
+ asinh, acosh, atanh, acoth, round, floor, ceil
+ }
+ { \exp_args:Nc \DeclareMathOperator{#1}{#1} }
+ }
+% \end{macrocode}
+%
+% \begin{macro}{\nan}
+% \begin{macrocode}
+\NewDocumentCommand { \nan } { } { \text { \texttt { nan } } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</cfg>
+% \end{macrocode}
+%
%
% \subsection{Makeindex configuration}
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
new file mode 100644
index 00000000000..5e2ba0a5e63
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3docstrip.dtx
@@ -0,0 +1,277 @@
+% \iffalse
+%
+%% File l3dosctrip.dtx Copyright (C) 2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver|program>
+\def\ExplFileDate{2012/06/08}
+\def\ExplFileName{l3docstrip}
+\def\ExplFileVersion{3787}
+%</driver|program>
+%<*driver>
+% The same approach as used in \textsf{DocStrip}: if \cs{documentclass}
+% is undefined then skip the driver, allowing the file to be used to extract
+% \texttt{l3docstrip.tex} from \texttt{l3docstrip.dtx} directly. This works
+% as the \cs{fi} is only seen if \LaTeX{} is not in use. The odd \cs{jobname}
+% business allows the extraction to work with \LaTeX{} provided an appropriate
+% \texttt{.ins} file is set up.
+%<*gobble>
+\ifx\jobname\relax\let\documentclass\undefined\fi
+\ifx\documentclass\undefined
+\else \csname fi\endcsname
+%</gobble>
+ \def\filename{docstrip.dtx}
+ \documentclass[full]{l3doc}
+ \begin{document}
+ \DocInput{\jobname.dtx}
+ \end{document}
+%<*gobble>
+\fi
+%</gobble>
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3docstrip} package\\ Code extraction and manipulation^^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}
+%
+% \section{Extending \textsf{DocStrip}}
+%
+% The \pkg{l3docstrip} module adds \LaTeX3 extensions to the \textsf{DocStrip}
+% program for extracting code from \texttt{.dtx}. As such, this documentation
+% should be read along with that for \textsf{DocStrip}.
+%
+% \section{Internal functions and variables}
+%
+% An important consideration for \LaTeX3 development is separating out public
+% and internal functions. Functions and variables which are private to one
+% module should not be used or modified by any other module. As \TeX{} does
+% not have any formal namespacing system, this requires a convention for
+% indicating which functions in a code-level module are public and which are
+% private.
+%
+% Using \pkg{l3docstrip} allows internal functions to be indicated using a
+% \enquote{two part} system. Within the \texttt{.dtx} file, internal functions
+% may be indicated using |@@| in place of the module name, for example
+% \begin{verbatim}
+% \cs_new_protected:Npn \@@_some_function:nn #1#2
+% {
+% % Some code here
+% }
+% \tl_new:N \l_@@_internal_tl
+% \end{verbatim}
+%
+% To extract the code using \pkg{l3docstrip}, the \enquote{guard} concept
+% used by \textsf{DocStrip} is extended by introduction of the syntax
+% \texttt{\%<@@=\meta{module}}. The \meta{module} name will be used when the
+% code is extracted to replace the |@@|, so that
+% \begin{verbatim}
+% %<*package>
+% %<@@=foo>
+% \cs_new_protected:Npn \@@_some_function:nn #1#2
+% {
+% % Some code here
+% }
+% \tl_new:N \l_@@_internal_tl
+% %</package>
+% \end{verbatim}
+% will be extracted as
+% \begin{verbatim}
+% \cs_new_protected:Npn \__foo_some_function:nn #1#2
+% {
+% % Some code here
+% }
+% \tl_new:N \l__foo_internal_tl
+% \end{verbatim}
+% where the |__| indicates that the functions and variables are internal
+% to the \texttt{foo} module.
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3docstrip} implementation}
+%
+% \begin{macrocode}
+%<*program>
+% \end{macrocode}
+%
+% We start by loading the existing \textsf{DocStrip} code using the \TeX{}
+% input convention.
+% \begin{macrocode}
+\input docstrip %
+% \end{macrocode}
+%
+% \begin{macro}{\checkOption}
+% The \cs{checkOption} macro is defined by \textsf{DocStrip} and is redefined
+% here to accommodate the new \texttt{\%<@} syntax.
+%
+% When the macros that process a line have found that the line starts with
+% \enquote{\texttt{\%<}}, a guard line has been encountered. The first
+% character of a guard can be an asterisk (\texttt{*}), a slash (\texttt{/}),
+% a plus (\texttt{+}), a minus (\texttt{-}), a less-than sign (\texttt{<})
+% starting verbatim mode, a commercial at (\texttt{@}) or any other character
+% that can be found in an option name. This means that we have to peek at the
+% next token and decide what kind of guard we have. We reinsert |#1| as it
+% may be needed by \cs{doOption}.
+% \begin{macrocode}
+\def\checkOption<#1{%
+ \ifcase
+ \ifx*#10\else \ifx/#11\else
+ \ifx+#12\else \ifx-#13\else
+ \ifx<#14\else \ifx @#15\else 6\fi\fi\fi\fi\fi\fi\relax
+ \expandafter\starOption\or
+ \expandafter\slashOption\or
+ \expandafter\plusOption\or
+ \expandafter\minusOption\or
+ \expandafter\verbOption\or
+ \expandafter\moduleOption\or
+ \expandafter\doOption\fi
+ #1%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\moduleOption}
+% In the case where the line starts |%<@|: the defined syntax requires that
+% this continues to |%<@@=|. At the moment, we assume that the syntax will
+% be correct and |#1| here is the module name for substitution into any
+% internal functions in the extracted material.
+% \begin{macrocode}
+\def\moduleOption @@=#1>#2\endLine{%
+ \maybeMsg{<@@=#1>}%
+ \prepareActiveModule{#1}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\prepareActiveModule}
+% \begin{macro}{\replaceModuleInLine}
+% Here, we set up to do the search-and-replace when doing the extraction.
+% The argument (|#1|) is the replacement text to use, or if empty an
+% indicator that no replacement should be done. The search material is
+% one of |__@@|, |_@@| or |@@|, done in order such that all three will end
+% up the same in the output. The replacement function is initialised as a
+% do-nothing for the case where |%<@@=| is never seen.
+% \begin{macrocode}
+\begingroup
+ \catcode`\_ = 12 %
+ \long\gdef\prepareActiveModule#1{%
+ \ifx\relax#1\relax
+ \let\replaceModuleInLine\empty
+ \else
+ \def\replaceModuleInLine{%
+ \replaceAllIn\inLine{__@@}{__#1}%
+ \replaceAllIn\inLine{_@@}{__#1}%
+ \replaceAllIn\inLine{@@}{__#1}%
+ }%
+ \fi
+ }
+\endgroup
+\let\replaceModuleInLine\empty
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\replaceAllIn}
+% \begin{macro}{\replaceAllInAuxI}
+% \begin{macro}{\replaceAllInAuxII}
+% \begin{macro}{\replaceAllInAuxIII}
+% The code here is a simple search-and-replace routine for a macro |#1|,
+% replacing |#2| by |#3|. As set up here, there is an assumption that nothing
+% is going to be expandable, which is reasonable as \pkg{l3docstrip} deals
+% with \enquote{string} material.
+% \begin{macrocode}
+\long\def\replaceAllIn#1#2#3{%
+ \long\def\tempa##1##2#2{%
+ ##2\qMark\replaceAllInAuxIII#3##1%
+ }%
+ \edef#1{\expandafter\replaceAllInAuxI#1\qMark#2\qStop}%
+}
+\def\replaceAllInAuxI{%
+ \expandafter\replaceAllInAuxII\tempa\replaceAllInAuxI\empty
+}
+\long\def\replaceAllInAuxII#1\qMark#2{#1}
+\long\def\replaceAllInAuxIII#1\qStop{}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\normalLine}
+% The \cs{normalLine} macro is present in \textsf{DocStrip} but is modified
+% here to include the search-and-replace macro \cs{replaceModuleInLine}. The
+% macro \cs{normalLine} writes its argument (which has to be delimited with
+% |\endLine|) on all active output files, i.e.~those with off-counters equal
+% to zero. The counter \cs{codeLinesPassed} is incremented by~$1$ for
+% statistics (the guards for this used in \textsf{DocStrip} are retained).
+% \begin{macrocode}
+\def\normalLine#1\endLine{%
+%<*stats>
+ \advance\codeLinesPassed\@ne
+%</stats>
+ \maybeMsg{.}%
+ \def\inLine{#1}%
+ \replaceModuleInLine
+ \let\do\putline@do
+ \activefiles
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</program>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
index 2729cad13ca..817a616897f 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3drivers.dtx
@@ -36,7 +36,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3drivers.dtx 3158 2012-01-09 00:47:42Z bruno $
+\GetIdInfo$Id: l3drivers.dtx 3986 2012-07-15 19:23:51Z joseph $
{L3 Experimental drivers}
%</driver|package>
%<*driver>
@@ -89,9 +89,9 @@
%
% \section{Box clipping}
%
-% \begin{function}[added = 2011-11-11]{\driver_box_use_clip:N}
+% \begin{function}[added = 2011-11-11]{\__driver_box_use_clip:N}
% \begin{syntax}
-% \cs{driver_box_use_clip:N} \meta{box}
+% \cs{__driver_box_use_clip:N} \meta{box}
% \end{syntax}
% Inserts the content of the \meta{box} at the current insertion point
% such that any material outside of the bounding box will not be displayed
@@ -101,32 +101,32 @@
%
% \section{Box rotation and scaling}
%
-% \begin{function}[added = 2011-09-01]
-% {\driver_box_rotate_begin:, \driver_box_rotate_end:}
+% \begin{function}[added = 2011-09-01, updated = 2012-05-18]
+% {\__driver_box_rotate_begin:, \__driver_box_rotate_end:}
% \begin{syntax}
-% \cs{driver_box_rotate_begin:}
-% \cs{box_use:N} \cs{l_box_internal_box}
-% \cs{driver_box_rotate_end:}
+% \cs{__driver_box_rotate_begin:}
+% \cs{box_use:N} \cs{l__box_internal_box}
+% \cs{__driver_box_rotate_end:}
% \end{syntax}
% Rotates the \meta{box material} anti-clockwise around the current
% insertion point. The angle of rotation (in degrees counter-clockwise)
% and the sine and cosine of this angle should be stored in
-% \cs{l_box_angle_fp}, \cs{l_box_sin_fp} and \cs{l_box_cos_fp},
+% \cs{l__box_angle_fp}, \cs{l__box_sin_fp} and \cs{l__box_cos_fp},
% respectively. Typically, the box material inserted between the beginning
-% and end markers will be stored in \cs{l_box_internal_box}: this fact is
+% and end markers will be stored in \cs{l__box_internal_box}: this fact is
% required by some drivers to obtain the correct output.
% \end{function}
%
-% \begin{function}[added = 2011-09-02]
-% {\driver_box_scale_begin:, \driver_box_scale_end:}
+% \begin{function}[added = 2011-09-02, updated = 2012-05-18]
+% {\__driver_box_scale_begin:, \__driver_box_scale_end:}
% \begin{syntax}
-% \cs{driver_box_scale_begin:}
+% \cs{__driver_box_scale_begin:}
% \meta{box material}
-% \cs{driver_box_scale_end:}
+% \cs{__driver_box_scale_end:}
% \end{syntax}
% Scales the \meta{box material} (which should be either a \cs{box_use:N}
% or \cs{hbox:n} construct). The \meta{box material} is scaled by the values
-% stored in \cs{l_box_scale_x_fp} and \cs{l_box_scale_y_fp} in the
+% stored in \cs{l__box_scale_x_fp} and \cs{l__box_scale_y_fp} in the
% horizontal and vertical directions, respectively. This function is
% also reused when resizing boxes: at a driver level, only scalings are
% supported and so the higher-level code must convert the absolute sizes
@@ -135,9 +135,10 @@
%
% \section{Colour support}
%
-% \begin{function}[added = 2011-09-03]{\driver_color_ensure_current:}
+% \begin{function}[added = 2011-09-03, updated = 2012-05-18]
+% {\__driver_color_ensure_current:}
% \begin{syntax}
-% \cs{driver_color_ensure_current:}
+% \cs{__driver_color_ensure_current:}
% \end{syntax}
% Ensures that the colour used to typeset material is that which was
% set when the material was placed in a box. This function is therefore
@@ -154,6 +155,7 @@
%
% \begin{macrocode}
%<*initex|package>
+%<@@=driver>
% \end{macrocode}
%
% \begin{macrocode}
@@ -171,7 +173,7 @@
{l3pdfmode.def}{\ExplFileDate}{\ExplFileVersion}
{L3~Experimental~driver:~xdvipdfmx}
%</xdvipdfmx>
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -208,50 +210,62 @@
%
% \subsection{Driver utility functions}
%
-% \begin{macro}{\driver_graphic_state_save:}
-% \begin{macro}{\driver_graphic_state_restore:}
+% \begin{macro}{\@@_graphic_state_save:, \@@_graphic_state_restore:}
% All of the drivers have a stack for saving the graphic state. These
-% have slightly different interfaces. As \texttt{dvips} does not
-% automatically save the current location, this is set up here.
+% have slightly different interfaces. For both \texttt{dvips} and
+% \texttt{xdvipdfmx} this is done using an appropriate special.
% \begin{macrocode}
-\cs_new_protected:Npn \driver_graphic_state_save:
+%<*dvips|xdvipdfmx>
+\cs_new_protected_nopar:Npn \@@_graphic_state_save:
%<*dvips>
{ \tex_special:D { ps:gsave } }
%</dvips>
-%<*pdfmode>
- { \pdftex_pdfsave:D }
-%</pdfmode>
%<*xdvipdfmx>
{ \tex_special:D { pdf:bcontent } }
%</xdvipdfmx>
-\cs_new_protected:Npn \driver_graphic_state_restore:
+\cs_new_protected_nopar:Npn \@@_graphic_state_restore:
%<*dvips>
{ \tex_special:D { ps:grestore } }
%</dvips>
-%<*pdfmode>
- { \pdftex_pdfrestore:D }
-%</pdfmode>
%<*xdvipdfmx>
{ \tex_special:D { pdf:econtent } }
%</xdvipdfmx>
+%</dvips|xdvipdfmx>
+% \end{macrocode}
+% For direct PDF output there is also a need to worry about the version
+% of \pdfTeX{} in use: the \tn{pdfsave} primitive was only introduced
+% in version~1.40.0.
+% \begin{macrocode}
+%<*pdfmode>
+\cs_if_exist:NTF \pdftex_pdfsave:D
+ {
+ \cs_new_eq:NN \@@_graphic_state_save: \pdftex_pdfsave:D
+ \cs_new_eq:NN \@@_graphic_state_restore: \pdftex_pdfrestore:D
+ }
+ {
+ \cs_new_protected_nopar:Npn \@@_graphic_state_save:
+ { \pdftex_pdfliteral:D { q } }
+ \cs_new_protected_nopar:Npn \@@_graphic_state_restore:
+ { \pdftex_pdfliteral:D { Q } }
+ }
+%</pdfmode>
% \end{macrocode}
-% \end{macro}
% \end{macro}
%
-% \begin{macro}{\driver_pdf_literal:n, \driver_pdf_literal_direct:n}
+% \begin{macro}{\@@_pdf_literal:n, \@@_pdf_literal_direct:n}
% Both direct PDF mode and \texttt{xdvipdfmx} make use of direct PDF
% special insertion. These are slightly different in the two cases.
% The |direct| versions do not save the current matrix.
% \begin{macrocode}
%<*pdfmode|xdvipdfmx>
-\cs_new_protected:Npn \driver_pdf_literal:n #1
+\cs_new_protected:Npn \@@_pdf_literal:n #1
%<*pdfmode>
{ \pdftex_pdfliteral:D {#1} }
%</pdfmode>
%<*xdvipdfmx>
{ \tex_special:D { pdf:content~ #1 } }
%</xdvipdfmx>
-\cs_new_protected:Npn \driver_pdf_literal_direct:n #1
+\cs_new_protected:Npn \@@_pdf_literal_direct:n #1
%<*pdfmode>
{ \pdftex_pdfliteral:D direct~{#1} }
%</pdfmode>
@@ -262,12 +276,12 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\driver_ps_literal:n}
+% \begin{macro}{\@@_ps_literal:n}
% The same concept for PostScript: these are \enquote{direct} by default,
% but by keeping the same name life should be a little clearer.
% \begin{macrocode}
%<*dvips>
-\cs_new_protected:Npn \driver_ps_literal:n #1
+\cs_new_protected:Npn \@@_ps_literal:n #1
{ \tex_special:D { ps: #1 } }
%</dvips>
% \end{macrocode}
@@ -275,7 +289,7 @@
%
% \subsection{Box clipping}
%
-% \begin{macro}{\driver_box_use_clip:N}
+% \begin{macro}{\@@_box_use_clip:N}
% The overall logic to clipping a box is the same in all cases. The general
% method is to save the current location, define a clipping path equivalent
% to the bounding box, then insert the content at the current position
@@ -285,9 +299,9 @@
% as much code as possible and uses the same conversions (and so same
% rounding errors) in all three cases.
% \begin{macrocode}
-\cs_new_protected:Npn \driver_box_use_clip:N #1
+\cs_new_protected:Npn \@@_box_use_clip:N #1
{
- \driver_graphic_state_save:
+ \@@_graphic_state_save:
% \end{macrocode}
% The business end of the code sets up the clip box, using the higher-level
% rectangle operators rather than the lower level direct line drawing. This
@@ -301,21 +315,21 @@
% \TeX{} current positions).
% \begin{macrocode}
%<*dvips>
- \driver_ps_literal:n
+ \@@_ps_literal:n
{
/savedmatrix~matrix~currentmatrix~def~
currentpoint~translate~
Resolution~72~div~VResolution~72~div~scale
}
- \driver_ps_literal:n
+ \@@_ps_literal:n
{
0~
- -\dim_strip_bp:n { \box_dp:N #1 } ~neg~
- \dim_strip_bp:n { \box_wd:N #1 } ~
- \dim_strip_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~neg~
+ \__dim_strip_bp:n { \box_dp:N #1 } ~
+ \__dim_strip_bp:n { \box_wd:N #1 } ~
+ \__dim_strip_bp:n { - \box_ht:N #1 - \box_dp:N #1 } ~
rectclip
}
- \driver_ps_literal:n { savedmatrix~setmatrix }
+ \@@_ps_literal:n { savedmatrix~setmatrix }
%</dvips>
% \end{macrocode}
% The PDF box is easier to define as it is automatically in big points and
@@ -323,12 +337,12 @@
% locations automatically.
% \begin{macrocode}
%<*pdfmode|xdvipdfmx>
- \driver_pdf_literal_direct:n
+ \@@_pdf_literal_direct:n
{
0 ~
- -\dim_strip_bp:n { \box_dp:N #1 } ~
- \dim_strip_bp:n { \box_wd:N #1 } ~
- \dim_strip_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~
+ \__dim_strip_bp:n { - \box_dp:N #1 } ~
+ \__dim_strip_bp:n { \box_wd:N #1 } ~
+ \__dim_strip_bp:n { \box_ht:N #1 + \box_dp:N #1 } ~
re~W~n
}
%</pdfmode|xdvipdfmx>
@@ -337,7 +351,7 @@
% and then insert the necessary width.
% \begin{macrocode}
\hbox_overlap_right:n { \box_use:N #1 }
- \driver_graphic_state_restore:
+ \@@_graphic_state_restore:
\skip_horizontal:n { \box_wd:N #1 }
}
% \end{macrocode}
@@ -345,16 +359,7 @@
%
% \subsection{Box rotation and scaling}
%
-% \begin{variable}{\l_driver_internal_fp}
-% Needed for a safe sign inversion in PDF mode.
-% \begin{macrocode}
-%<*pdfmode|xdvipdfmx>
-\fp_new:N \l_driver_internal_fp
-%</pdfmode|xdvipdfmx>
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}{\driver_box_rotate_begin:, \driver_box_rotate_end:}
+% \begin{macro}{\@@_box_rotate_begin:, \@@_box_rotate_end:}
% The driver for \texttt{dvips} works with a simple rotation angle.
% In PDF mode, an affine matrix is used instead. The transformation for
% \texttt{xdvipdfmx} can be done either way: to have some code sharing,
@@ -362,137 +367,189 @@
% shared in this way). For the \texttt{dvips}, that odd-looking
% |currentpoint| at the beginning is used to put this data onto the
% stack for |neg exch neg exch translate| to pick up.
+%
+% In both cases, some rounding code is included to limit the floating
+% point values to five decimal places. There is no point using any more
+% as \TeX{}'s dimensions are of that precision, and the extra figures
+% will simply bloat the PDF and make values harder to trace. In the
+% case where the sine and cosine are used, we store the rounded values to
+% avoid rounding twice. There are also a couple of comparisons to ensure
+% that |-0| is not written to the output, as this avoids any issues with
+% problematic display programs.
% \begin{macrocode}
-\cs_new_protected:Npn \driver_box_rotate_begin:
+\cs_new_protected_nopar:Npn \@@_box_rotate_begin:
{
- \driver_graphic_state_save:
+ \@@_graphic_state_save:
%<*dvips>
- \driver_ps_literal:n
+ \@@_ps_literal:n
{
currentpoint~
currentpoint~translate~
- \fp_use:N \l_box_angle_fp \c_space_tl neg~rotate~
+ \fp_compare:nTnTF \l__box_angle_fp = \c_zero_fp
+ { 0 }
+ { \fp_eval:n { round ( - \l__box_angle_fp , 5 ) } }
+ ~rotate~
neg~exch~neg~exch~translate
}
%</dvips>
%<*pdfmode|xdvipdfmx>
- \box_set_wd:Nn \l_box_internal_box \c_zero_dim
- \fp_set_eq:NN \l_driver_internal_fp \l_box_sin_fp
- \fp_neg:N \l_driver_internal_fp
-%<*pdfmode>
- \pdftex_pdfsetmatrix:D
-%</pdfmode>
-%<*xdvipdfmx>
- \driver_pdf_literal_direct:n
-%</xdvipdfmx>
+ \box_set_wd:Nn \l__box_internal_box \c_zero_dim
+ \fp_set:Nn \l__box_cos_fp
{
- \fp_use:N \l_box_cos_fp \c_space_tl
- \fp_use:N \l_box_sin_fp \c_space_tl
- \fp_use:N \l_driver_internal_fp \c_space_tl
- \fp_use:N \l_box_cos_fp
-%<*xdvipdfmx>
- \c_space_tl 0~0~cm
-%</xdvipdfmx>
+ \fp_compare:nNnTF \l__box_cos_fp = \c_zero_fp
+ { 0 }
+ { round ( \l__box_cos_fp , 5 ) }
+ }
+ \fp_set:Nn \l__box_sin_fp { round ( \l__box_sin_fp , 5 ) }
+ \@@_pdf_matrix:n
+ {
+ \fp_use:N \l__box_cos_fp \c_space_tl
+ \fp_compare:nNnTF \l__box_sin_fp = \c_zero_fp
+ { 0~0 }
+ {
+ \fp_use:N \l__box_sin_fp
+ \c_space_tl
+ \fp_eval:n { -\l__box_sin_fp }
+ }
+ \c_space_tl
+ \fp_use:N \l__box_cos_fp
}
%</pdfmode|xdvipdfmx>
}
% \end{macrocode}
-% The end of a rotation means tidying up the output grouping.
+% The end of a rotation means tidying up the output grouping.
% \begin{macrocode}
-\cs_new_eq:NN \driver_box_rotate_end: \driver_graphic_state_restore:
+\cs_new_eq:NN \@@_box_rotate_end: \@@_graphic_state_restore:
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\driver_box_scale_begin:, \driver_box_scale_end:}
+% \begin{macro}{\@@_box_scale_begin:, \@@_box_scale_end:}
% Scaling is not dissimilar to rotation, but the calculations are somewhat
% less complex.
% \begin{macrocode}
-\cs_new_protected:Npn \driver_box_scale_begin:
+\cs_new_protected_nopar:Npn \@@_box_scale_begin:
{
- \driver_graphic_state_save:
+ \fp_set:Nn \l__box_scale_x_fp { round ( \l__box_scale_x_fp , 5 ) }
+ \fp_set:Nn \l__box_scale_y_fp { round ( \l__box_scale_y_fp , 5 ) }
+ \@@_graphic_state_save:
%<*dvips>
- \driver_ps_literal:n
+ \@@_ps_literal:n
{
currentpoint~
currentpoint~translate~
- \fp_use:N \l_box_scale_x_fp \c_space_tl
- \fp_use:N \l_box_scale_y_fp \c_space_tl scale~
+ \fp_use:N \l__box_scale_x_fp \c_space_tl
+ \fp_use:N \l__box_scale_y_fp \c_space_tl scale~
neg~exch~neg~exch~translate
}
%</dvips>
%<*pdfmode|xdvipdfmx>
-%<*pdfmode>
- \pdftex_pdfsetmatrix:D
-%</pdfmode>
-%<*xdvipdfmx>
- \driver_pdf_literal_direct:n
-%</xdvipdfmx>
+ \@@_pdf_matrix:n
{
- \fp_use:N \l_box_scale_x_fp \c_space_tl
+ \fp_use:N \l__box_scale_x_fp \c_space_tl
0~0~
- \fp_use:N \l_box_scale_y_fp
-%<*xdvipdfmx>
- \c_space_tl 0~0~cm
-%</xdvipdfmx>
+ \fp_use:N \l__box_scale_y_fp
}
%</pdfmode|xdvipdfmx>
}
-\cs_new_eq:NN \driver_box_scale_end: \driver_graphic_state_restore:
+\cs_new_eq:NN \@@_box_scale_end: \@@_graphic_state_restore:
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_pdf_matrix:n}
+% Here the appropriate function is set up to insert an affine matrix
+% into the PDF. With a new enough \pdfTeX{} (version~1.40.0 or later)
+% there is a primitive for this, which only needs the rotation/scaling/skew
+% part. With an older \pdfTeX{} or with \texttt{xdvipdfmx} the matrix
+% also has to include a translation part: that is always zero and so is
+% built in here.
+% \begin{macrocode}
+%<*pdfmode>
+\cs_if_exist:NTF \pdftex_pdfsetmatrix:D
+ {
+ \cs_new_protected:Npn \@@_pdf_matrix:n #1
+ { \pdftex_pdfsetmatrix:D {#1} }
+ }
+ {
+ \cs_new_protected:Npn \@@_pdf_matrix:n #1
+ { \@@_pdf_literal:n { #1 \c_space_tl 0~0~cm } }
+ }
+%</pdfmode>
+%<*xdvipdfmx>
+\cs_new_protected:Npn \@@_pdf_matrix:n #1
+ { \@@_pdf_literal_direct:n { #1 \c_space_tl 0~0~cm } }
+%</xdvipdfmx>
% \end{macrocode}
% \end{macro}
%
% \subsection{Colour support}
%
-% \begin{variable}{\l_driver_current_color_tl}
+% \begin{variable}{\l_@@_current_color_tl}
% The current colour is needed by all of the engines, but the way this
% is stored varies.
% \begin{macrocode}
-\tl_new:N \l_driver_current_color_tl
+\tl_new:N \l_@@_current_color_tl
%<*dvips>
-\tl_set:Nn \l_driver_current_color_tl { Black }
+\tl_set:Nn \l_@@_current_color_tl { Black }
%</dvips>
%<*pdfmode>
-\tl_set:Nn \l_driver_current_color_tl { 0~g~0~G }
+\tl_set:Nn \l_@@_current_color_tl { 0~g~0~G }
%</pdfmode>
%<*xdvipdfmx>
-\tl_set:Nn \l_driver_current_color_tl { gray~0 }
+\tl_set:Nn \l_@@_current_color_tl { gray~0 }
%</xdvipdfmx>
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_driver_color_stack_int}
-% \pdfTeX{} and \LuaTeX{} have multiple stacks available, and the colour
-% stack therefore needs a number.
+% \begin{variable}{\l_@@_color_stack_int}
+% \pdfTeX{} (version~1.40.0 or later) and \LuaTeX{} have multiple stacks
+% available, and the colour stack therefore needs a number.
% \begin{macrocode}
%<*pdfmode>
-\int_new:N \l_driver_color_stack_int
+\int_new:N \l_@@_color_stack_int
%</pdfmode>
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}{\driver_color_ensure_current:}
-% \begin{macro}[aux]{\driver_color_reset:}
+% \begin{macro}{\@@_color_ensure_current:}
+% \begin{macro}[aux]{\@@_color_reset:}
% Setting the current colour depends on the nature of the colour stack
% available. In all cases there is a need to reset the colour after
% the current group.
% \begin{macrocode}
-\cs_new_protected:Npn \driver_color_ensure_current:
- {
%<*dvips|xdvipdfmx>
- \tex_special:D { color~push~\l_driver_current_color_tl }
-%</dvips|xdvipdfmx>
-%<*pdfmode>
- \pdftex_pdfcolorstack:D \l_driver_color_stack_int push
- { \l_driver_current_color_tl }
-%</pdfmode>
- \group_insert_after:N \driver_color_reset:
+\cs_new_protected_nopar:Npn \@@_color_ensure_current:
+ {
+ \tex_special:D { color~push~\l_@@_current_color_tl }
+ \group_insert_after:N \@@_color_reset:
}
-\cs_new_protected:Npn \driver_color_reset:
-%<*dvips|xdvipdfmx>
+\cs_new_protected_nopar:Npn \@@_color_reset:
{ \tex_special:D { color~pop } }
%</dvips|xdvipdfmx>
+% \end{macrocode}
+% Once again there is a version switch for \pdfTeX{}, as the
+% \tn{pdfcolorstack} primitive was introduced in version~1.40.0.
+% \begin{macrocode}
%<*pdfmode>
- { \pdftex_pdfcolorstack:D \l_driver_color_stack_int pop }
+\cs_if_exist:NTF \pdftex_pdfcolorstack:D
+ {
+ \cs_new_protected_nopar:Npn \@@_color_ensure_current:
+ {
+ \pdftex_pdfcolorstack:D \l_@@_color_stack_int push
+ { \l_@@_current_color_tl }
+ \group_insert_after:N \@@_color_reset:
+ }
+ \cs_new_protected_nopar:Npn \@@_color_reset:
+ { \pdftex_pdfcolorstack:D \l_@@_color_stack_int pop }
+ }
+ {
+ \cs_new_protected_nopar:Npn \@@_color_ensure_current:
+ {
+ \@@_pdf_literal:n { \l_@@_current_color_tl }
+ \group_insert_after:N \@@_color_reset:
+ }
+ \cs_new_protected_nopar:Npn \@@_color_reset:
+ { \@@_pdf_literal:n { \l_@@_current_color_tl } }
+ }
%</pdfmode>
% \end{macrocode}
% \end{macro}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
index 01024ff6593..8e14807cfcf 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3expan.dtx
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3expan.dtx 3460 2012-02-26 12:16:41Z will $
- {L3 Experimental argument expansion}
+\GetIdInfo$Id: l3expan.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Argument expansion}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -85,17 +85,17 @@
%
% 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
+% \cs{exp_args:NNo}. This function has three arguments, the first and the
% second are a single tokens, while the third argument should be given
-% in braces. Applying |\exp_args:NNo| will expand the content of third
+% in braces. Applying \cs{exp_args:NNo} will expand the content of third
% argument once before any expansion of the first and second arguments.
-% If |\seq_gpush:No| was not define it could be coded in the following way:
+% If \cs{seq_gpush:No} was not defined it could be coded in the following way:
% \begin{verbatim}
% \exp_args:NNo \seq_gpush:Nn
% \g_file_name_stack
% \l_tmpa_tl
% \end{verbatim}
-% In other words, the first argument to |\exp_args:NNo| is the base
+% In other words, the first argument to \cs{exp_args:NNo} is the base
% function and the other arguments are preprocessed and then passed to
% this base function. In the example the first argument to the base
% function should be a single token which is left unchanged while the
@@ -106,17 +106,17 @@
% |\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
+% \cs{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.
+% \cs{cs_generate_variant:Nn}, described next.
%
% \section{Methods for defining variants}
%
-% \begin{function}[updated = 2011-09-15]{\cs_generate_variant:Nn}
+% \begin{function}[updated = 2012-06-21]{\cs_generate_variant:Nn}
% \begin{syntax}
% \cs{cs_generate_variant:Nn} \meta{parent control sequence} \Arg{variant argument specifiers}
% \end{syntax}
@@ -165,7 +165,7 @@
% 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|
+% not work correctly in arguments that are themselves subject to |x|
% expansion.
% \item
% In general, unless in the last position, multi-token arguments
@@ -176,6 +176,7 @@
% not expanded.
% \end{itemize}
%
+% ^^A Bruno: We should drop part of that paragraph eventually.
% 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
@@ -204,13 +205,13 @@
% 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:NN \aaa = \blurb| as we probably wanted. Using
-% |\tl_set:Nx| is not an option as that will die horribly. Instead
+% \cs{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
+% \cs{tl_set:Nf} to be defined as
% \begin{quote}
% |\cs_set_nopar:Npn \tl_set:Nf { \exp_args:NNf \tl_set:Nn }|
% \end{quote}
@@ -315,7 +316,7 @@
% \exp_args:NVV
% }
% \begin{syntax}
-% \cs{exp_args:NNc} \meta{token1} \meta{token2} \Arg{tokens}
+% \cs{exp_args:NNc} \meta{token_1} \meta{token_2} \Arg{tokens}
% \end{syntax}
% These optimized functions absorb three arguments and expand the second and
% third as detailed by their argument specifier. The first argument
@@ -355,7 +356,7 @@
% \exp_args:Nxx
% }
% \begin{syntax}
-% \cs{exp_args:NNx} \meta{token1} \meta{token2} \Arg{tokens}
+% \cs{exp_args:NNx} \meta{token_1} \meta{token_2} \Arg{tokens}
% \end{syntax}
% These functions absorb three arguments and expand the second and
% third as detailed by their argument specifier. The first argument
@@ -376,7 +377,7 @@
% \exp_args:Ncco
% }
% \begin{syntax}
-% \cs{exp_args:NNNo} \meta{token1} \meta{token2} \meta{token3} \Arg{tokens}
+% \cs{exp_args:NNNo} \meta{token_1} \meta{token_2} \meta{token_3} \Arg{tokens}
% \end{syntax}
% These optimized functions absorb four arguments and expand the second, third
% and fourth as detailed by their argument specifier. The first
@@ -393,7 +394,7 @@
% \exp_args:Nooo,
% }
% \begin{syntax}
-% \cs{exp_args:NNNo} \meta{token1} \meta{token2} \meta{token3} \Arg{tokens}
+% \cs{exp_args:NNNo} \meta{token_1} \meta{token_2} \meta{token_3} \Arg{tokens}
% \end{syntax}
% These functions absorb four arguments and expand the second, third
% and fourth as detailed by their argument specifier. The first
@@ -413,7 +414,7 @@
% \exp_args:Nccx
% }
% \begin{syntax}
-% \cs{exp_args:NNnx} \meta{token1} \meta{token2} \Arg{tokens_1} \Arg{tokens_2}
+% \cs{exp_args:NNnx} \meta{token_1} \meta{token_2} \Arg{tokens_1} \Arg{tokens_2}
% \end{syntax}
% These functions absorb four arguments and expand the second, third
% and fourth as detailed by their argument specifier. The first
@@ -441,7 +442,7 @@
% \exp_last_unbraced:NnNo
% }
% \begin{syntax}
-% \cs{exp_last_unbraced:Nno} \meta{token} \meta{tokens1} \meta{tokens2}
+% \cs{exp_last_unbraced:Nno} \meta{token} \meta{tokens_1} \meta{tokens_2}
% \end{syntax}
% These functions absorb the number of arguments given by their
% specification, carry out the expansion
@@ -469,7 +470,7 @@
%
% \begin{function}[EXP]{\exp_last_two_unbraced:Noo}
% \begin{syntax}
-% \cs{exp_last_two_unbraced:Noo} \meta{token} \meta{tokens1} \Arg{tokens_2}
+% \cs{exp_last_two_unbraced:Noo} \meta{token} \meta{tokens_1} \Arg{tokens_2}
% \end{syntax}
% This function absorbs three arguments and expand the second and third
% once. The first argument of the function is then the next item on the
@@ -480,14 +481,14 @@
%
% \begin{function}[EXP]{\exp_after:wN}
% \begin{syntax}
-% \cs{exp_after:wN} \meta{token1} \meta{token2}
+% \cs{exp_after:wN} \meta{token_1} \meta{token_2}
% \end{syntax}
-% Carries out a single expansion of \meta{token2} (which may consume
+% Carries out a single expansion of \meta{token_2} (which may consume
% arguments) prior to the expansion
-% of \meta{token1}. If \meta{token2} is a \TeX{} primitive, it will
-% be executed rather than expanded, while if \meta{token2} has not
+% of \meta{token_1}. If \meta{token_2} is a \TeX{} primitive, it will
+% be executed rather than expanded, while if \meta{token_2} has not
% expansion (for example, if it is a character) then it will be left
-% unchanged. It is important to notice that \meta{token1} may be
+% unchanged. It is important to notice that \meta{token_1} may be
% \emph{any} single token, including group-opening and -closing
% tokens (|{| or |}| assuming normal \TeX{} category codes). Unless
% specifically required, expansion should be carried out using an
@@ -529,11 +530,11 @@
% \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.
+% Prevents expansion of the \meta{tokens} in a context where they
+% would otherwise be expanded, for example an |x|-type argument.
% \begin{texnote}
-% This is the \eTeX{} \tn{unexpanded} primitive.
+% This is the \eTeX{} \tn{unexpanded} primitive. Hence its argument
+% \emph{must} be surrounded by braces.
% \end{texnote}
% \end{function}
%
@@ -591,24 +592,12 @@
%
% \section{Internal functions and variables}
%
-% \begin{variable}{\l_exp_internal_tl}
+% \begin{variable}{\l__exp_internal_tl}
% The |\exp_| module has its private variables to temporarily store
% results of the argument expansion. This is done to avoid interference
% with other functions using temporary variables.
% \end{variable}
%
-% \begin{function}[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), preceded by \cs{c_zero} which stops
-% the expansion of a previous \tn{romannumeral}.
-% 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 \::: }|
@@ -618,15 +607,6 @@
% 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}
@@ -636,13 +616,17 @@
% \begin{macrocode}
%<*initex|package>
% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=exp>
+% \end{macrocode}
%
% We start by ensuring that the required packages are loaded.
% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -659,23 +643,23 @@
% 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.})
+% to use one of the \LaTeX3 names for \cs{cs_set_nopar:Npx} at some
+% point, and so is never going to be expandable.\footnote{Some
+% primitives have certain characteristics that means that their
+% arguments undergo an expansion similar to an \texttt{x} type
+% expansion but the primitive is in fact still expandable. We 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|.
+% method for efficiency, typically using calls to \cs{exp_after:wN}.
%
-% \begin{variable}{\l_exp_internal_tl}
+% \begin{variable}{\l_@@_internal_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_internal_tl { }
+\cs_new_nopar:Npn \l_@@_internal_tl { }
% \end{macrocode}
% \end{variable}
%
@@ -686,12 +670,12 @@
%
% 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|
+% \cs{:::} serves as an end marker for the list of manipulations, |#2|
% is the carried over result of the previous expansion steps and |#3| is
% the argument about to be processed.
%
-% \begin{macro}[aux, EXP]{\exp_arg_next:nnn}
-% \begin{macro}[aux, EXP]{\exp_arg_next:Nnn}
+% \begin{macro}[aux, EXP]{\@@_arg_next:nnn}
+% \begin{macro}[aux, EXP]{\@@_arg_next:Nnn}
% |#1| is the result of an expansion step, |#2| is the remaining
% argument manipulations and |#3| is the current result of the
% expansion chain. This auxiliary function moves |#1| back after
@@ -702,8 +686,8 @@
% 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:Nnn #1#2#3 { #2 \::: { #3 #1 } }
+\cs_new:Npn \@@_arg_next:nnn #1#2#3 { #2 \::: { #3 {#1} } }
+\cs_new:Npn \@@_arg_next:Nnn #1#2#3 { #2 \::: { #3 #1 } }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -736,7 +720,7 @@
% as control sequence without expansion.
% \begin{macrocode}
\cs_new:Npn \::c #1 \::: #2#3
- { \exp_after:wN \exp_arg_next:Nnn \cs:w #3 \cs_end: {#1} {#2} }
+ { \exp_after:wN \@@_arg_next:Nnn \cs:w #3 \cs_end: {#1} {#2} }
% \end{macrocode}
% \end{macro}
%
@@ -744,7 +728,7 @@
% 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} }
+ { \exp_after:wN \@@_arg_next:nnn \exp_after:wN {#3} {#1} {#2} }
% \end{macrocode}
% \end{macro}
%
@@ -755,13 +739,13 @@
% 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:|
+% something non-expandable or a space. We introduce \cs{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:NN \aaa = \blurb| which then turned out to contain
-% the non-expandable token |\cs_set_eq:NN|. Since the expansion of
+% the non-expandable token \cs{cs_set_eq:NN}. Since the expansion of
% \tn{romannumeral} |-`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
@@ -769,7 +753,7 @@
% \begin{macrocode}
\cs_new:Npn \::f #1 \::: #2#3
{
- \exp_after:wN \exp_arg_next:nnn
+ \exp_after:wN \@@_arg_next:nnn
\exp_after:wN { \tex_romannumeral:D -`0 #3 }
{#1} {#2}
}
@@ -783,8 +767,8 @@
% \begin{macrocode}
\cs_new_protected:Npn \::x #1 \::: #2#3
{
- \cs_set_nopar:Npx \l_exp_internal_tl { {#3} }
- \exp_after:wN \exp_arg_next:nnn \l_exp_internal_tl {#1} {#2}
+ \cs_set_nopar:Npx \l_@@_internal_tl { {#3} }
+ \exp_after:wN \@@_arg_next:nnn \l_@@_internal_tl {#1} {#2}
}
% \end{macrocode}
% \end{macro}
@@ -801,22 +785,22 @@
% \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 }
+ \exp_after:wN \@@_arg_next:nnn
+ \exp_after:wN { \tex_romannumeral:D \@@_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} }
+ \exp_after:wN \@@_arg_next:nnn
+ \exp_after:wN { \tex_romannumeral:D \@@_eval_register:c {#3} }
{#1} {#2}
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int, EXP]{\exp_eval_register:N, \exp_eval_register:c}
-% \begin{macro}[aux, EXP]{\exp_eval_error_msg:w}
+% \begin{macro}[int, EXP]{\@@_eval_register:N, \@@_eval_register:c}
+% \begin{macro}[aux, EXP]{\@@_eval_error_msg:w}
% This function evaluates a register. Now a register might exist as
% one of two things: A parameter-less macro or a built-in \TeX{}
% register such as |\count|. For the \TeX{} registers we have to
@@ -824,19 +808,19 @@
% expand them once. The trick is to find out when to use
% \tn{the} and when not to. What we do here is try to find out
% whether the token will expand to something else when hit with
-% |\exp_after:wN|. The technique is to compare the meaning of the
-% register in question when it has been prefixed with |\exp_not:N|
+% \cs{exp_after:wN}. The technique is to compare the meaning of the
+% register in question when it has been prefixed with \cs{exp_not:N}
% and the register itself. If it is a macro, the prefixed
-% |\exp_not:N| will temporarily turn it into the primitive
-% |\scan_stop:|.
+% \cs{exp_not:N} will temporarily turn it into the primitive
+% \cs{scan_stop:}.
% \begin{macrocode}
-\cs_new:Npn \exp_eval_register:N #1
+\cs_new:Npn \@@_eval_register:N #1
{
\exp_after:wN \if_meaning:w \exp_not:N #1 #1
% \end{macrocode}
% If the token was not a macro it may be a malformed variable from a
% |c| expansion in which case it is equal to the primitive
-% |\scan_stop:|. In that case we throw an error. We could let \TeX{}
+% \cs{scan_stop:}. In that case we throw an error. We could let \TeX{}
% do it for us but that would result in the rather obscure
% \begin{quote}
% |! You can't use `\relax' after \the.|
@@ -845,7 +829,7 @@
% went wrong. We provide something more sensible.
% \begin{macrocode}
\if_meaning:w \scan_stop: #1
- \exp_eval_error_msg:w
+ \@@_eval_error_msg:w
\fi:
% \end{macrocode}
% The next bit requires some explanation. The function must be
@@ -856,15 +840,15 @@
% |\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|.
+% remove the \cs{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:Npn \exp_eval_register:c #1
- { \exp_after:wN \exp_eval_register:N \cs:w #1 \cs_end: }
+\cs_new:Npn \@@_eval_register:c #1
+ { \exp_after:wN \@@_eval_register:N \cs:w #1 \cs_end: }
% \end{macrocode}
% Clean up nicely, then call the undefined control sequence. The
% result is an error message looking like this:
@@ -875,11 +859,11 @@
% l.55 \tl_set:Nv \l_tmpa_tl {undefined_tl}
% \end{verbatim}
% \begin{macrocode}
-\cs_new:Npn \exp_eval_error_msg:w #1 \tex_the:D #2
+\cs_new:Npn \@@_eval_error_msg:w #1 \tex_the:D #2
{
\fi:
\fi:
- \msg_expandable_kernel_error:nnn { kernel } { bad-var } {#2}
+ \__msg_kernel_expandable_error:nnn { kernel } { bad-variable } {#2}
\c_zero
}
% \end{macrocode}
@@ -891,7 +875,7 @@
%
% One of the most important features of these functions is that they
% are fully expandable and therefore allow to prefix them with
-% |\tex_global:D| for example.
+% \cs{tex_global:D} for example.
%
% \begin{macro}[EXP]{\exp_args:No}
% \begin{macro}[EXP]{\exp_args:NNo}
@@ -940,12 +924,12 @@
\cs_new:Npn \exp_args:Nv #1#2
{
\exp_after:wN #1 \exp_after:wN
- { \tex_romannumeral:D \exp_eval_register:c {#2} }
+ { \tex_romannumeral:D \@@_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 }
+ { \tex_romannumeral:D \@@_eval_register:N #2 }
}
% \end{macrocode}
% \end{macro}
@@ -971,13 +955,13 @@
{
\exp_after:wN #1
\exp_after:wN #2
- \exp_after:wN { \tex_romannumeral:D \exp_eval_register:c {#3} }
+ \exp_after:wN { \tex_romannumeral:D \@@_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 }
+ \exp_after:wN { \tex_romannumeral:D \@@_eval_register:N #3 }
}
\cs_new:Npn \exp_args:Nco #1#2#3
{
@@ -995,8 +979,8 @@
{
\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 }
+ \@@_eval_register:N \exp_after:wN #2 \exp_after:wN }
+ \exp_after:wN { \tex_romannumeral:D \@@_eval_register:N #3 }
}
% \end{macrocode}
% \end{macro}
@@ -1013,7 +997,7 @@
\exp_after:wN #1
\exp_after:wN #2
\exp_after:wN #3
- \exp_after:wN { \tex_romannumeral:D \exp_eval_register:N #4 }
+ \exp_after:wN { \tex_romannumeral:D \@@_eval_register:N #4 }
}
\cs_new:Npn \exp_args:NcNc #1#2#3#4
{
@@ -1114,7 +1098,7 @@
%
% \subsection{Last-unbraced versions}
%
-% \begin{macro}[aux, EXP]{\exp_arg_last_unbraced:nn}
+% \begin{macro}[aux, EXP]{\@@_arg_last_unbraced:nn}
% \begin{macro}[aux, EXP]{\::f_unbraced}
% \begin{macro}[aux, EXP]{\::o_unbraced}
% \begin{macro}[aux, EXP]{\::V_unbraced}
@@ -1123,28 +1107,28 @@
% 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 \@@_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 \@@_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} }
+ { \exp_after:wN \@@_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}
+ \exp_after:wN \@@_arg_last_unbraced:nn
+ \exp_after:wN { \tex_romannumeral:D \@@_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}
+ \exp_after:wN \@@_arg_last_unbraced:nn
+ \exp_after:wN { \tex_romannumeral:D \@@_eval_register:c {#2} } {#1}
}
\cs_new_protected:Npn \::x_unbraced \::: #1#2
{
- \cs_set_nopar:Npx \l_exp_internal_tl { \exp_not:n {#1} #2 }
- \l_exp_internal_tl
+ \cs_set_nopar:Npx \l_@@_internal_tl { \exp_not:n {#1} #2 }
+ \l_@@_internal_tl
}
% \end{macrocode}
% \end{macro}
@@ -1173,9 +1157,9 @@
% 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 }
+ { \exp_after:wN #1 \tex_romannumeral:D \@@_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} }
+ { \exp_after:wN #1 \tex_romannumeral:D \@@_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 }
@@ -1185,13 +1169,13 @@
{
\exp_after:wN #1
\cs:w #2 \exp_after:wN \cs_end:
- \tex_romannumeral:D \exp_eval_register:N #3
+ \tex_romannumeral:D \@@_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
+ \tex_romannumeral:D \@@_eval_register:N #3
}
\cs_new:Npn \exp_last_unbraced:NNo #1#2#3
{ \exp_after:wN #1 \exp_after:wN #2 #3 }
@@ -1200,7 +1184,7 @@
\exp_after:wN #1
\exp_after:wN #2
\exp_after:wN #3
- \tex_romannumeral:D \exp_eval_register:N #4
+ \tex_romannumeral:D \@@_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 }
@@ -1227,6 +1211,7 @@
% \end{macro}
%
% \begin{macro}[EXP]{\exp_last_two_unbraced:Noo}
+% \begin{macro}[EXP, aux]{\@@_last_two_unbraced:noN}
% If |#2| is a single token then this can be implemented as
% \begin{verbatim}
% \cs_new:Npn \exp_last_two_unbraced:Noo #1 #2 #3
@@ -1236,11 +1221,12 @@
% 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:noN \exp_after:wN {#3} {#2} #1 }
-\cs_new:Npn \exp_last_two_unbraced_aux:noN #1#2#3
+ { \exp_after:wN \@@_last_two_unbraced:noN \exp_after:wN {#3} {#2} #1 }
+\cs_new:Npn \@@_last_two_unbraced:noN #1#2#3
{ \exp_after:wN #3 #2 #1 }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \subsection{Preventing expansion}
%
@@ -1257,12 +1243,12 @@
\cs_new:Npn \exp_not:V #1
{
\etex_unexpanded:D \exp_after:wN
- { \tex_romannumeral:D \exp_eval_register:N #1 }
+ { \tex_romannumeral:D \@@_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} }
+ { \tex_romannumeral:D \@@_eval_register:c {#1} }
}
% \end{macrocode}
% \end{macro}
@@ -1273,94 +1259,197 @@
%
% \subsection{Defining function variants}
%
+% \begin{macrocode}
+%<@@=cs>
+% \end{macrocode}
+%
% \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{arguments}
-% \item Base form of a function; \emph{e.g.},~|\tl_set:Nn|
+% \item Base form of a function; \emph{e.g.},~\cs{tl_set:Nn}
% \item One or more variant argument specifiers; e.g., |{Nx,c,cx}|
% \end{arguments}
-% Test whether the base function is protected or not
-% and define \cs{cs_tmp:w} as either \cs{cs_new_nopar:Npx} or
-% \cs{cs_new_protected_nopar:Npx}, then used to define all the
-% variants.
-% 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|.
+% After making sure that the base form exists, test whether it is
+% protected or not and define \cs{@@_tmp:w} as either
+% \cs{cs_new_nopar:Npx} or \cs{cs_new_protected_nopar:Npx}, which is
+% then used to define all the variants (except those involving
+% \texttt{x}-expansion, always protected). Split up the original base
+% function only once, to grab its name and signature. Then we wish to
+% iterate through the comma list of variant argument specifiers, which
+% we first convert to a string: the reason is explained later.
% \begin{macrocode}
-\cs_new_protected:Npn \cs_generate_variant:Nn #1
+\cs_new_protected:Npn \cs_generate_variant:Nn #1#2
{
- \chk_if_exist_cs:N #1
- \cs_generate_variant_aux:N #1
- \cs_split_function:NN #1 \cs_generate_variant_aux:nnNNn
- #1
+ \__chk_if_exist_cs:N #1
+ \@@_generate_variant:N #1
+ \exp_after:wN \@@_split_function:NN
+ \exp_after:wN #1
+ \exp_after:wN \@@_generate_variant:nnNN
+ \exp_after:wN #1
+ \etex_detokenize:D {#2} , ? , \q_recursion_stop
}
% \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.
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_generate_variant:N}
+% \begin{macro}[aux]{\@@_generate_variant:w}
+% The idea here is to pick up protected parent functions, using the
+% nature of the meaning string that they generate. If |\protected|
+% appears in the meaning, the first \cs{q_mark} is taken as an
+% argument, and |#3| is \cs{cs_new_protected_nopar:Npx}, otherwise it
+% is \cs{cs_new_nopar:Npx}.
% \begin{macrocode}
-\cs_new_protected:Npn \cs_generate_variant_aux:nnNNn #1#2#3#4#5
- { \cs_generate_variant_aux:Nnnw #4 {#1}{#2} #5 , ? , \q_recursion_stop }
+\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_protected:Npn \@@_generate_variant:N #1
+ {
+ \exp_after:wN \@@_generate_variant:w
+ \token_to_meaning:N #1
+ \q_mark \cs_new_protected_nopar:Npx
+ ? PROTECTEZ
+ \q_mark \cs_new_nopar:Npx
+ \q_stop
+ }
+ \cs_new_protected:Npn \@@_generate_variant:w
+ #1 ? PROTECTEZ #2 \q_mark #3 #4 \q_stop
+ {
+ \cs_set_eq:NN \@@_tmp:w #3
+ }
+ }
% \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|. Depending on
-% the number of characters in |#4|, the relevant \cs{use_none:n\ldots{}n}
-% is called.
-%
-% Firstly though, we check whether to terminate the loop.
-% Then build the variant function once, to avoid repeating this
-% relatively expensive operation. Then recurse.
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_generate_variant:nnNN}
+% \begin{arguments}
+% \item Base name.
+% \item Base signature.
+% \item Boolean.
+% \item Base function.
+% \end{arguments}
+% We discard the boolean and then set off a loop through the desired
+% variant forms. The original function is retained as |#4| for
+% efficiency.
% \begin{macrocode}
-\cs_new_protected:Npn \cs_generate_variant_aux:Nnnw #1#2#3#4 ,
+\cs_new_protected:Npn \@@_generate_variant:nnNN #1#2#3#4
+ { \@@_generate_variant:Nnnw #4 {#1}{#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_generate_variant:Nnnw}
+% \begin{arguments}
+% \item Base function.
+% \item Base name.
+% \item Base signature.
+% \item Beginning of variant signature.
+% \end{arguments}
+% First check whether to terminate the loop over variant forms. Then
+% build the variant function name once, to avoid repeating this
+% relatively expensive operation. Then recurse, calling
+% \cs{@@_generate_variant:Nnnw} with the three same arguments (and a
+% new item from the comma list of variant forms).
+%
+% For each variant form, construct a new function name using the
+% original base name, the variant signature consisting of $l$ letters
+% and the last $k-l$ letters of the base signature (of length $k$).
+% For example, for a base function \cs{prop_put:Nnn} which needs a
+% |cV| variant form, we want the new signature to be |cVn|. This
+% could be done by placing the variant form letters, then
+% \cs{use_none:nn} followed by the signature (the choice of
+% \cs{use_none:nn} would depend on the variant form). However, this
+% would crash badly if the base signature is mistakenly shorter than
+% the variant form (this includes cases where the base function had no
+% colon). Instead, we do a loop which at each step removes a
+% character from the base signature and leaves one from the variant
+% form behind it in a \cs{cs:w} \ldots{} \cs{cs_end:} construction.
+% This \texttt{c}-type expansion is not done using \cs{exp_args:NNc}
+% because some error-reporting mechanism must escape out of this
+% construction.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_generate_variant: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
- \exp_after:wN \use_i_delimit_by_q_stop:nw
- \use_none:nnnnnnnnn #4
- \use_none:nnnnnnnnn
- \use_none:nnnnnnnn
- \use_none:nnnnnnn
- \use_none:nnnnnn
- \use_none:nnnnn
- \use_none:nnnn
- \use_none:nnn
- \use_none:nn
- \use_none:n
- { }
+ \exp_after:wN \@@_generate_variant:NNn
+ \exp_after:wN #1
+ \cs:w
+ #2 :
+ \@@_generate_variant_loop:NwN
+ ? #3
+ \q_mark #4 \@@_generate_variant_loop_end:w
+ \q_mark \@@_generate_variant_loop_error:wnNNnn
\q_stop
- #3
- }
+ \cs_end:
{#4}
- \cs_generate_variant_aux:Nnnw #1 {#2} {#3}
+ \@@_generate_variant:Nnnw #1 {#2} {#3}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_generate_variant_loop:NwN}
+% \begin{macro}[aux, EXP]
+% {
+% \@@_generate_variant_loop_end:w,
+% \@@_generate_variant_loop_error:wnNNnn
+% }
+% Normally, the loop takes one character of the base signature and one
+% from the variant form (after \cs{q_mark}), and leaves the latter one
+% in the input stream. This stops when |#3| is the \texttt{loop_end}
+% auxiliary, which, once left in the input stream, cleans up the rest
+% of the csname construction. In case the base signature was in fact
+% shorter, one reaches the point where |#1| is the \cs{q_mark} which
+% is supposed to separate the base signature from the variant form.
+% Then |#2| is delimited by the next \cs{q_mark}, and the
+% \texttt{loop_error} auxiliary is taken as |#3|. This function
+% fetches appropriate arguments for an error message, and places it
+% outside the csname construction.
+%
+% Note in the definition of \cs{@@_generate_variant:Nnnw} the base
+% signature is preceeded by a question mark. This shifts the base
+% signature and variant form to compensate for the presence of the
+% \texttt{loop_end} auxiliary at the end of the variant form.
+% \begin{macrocode}
+\cs_new:Npn \@@_generate_variant_loop:NwN #1 #2 \q_mark #3
+ { #3 \@@_generate_variant_loop:NwN #2 \q_mark }
+\cs_new:Npn \@@_generate_variant_loop_end:w #1#2 \q_mark #3 \q_stop {#2}
+\cs_new:Npn \@@_generate_variant_loop_error:wnNNnn
+ #1 \q_stop \cs_end: #2 #3#4#5#6
+ {
+ \cs_end: {#2}
+ \__msg_kernel_error:nnxx { kernel } { variant-too-long }
+ { \tl_to_str:n {#2} } { \token_to_str:N #4 }
+ #3 #4 {#5} {#6}
}
% \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.
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_generate_variant:NNn}
+% If the variant form has already been defined, log its existence.
+% Otherwise, make sure that the |\exp_args:N #3| form is defined, and
+% if it contains |x|, change \cs{@@_tmp:w} locally to
+% \cs{cs_new_protected_nopar:Npx}. Then define the variant by
+% combining the |\exp_args:N #3| variant and the base function.
% \begin{macrocode}
-\cs_new_protected:Npn \cs_generate_variant_aux:NNn #1 #2 #3
+\cs_new_protected:Npn \@@_generate_variant:NNn #1 #2 #3
{
\cs_if_free:NTF #2
{
- \cs_tmp:w #2 { \exp_not:c { exp_args:N #3 } \exp_not:N #1 }
- \cs_generate_internal_variant:n {#3}
+ \group_begin:
+ \@@_generate_internal_variant:n {#3}
+ \@@_tmp:w #2 { \exp_not:c { exp_args:N #3 } \exp_not:N #1 }
+ \group_end:
}
{
\iow_log:x
@@ -1373,86 +1462,65 @@
}
% \end{macrocode}
% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
-% \begin{macro}[aux]{\cs_generate_variant_aux:N}
-% \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{macro}[int]{\@@_generate_internal_variant:n}
+% \begin{macro}[aux]{\@@_generate_internal_variant:wwnw}
+% \begin{macro}[aux, rEXP]{\@@_generate_internal_variant_loop:n}
+% Test if |\exp_args:N #1| is already defined and if not define it via
+% the |\::| commands using the chars in |#1|. If |#1| contains an |x|
+% (this is the place where having converted the original comma-list
+% argument to a string is very important), the result should be
+% protected, and the next variant to be defined using that internal
+% variant should be protected.
% \begin{macrocode}
\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_catcode:D `\X = 12 \scan_stop:
+ \tex_lccode:D `\N = `\N \scan_stop:
\tex_lowercase:D
{
\group_end:
- \cs_new_protected:Npn \cs_generate_variant_aux:N #1
- {
- \exp_after:wN \cs_generate_variant_aux:w
- \token_to_meaning:N #1
- \q_mark \cs_new_protected_nopar:Npx
- ? PROTECTEZ
- \q_mark \cs_new_nopar:Npx
- \q_stop
- }
- \cs_new_protected:Npn \cs_generate_variant_aux:w
- #1 ? PROTECTEZ #2 \q_mark #3 #4 \q_stop
+ \cs_new_protected:Npn \@@_generate_internal_variant:n #1
{
- \cs_set_eq:NN \cs_tmp:w #3
+ \@@_generate_internal_variant:wwnNwnn
+ #1 \q_mark
+ { \cs_set_eq:NN \@@_tmp:w \cs_new_protected_nopar:Npx }
+ \cs_new_protected_nopar:cpx
+ X \q_mark
+ { }
+ \cs_new_nopar:cpx
+ \q_stop
+ { exp_args:N #1 }
+ { \@@_generate_internal_variant_loop:n #1 { : \use_i:nn } }
}
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[int]{\cs_generate_internal_variant:n}
-% \begin{macro}[aux, rEXP]{\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_protected:Npn \@@_generate_internal_variant:wwnNwnn
+ #1 X #2 \q_mark #3 #4 #5 \q_stop #6 #7
{
- \cs_new:cpx { exp_args:N #1 }
- { \cs_generate_internal_variant_aux:N #1 : }
+ #3
+ \cs_if_free:cT {#6} { #4 {#6} {#7} }
}
}
% \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.
+% further). We avoid tests by putting a trailing |: \use_i:nn|, which
+% leaves \cs{cs_end:} and removes the looping macro. The colon is in
+% fact also turned into \cs{:::} so that the required structure for
+% |\exp_args:N...| commands is correctly terminated.
% \begin{macrocode}
-\cs_new:Npn \cs_generate_internal_variant_aux:N #1
+\cs_new:Npn \@@_generate_internal_variant_loop:n #1
{
- \exp_not:c { :: #1 }
- \if_meaning:w : #1
- \exp_after:wN \use_none:n
- \fi:
- \cs_generate_internal_variant_aux:N
+ \exp_after:wN \exp_not:N \cs:w :: #1 \cs_end:
+ \@@_generate_internal_variant_loop:n
}
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
%\subsection{Variants which cannot be created earlier}
%
% \begin{macro}[EXP,pTF]
% {\str_if_eq:Vn, \str_if_eq:on, \str_if_eq:nV, \str_if_eq:no, \str_if_eq:VV}
+% \begin{macro}[EXP]{\str_case:onn}
% 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 }
@@ -1463,8 +1531,10 @@
\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 }
+\cs_generate_variant:Nn \str_case:nnn { o }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macrocode}
%</initex|package>
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
index 9b8bd6b1a0a..919281bd552 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3file.dtx
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3file.dtx 3520 2012-03-09 19:34:07Z joseph $
- {L3 Experimental file and I/O operations}
+\GetIdInfo$Id: l3file.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 File and I/O operations}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -78,6 +78,13 @@
% \enquote{current path} for \TeX{} is somewhat broader than that for other
% programs.
%
+% For functions which expect a \meta{file name} argument, this argument
+% may contain both literal items and expandable content, which should on
+% full expansion be the desired file name. Any active characters (as
+% declared in \cs{l_char_active_seq}) will \emph{not} be expanded,
+% allowing the direct use of these in file names.
+% Spaces are not allowed in file names.
+%
% \section{File operation functions}
%
% \begin{variable}{\g_file_current_name_tl}
@@ -95,11 +102,6 @@
% Searches for \meta{file name} using the current \TeX{} search
% path and the additional paths controlled by
% \cs{file_path_include:n}).
-% \begin{texnote}
-% The \meta{file name} may contain both literal items and expandable
-% content, which should on full expansion be the desired file name.
-% The expansion occurs when \TeX{} searches for the file.
-% \end{texnote}
% \end{function}
%
% \begin{function}[updated = 2012-02-10]{\file_add_path:nN}
@@ -108,16 +110,9 @@
% \end{syntax}
% Searches for \meta{file name} in the path as detailed for
% \cs{file_if_exist:nTF}, and if found sets the \meta{tl var} the
-% fully-qualified name of the file, \emph{i.e}.~the path and file name.
+% fully-qualified name of the file, \emph{i.e.}~the path and file name.
% If the file is not found then the \meta{tl var} will contain the
% marker \cs{q_no_value}.
-% \begin{texnote}
-% The \meta{file name} may contain both literal items and expandable
-% content, which should on full expansion be the desired file name.
-% Any active characters (as declared in \cs{l_char_active_seq}) will
-% \emph{not} be expanded, allowing the direct use of these in
-% file names.
-% \end{texnote}
% \end{function}
%
% \begin{function}[updated = 2012-02-17]{\file_input:n}
@@ -128,30 +123,29 @@
% \cs{file_if_exist:nTF}, and if found reads in the file as
% additional \LaTeX{} source. All files read are recorded
% for information and the file name stack is updated by this
-% function. An error will be raised if the file is not found
-% \begin{texnote}
-% The \meta{file name} may contain both literal items and expandable
-% content, which should on full expansion be the desired file name.
-% Any active characters (as declared in \cs{l_char_active_seq}) will
-% \emph{not} be expanded, allowing the direct use of these in
-% file names.
-% \end{texnote}
+% function. An error will be raised if the file is not found.
% \end{function}
%
-% \begin{function}{\file_path_include:n}
+% \begin{function}[updated = 2012-07-04]{\file_path_include:n}
% \begin{syntax}
% \cs{file_path_include:n} \Arg{path}
% \end{syntax}
% Adds \meta{path} to the list of those used to search when reading
% files. The assignment is local.
+% The \meta{path} is processed in the same way as a \meta{file name},
+% \emph{i.e.}, with \texttt{x}-type expansion except active
+% characters. Spaces are not allowed in the \meta{path}.
% \end{function}
%
-% \begin{function}{\file_path_remove:n}
+% \begin{function}[updated = 2012-07-04]{\file_path_remove:n}
% \begin{syntax}
% \cs{file_path_remove:n} \Arg{path}
% \end{syntax}
% Removes \meta{path} from the list of those used to search when reading
% files. The assignment is local.
+% The \meta{path} is processed in the same way as a \meta{file name},
+% \emph{i.e.}, with \texttt{x}-type expansion except active
+% characters. Spaces are not allowed in the \meta{path}.
% \end{function}
%
% \begin{function}{\file_list:}
@@ -171,16 +165,20 @@
% close streams when they are no longer needed, to release them for other
% processes.
%
+% Note that I/O operations are global: streams should all be declared
+% with global names and treated accordingly.
+%
% \begin{function}[added = 2011-09-26, updated = 2011-12-27]
% {\ior_new:N, \ior_new:c, \iow_new:N, \iow_new:c}
% \begin{syntax}
-% \cs{ior_new:Nn} \meta{stream}
+% \cs{ior_new:N} \meta{stream}
+% \cs{iow_new:N} \meta{stream}
% \end{syntax}
% Globally reserves the name of the \meta{stream}, either for reading
-% or for writing as appropriate. The \meta{stream} is not opened until the
-% appropriate \cs{\ldots_open:Nn} function is used. Attempting to use
-% a \meta{stream} which has not been opened will result in a \TeX{}
-% error.
+% or for writing as appropriate. The \meta{stream} is not opened until
+% the appropriate \cs{\ldots_open:Nn} function is used. Attempting to
+% use a \meta{stream} which has not been opened is an error, and the
+% \meta{stream} will behave as the corresponding \cs{c_term_\ldots}.
% \end{function}
%
% \begin{function}[updated = 2012-02-10]{\ior_open:Nn, \ior_open:cn}
@@ -192,14 +190,7 @@
% open it is closed before the new operation begins. The
% \meta{stream} is available for access immediately and will remain
% allocated to \meta{file name} until a \cs{ior_close:N} instruction
-% is given or the file ends.
-% \begin{texnote}
-% The \meta{file name} may contain both literal items and expandable
-% content, which should on full expansion be the desired file name.
-% Any active characters (as declared in \cs{l_char_active_seq}) will
-% \emph{not} be expanded, allowing the direct use of these in
-% file names.
-% \end{texnote}
+% is given or the \TeX{} run ends.
% \end{function}
%
% \begin{function}[updated = 2012-02-09]{\iow_open:Nn, \iow_open:cn}
@@ -211,34 +202,20 @@
% open it is closed before the new operation begins. The
% \meta{stream} is available for access immediately and will remain
% allocated to \meta{file name} until a \cs{iow_close:N} instruction
-% is given or the file ends. Opening a file for writing will clear
+% is given or the \TeX{} run ends. Opening a file for writing will clear
% any existing content in the file (\emph{i.e.}~writing is \emph{not}
% additive).
-% \begin{texnote}
-% The \meta{file name} may contain both literal items and expandable
-% content, which should on full expansion be the desired file name.
-% Any active characters (as declared in \cs{l_char_active_seq}) will
-% \emph{not} be expanded, allowing the direct use of these in
-% file names.
-% \end{texnote}
% \end{function}
%
-% \begin{function}[updated = 2011-12-27]{\ior_close:N, \ior_close:c}
+% \begin{function}[updated = 2012-07-03]
+% {\ior_close:N, \ior_close:c, \iow_close:N, \iow_close:c}
% \begin{syntax}
% \cs{ior_close:N} \meta{stream}
-% \end{syntax}
-% Closes the \meta{stream}. Streams should always be closed when
-% they are finished with as this ensures that they remain available
-% to other programmer.
-% \end{function}
-%
-% \begin{function}[updated = 2011-12-27]{\iow_close:N, \iow_close:c}
-% \begin{syntax}
% \cs{iow_close:N} \meta{stream}
% \end{syntax}
% Closes the \meta{stream}. Streams should always be closed when
% they are finished with as this ensures that they remain available
-% to other programmer.
+% to other programmers.
% \end{function}
%
% \begin{function}{\ior_list_streams:, \iow_list_streams:}
@@ -250,38 +227,38 @@
% stream: intended for tracking down problems.
% \end{function}
%
-% \section{Reading from files}
+% \subsection{Reading from files}
%
-% \begin{function}{\ior_to:NN,\ior_gto:NN}
+% \begin{function}[added = 2012-06-24]{\ior_get:NN}
% \begin{syntax}
-% \cs{ior_to:NN} \meta{stream} \meta{token list variable}
+% \cs{ior_get:NN} \meta{stream} \meta{token list variable}
% \end{syntax}
-% Functions that reads one or more lines (until an equal number of left
+% Function that reads one or more lines (until an equal number of left
% and right braces are found) from the input \meta{stream} and stores
-% the result in the \meta{token list} variable, locally or globally. If the
+% the result locally in the \meta{token list} variable. If the
% \meta{stream} is not open, input is requested from the terminal.
% The material read from the \meta{stream} will be tokenized by
% \TeX{} according to the category codes in force when the function
% is used.
% \begin{texnote}
-% This protected macro expands to the \TeX{} primitives \tn{read}
-% or \tn{global}\tn{read} along with the |to| keyword.
+% This protected macro expands to the \TeX{} primitive \tn{read}
+% along with the |to| keyword.
% \end{texnote}
% \end{function}
%
-% \begin{function}{\ior_str_to:NN,\ior_str_gto:NN}
+% \begin{function}[added = 2012-06-24]{\ior_get_str:NN}
% \begin{syntax}
-% \cs{ior_str_to:NN} \meta{stream} \meta{token list variable}
+% \cs{ior_get_str:NN} \meta{stream} \meta{token list variable}
% \end{syntax}
-% Functions that reads one line from the input \meta{stream} and stores
-% the result in the \meta{token list} variable, locally or globally. If the
+% Function that reads one line from the input \meta{stream} and stores
+% the result locally in the \meta{token list} variable. If the
% \meta{stream} is not open, input is requested from the terminal.
-% The material read from the \meta{stream} as a series of tokens with
+% The material is read from the \meta{stream} as a series of tokens with
% category code $12$ (other), with the exception of space
% characters which are given category code $10$ (space).
% \begin{texnote}
-% This protected macro expands to the \eTeX{} primitives \tn{readline}
-% or \tn{global}\tn{readline} along with the |to| keyword.
+% This protected macro expands to the \eTeX{} primitive \tn{readline}
+% along with the |to| keyword.
% \end{texnote}
% \end{function}
%
@@ -297,17 +274,13 @@
%
% \section{Writing to files}
%
-% \begin{function}{\iow_now:Nn, \iow_now:Nx}
+% \begin{function}[updated = 2012-06-05]{\iow_now:Nn, \iow_now:Nx}
% \begin{syntax}
% \cs{iow_now:Nn} \meta{stream} \Arg{tokens}
% \end{syntax}
% This functions writes \meta{tokens} to the specified
% \meta{stream} immediately (\emph{i.e.}~the write operation is called
% on expansion of \cs{iow_now:Nn}).
-% \begin{texnote}
-% \cs{iow_now:Nx} is a protected macro which expands to
-% the two \TeX{} primitives \tn{immediate}\tn{write}.
-% \end{texnote}
% \end{function}
%
% \begin{function}{\iow_log:n, \iow_log:x}
@@ -355,9 +328,9 @@
%
% \begin{function}[EXP]{\iow_char:N}
% \begin{syntax}
-% \cs{iow_char:N} \meta{token}
+% \cs{iow_char:N} |\|\meta{char}
% \end{syntax}
-% Inserts \meta{token} into the output stream. Useful when trying to
+% Inserts \meta{char} into the output stream. Useful when trying to
% write difficult characters such as |%|, |{|, |}|,
% \emph{etc.}~in messages, for example:
% \begin{verbatim}
@@ -376,47 +349,59 @@
% expansion (\emph{e.g.}~in the second argument of \cs{iow_now:Nn}).
% \end{function}
%
-% \section{Wrapping lines in output}
+% \subsection{Wrapping lines in output}
%
-% \begin{function}[updated = 2011-09-21]{\iow_wrap:xnnnN}
+% \begin{function}[added = 2012-06-28]{\iow_wrap:nnnN}
% \begin{syntax}
-% \cs{iow_wrap:xnnnN} \Arg{text} \Arg{run-on text} \Arg{run-on length} \Arg{set up} \meta{function}
+% \cs{iow_wrap:nnnN} \Arg{text} \Arg{run-on text} \Arg{set up} \meta{function}
% \end{syntax}
% This function will wrap the \meta{text} to a fixed number of
% characters per line. At the start of each line which is wrapped,
-% the \meta{run-on text} will be inserted. The line length targeted
-% will be the value of \cs{l_iow_line_length_int} minus the
-% \meta{run-on length}. The later value should be the number of
-% characters in the \meta{run-on text}. Additional functions may be
-% added to the wrapping by using the \meta{set up}, which is executed
-% before the wrapping takes place. The result of the wrapping operation
-% is passed as a braced argument to the \meta{function}, which will
-% typically be a wrapper around a writing operation. Within the
-% \meta{text},
+% the \meta{run-on text} will be inserted. The line character count
+% targeted will be the value of \cs{l_iow_line_count_int} minus the
+% number of characters in the \meta{run-on text}. The \meta{text} and
+% \meta{run-on text} are exhaustively expanded by the function, with the
+% following substitutions:
% \begin{itemize}
-% \item |\\| may be used to force a new line,
-% \item \verb|\ | may be used to represent a forced space
-% (for example after a control sequence),
-% \item |\#|, |\%|, |\{|, |\}|, |\~| may be used to represent
-% the corresponding character,
-% \item \cs{iow_indent:n} may be used to indent a part of the
-% message.
+% \item |\\| may be used to force a new line,
+% \item \verb*|\ | may be used to represent a forced space
+% (for example after a control sequence),
+% \item |\#|, |\%|, |\{|, |\}|, |\~| may be used to represent
+% the corresponding character,
+% \item \cs{iow_indent:n} may be used to indent a part of the
+% message.
% \end{itemize}
-% Both the wrapping process and the subsequent write operation
-% will perform \texttt{x}-type expansion. For this reason, material which
-% is to be written \enquote{as is} should be given as the argument to
-% \cs{token_to_str:N} or \cs{tl_to_str:n} (as appropriate) within
-% the \meta{text}. The output of \cs{iow_wrap:xnnnN} (\emph{i.e.}~the
-% argument passed to the \meta{function}) will consist of characters of
-% category code $12$ (other) and $10$ (space) only. This means that the
+% Additional functions may be added to the wrapping by using the
+% \meta{set up}, which is executed before the wrapping takes place: this
+% may include overriding the substitutions listed.
+%
+% Any expandable material in the \meta{text} which is not to be expanded
+% on wrapping should be converted to a string using \cs{token_to_str:N},
+% \cs{tl_to_str:n}, \cs{tl_to_str:N}, \emph{etc.}
+%
+% The result of the wrapping operation is passed as a braced argument to the
+% \meta{function}, which will typically be a wrapper around a write
+% operation. The output of \cs{iow_wrap:nnnN} (\emph{i.e.}~the argument
+% passed to the \meta{function}) will consist of characters of category
+% \enquote{other} (category code~12), with the exception of spaces which
+% will have category \enquote{space} (category code~10). This means that the
% output will \emph{not} expand further when written to a file.
+%
+% \begin{texnote}
+% Internally, \cs{iow_wrap:nnnN} carries out an \texttt{x}-type expansion
+% on the \meta{text} to expand it. This is done in such a way that
+% \cs{exp_not:N} or \cs{exp_not:n} \emph{could} be used to prevent
+% expansion of material. However, this is less conceptually clear than
+% conversion to a string, which is therefore the supported method for
+% handling expandable material in the \meta{text}.
+% \end{texnote}
% \end{function}
%
% \begin{function}[added = 2011-09-21]{\iow_indent:n}
% \begin{syntax}
% \cs{iow_indent:n} \Arg{text}
% \end{syntax}
-% In the context of \cs{iow_wrap:xnnnN} (for instance in messages),
+% In the context of \cs{iow_wrap:nnnN} (for instance in messages),
% indents \meta{text} by four spaces. This function will not cause
% a line break, and only affects lines which start within the scope
% of the \meta{text}. In case the indented \meta{text} should appear
@@ -424,8 +409,9 @@
% line breaks.
% \end{function}
%
-% \begin{variable}{\l_iow_line_length_int}
-% The maximum length of a line to be written by the \cs{iow_wrap:xxnnN}
+% \begin{variable}[added = 2012-06-24]{\l_iow_line_count_int}
+% The maximum number of characters in a line to be written
+% by the \cs{iow_wrap:nnnN}
% function. This value depends on the \TeX{} system in use: the standard
% value is $78$, which is typically correct for unmodified \TeX{}live
% and MiK\TeX{} systems.
@@ -436,11 +422,11 @@
% (\enquote{other}), and character code $32$ (space).
% \end{variable}
%
-% \section{Constant input--output streams}
+% \subsection{Constant input--output streams}
%
% \begin{variable}{\c_term_ior}
% Constant input stream for reading from the terminal. Reading from this
-% stream using \cs{ior_to:NN} or similar will result in a prompt from
+% stream using \cs{ior_get:NN} or similar will result in a prompt from
% \TeX{} of the form
% \begin{verbatim}
% <tl>=
@@ -452,123 +438,61 @@
% (plus the log), respectively.
% \end{variable}
%
-% \section{Experimental functions}
-%
-% \begin{function}[added = 2012-02-11]{\ior_map_inline:Nn}
-% \begin{syntax}
-% \cs{ior_map_inline:Nn} \meta{stream} \Arg{inline function}
-% \end{syntax}
-% Applies the \meta{inline function} to \meta{items} obtained by
-% reading one or more lines (until an equal number of left and right
-% braces are found) from the \meta{stream}. The \meta{inline function}
-% should consist of code which will receive the \meta{line} as |#1|.
-% \end{function}
+% \subsection{Primitive conditionals}
%
-% \begin{function}[added = 2012-02-11]{\ior_str_map_inline:nn}
+% \begin{function}[EXP]{\if_eof:w}
% \begin{syntax}
-% \cs{ior_str_map_inline:Nn} \Arg{stream} \Arg{inline function}
+% \cs{if_eof:w} \meta{stream}
+% ~~\meta{true code}
+% \cs{else:}
+% ~~\meta{false code}
+% \cs{fi:}
% \end{syntax}
-% Applies the \meta{inline function} to every \meta{line}
-% in the \meta{file}. The material is read from the \meta{stream}
-% as a series of tokens with category code $12$ (other), with the
-% exception of space characters which are given category code $10$
-% (space). The \meta{inline function} should consist of code which
-% will receive the \meta{line} as |#1|.
+% Tests if the \meta{stream} returns \enquote{end of file}, which is true
+% for non-existent files. The \cs{else:} branch is optional.
+% \begin{texnote}
+% This is the \TeX{} primitive \tn{ifeof}.
+% \end{texnote}
% \end{function}
%
-% \section{Internal file functions}
-%
-% \begin{variable}{\g_file_stack_seq}
-% Stores the stack of nested files loaded using \cs{file_input:n}. This
-% is needed to restore the appropriate file name to
-% \cs{g_file_current_name_tl} at the end of each file.
-% \end{variable}
+% \subsection{Internal file functions and variables}
%
-% \begin{variable}{\g_file_record_seq}
-% Stores the name of every file loaded using \cs{file_input:n}. In
-% contrast to \cs{g_file_stack_seq}, no items are ever removed from this
-% sequence.
+% \begin{variable}{\l__file_internal_name_ior}
+% Used to test for the existence of files when opening.
% \end{variable}
%
-% \begin{variable}{\l_file_internal_name_tl}
+% \begin{variable}{\l__file_internal_name_tl}
% Used to return the full name of a file for internal use.
% \end{variable}
%
-% \begin{variable}{\l_file_search_path_seq}
-% The sequence of file paths to search when loading a file.
-% \end{variable}
-%
-% \begin{variable}{\l_file_internal_saved_path_seq}
-% When loaded on top of \LaTeXe{}, there is a need to save the search
-% path so that \tn{input@path} can be used as appropriate.
-% \end{variable}
-%
-% \begin{variable}[added = 2011-09-06]{\l_file_internal_seq}
-% When loaded on top of \LaTeXe{}, there is a need to convert
-% the comma lists \tn{input@path} and \tn{@filelist} to sequences.
-% \end{variable}
-%
-% \section{Internal input--output functions}
-%
-% \begin{function}[added = 2012-02-09]{\file_name_sanitize:nn}
+% \begin{function}[added = 2012-02-09]{\__file_name_sanitize:nn}
% \begin{syntax}
-% \cs{file_name_sanitize:nn} \Arg{name} \Arg{tokens}
+% \cs{__file_name_sanitize:nn} \Arg{name} \Arg{tokens}
% \end{syntax}
% Exhaustively-expands the \meta{name} with the exception of any
-% category \meta{active} (catcode~$12$) tokens, which are not expanded.
+% category \meta{active} (catcode~$13$) tokens, which are not expanded.
% The list of \meta{active} tokens is taken from \cs{l_char_active_seq}.
% The \meta{sanitized name} is then inserted (in braces) after the
% \meta{tokens}, which should further process the file name. If any
% spaces are found in the name after expansion, an error is raised.
% \end{function}
%
-% \begin{function}[EXP]{\if_eof:w}
-% \begin{syntax}
-% \cs{if_eof:w} \meta{stream}
-% ~~\meta{true code}
-% \cs{else:}
-% ~~\meta{false code}
-% \cs{fi:}
-% \end{syntax}
-% Tests if the \meta{stream} returns \enquote{end of file}, which is true
-% for non-existent files. The \cs{else:} branch is optional.
-% \begin{texnote}
-% This is the \TeX{} primitive \tn{ifeof}.
-% \end{texnote}
-% \end{function}
+% \subsection{Internal input--output functions}
%
-% \begin{function}[added = 2012-01-23]
-% {\ior_open_unsafe:Nn, \ior_open_unsafe:No, \iow_open_unsafe:Nn}
+% \begin{function}[added = 2012-01-23]{\__ior_open:Nn, \__ior_open:No}
% \begin{syntax}
-% \cs{ior_open_unsafe:Nn} \meta{stream} \Arg{file name}
+% \cs{__ior_open:Nn} \meta{stream} \Arg{file name}
% \end{syntax}
-% These functions have identical syntax to the generally-available
-% versions without the |_unsafe| suffix. However, these functions do not
-% take precautions against active characters in the \meta{file name}: they
-% are therefore intended to be used by higher-level functions which
-% have already fully expanded the \meta{file name} and which need to
-% perform multiple open or close operations. See for example the
+% This function has identical syntax to the public version. However,
+% is does not take precautions against active characters in the
+% \meta{file name}, and it does not attempt to add a \meta{path} to
+% the \meta{file name}: it is therefore intended to be used by
+% higher-level
+% functions which have already fully expanded the \meta{file name} and which
+% need to perform multiple open or close operations. See for example the
% implementation of \cs{file_add_path:Nn},
% \end{function}
%
-% \begin{function}{\ior_raw_new:N, \ior_raw_new:c}
-% \begin{syntax}
-% \cs{ior_raw_new:N} \meta{stream}
-% \end{syntax}
-% Directly allocates a new stream for reading, bypassing the stack
-% system. This is to be used only when a new stream is required at a
-% \TeX{} level, when a new stream is requested by the stack itself.
-% \end{function}
-%
-% \begin{function}{\iow_raw_new:N, \iow_raw_new:c}
-% \begin{syntax}
-% \cs{iow_raw_new:N} \meta{stream}
-% \end{syntax}
-% Directly allocates a new stream for writing, bypassing the stack
-% system. This is to be used only when a new stream is required at a
-% \TeX{} level, when a new stream is requested by the stack itself.
-% \end{function}
-%
% \end{documentation}
%
% \begin{implementation}
@@ -582,10 +506,14 @@
% \end{macrocode}
%
% \begin{macrocode}
+%<@@=file>
+% \end{macrocode}
+%
+% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -593,12 +521,10 @@
%
% \begin{variable}{\g_file_current_name_tl}
% The name of the current file should be available at all times.
-% \begin{macrocode}
-\tl_new:N \g_file_current_name_tl
-% \end{macrocode}
% For the format the file name needs to be picked up at the start of the
% file. In package mode the current file name is collected from \LaTeXe{}.
% \begin{macrocode}
+\tl_new:N \g_file_current_name_tl
%<*initex>
\tex_everyjob:D \exp_after:wN
{
@@ -612,91 +538,92 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\g_file_stack_seq}
+% \begin{variable}{\g_@@_stack_seq}
% The input list of files is stored as a sequence stack.
% \begin{macrocode}
-\seq_new:N \g_file_stack_seq
+\seq_new:N \g_@@_stack_seq
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\g_file_record_seq}
-% The total list of files used is recorded separately from the current file
-% stack, as nothing is ever popped from this list.
-% \begin{macrocode}
-\seq_new:N \g_file_record_seq
-% \end{macrocode}
-% The current file name should be included in the file list!
+% \begin{variable}{\g_@@_record_seq}
+% The total list of files used is recorded separately from the current
+% file stack, as nothing is ever popped from this list. The current
+% file name should be included in the file list! In format mode, this
+% is done at the very start of the \TeX{} run. In package mode we
+% will eventually copy the contents of \cs{@filelist}.
% \begin{macrocode}
+\seq_new:N \g_@@_record_seq
%<*initex>
\tex_everyjob:D \exp_after:wN
{
\tex_the:D \tex_everyjob:D
- \seq_gput_right:NV \g_file_record_seq \g_file_current_name_tl
+ \seq_gput_right:NV \g_@@_record_seq \g_file_current_name_tl
}
%</initex>
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_file_internal_name_tl}
+% \begin{variable}{\l_@@_internal_name_tl}
% Used to return the fully-qualified name of a file.
% \begin{macrocode}
-\tl_new:N \l_file_internal_name_tl
+\tl_new:N \l_@@_internal_name_tl
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_file_search_path_seq}
+% \begin{variable}{\l_@@_search_path_seq}
% The current search path.
% \begin{macrocode}
-\seq_new:N \l_file_search_path_seq
+\seq_new:N \l_@@_search_path_seq
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_file_internal_saved_path_seq}
+% \begin{variable}{\l_@@_saved_search_path_seq}
% The current search path has to be saved for package use.
% \begin{macrocode}
%<*package>
-\seq_new:N \l_file_internal_saved_path_seq
+\seq_new:N \l_@@_saved_search_path_seq
%</package>
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_file_internal_seq}
+% \begin{variable}{\l_@@_internal_seq}
% Scratch space for comma list conversion in package mode.
% \begin{macrocode}
%<*package>
-\seq_new:N \l_file_internal_seq
+\seq_new:N \l_@@_internal_seq
%</package>
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}[int]{\file_name_sanitize:nn}
+% \begin{macro}[aux]{\@@_name_sanitize:nn}
% For converting a token list to a string where active characters are treated
% as strings from the start.
% \begin{macrocode}
-\cs_new_protected:Npn \file_name_sanitize:nn #1#2
+\cs_new_protected:Npn \@@_name_sanitize:nn #1#2
{
\group_begin:
\seq_map_inline:Nn \l_char_active_seq
{ \cs_set_nopar:Npx ##1 { \token_to_str:N ##1 } }
- \tl_set:Nx \l_file_internal_name_tl {#1}
- \tl_set:Nx \l_file_internal_name_tl
- { \tl_to_str:N \l_file_internal_name_tl }
- \tl_if_in:NnTF \l_file_internal_name_tl { ~ }
+ \tl_set:Nx \l_@@_internal_name_tl {#1}
+ \tl_set:Nx \l_@@_internal_name_tl
+ { \tl_to_str:N \l_@@_internal_name_tl }
+ \tl_if_in:NnT \l_@@_internal_name_tl { ~ }
{
- \msg_kernel_error:nnx { file } { space-in-file-name }
- { \l_file_internal_name_tl }
+ \__msg_kernel_error:nnx { kernel } { space-in-file-name }
+ { \l_@@_internal_name_tl }
+ \tl_remove_all:Nn \l_@@_internal_name_tl { ~ }
}
\use:x
{
\group_end:
- \exp_not:n {#2} { \l_file_internal_name_tl }
+ \exp_not:n {#2} { \l_@@_internal_name_tl }
}
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\file_add_path:nN}
-% \begin{macro}[aux]{\file_add_path_aux:nN, \file_add_path_search:nN}
+% \begin{macro}[aux]{\@@_add_path:nN, \@@_add_path_search:nN}
% The way to test if a file exists is to try to open it: if it does not
% exist then \TeX{} will report end-of-file. For files which are in the
% current directory, this is straight-forward. For other locations, a
@@ -705,33 +632,31 @@
% |#2| is returned empty.
% \begin{macrocode}
\cs_new_protected:Npn \file_add_path:nN #1
- { \file_name_sanitize:nn {#1} { \file_add_path_aux:nN } }
-\cs_new_protected:Npn \file_add_path_aux:nN #1#2
+ { \@@_name_sanitize:nn {#1} { \@@_add_path:nN } }
+\cs_new_protected:Npn \@@_add_path:nN #1#2
{
- \ior_open_unsafe:Nn \g_file_internal_ior {#1}
- \ior_if_eof:NTF \g_file_internal_ior
- { \file_add_path_search:nN {#1} #2 }
- {
- \ior_close:N \g_file_internal_ior
- \tl_set:Nn #2 {#1}
- }
+ \__ior_open:Nn \g__file_internal_ior {#1}
+ \ior_if_eof:NTF \g__file_internal_ior
+ { \@@_add_path_search:nN {#1} #2 }
+ { \tl_set:Nn #2 {#1} }
+ \ior_close:N \g__file_internal_ior
}
-\cs_new_protected:Npn \file_add_path_search:nN #1#2
+\cs_new_protected:Npn \@@_add_path_search:nN #1#2
{
- \tl_set:Nn #2 { \q_no_value }
+ \tl_set:Nn #2 { \q_no_value }
%<*package>
\cs_if_exist:NT \input@path
{
- \seq_set_eq:NN \l_file_internal_saved_path_seq \l_file_search_path_seq
- \seq_set_from_clist:NN \l_file_internal_seq \input@path
- \seq_concat:NNN \l_file_search_path_seq
- \l_file_search_path_seq \l_file_internal_seq
+ \seq_set_eq:NN \l_@@_saved_search_path_seq \l_@@_search_path_seq
+ \seq_set_split:NnV \l_@@_internal_seq { , } \input@path
+ \seq_concat:NNN \l_@@_search_path_seq
+ \l_@@_search_path_seq \l_@@_internal_seq
}
%</package>
- \seq_map_inline:Nn \l_file_search_path_seq
+ \seq_map_inline:Nn \l_@@_search_path_seq
{
- \ior_open_unsafe:Nn \g_file_internal_ior { ##1 #1 }
- \ior_if_eof:NF \g_file_internal_ior
+ \__ior_open:Nn \g__file_internal_ior { ##1 #1 }
+ \ior_if_eof:NF \g__file_internal_ior
{
\tl_set:Nx #2 { ##1 #1 }
\seq_map_break:
@@ -739,9 +664,8 @@
}
%<*package>
\cs_if_exist:NT \input@path
- { \seq_set_eq:NN \l_file_search_path_seq \l_file_internal_saved_path_seq }
+ { \seq_set_eq:NN \l_@@_search_path_seq \l_@@_saved_search_path_seq }
%</package>
- \ior_close:N \g_file_internal_ior
}
% \end{macrocode}
% \end{macro}
@@ -751,12 +675,12 @@
% The test for the existence of a file is a wrapper around the function to
% add a path to a file. If the file was found, the path will contain
% something, whereas if the file was not located then the return value
-% will be empty.
+% will be \cs{q_no_value}.
% \begin{macrocode}
\prg_new_protected_conditional:Npnn \file_if_exist:n #1 { T , F , TF }
{
- \file_add_path:nN {#1} \l_file_internal_name_tl
- \quark_if_no_value:NTF \l_file_internal_name_tl
+ \file_add_path:nN {#1} \l_@@_internal_name_tl
+ \quark_if_no_value:NTF \l_@@_internal_name_tl
{ \prg_return_false: }
{ \prg_return_true: }
}
@@ -764,78 +688,124 @@
% \end{macro}
%
% \begin{macro}{\file_input:n}
-% \begin{macro}[aux]{\file_input_aux:n \file_input_aux:V, \file_input_error:n}
+% \begin{macro}[aux]{\@@_input:n \@@_input:V}
+% \begin{macro}[aux, EXP]{\@@_input_aux:w}
+% \begin{macro}[aux]{\@@_input_aux:n, \@@_input_aux:o}
% Loading a file is done in a safe way, checking first that the file
-% exists and loading only if it does.
+% exists and loading only if it does. Push the file name on the
+% \cs{g_@@_stack_seq}, and add it to the file list, either
+% \cs{g_@@_record_seq}, or \cs{@filelist} in package mode.
% \begin{macrocode}
\cs_new_protected:Npn \file_input:n #1
{
- \file_add_path:nN {#1} \l_file_internal_name_tl
- \quark_if_no_value:NTF \l_file_internal_name_tl
- { \file_name_sanitize:nn {#1} { \file_input_error:n } }
- { \file_input_aux:V \l_file_internal_name_tl }
+ \file_add_path:nN {#1} \l_@@_internal_name_tl
+ \quark_if_no_value:NTF \l_@@_internal_name_tl
+ {
+ \@@_name_sanitize:nn {#1}
+ { \__msg_kernel_error:nnx { kernel } { file-not-found } }
+ }
+ { \@@_input:V \l_@@_internal_name_tl }
}
-\cs_new_protected:Npn \file_input_aux:n #1
+\cs_new_protected:Npn \@@_input:n #1
+ {
+ \quark_if_nil:oTF { \@@_input_aux:w #1 . \q_nil . \q_stop }
+ { \@@_input_aux:o { \tl_to_str:n { #1 .tex } } }
+ { \@@_input_aux:n {#1} }
+ }
+\cs_generate_variant:Nn \@@_input:n { V }
+\cs_new:Npn \@@_input_aux:w #1 . #2 . #3 \q_stop { #2 }
+\cs_new_protected:Npn \@@_input_aux:n #1
{
%<*initex>
- \seq_gput_right:Nn \g_file_record_seq {#1}
+ \seq_gput_right:Nn \g_@@_record_seq {#1}
%</initex>
%<*package>
- \@addtofilelist {#1}
+ \clist_if_exist:NTF \@filelist
+ { \@addtofilelist {#1} }
+ { \seq_gput_right:Nn \g_@@_record_seq {#1} }
%</package>
- \seq_gpush:Nn \g_file_stack_seq \g_file_current_name_tl
+ \seq_gpush:Nn \g_@@_stack_seq \g_file_current_name_tl
\tl_gset:Nn \g_file_current_name_tl {#1}
\tex_input:D #1 \c_space_tl
- \seq_gpop:NN \g_file_stack_seq \g_file_current_name_tl
+ \seq_gpop:NN \g_@@_stack_seq \g_file_current_name_tl
}
-\cs_generate_variant:Nn \file_input_aux:n { V }
-\cs_new_protected:Npn \file_input_error:n #1
- { \msg_kernel_error:nnx { file } { file-not-found } {#1} }
+\cs_generate_variant:Nn \@@_input_aux:n { o }
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
%
% \begin{macro}{\file_path_include:n}
% \begin{macro}{\file_path_remove:n}
+% \begin{macro}[aux]{\@@_path_include:n}
% Wrapper functions to manage the search path.
% \begin{macrocode}
\cs_new_protected:Npn \file_path_include:n #1
+ { \@@_name_sanitize:nn {#1} { \@@_path_include:n } }
+\cs_new_protected:Npn \@@_path_include:n #1
{
- \seq_if_in:NnF \l_file_search_path_seq {#1}
- { \seq_put_right:Nn \l_file_search_path_seq {#1} }
+ \seq_if_in:NnF \l_@@_search_path_seq {#1}
+ { \seq_put_right:Nn \l_@@_search_path_seq {#1} }
}
\cs_new_protected:Npn \file_path_remove:n #1
- { \seq_remove_all:Nn \l_file_search_path_seq {#1} }
+ {
+ \@@_name_sanitize:nn {#1}
+ { \seq_remove_all:Nn \l_@@_search_path_seq }
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\file_list:}
-% A function to list all files used to the log.
+% A function to list all files used to the log, without duplicates.
+% In package mode, if \cs{@filelist} is still defined, we need to take
+% it into account (we capture it \cs{AtBeginDocument} into
+% \cs{g_@@_record_seq}), turning each file name into a string.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \file_list:
{
- \seq_remove_duplicates:N \g_file_record_seq
+ \seq_set_eq:NN \l_@@_internal_seq \g_@@_record_seq
+%<*package>
+ \clist_if_exist:NT \@filelist
+ {
+ \clist_map_inline:Nn \@filelist
+ {
+ \seq_put_right:No \l_@@_internal_seq
+ { \tl_to_str:n {##1} }
+ }
+ }
+%</package>
+ \seq_remove_duplicates:N \l_@@_internal_seq
\iow_log:n { *~File~List~* }
- \seq_map_inline:Nn \g_file_record_seq { \iow_log:n {##1} }
+ \seq_map_inline:Nn \l_@@_internal_seq { \iow_log:n {##1} }
\iow_log:n { ************* }
}
% \end{macrocode}
% \end{macro}
%
-% When used as a package, there is a need to hold onto the standard
-% file list as well as the new one here.
+% When used as a package, there is a need to hold onto the standard file
+% list as well as the new one here. File names recorded in
+% \cs{@filelist} must be turned to strings before being added to
+% \cs{g_@@_record_seq}.
% \begin{macrocode}
%<*package>
\AtBeginDocument
{
- \seq_set_from_clist:NN \l_file_internal_seq \@filelist
- \seq_gconcat:NNN \g_file_record_seq \g_file_record_seq \l_file_internal_seq
+ \clist_map_inline:Nn \@filelist
+ { \seq_gput_right:No \g_@@_record_seq { \tl_to_str:n {#1} } }
}
%</package>
% \end{macrocode}
%
-% \subsection{Input--output variables constants}
+% \subsection{Input operations}
+%
+% \begin{macrocode}
+%<@@=ior>
+% \end{macrocode}
+%
+% \subsubsection{Variables and constants}
%
% \begin{variable}{\c_term_ior}
% Reading from the terminal (with a prompt) is done using a positive
@@ -846,20 +816,10 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\c_log_iow, \c_term_iow}
-% Here we allocate two output streams for writing to the transcript
-% file only (\cs{c_log_iow}) and to both the terminal and
-% transcript file (\cs{c_term_iow}).
-% \begin{macrocode}
-\cs_new_eq:NN \c_log_iow \c_minus_one
-\cs_new_eq:NN \c_term_iow \c_sixteen
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\c_iow_streams_tl, \c_ior_streams_tl}
+% \begin{variable}{\c_@@_streams_tl}
% The list of streams available, by number.
% \begin{macrocode}
-\tl_const:Nn \c_iow_streams_tl
+\tl_const:Nn \c_@@_streams_tl
{
\c_zero
\c_one
@@ -878,151 +838,118 @@
\c_fourteen
\c_fifteen
}
-\cs_new_eq:NN \c_ior_streams_tl \c_iow_streams_tl
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\g_iow_streams_prop, \g_ior_streams_prop}
+% \begin{variable}{\g_@@_streams_prop}
% The allocations for streams are stored in property lists, which
% are set up to have a \enquote{full} set of allocations from the start.
% In package mode, a few slots are always taken, so these are
% blocked off from use.
% \begin{macrocode}
-\prop_new:N \g_iow_streams_prop
-\prop_new:N \g_ior_streams_prop
+\prop_new:N \g_@@_streams_prop
%<*package>
-\prop_put:Nnn \g_iow_streams_prop { 0 } { LaTeX2e~reserved }
-\prop_put:Nnn \g_iow_streams_prop { 1 } { LaTeX2e~reserved }
-\prop_put:Nnn \g_iow_streams_prop { 2 } { LaTeX2e~reserved }
-\prop_put:Nnn \g_ior_streams_prop { 0 } { LaTeX2e~reserved }
+\prop_put:Nnn \g_@@_streams_prop { 0 } { LaTeX2e~reserved }
%</package>
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_iow_stream_int, \l_ior_stream_int}
+% \begin{variable}{\l_@@_stream_int}
% Used to track the number allocated to the stream being created:
% this is taken from the property list but does alter.
% \begin{macrocode}
-\int_new:N \l_iow_stream_int
-\cs_new_eq:NN \l_ior_stream_int \l_iow_stream_int
+\int_new:N \l_@@_stream_int
% \end{macrocode}
% \end{variable}
%
-% \subsection{Stream management}
+% \subsubsection{Stream management}
%
-% \begin{macro}[int]{\ior_raw_new:N, \ior_raw_new:c}
-% \begin{macro}[int]{\iow_raw_new:N, \iow_raw_new:c}
-% The lowest level for stream management is actually creating raw \TeX{}
-% streams. As these are very limited (even with \eTeX{}), this should not
-% be addressed directly.
+% \begin{macro}[int]{\@@_new:N, \@@_new:c}
+% The lowest level for stream management is actually creating raw \TeX{}
+% streams. As these are very limited (even with \eTeX{}), this should not
+% be addressed directly.
% \begin{macrocode}
%<*initex>
-\alloc_setup_type:nnn { ior } \c_zero \c_sixteen
-\cs_new_protected:Npn \ior_raw_new:N #1
- { \alloc_reg:nNN { ior } \tex_chardef:D #1 }
-\alloc_setup_type:nnn { iow } \c_zero \c_sixteen
-\cs_new_protected:Npn \iow_raw_new:N #1
- { \alloc_reg:nNN { iow } \tex_chardef:D #1 }
+\__alloc_setup_type:nnn { ior } \c_zero \c_sixteen
+\cs_new_protected:Npn \@@_new:N #1
+ { \__alloc_reg:nNN { ior } \tex_chardef:D #1 }
%</initex>
%<*package>
-\cs_set_eq:NN \iow_raw_new:N \newwrite
-\cs_set_eq:NN \ior_raw_new:N \newread
+\cs_set_eq:NN \@@_new:N \newread
%</package>
-\cs_generate_variant:Nn \ior_raw_new:N { c }
-\cs_generate_variant:Nn \iow_raw_new:N { c }
+\cs_generate_variant:Nn \@@_new:N { c }
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\ior_new:N, \ior_new:c, \iow_new:N, \iow_new:c}
+% \begin{macro}{\ior_new:N, \ior_new:c}
% Reserving a new stream is done by defining the name as equal to using the
% terminal.
% \begin{macrocode}
\cs_new_protected:Npn \ior_new:N #1 { \cs_new_eq:NN #1 \c_term_ior }
\cs_generate_variant:Nn \ior_new:N { c }
-\cs_new_protected:Npn \iow_new:N #1 { \cs_new_eq:NN #1 \c_term_iow }
-\cs_generate_variant:Nn \iow_new:N { c }
% \end{macrocode}
% \end{macro}
%
-% \begin{variable}{\g_file_internal_ior}
-% Delayed from above so that the mechanisms are in place.
+% \begin{variable}{\g__file_internal_ior}
+% Delayed from the \texttt{file} section so that the mechanisms are in place.
% \begin{macrocode}
-\ior_new:N \g_file_internal_ior
+\ior_new:N \g__file_internal_ior
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}{\ior_open:Nn, \ior_open:cn, \iow_open:Nn, \iow_open:cn}
-% \begin{macro}[int]{\ior_open_aux:Nn}
+% \begin{macro}{\ior_open:Nn, \ior_open:cn}
% \begin{macro}[TF]{\ior_open:Nn}
-% \begin{macro}[aux]{\ior_open_aux:NnTF}
-% \begin{macro}[int]
-% {\ior_open_unsafe:Nn, \ior_open_unsafe:No, \iow_open_unsafe:Nn}
-% In both cases, opening a stream starts with a call to the closing
-% function: this is safest. There is then a loop through the
-% allocation number list to find the first free stream number.
-% When one is found the allocation can take place, the information
-% can be stored and finally the file can actually be opened. Before
-% any actual file operations there is a precaution against special
-% characters in file names. For reading files, there is an intermediate
-% auxiliary to allow path addition, keeping the internal function fast
-% and avoiding an infinite loop.
+% \begin{macro}[aux]{\@@_open_aux:Nn}
+% \begin{macro}[aux]{\@@_open_aux:NnTF}
+% \begin{macro}[aux]{\@@_open:Nn, \@@_open:No}
+% Opening a stream starts with a call to the closing function: this is
+% safest. There is then a loop through the allocation number list to find
+% the first free stream number. When one is found the allocation can take
+% place, the information can be stored and finally the file can actually be
+% opened. Before any actual file operations there is a precaution against
+% special characters in file names. There is an intermediate auxiliary to
+% allow path addition, keeping the internal function fast and avoiding an
+% infinite loop.
% \begin{macrocode}
\cs_new_protected:Npn \ior_open:Nn #1#2
- { \file_name_sanitize:nn {#2} { \ior_open_aux:Nn #1 } }
+ { \__file_name_sanitize:nn {#2} { \@@_open_aux:Nn #1 } }
\cs_generate_variant:Nn \ior_open:Nn { c }
-\cs_new_protected:Npn \iow_open:Nn #1#2
- { \file_name_sanitize:nn {#2} { \iow_open_unsafe:Nn #1 } }
-\cs_generate_variant:Nn \iow_open:Nn { c }
-\cs_new_protected:Npn \ior_open_aux:Nn #1#2
+\cs_new_protected:Npn \@@_open_aux:Nn #1#2
{
- \file_add_path:nN {#2} \l_file_internal_name_tl
- \quark_if_no_value:NTF \l_file_internal_name_tl
- { \file_input_error:n {#2} }
- { \ior_open_unsafe:No #1 \l_file_internal_name_tl }
+ \file_add_path:nN {#2} \l__file_internal_name_tl
+ \quark_if_no_value:NTF \l__file_internal_name_tl
+ { \__msg_kernel_error:nnx { kernel } { file-not-found } {#2} }
+ { \@@_open:No #1 \l__file_internal_name_tl }
}
\prg_new_protected_conditional:Npnn \ior_open:Nn #1#2 { T , F , TF }
- { \file_name_sanitize:nn {#2} { \ior_open_aux:NnTF #1 } }
-\cs_new_protected:Npn \ior_open_aux:NnTF #1#2
+ { \__file_name_sanitize:nn {#2} { \@@_open_aux:NnTF #1 } }
+\cs_new_protected:Npn \@@_open_aux:NnTF #1#2
{
- \file_add_path:nN {#2} \l_file_internal_name_tl
- \quark_if_no_value:NTF \l_file_internal_name_tl
+ \file_add_path:nN {#2} \l__file_internal_name_tl
+ \quark_if_no_value:NTF \l__file_internal_name_tl
{ \prg_return_false: }
{
- \ior_open_unsafe:No #1 \l_file_internal_name_tl
+ \@@_open:No #1 \l__file_internal_name_tl
\prg_return_true:
}
}
\cs_generate_variant:Nn \ior_open:NnT { c }
\cs_generate_variant:Nn \ior_open:NnF { c }
\cs_generate_variant:Nn \ior_open:NnTF { c }
-\cs_new_protected:Npn \ior_open_unsafe:Nn #1#2
+\cs_new_protected:Npn \@@_open:Nn #1#2
{
\ior_close:N #1
- \int_set:Nn \l_ior_stream_int \c_sixteen
- \tl_map_function:NN \c_ior_streams_tl \ior_alloc_read:n
- \int_compare:nNnTF \l_ior_stream_int = \c_sixteen
- { \msg_kernel_fatal:nn { ior } { streams-exhausted } }
+ \int_set_eq:NN \l_@@_stream_int \c_sixteen
+ \tl_map_function:NN \c_@@_streams_tl \@@_alloc:n
+ \int_compare:nNnTF \l_@@_stream_int = \c_sixteen
+ { \__msg_kernel_fatal:nn { kernel } { input-streams-exhausted } }
{
- \ior_stream_alloc:N #1
- \prop_gput:NVn \g_ior_streams_prop \l_ior_stream_int {#2}
+ \@@_alloc:N #1
+ \prop_gput:NVn \g_@@_streams_prop \l_@@_stream_int {#2}
\tex_openin:D #1#2 \scan_stop:
}
}
-\cs_generate_variant:Nn \ior_open_unsafe:Nn { No }
-\cs_new_protected:Npn \iow_open_unsafe:Nn #1#2
- {
- \iow_close:N #1
- \int_set:Nn \l_iow_stream_int \c_sixteen
- \tl_map_function:NN \c_iow_streams_tl \iow_alloc_write:n
- \int_compare:nNnTF \l_iow_stream_int = \c_sixteen
- { \msg_kernel_fatal:nn { iow } { streams-exhausted } }
- {
- \iow_stream_alloc:N #1
- \prop_gput:NVn \g_iow_streams_prop \l_iow_stream_int {#2}
- \tex_immediate:D \tex_openout:D #1#2 \scan_stop:
- }
- }
+\cs_generate_variant:Nn \@@_open:Nn { No }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1030,114 +957,321 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux]{\ior_alloc_read:n}
-% \begin{macro}[aux]{\iow_alloc_write:n}
-% These functions are used to see if a particular stream is available.
-% The property list contains file names for streams in use, so
-% any unused ones are for the taking.
+% \begin{macro}[aux]{\@@_alloc:n}
+% See if a particular stream is available: the property list contains file
+% names for streams in use, so any unused ones are for the taking.
% \begin{macrocode}
-\cs_new_protected:Npn \iow_alloc_write:n #1
+\cs_new_protected:Npn \@@_alloc:n #1
{
- \prop_if_in:NnF \g_iow_streams_prop {#1}
+ \prop_if_in:NnF \g_@@_streams_prop {#1}
{
- \int_set:Nn \l_iow_stream_int {#1}
- \tl_map_break:
- }
- }
-\cs_new_protected:Npn \ior_alloc_read:n #1
- {
- \prop_if_in:NnF \g_iow_streams_prop {#1}
- {
- \int_set:Nn \l_ior_stream_int {#1}
+ \int_set:Nn \l_@@_stream_int {#1}
\tl_map_break:
}
}
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
-% \begin{macro}[aux]{\iow_stream_alloc:N, \ior_stream_alloc:N}
-% \begin{macro}[aux]{\iow_stream_alloc_aux:, \ior_stream_alloc_aux:}
-% \begin{variable}{\g_iow_internal_iow, \g_ior_internal_ior}
-% Allocating a raw stream is much easier in \IniTeX{} mode than for
-% the package. For the format, all streams will be allocated by
-% \pkg{l3file} and so there is a simple check to see if a raw
-% stream is actually available. On the other hand, for the
-% package there will be non-managed streams. So if the managed
-% one is not open, a check is made to see if some other managed
-% stream is available before deciding to open a new one. If a new
-% one is needed, we get the number allocated by \LaTeXe{} to get
-% \enquote{back on track} with allocation.
+% \begin{macro}[aux]{\@@_alloc:N}
+% \begin{macro}[aux]{\@@_alloc:}
+% \begin{variable}{\g_@@_internal_ior}
+% Allocating a raw stream is much easier in \IniTeX{} mode than for the
+% package. For the format, all streams will be allocated by \pkg{l3file} and
+% so there is a simple check to see if a raw stream is actually available. On
+% the other hand, for the package there will be non-managed streams. So if
+% the managed one is not open, a check is made to see if some other managed
+% stream is available before deciding to open a new one. If a new one is
+% needed, we get the number allocated by \LaTeXe{} to get \enquote{back on
+% track} with allocation.
% \begin{macrocode}
-\iow_new:N \g_iow_internal_iow
-\ior_new:N \g_ior_internal_ior
-\cs_new_protected:Npn \iow_stream_alloc:N #1
+\ior_new:N \g_@@_internal_ior
+\cs_new_protected:Npn \@@_alloc:N #1
{
- \cs_if_exist:cF { g_iow_ \int_use:N \l_iow_stream_int _iow }
+ \cs_if_exist:cF { g_ior_ \int_use:N \l_@@_stream_int _ior }
{
%<*package>
- \iow_stream_alloc_aux:
- \int_compare:nNnT \l_iow_stream_int = \c_sixteen
+ \@@_alloc:
+ \int_compare:nNnT \l_@@_stream_int = \c_sixteen
{
- \iow_raw_new:N \g_iow_internal_iow
- \int_set:Nn \l_iow_stream_int { \g_iow_internal_iow }
+ \@@_new:N \g_@@_internal_ior
+ \int_set:Nn \l_@@_stream_int { \g_@@_internal_ior }
\cs_gset_eq:cN
- { g_iow_ \int_use:N \l_iow_stream_int _iow } \g_iow_internal_iow
+ { g_ior_ \int_use:N \l_@@_stream_int _ior } \g_@@_internal_ior
}
%</package>
%<*initex>
- \iow_raw_new:c { g_iow_ \int_use:N \l_iow_stream_int _iow }
+ \@@_new:c { g_ior_ \int_use:N \l_@@_stream_int _ior }
%</initex>
}
- \cs_gset_eq:Nc #1 { g_iow_ \int_use:N \l_iow_stream_int _iow }
+ \cs_gset_eq:Nc #1 { g_ior_ \int_use:N \l_@@_stream_int _ior }
}
%<*package>
-\cs_new_protected_nopar:Npn \iow_stream_alloc_aux:
+\cs_new_protected_nopar:Npn \@@_alloc:
{
- \int_incr:N \l_iow_stream_int
- \int_compare:nNnT \l_iow_stream_int < \c_sixteen
+ \int_incr:N \l_@@_stream_int
+ \int_compare:nNnT \l_@@_stream_int < \c_sixteen
{
- \cs_if_exist:cTF { g_iow_ \int_use:N \l_iow_stream_int _iow }
+ \cs_if_exist:cTF { g_ior_ \int_use:N \l_@@_stream_int _ior }
{
- \prop_if_in:NVT \g_iow_streams_prop \l_iow_stream_int
- { \iow_stream_alloc_aux: }
+ \prop_if_in:NVT \g_@@_streams_prop \l_@@_stream_int
+ { \@@_alloc: }
}
- { \iow_stream_alloc_aux: }
+ { \@@_alloc: }
+ }
+ }
+%</package>
+% \end{macrocode}
+% \end{variable}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\ior_close:N, \ior_close:c}
+% Closing a stream is not quite the reverse of opening one. First,
+% the close operation is easier than the open one, and second as the
+% stream is actually a number we can use it directly to show that the
+% slot has been freed up.
+% \begin{macrocode}
+\cs_new_protected:Npn \ior_close:N #1
+ {
+ \__chk_if_exist_cs:N #1
+ \int_compare:nNnF #1 < \c_zero
+ {
+ \int_compare:nNnF #1 > \c_fifteen
+ {
+ \tex_closein:D #1
+ \prop_gremove:NV \g_@@_streams_prop #1
+ \cs_gset_eq:NN #1 \c_term_ior
+ }
+ }
+ }
+\cs_generate_variant:Nn \ior_close:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ior_list_streams:}
+% \begin{macro}[aux]{\@@_list_streams:Nn}
+% Show the property lists, but with some \enquote{pretty printing}.
+% See the \pkg{l3msg} module. If there are no open read streams,
+% issue the message \texttt{show-no-stream}, and show an empty
+% token list. If there are open read streams, format them with
+% \cs{__msg_show_item_unbraced:nn}, and with the message
+% \texttt{show-open-streams}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \ior_list_streams:
+ { \@@_list_streams:Nn \g_@@_streams_prop { input } }
+\cs_new_protected:Npn \@@_list_streams:Nn #1#2
+ {
+ \__msg_term:nnn { LaTeX / kernel }
+ { \prop_if_empty:NTF #1 { show-no-stream } { show-open-streams } }
+ {#2}
+ \__msg_show_variable:x
+ { \prop_map_function:NN #1 \__msg_show_item_unbraced:nn }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsubsection{Reading input}
+%
+% \begin{macro}[int]{\if_eof:w}
+% The primitive conditional
+% \begin{macrocode}
+\cs_new_eq:NN \if_eof:w \tex_ifeof:D
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\ior_if_eof:N}
+% To test if some particular input stream is exhausted the following
+% conditional is provided.
+% \begin{macrocode}
+\prg_new_conditional:Nnn \ior_if_eof:N { p , T , F , TF }
+ {
+ \cs_if_exist:NTF #1
+ {
+ \if_int_compare:w #1 = \c_sixteen
+ \prg_return_true:
+ \else:
+ \if_eof:w #1
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ \fi:
}
+ { \prg_return_true: }
}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ior_get:NN}
+% And here we read from files.
+% \begin{macrocode}
+\cs_new_protected:Npn \ior_get:NN #1#2
+ { \tex_read:D #1 to #2 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ior_get_str:NN}
+% Reading as strings is also a primitive wrapper.
+% \begin{macrocode}
+\cs_new_protected:Npn \ior_get_str:NN #1#2
+ { \etex_readline:D #1 to #2 }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Output operations}
+%
+% \begin{macrocode}
+%<@@=iow>
+% \end{macrocode}
+%
+% There is a lot of similarity here to the input operations, at least for
+% many of the basics. Thus quite a bit is copied from the earlier material.
+%
+% \subsubsection{Variables and constants}
+%
+% \begin{variable}{\c_log_iow, \c_term_iow}
+% Here we allocate two output streams for writing to the transcript
+% file only (\cs{c_log_iow}) and to both the terminal and
+% transcript file (\cs{c_term_iow}).
+% \begin{macrocode}
+\cs_new_eq:NN \c_log_iow \c_minus_one
+\cs_new_eq:NN \c_term_iow \c_sixteen
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_@@_streams_tl}
+% The list of streams available, by number: copied from the input
+% operations.
+% \begin{macrocode}
+\cs_new_eq:NN \c_@@_streams_tl \c__ior_streams_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\g_@@_streams_prop}
+% As for reads, but with more reserved as \LaTeXe{} takes up a few here.
+% \begin{macrocode}
+\prop_new:N \g_@@_streams_prop
+%<*package>
+\prop_put:Nnn \g_@@_streams_prop { 0 } { LaTeX2e~reserved }
+\prop_put:Nnn \g_@@_streams_prop { 1 } { LaTeX2e~reserved }
+\prop_put:Nnn \g_@@_streams_prop { 2 } { LaTeX2e~reserved }
+%</package>
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_stream_int}
+% Used to track the number allocated to the stream being created:
+% this is taken from the property list but does alter. The two allocation
+% routines only need one register, so we save one here.
+% \begin{macrocode}
+\cs_new_eq:NN \l_@@_stream_int \l__ior_stream_int
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Stream management}
+%
+% \begin{macro}[aux]{\@@_new:N, \@@_new:c}
+% The same idea as for input, but with a separate set of functions.
+% \begin{macrocode}
+%<*initex>
+\__alloc_setup_type:nnn { iow } \c_zero \c_sixteen
+\cs_new_protected:Npn \@@_new:N #1
+ { \__alloc_reg:nNN { iow } \tex_chardef:D #1 }
+%</initex>
+%<*package>
+\cs_set_eq:NN \@@_new:N \newwrite
%</package>
-\cs_new_protected:Npn \ior_stream_alloc:N #1
+\cs_generate_variant:Nn \@@_new:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\iow_new:N, \iow_new:c}
+% Reserving a new stream is done by defining the name as equal to writing
+% to the terminal: odd but at least consistent.
+% \begin{macrocode}
+\cs_new_protected:Npn \iow_new:N #1 { \cs_new_eq:NN #1 \c_term_iow }
+\cs_generate_variant:Nn \iow_new:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\iow_open:Nn, \iow_open:cn}
+% \begin{macro}[aux]{\@@_open:Nn}
+% The same idea as for reading, but without the path.
+% \begin{macrocode}
+\cs_new_protected:Npn \iow_open:Nn #1#2
+ { \__file_name_sanitize:nn {#2} { \@@_open:Nn #1 } }
+\cs_generate_variant:Nn \iow_open:Nn { c }
+\cs_new_protected:Npn \@@_open:Nn #1#2
{
- \cs_if_exist:cF { g_ior_ \int_use:N \l_ior_stream_int _ior }
+ \iow_close:N #1
+ \int_set_eq:NN \l_@@_stream_int \c_sixteen
+ \tl_map_function:NN \c_@@_streams_tl \@@_alloc:n
+ \int_compare:nNnTF \l_@@_stream_int = \c_sixteen
+ { \__msg_kernel_fatal:nn { kernel } { output-streams-exhausted } }
+ {
+ \@@_alloc:N #1
+ \prop_gput:NVn \g_@@_streams_prop \l_@@_stream_int {#2}
+ \tex_immediate:D \tex_openout:D #1#2 \scan_stop:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_alloc:n}
+% Identical to the input routine, but with the appropriate names used
+% (when \pkg{l3docstrip} has done it's job!).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_alloc:n #1
+ {
+ \prop_if_in:NnF \g_@@_streams_prop {#1}
+ {
+ \int_set:Nn \l_@@_stream_int {#1}
+ \tl_map_break:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_alloc:N}
+% \begin{macro}[aux]{\@@_alloc:}
+% \begin{variable}{\g_@@_internal_iow}
+% Exactly the same as for reading!
+% \begin{macrocode}
+\iow_new:N \g_@@_internal_iow
+\cs_new_protected:Npn \@@_alloc:N #1
+ {
+ \cs_if_exist:cF { g_iow_ \int_use:N \l_@@_stream_int _iow }
{
%<*package>
- \ior_stream_alloc_aux:
- \int_compare:nNnT \l_ior_stream_int = \c_sixteen
+ \@@_alloc:
+ \int_compare:nNnT \l_@@_stream_int = \c_sixteen
{
- \ior_raw_new:N \g_ior_internal_ior
- \int_set:Nn \l_ior_stream_int { \g_ior_internal_ior }
+ \@@_new:N \g_@@_internal_iow
+ \int_set:Nn \l_@@_stream_int { \g_@@_internal_iow }
\cs_gset_eq:cN
- { g_ior_ \int_use:N \l_iow_stream_int _ior } \g_ior_internal_ior
+ { g_iow_ \int_use:N \l_@@_stream_int _iow } \g_@@_internal_iow
}
%</package>
%<*initex>
- \ior_raw_new:c { g_ior_ \int_use:N \l_ior_stream_int _ior }
+ \@@_new:c { g_iow_ \int_use:N \l_@@_stream_int _iow }
%</initex>
}
- \cs_gset_eq:Nc #1 { g_ior_ \int_use:N \l_ior_stream_int _ior }
+ \cs_gset_eq:Nc #1 { g_iow_ \int_use:N \l_@@_stream_int _iow }
}
%<*package>
-\cs_new_protected_nopar:Npn \ior_stream_alloc_aux:
+\cs_new_protected_nopar:Npn \@@_alloc:
{
- \int_incr:N \l_ior_stream_int
- \int_compare:nNnT \l_ior_stream_int < \c_sixteen
+ \int_incr:N \l_@@_stream_int
+ \int_compare:nNnT \l_@@_stream_int < \c_sixteen
{
- \cs_if_exist:cTF { g_ior_ \int_use:N \l_ior_stream_int _ior }
+ \cs_if_exist:cTF { g_iow_ \int_use:N \l_@@_stream_int _iow }
{
- \prop_if_in:NVT \g_ior_streams_prop \l_ior_stream_int
- { \ior_stream_alloc_aux: }
+ \prop_if_in:NVT \g_@@_streams_prop \l_@@_stream_int
+ { \@@_alloc: }
}
- { \ior_stream_alloc_aux: }
+ { \@@_alloc: }
}
}
%</package>
@@ -1146,84 +1280,41 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\ior_close:N, \ior_close:c, \iow_close:N, \iow_close:c}
+% \begin{macro}{\iow_close:N, \iow_close:c}
% Closing a stream is not quite the reverse of opening one. First,
% the close operation is easier than the open one, and second as the
% stream is actually a number we can use it directly to show that the
% slot has been freed up.
% \begin{macrocode}
-\cs_new_protected:Npn \ior_close:N #1
- {
- \cs_if_exist:NT #1
- {
- \int_compare:nNnF #1 = \c_minus_one
- {
- \int_compare:nNnF #1 = \c_sixteen
- { \tex_closein:D #1 }
- \prop_gdel:NV \g_ior_streams_prop #1
- \cs_gset_eq:NN #1 \c_term_ior
- }
- }
- }
\cs_new_protected:Npn \iow_close:N #1
{
- \cs_if_exist:NT #1
+ \__chk_if_exist_cs:N #1
+ \int_compare:nNnF #1 < \c_zero
{
- \int_compare:nNnF #1 = \c_minus_one
+ \int_compare:nNnF #1 > \c_fifteen
{
- \int_compare:nNnF #1 = \c_sixteen
- { \tex_closein:D #1 }
- \prop_gdel:NV \g_iow_streams_prop #1
+ \tex_closeout:D #1
+ \prop_gremove:NV \g_@@_streams_prop #1
\cs_gset_eq:NN #1 \c_term_iow
}
}
}
-\cs_generate_variant:Nn \ior_close:N { c }
\cs_generate_variant:Nn \iow_close:N { c }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\ior_list_streams:}
-% Show the property lists, but with some \enquote{pretty printing}.
-% See the \pkg{l3msg} module. If there are no open read streams,
-% issue the message \texttt{show-no-stream}, and show an empty
-% token list. If there are open read streams, format them with
-% \cs{msg_aux_show_unbraced:nn}, and with the message
-% \texttt{show-open-streams}.
+% \begin{macro}{\iow_list_streams:}
+% \begin{macro}{\@@_list_streams:Nn}
+% Done as for input, but with a copy of the auxiliary so the name is correct.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \ior_list_streams:
- { \ior_list_streams_aux:Nn \g_ior_streams_prop { ior } }
\cs_new_protected_nopar:Npn \iow_list_streams:
- { \ior_list_streams_aux:Nn \g_iow_streams_prop { iow } }
-\cs_new_protected:Npn \ior_list_streams_aux:Nn #1#2
- {
- \msg_aux_use:nn { LaTeX / #2 }
- { \prop_if_empty:NTF #1 { show-no-stream } { show-open-streams } }
- \msg_aux_show:x
- { \prop_map_function:NN #1 \msg_aux_show_unbraced:nn }
- }
+ { \@@_list_streams:Nn \g_@@_streams_prop { output } }
+\cs_new_eq:NN \@@_list_streams:Nn \__ior_list_streams:Nn
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
-% Text for the error messages.
-% \begin{macrocode}
-\msg_kernel_new:nnnn { iow } { streams-exhausted }
- { Output~streams~exhausted }
- {
- TeX~can~only~open~up~to~16~output~streams~at~one~time.\\
- All~16 are currently~in~use,~and~something~wanted~to~open
- another~one.
- }
-\msg_kernel_new:nnnn { ior } { streams-exhausted }
- { Input~streams~exhausted }
- {
- TeX~can~only~open~up~to~16~input~streams~at~one~time.\\
- All~16 are currently~in~use,~and~something~wanted~to~open
- another~one.
- }
-% \end{macrocode}
-%
-% \subsection{Deferred writing}
+% \subsubsection{Deferred writing}
%
% \begin{macro}{\iow_shipout_x:Nn, \iow_shipout_x:Nx}
% First the easy part, this is the primitive.
@@ -1234,7 +1325,7 @@
% \end{macro}
%
% \begin{macro}{\iow_shipout:Nn, \iow_shipout:Nx}
-% With \eTeX{} available deferred writing is easy.
+% With \eTeX{} available deferred writing without expansion is easy.
% \begin{macrocode}
\cs_new_protected:Npn \iow_shipout:Nn #1#2
{ \iow_shipout_x:Nn #1 { \exp_not:n {#2} } }
@@ -1242,30 +1333,26 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Immediate writing}
+% \subsubsection{Immediate writing}
%
-% \begin{macro}{\iow_now:Nx}
-% An abbreviation for an often used operation, which immediately
-% writes its second argument expanded to the output stream.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \iow_now:Nx { \tex_immediate:D \iow_shipout_x:Nn }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\iow_now:Nn}
+% \begin{macro}{\iow_now:Nn, \iow_now:Nx}
% This routine writes the second argument onto the output stream without
% expansion. If this stream isn't open, the output goes to the terminal
% instead. If the first argument is no output stream at all, we get an
-% internal error.
+% internal error. We don't use the expansion done by \tn{write} to
+% get the |Nx| variant, because it differs in subtle ways from
+% \texttt{x}-expansion, namely, macro parameter characters would not
+% need to be doubled.
% \begin{macrocode}
\cs_new_protected:Npn \iow_now:Nn #1#2
- { \iow_now:Nx #1 { \exp_not:n {#2} } }
+ { \tex_immediate:D \iow_shipout_x:Nn #1 { \exp_not:n {#2} } }
+\cs_generate_variant:Nn \iow_now:Nn { Nx }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\iow_log:n, \iow_log:x}
% \begin{macro}{\iow_term:n, \iow_term:x}
-% Writing to the log and the terminal directly are relatively easy.
+% Writing to the log and the terminal directly are relatively easy.
% \begin{macrocode}
\cs_set_protected_nopar:Npn \iow_log:x { \iow_now:Nx \c_log_iow }
\cs_new_protected_nopar:Npn \iow_log:n { \iow_now:Nn \c_log_iow }
@@ -1275,7 +1362,7 @@
%\end{macro}
%\end{macro}
%
-% \subsection{Special characters for writing}
+% \subsubsection{Special characters for writing}
%
% \begin{macro}{\iow_newline:}
% Global variable holding the character that forces a new line when
@@ -1292,83 +1379,87 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Hard-wrapping lines based on length}
+% \subsubsection{Hard-wrapping lines to a character count}
%
% The code here implements a generic hard-wrapping function. This is
% used by the messaging system, but is designed such that it is
% available for other uses.
%
-% \begin{macro}{\l_iow_line_length_int}
-% This is the \enquote{raw} length of a line which can be written to a
-% file. The standard value is the line length typically used by
+% \begin{macro}[var, added = 2012-06-24]{\l_iow_line_count_int}
+% This is the \enquote{raw} number of characters in a line which
+% can be written to the terminal.
+% The standard value is the line length typically used by
% \TeX{}Live and Mik\TeX{}.
% \begin{macrocode}
-\int_new:N \l_iow_line_length_int
-\int_set:Nn \l_iow_line_length_int { 78 }
+\int_new:N \l_iow_line_count_int
+\int_set:Nn \l_iow_line_count_int { 78 }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\l_iow_target_length_int}
-% This stores the target line length: the full length minus any
-% part for a leader at the start of each line.
+% \begin{macro}[aux]{\l_@@_target_count_int}
+% This stores the target line count: the full number of characters
+% in a line, minus any part for a leader at the start of each line.
% \begin{macrocode}
-\int_new:N \l_iow_target_length_int
+\int_new:N \l_@@_target_count_int
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]
% {
-% \l_iow_current_line_int,
-% \l_iow_current_word_int,
-% \l_iow_current_indentation_int
+% \l_@@_current_line_int,
+% \l_@@_current_word_int,
+% \l_@@_current_indentation_int
% }
% These store the number of characters in the line and word currently
% being constructed, and the current indentation, respectively.
% \begin{macrocode}
-\int_new:N \l_iow_current_line_int
-\int_new:N \l_iow_current_word_int
-\int_new:N \l_iow_current_indentation_int
+\int_new:N \l_@@_current_line_int
+\int_new:N \l_@@_current_word_int
+\int_new:N \l_@@_current_indentation_int
% \end{macrocode}
% \end{macro}
%
% \begin{macro}[aux]
% {
-% \l_iow_current_line_tl,
-% \l_iow_current_word_tl,
-% \l_iow_current_indentation_tl
+% \l_@@_current_line_tl,
+% \l_@@_current_word_tl,
+% \l_@@_current_indentation_tl
% }
% These hold the current line of text and current word,
% and a number of spaces for indentation, respectively.
% \begin{macrocode}
-\tl_new:N \l_iow_current_line_tl
-\tl_new:N \l_iow_current_word_tl
-\tl_new:N \l_iow_current_indentation_tl
+\tl_new:N \l_@@_current_line_tl
+\tl_new:N \l_@@_current_word_tl
+\tl_new:N \l_@@_current_indentation_tl
% \end{macrocode}
%\end{macro}
%
-% \begin{macro}[aux]{\l_iow_wrap_tl}
-% Used for the expansion step before detokenizing.
+% \begin{macro}[aux]{\l_@@_wrap_tl}
+% Used for the expansion step before detokenizing, and for the output
+% from wrapping text: fully expanded and with lines which are not
+% overly long.
% \begin{macrocode}
-\tl_new:N \l_iow_wrap_tl
+\tl_new:N \l_@@_wrap_tl
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\l_iow_wrapped_tl}
-% The output from wrapping text: fully expanded and with lines
-% which are not overly long.
+% \begin{macro}[aux]{\l_@@_newline_tl}
+% The token list inserted to produce the new line, with the
+% \meta{run-on text}.
% \begin{macrocode}
-\tl_new:N \l_iow_wrapped_tl
+\tl_new:N \l_@@_newline_tl
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\l_iow_line_start_bool}
-% Boolean to avoid adding a space at the beginning of forced newlines.
+% \begin{macro}[aux]{\l_@@_line_start_bool}
+% Boolean to avoid adding a space at the beginning of forced newlines,
+% and to know when to add the indentation.
% \begin{macrocode}
-\bool_new:N \l_iow_line_start_bool
+\bool_new:N \l_@@_line_start_bool
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\c_catcode_other_space_tl}
+% \begin{macro}{\c_catcode_other_space_tl}
% Lowercase a character with category code $12$ to produce an
% \enquote{other} space. We can do everything within the group,
% because \cs{tl_const:Nn} defines its argument globally.
@@ -1381,49 +1472,45 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\c_iow_wrap_marker_tl}
-% \begin{macro}[aux]{
-% \c_iow_wrap_end_marker_tl,
-% \c_iow_wrap_newline_marker_tl,
-% \c_iow_wrap_indent_marker_tl,
-% \c_iow_wrap_unindent_marker_tl}
-% \begin{macro}[aux]{\iow_wrap_new_marker:n}
+% \begin{macro}[aux]{\c_@@_wrap_marker_tl}
+% \begin{macro}[aux]
+% {
+% \c_@@_wrap_end_marker_tl,
+% \c_@@_wrap_newline_marker_tl,
+% \c_@@_wrap_indent_marker_tl,
+% \c_@@_wrap_unindent_marker_tl
+% }
% Every special action of the wrapping code is preceeded by
-% the same recognizable string, \cs{c_iow_wrap_marker_tl}.
+% the same recognizable string, \cs{c_@@_wrap_marker_tl}.
% Upon seeing that \enquote{word}, the wrapping code reads
% one space-delimited argument to know what operation to
% perform. The setting of \tn{escapechar} here is not
-% very important, but makes \cs{c_iow_wrap_marker_tl} look
-% nicer. Note that \cs{iow_wrap_new_marker:n} does not
-% survive the group, but all constants are defined globally.
+% very important, but makes \cs{c_@@_wrap_marker_tl} look
+% nicer.
% \begin{macrocode}
\group_begin:
\int_set_eq:NN \tex_escapechar:D \c_minus_one
- \tl_const:Nx \c_iow_wrap_marker_tl
+ \tl_const:Nx \c_@@_wrap_marker_tl
{ \tl_to_str:n { \^^I \^^O \^^W \^^_ \^^W \^^R \^^A \^^P } }
- \cs_set:Npn \iow_wrap_new_marker:n #1
- {
- \tl_const:cx { c_iow_wrap_ #1 _marker_tl }
- {
- \c_catcode_other_space_tl
- \c_iow_wrap_marker_tl
- \c_catcode_other_space_tl
- #1
- \c_catcode_other_space_tl
- }
- }
- \iow_wrap_new_marker:n { end }
- \iow_wrap_new_marker:n { newline }
- \iow_wrap_new_marker:n { indent }
- \iow_wrap_new_marker:n { unindent }
\group_end:
+\tl_map_inline:nn
+ { { end } { newline } { indent } { unindent } }
+ {
+ \tl_const:cx { c_@@_wrap_ #1 _marker_tl }
+ {
+ \c_catcode_other_space_tl
+ \c_@@_wrap_marker_tl
+ \c_catcode_other_space_tl
+ #1
+ \c_catcode_other_space_tl
+ }
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
%
% \begin{macro}{\iow_indent:n}
-% \begin{macro}[aux]{\iow_indent_expandable:n}
+% \begin{macro}[aux]{\@@_indent:n}
% We give a dummy (protected) definition to \cs{iow_indent:n}
% when outside messages. Within wrapped message, it places
% the instruction for increasing the indentation before its
@@ -1432,23 +1519,26 @@
% only changes when the next line is started.
% \begin{macrocode}
\cs_new_protected:Npn \iow_indent:n #1 { }
-\cs_new:Npx \iow_indent_expandable:n #1
+\cs_new:Npx \@@_indent:n #1
{
- \c_iow_wrap_indent_marker_tl
+ \c_@@_wrap_indent_marker_tl
#1
- \c_iow_wrap_unindent_marker_tl
+ \c_@@_wrap_unindent_marker_tl
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\iow_wrap:xnnnN}
-% The main wrapping function works as follows. The target number of
-% characters in a line is calculated, before fully-expanding the input
-% such that |\\| and \verb*|\ | are converted into the appropriate
-% values. There is then a loop over each word in the input, which
-% will do the actual wrapping. After the loop, the resulting text is
-% passed on to the function which has been given as a post-processor.
+% \begin{macro}{\iow_wrap:nnnN}
+% The main wrapping function works as follows. First give |\\|,
+% \verb*|\ | and other formatting commands the correct definition for
+% messages, before fully-expanding the input. In package mode, the
+% expansion uses \LaTeXe{}'s \cs{protect} mechanism. Afterwards, set
+% the newline marker (two assignments to fully expand, then convert
+% to a string) and its length, and initialize some registers.
+% There is then a loop over each word in the input, which will do the
+% actual wrapping. After the loop, the resulting text is passed on to
+% the function which has been given as a post-processor.
% The argument |#4| is available for additional set up steps for
% the output. The definition of |\\| and \verb*|\ | use an
% \enquote{other} space rather than a normal space, because the latter
@@ -1456,16 +1546,9 @@
% expansions. The \cs{tl_to_str:N} step converts the \enquote{other}
% space back to a normal space.
% \begin{macrocode}
-\cs_new_protected:Npn \iow_wrap:xnnnN #1#2#3#4#5
+\cs_new_protected:Npn \iow_wrap:nnnN #1#2#3#4
{
\group_begin:
- \int_set:Nn \l_iow_target_length_int { \l_iow_line_length_int - ( #3 ) }
- \int_zero:N \l_iow_current_indentation_int
- \tl_clear:N \l_iow_current_indentation_tl
- \int_zero:N \l_iow_current_line_int
- \tl_clear:N \l_iow_current_line_tl
- \tl_clear:N \l_iow_wrap_tl
- \bool_set_true:N \l_iow_line_start_bool
\int_set_eq:NN \tex_escapechar:D \c_minus_one
\cs_set_nopar:Npx \{ { \token_to_str:N \{ }
\cs_set_nopar:Npx \# { \token_to_str:N \# }
@@ -1473,103 +1556,119 @@
\cs_set_nopar:Npx \% { \token_to_str:N \% }
\cs_set_nopar:Npx \~ { \token_to_str:N \~ }
\int_set:Nn \tex_escapechar:D { 92 }
- \cs_set_eq:NN \\ \c_iow_wrap_newline_marker_tl
+ \cs_set_eq:NN \\ \c_@@_wrap_newline_marker_tl
\cs_set_eq:NN \ \c_catcode_other_space_tl
- \cs_set_eq:NN \iow_indent:n \iow_indent_expandable:n
- #4
+ \cs_set_eq:NN \iow_indent:n \@@_indent:n
+ #3
%<*initex>
- \tl_set:Nx \l_iow_wrap_tl {#1}
+ \tl_set:Nx \l_@@_wrap_tl {#1}
%</initex>
%<*package>
- \protected@edef \l_iow_wrap_tl {#1}
+ \protected@edef \l_@@_wrap_tl {#1}
%</package>
- \cs_set:Npn \\ { \iow_newline: #2 }
+% \end{macrocode}
+% This is a bit of a hack to measure the string length of the run on text
+% without the \pkg{l3str} module (which is still experimental). This should
+% be replaced once the string module is finalised with something a little
+% cleaner.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_newline_tl { \iow_newline: #2 }
+ \tl_set:Nx \l_@@_newline_tl { \tl_to_str:N \l_@@_newline_tl }
+ \tl_replace_all:Nnn \l_@@_newline_tl { ~ } { \c_space_tl }
+ \int_set:Nn \l_@@_target_count_int
+ { \l_iow_line_count_int - \tl_count:N \l_@@_newline_tl + \c_one }
+ \int_zero:N \l_@@_current_indentation_int
+ \tl_clear:N \l_@@_current_indentation_tl
+ \int_zero:N \l_@@_current_line_int
+ \tl_clear:N \l_@@_current_line_tl
+ \bool_set_true:N \l_@@_line_start_bool
\use:x
{
- \iow_wrap_loop:w
- \tl_to_str:N \l_iow_wrap_tl
- \tl_to_str:N \c_iow_wrap_end_marker_tl
+ \exp_not:n { \tl_clear:N \l_@@_wrap_tl }
+ \@@_wrap_loop:w
+ \tl_to_str:N \l_@@_wrap_tl
+ \tl_to_str:N \c_@@_wrap_end_marker_tl
\c_space_tl \c_space_tl
\exp_not:N \q_stop
}
\exp_args:NNo \group_end:
- #5 \l_iow_wrapped_tl
+ #4 \l_@@_wrap_tl
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\iow_wrap_loop:w}
+% \begin{macro}[aux]{\@@_wrap_loop:w}
% The loop grabs one word in the input, and checks whether it is
% the special marker, or a normal word.
% \begin{macrocode}
-\cs_new_protected:Npn \iow_wrap_loop:w #1 ~ %
+\cs_new_protected:Npn \@@_wrap_loop:w #1 ~ %
{
- \tl_set:Nn \l_iow_current_word_tl {#1}
- \tl_if_eq:NNTF \l_iow_current_word_tl \c_iow_wrap_marker_tl
- { \iow_wrap_special:w }
- { \iow_wrap_word: }
+ \tl_set:Nn \l_@@_current_word_tl {#1}
+ \tl_if_eq:NNTF \l_@@_current_word_tl \c_@@_wrap_marker_tl
+ { \@@_wrap_special:w }
+ { \@@_wrap_word: }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\iow_wrap_word:}
-% \begin{macro}[aux]{\iow_wrap_word_fits:}
-% \begin{macro}[aux]{\iow_wrap_word_newline:}
-% For a normal word, update the line length, then test if the current
+% \begin{macro}[aux]{\@@_wrap_word:}
+% \begin{macro}[aux]{\@@_wrap_word_fits:}
+% \begin{macro}[aux]{\@@_wrap_word_newline:}
+% For a normal word, update the line count, then test if the current
% word would fit in the current line, and call the appropriate function.
% If the word fits in the current line, add it to the line, preceded by
% a space unless it is the first word of the line.
% Otherwise, the current line is added to the result, with the run-on text.
-% The current word (and its length) are then put in the new line.
+% The current word (and its character count) are then put in the new line.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \iow_wrap_word:
+\cs_new_protected_nopar:Npn \@@_wrap_word:
{
- \int_set:Nn \l_iow_current_word_int
- { \str_length_skip_spaces:N \l_iow_current_word_tl }
- \int_add:Nn \l_iow_current_line_int { \l_iow_current_word_int }
- \int_compare:nNnTF \l_iow_current_line_int < \l_iow_target_length_int
- { \iow_wrap_word_fits: }
- { \iow_wrap_word_newline: }
- \iow_wrap_loop:w
+ \int_set:Nn \l_@@_current_word_int
+ { \__str_count_ignore_spaces:N \l_@@_current_word_tl }
+ \int_add:Nn \l_@@_current_line_int { \l_@@_current_word_int }
+ \int_compare:nNnTF \l_@@_current_line_int < \l_@@_target_count_int
+ { \@@_wrap_word_fits: }
+ { \@@_wrap_word_newline: }
+ \@@_wrap_loop:w
}
-\cs_new_protected_nopar:Npn \iow_wrap_word_fits:
+\cs_new_protected_nopar:Npn \@@_wrap_word_fits:
{
- \bool_if:NTF \l_iow_line_start_bool
+ \bool_if:NTF \l_@@_line_start_bool
{
- \bool_set_false:N \l_iow_line_start_bool
- \tl_put_right:Nx \l_iow_current_line_tl
- { \l_iow_current_indentation_tl \l_iow_current_word_tl }
- \int_add:Nn \l_iow_current_line_int
- { \l_iow_current_indentation_int }
+ \bool_set_false:N \l_@@_line_start_bool
+ \tl_put_right:Nx \l_@@_current_line_tl
+ { \l_@@_current_indentation_tl \l_@@_current_word_tl }
+ \int_add:Nn \l_@@_current_line_int
+ { \l_@@_current_indentation_int }
}
{
- \tl_put_right:Nx \l_iow_current_line_tl
- { ~ \l_iow_current_word_tl }
- \int_incr:N \l_iow_current_line_int
+ \tl_put_right:Nx \l_@@_current_line_tl
+ { ~ \l_@@_current_word_tl }
+ \int_incr:N \l_@@_current_line_int
}
}
-\cs_new_protected_nopar:Npn \iow_wrap_word_newline:
+\cs_new_protected_nopar:Npn \@@_wrap_word_newline:
{
- \tl_put_right:Nx \l_iow_wrapped_tl
- { \l_iow_current_line_tl \\ }
- \int_set:Nn \l_iow_current_line_int
+ \tl_put_right:Nx \l_@@_wrap_tl
+ { \l_@@_current_line_tl \l_@@_newline_tl }
+ \int_set:Nn \l_@@_current_line_int
{
- \l_iow_current_word_int
- + \l_iow_current_indentation_int
+ \l_@@_current_word_int
+ + \l_@@_current_indentation_int
}
- \tl_set:Nx \l_iow_current_line_tl
- { \l_iow_current_indentation_tl \l_iow_current_word_tl }
+ \tl_set:Nx \l_@@_current_line_tl
+ { \l_@@_current_indentation_tl \l_@@_current_word_tl }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux]{\iow_wrap_special:w}
-% \begin{macro}[aux]{\iow_wrap_newline:w}
-% \begin{macro}[aux]{\iow_wrap_indent:w}
-% \begin{macro}[aux]{\iow_wrap_unindent:w}
-% \begin{macro}[aux]{\iow_wrap_end:w}
+% \begin{macro}[aux]{\@@_wrap_special:w}
+% \begin{macro}[aux]{\@@_wrap_newline:w}
+% \begin{macro}[aux]{\@@_wrap_indent:w}
+% \begin{macro}[aux]{\@@_wrap_unindent:w}
+% \begin{macro}[aux]{\@@_wrap_end:w}
% When the \enquote{special} marker is encountered,
% read what operation to perform, as a space-delimited
% argument, perform it, and remember to loop.
@@ -1584,37 +1683,37 @@
% At the end, we simply save the last line (without the run-on text),
% and prevent the loop.
% \begin{macrocode}
-\cs_new_protected:Npn \iow_wrap_special:w #1 ~ #2 ~ #3 ~ %
+\cs_new_protected:Npn \@@_wrap_special:w #1 ~ #2 ~ #3 ~ %
{
- \use:c { iow_wrap_#1: }
- \str_if_eq:xxTF { #2~#3 } { ~ \c_iow_wrap_marker_tl }
- { \iow_wrap_special:w }
- { \iow_wrap_loop:w #2 ~ #3 ~ }
+ \use:c { @@_wrap_#1: }
+ \str_if_eq_x:nnTF { #2~#3 } { ~ \c_@@_wrap_marker_tl }
+ { \@@_wrap_special:w }
+ { \@@_wrap_loop:w #2 ~ #3 ~ }
}
-\cs_new_protected_nopar:Npn \iow_wrap_newline:
+\cs_new_protected_nopar:Npn \@@_wrap_newline:
{
- \tl_put_right:Nx \l_iow_wrapped_tl
- { \l_iow_current_line_tl \\ }
- \int_zero:N \l_iow_current_line_int
- \tl_clear:N \l_iow_current_line_tl
- \bool_set_true:N \l_iow_line_start_bool
+ \tl_put_right:Nx \l_@@_wrap_tl
+ { \l_@@_current_line_tl \l_@@_newline_tl }
+ \int_zero:N \l_@@_current_line_int
+ \tl_clear:N \l_@@_current_line_tl
+ \bool_set_true:N \l_@@_line_start_bool
}
-\cs_new_protected_nopar:Npx \iow_wrap_indent:
+\cs_new_protected_nopar:Npx \@@_wrap_indent:
{
- \int_add:Nn \l_iow_current_indentation_int \c_four
- \tl_put_right:Nx \exp_not:N \l_iow_current_indentation_tl
+ \int_add:Nn \l_@@_current_indentation_int \c_four
+ \tl_put_right:Nx \exp_not:N \l_@@_current_indentation_tl
{ \c_space_tl \c_space_tl \c_space_tl \c_space_tl }
}
-\cs_new_protected_nopar:Npn \iow_wrap_unindent:
+\cs_new_protected_nopar:Npn \@@_wrap_unindent:
{
- \int_sub:Nn \l_iow_current_indentation_int \c_four
- \tl_set:Nx \l_iow_current_indentation_tl
- { \prg_replicate:nn \l_iow_current_indentation_int { ~ } }
+ \int_sub:Nn \l_@@_current_indentation_int \c_four
+ \tl_set:Nx \l_@@_current_indentation_tl
+ { \prg_replicate:nn \l_@@_current_indentation_int { ~ } }
}
-\cs_new_protected_nopar:Npn \iow_wrap_end:
+\cs_new_protected_nopar:Npn \@@_wrap_end:
{
- \tl_put_right:Nx \l_iow_wrapped_tl
- { \l_iow_current_line_tl }
+ \tl_put_right:Nx \l_@@_wrap_tl
+ { \l_@@_current_line_tl }
\use_none_delimit_by_q_stop:w
}
% \end{macrocode}
@@ -1624,29 +1723,29 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux]{\str_length_skip_spaces:N}
-% \begin{macro}[aux]{\str_length_skip_spaces:n}
-% \begin{macro}[aux]{\str_length_loop:NNNNNNNNN}
+% \begin{macro}[aux]{\__str_count_ignore_spaces:N}
+% \begin{macro}[aux]{\__str_count_ignore_spaces:n}
+% \begin{macro}[aux]{\__str_count_loop:NNNNNNNNN}
% The wrapping code requires to measure the number of character
-% in each word. This could be done with \cs{tl_length:n}, but
+% in each word. This could be done with \cs{tl_count:n}, but
% it is ten times faster (literally) to use the code below.
% \begin{macrocode}
-\cs_new_nopar:Npn \str_length_skip_spaces:N
- { \exp_args:No \str_length_skip_spaces:n }
-\cs_new:Npn \str_length_skip_spaces:n #1
+\cs_new_nopar:Npn \__str_count_ignore_spaces:N
+ { \exp_args:No \__str_count_ignore_spaces:n }
+\cs_new:Npn \__str_count_ignore_spaces:n #1
{
- \int_value:w \int_eval:w
- \exp_after:wN \str_length_loop:NNNNNNNNN \tl_to_str:n {#1}
+ \__int_value:w \__int_eval:w
+ \exp_after:wN \__str_count_loop:NNNNNNNNN \tl_to_str:n {#1}
{ X8 } { X7 } { X6 } { X5 } { X4 } { X3 } { X2 } { X1 } { X0 } \q_stop
- \int_eval_end:
+ \__int_eval_end:
}
-\cs_new:Npn \str_length_loop:NNNNNNNNN #1#2#3#4#5#6#7#8#9
+\cs_new:Npn \__str_count_loop:NNNNNNNNN #1#2#3#4#5#6#7#8#9
{
\if_catcode:w X #9
\exp_after:wN \use_none_delimit_by_q_stop:w
\else:
9 +
- \exp_after:wN \str_length_loop:NNNNNNNNN
+ \exp_after:wN \__str_count_loop:NNNNNNNNN
\fi:
}
% \end{macrocode}
@@ -1654,132 +1753,80 @@
% \end{macro}
% \end{macro}
%
-% \subsection{Reading input}
+% \subsection{Messages}
%
-% \begin{macro}[int]{\if_eof:w}
-% The primitive conditional
% \begin{macrocode}
-\cs_new_eq:NN \if_eof:w \tex_ifeof:D
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[pTF]{\ior_if_eof:N}
-% To test if some particular input stream is exhausted the following
-% conditional is provided.
-% \begin{macrocode}
-\prg_new_conditional:Nnn \ior_if_eof:N { p , T , F , TF }
+\__msg_kernel_new:nnnn { kernel } { file-not-found }
+ { File~'#1'~not~found. }
{
- \cs_if_exist:NTF #1
- {
- \if_int_compare:w #1 = \c_sixteen
- \prg_return_true:
- \else:
- \if_eof:w #1
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- \fi:
- }
- { \prg_return_true: }
+ The~requested~file~could~not~be~found~in~the~current~directory,~
+ in~the~TeX~search~path~or~in~the~LaTeX~search~path.
+ }
+\__msg_kernel_new:nnnn { kernel } { input-streams-exhausted }
+ { Input~streams~exhausted }
+ {
+ TeX~can~only~open~up~to~16~input~streams~at~one~time.\\
+ All~16~are~currently~in~use,~and~something~wanted~to~open~
+ another~one.
+ }
+\__msg_kernel_new:nnnn { kernel } { output-streams-exhausted }
+ { Output~streams~exhausted }
+ {
+ TeX~can~only~open~up~to~16~output~streams~at~one~time.\\
+ All~16~are~currently~in~use,~and~something~wanted~to~open~
+ another~one.
+ }
+\__msg_kernel_new:nnnn { kernel } { space-in-file-name }
+ { Space~in~file~name~'#1'. }
+ {
+ Spaces~are~not~permitted~in~files~loaded~by~LaTeX: \\
+ Further~errors~may~follow!
}
% \end{macrocode}
-% \end{macro}
%
-% \begin{macro}{\ior_to:NN, \ior_gto:NN}
-% And here we read from files.
-% \begin{macrocode}
-\cs_new_protected:Npn \ior_to:NN #1#2
- { \tex_read:D #1 to #2 }
-\cs_new_protected:Npn \ior_gto:NN #1#2
- { \tex_global:D \tex_read:D #1 to #2 }
-% \end{macrocode}
-% \end{macro}
+% \subsection{Deprecated functions}
%
-% \begin{macro}{\ior_str_to:NN, \ior_str_gto:NN}
-% Reading as strings is also a primitive wrapper.
+% Deprecated on 2012-06-28, for removal by 2012-12-31.
+%
+% \begin{macro}{\iow_wrap:xnnnN}
+% This was renamed and one unneed argument was removed.
% \begin{macrocode}
-\cs_new_protected:Npn \ior_str_to:NN #1#2
- { \etex_readline:D #1 to #2 }
-\cs_new_protected:Npn \ior_str_gto:NN #1#2
- { \tex_global:D \etex_readline:D #1 to #2 }
+\cs_new_protected:Npn \iow_wrap:xnnnN #1#2#3#4#5
+ { \iow_wrap:nnnN {#1} {#2} {#4} #5 }
% \end{macrocode}
% \end{macro}
%
-% \subsection{Experimental functions}
+% Deprecated on 2012-06-24, for removal by 2012-12-31.
%
-% \begin{macro}{\ior_map_inline:Nn, \ior_str_map_inline:Nn}
-% \begin{macro}[aux]{\ior_str_map_inline_aux:NNn}
-% \begin{macro}[aux]{\ior_str_map_inline_aux:NNNn}
-% \begin{macro}[aux]{\ior_str_map_inline_loop:NNN}
-% \begin{variable}{\l_ior_internal_tl}
-% Mapping to an input stream can be done on either a token or a string
-% basis, hence the set up. Within that, there is a check to avoid reading
-% past the end of a file, hence the two applications of \cs{ior_if_eof:N}.
-% This mapping cannot be nested as the stream has only one \enquote{current
-% line}.
+% \begin{variable}{\l_iow_line_length_int}
+% Simple rename. Here we copy the \TeX{} register.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \ior_map_inline:Nn
- { \ior_map_inline_aux:NNn \ior_to:NN }
-\cs_new_protected_nopar:Npn \ior_str_map_inline:Nn
- { \ior_map_inline_aux:NNn \ior_str_to:NN }
-\cs_new_protected_nopar:Npn \ior_map_inline_aux:NNn
- {
- \exp_args:Nc \ior_map_inline_aux:NNNn
- { ior_map_ \int_use:N \g_prg_map_int :n }
- }
-\cs_new_protected:Npn \ior_map_inline_aux:NNNn #1#2#3#4
- {
- \cs_set:Npn #1 ##1 {#4}
- \int_gincr:N \g_prg_map_int
- \ior_if_eof:NF #3 { \ior_map_inline_loop:NNN #1#2#3 }
- \prg_break_point:n { \int_gdecr:N \g_prg_map_int }
- }
-\cs_new_protected:Npn \ior_map_inline_loop:NNN #1#2#3
- {
- #2 #3 \l_ior_internal_tl
- \ior_if_eof:NF #3
- {
- \exp_args:No #1 \l_ior_internal_tl
- \ior_map_inline_loop:NNN #1#2#3
- }
- }
-\tl_new:N \l_ior_internal_tl
+\cs_new_eq:NN \l_iow_line_length_int \l_iow_line_count_int
% \end{macrocode}
% \end{variable}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Messages}
%
+% \begin{macro}{\ior_to:NN, \ior_gto:NN, \ior_str_to:NN, \ior_str_gto:NN}
+% The local variants are renames, while the global variants are
+% deprecated and add the \TeX{} primitive \tn{global}.
% \begin{macrocode}
-\msg_kernel_new:nnnn { file } { file-not-found }
- { File~'#1'~not~found. }
- {
- The~requested~file~could~not~be~found~in~the~current~directory,~
- in~the~TeX~search~path~or~in~the~LaTeX~search~path.
- }
-\msg_kernel_new:nnnn { file } { space-in-file-name }
- { Space~in~file~name~'#1'. }
- {
- Spaces~are~not~permitted~in~files~loaded~by~LaTeX: \\
- Further~errors~may~follow!
- }
+\cs_new_eq:NN \ior_to:NN \ior_get:NN
+\cs_new_protected_nopar:Npn \ior_gto:NN { \tex_global:D \ior_to:NN }
+\cs_new_eq:NN \ior_str_to:NN \ior_get_str:NN
+\cs_new_protected_nopar:Npn \ior_str_gto:NN { \tex_global:D \ior_str_to:NN }
% \end{macrocode}
-%
-% \subsection{Deprecated functions}
+% \end{macro}
%
% Deprecated on 2012-02-10, for removal by 2012-05-31.
%
% \begin{macro}{\iow_now_when_avail:Nn, \iow_now_when_avail:Nx}
% For writing only if the stream requested is open at all.
% \begin{macrocode}
+%<*deprecated>
\cs_new_protected:Npn \iow_now_when_avail:Nn #1
{ \cs_if_free:NTF #1 { \use_none:n } { \iow_now:Nn #1 } }
\cs_new_protected:Npn \iow_now_when_avail:Nx #1
{ \cs_if_free:NTF #1 { \use_none:n } { \iow_now:Nx #1 } }
+%</deprecated>
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx
index c86e9f269db..845d47814d5 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3final.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3final.dtx
@@ -35,7 +35,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3final.dtx 3213 2012-01-20 11:03:46Z joseph $
+\GetIdInfo$Id: l3final.dtx 3986 2012-07-15 19:23:51Z joseph $
{L3 Experimental format finalisation}
%</driver|package>
%<*driver>
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
new file mode 100644
index 00000000000..981e642653b
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-assign.dtx
@@ -0,0 +1,235 @@
+% \iffalse meta-comment
+%%
+%% File: l3fp-assign.dtx Copyright (C) 2011-2012 The LaTeX3 project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-assign.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Floating-point assignments}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-assign} package\thanks{This file
+% has version number \ExplFileVersion, last
+% revised \ExplFileDate.}\\
+% Floating point expressions}
+% \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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-assign} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{Assigning values}
+%
+% \begin{macro}{\fp_new:N}
+% Floating point variables are initialized to be $+0$.
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_new:N #1
+ { \cs_new_eq:NN #1 \c_zero_fp }
+\cs_generate_variant:Nn \fp_new:N {c}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \fp_set:Nn, \fp_set:cn,
+% \fp_gset:Nn, \fp_gset:cn,
+% \fp_const:Nn, \fp_const:cn
+% }
+% Simply use \cs{@@_parse:n} within various \texttt{x}-expanding
+% assignments.
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_set:Nn #1#2
+ { \tl_set:Nx #1 { \@@_parse:n {#2} } }
+\cs_new_protected:Npn \fp_gset:Nn #1#2
+ { \tl_gset:Nx #1 { \@@_parse:n {#2} } }
+\cs_new_protected:Npn \fp_const:Nn #1#2
+ { \tl_const:Nx #1 { \@@_parse:n {#2} } }
+\cs_generate_variant:Nn \fp_set:Nn {c}
+\cs_generate_variant:Nn \fp_gset:Nn {c}
+\cs_generate_variant:Nn \fp_const:Nn {c}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \fp_set_eq:NN , \fp_set_eq:cN , \fp_set_eq:Nc , \fp_set_eq:cc,
+% \fp_gset_eq:NN, \fp_gset_eq:cN, \fp_gset_eq:Nc, \fp_gset_eq:cc
+% }
+% Copying a floating point is the same as copying the underlying token
+% list.
+% \begin{macrocode}
+\cs_new_eq:NN \fp_set_eq:NN \tl_set_eq:NN
+\cs_new_eq:NN \fp_gset_eq:NN \tl_gset_eq:NN
+\cs_generate_variant:Nn \fp_set_eq:NN { c , Nc , cc }
+\cs_generate_variant:Nn \fp_gset_eq:NN { c , Nc , cc }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\fp_zero:N, \fp_zero:c, \fp_gzero:N, \fp_gzero:c}
+% Setting a floating point to zero: copy \cs{c_zero_fp}.
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_zero:N #1 { \fp_set_eq:NN #1 \c_zero_fp }
+\cs_new_protected:Npn \fp_gzero:N #1 { \fp_gset_eq:NN #1 \c_zero_fp }
+\cs_generate_variant:Nn \fp_zero:N { c }
+\cs_generate_variant:Nn \fp_gzero:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {\fp_zero_new:N, \fp_zero_new:c, \fp_gzero_new:N, \fp_gzero_new:c}
+% Set the floating point to zero, or define it if needed.
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_zero_new:N #1
+ { \fp_if_exist:NTF #1 { \fp_zero:N #1 } { \fp_new:N #1 } }
+\cs_new_protected:Npn \fp_gzero_new:N #1
+ { \fp_if_exist:NTF #1 { \fp_gzero:N #1 } { \fp_new:N #1 } }
+\cs_generate_variant:Nn \fp_zero_new:N { c }
+\cs_generate_variant:Nn \fp_gzero_new:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Updating values}
+%
+% These match the equivalent functions in \pkg{l3int} and \pkg{l3skip}.
+%
+% \begin{macro}
+% {
+% \fp_add:Nn, \fp_add:cn, \fp_gadd:Nn, \fp_gadd:cn,
+% \fp_sub:Nn, \fp_sub:cn, \fp_gsub:Nn, \fp_gsub:cn,
+% }
+% \begin{macro}[aux]{\@@_add:NNNn}
+% The auxiliary's arguments are 1: the assignment function, 2: the
+% operation, 3: the fp variable, 4: the second operand. The
+% parentheses around the second operand are needed because |+| and |-|
+% are not the operations with the lowest priority.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_add:Nn { \@@_add:NNNn \fp_set:Nn + }
+\cs_new_protected_nopar:Npn \fp_gadd:Nn { \@@_add:NNNn \fp_gset:Nn + }
+\cs_new_protected_nopar:Npn \fp_sub:Nn { \@@_add:NNNn \fp_set:Nn - }
+\cs_new_protected_nopar:Npn \fp_gsub:Nn { \@@_add:NNNn \fp_gset:Nn - }
+\cs_new_protected:Npn \@@_add:NNNn #1#2#3#4 { #1 #3 { #3 #2 (#4) } }
+\cs_generate_variant:Nn \fp_add:Nn { c }
+\cs_generate_variant:Nn \fp_gadd:Nn { c }
+\cs_generate_variant:Nn \fp_sub:Nn { c }
+\cs_generate_variant:Nn \fp_gsub:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Showing values}
+%
+% \begin{macro}{\fp_show:N, \fp_show:c, \fp_show:n}
+% This shows the result of computing its argument. The
+% \cs{__msg_show_variable:x} auxiliary expects its input in a slightly odd
+% form, starting with |>|, and displays the rest.
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_show:N #1
+ { \__msg_show_variable:x { > \fp_to_tl:N #1 } }
+\cs_new_protected:Npn \fp_show:n #1
+ { \__msg_show_variable:x { > \fp_to_tl:n {#1} } }
+\cs_generate_variant:Nn \fp_show:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Some useful constants and scratch variables}
+%
+% \begin{variable}{\c_one_fp, \c_e_fp}
+% Some constants.
+% \begin{macrocode}
+\fp_const:Nn \c_e_fp { 2.718 2818 2845 9045 }
+\fp_const:Nn \c_one_fp { 1 }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_pi_fp, \c_one_degree_fp}
+% We do not round $\pi$ to the closest multiple of $10^{-15}$, which
+% would underestimate it by roughly $2.4\cdot 10^{-16}$, but instead
+% round it up to the next nearest multiple, which is an overestimate
+% by roughly $7.7\cdot 10^{-16}$. This particular choice of rounding
+% has very nice properties: it is exactly divisible by $4$ and by
+% $180$ as a $16$-digit precision floating point number, hence
+% ensuring that $\sin(180\mathrm{deg}) = \sin(\pi) = 0$ exactly, with
+% no rounding artifact.
+% \begin{macrocode}
+\fp_const:Nn \c_pi_fp { 3.141 5926 5358 9794 }
+\fp_const:Nn \c_one_degree_fp { 0.0 1745 3292 5199 4330 }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_tmpa_fp, \l_tmpb_fp, \g_tmpa_fp, \g_tmpb_fp}
+% Scratch variables are simply initialized there.
+% \begin{macrocode}
+\fp_new:N \l_tmpa_fp
+\fp_new:N \l_tmpb_fp
+\fp_new:N \g_tmpa_fp
+\fp_new:N \g_tmpb_fp
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
new file mode 100644
index 00000000000..566eec13ec5
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-aux.dtx
@@ -0,0 +1,850 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-aux.dtx Copyright(C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-aux.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Floating-point support functions}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \textsf{l3fp-aux} package\\ Support for floating points^^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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-aux} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{Using arguments and semicolons}
+%
+% \begin{macro}[int, EXP]{\@@_use_none_stop_f:n}
+% This function removes an argument (typically a digit) and replaces
+% it by \cs{exp_stop_f:}, a marker which stops \texttt{f}-type
+% expansion.
+% \begin{macrocode}
+\cs_new:Npn \@@_use_none_stop_f:n #1 { \exp_stop_f: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_use_s:n, \@@_use_s:nn}
+% Those functions place a semicolon after one or two arguments
+% (typically digits).
+% \begin{macrocode}
+\cs_new:Npn \@@_use_s:n #1 { #1; }
+\cs_new:Npn \@@_use_s:nn #1#2 { #1#2; }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]
+% {\@@_use_none_until_s:w, \@@_use_i_until_s:nw, \@@_use_ii_until_s:nnw}
+% Those functions select specific arguments among a set of arguments
+% delimited by a semicolon.
+% \begin{macrocode}
+\cs_new:Npn \@@_use_none_until_s:w #1; { }
+\cs_new:Npn \@@_use_i_until_s:nw #1#2; {#1}
+\cs_new:Npn \@@_use_ii_until_s:nnw #1#2#3; {#2}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_reverse_args:Nww}
+% Many internal functions take arguments delimited by semicolons, and
+% it is occasionally useful to swap two such arguments.
+% \begin{macrocode}
+\cs_new:Npn \@@_reverse_args:Nww #1 #2; #3; { #1 #3; #2; }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Constants, and structure of floating points}
+%
+% \begin{macro}[int]{\s_@@, \@@_chk:w}
+% Floating points numbers all start with \cs{s_@@} \cs{@@_chk:w},
+% where \cs{s_@@} is equal to the \TeX{} primitive \tn{relax}, and
+% \cs{@@_chk:w} is protected. The rest of the floating point number
+% is made of characters (or \tn{relax}). This ensures that nothing
+% expands under \texttt{f}-expansion, nor under \texttt{x}-expansion.
+% However, when typeset, \cs{s_@@} does nothing, and \cs{@@_chk:w} is
+% expanded. We define \cs{@@_chk:w} to produce an error.
+% \begin{macrocode}
+\__scan_new:N \s_@@
+\cs_new_protected:Npn \@@_chk:w #1 ;
+ {
+ \__msg_kernel_error:nnx { kernel } { misused-fp }
+ { \@@_to_tl:w \s_@@ \@@_chk:w #1 ; }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\s_@@_mark, \s_@@_stop}
+% Aliases of \cs{tex_relax:D}, used to terminate expressions.
+% \begin{macrocode}
+\__scan_new:N \s_@@_mark
+\__scan_new:N \s_@@_stop
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]
+% {
+% \s_@@_invalid, \s_@@_underflow, \s_@@_overflow,
+% \s_@@_division, \s_@@_exact
+% }
+% A couple of scan marks used to indicate where special floating point
+% numbers come from.
+% \begin{macrocode}
+\__scan_new:N \s_@@_invalid
+\__scan_new:N \s_@@_underflow
+\__scan_new:N \s_@@_overflow
+\__scan_new:N \s_@@_division
+\__scan_new:N \s_@@_exact
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}
+% {\c_zero_fp, \c_minus_zero_fp, \c_inf_fp, \c_minus_inf_fp, \c_nan_fp}
+% The special floating points. All of them have the form
+% \begin{quote}
+% \cs{s_@@} \cs{@@_chk:w} \meta{case} \meta{sign} \cs{s_@@_...} |;|
+% \end{quote}
+% where the dots in \cs{s_@@_...} are one of \texttt{invalid},
+% \texttt{underflow}, \texttt{overflow}, \texttt{division},
+% \texttt{exact}, describing how the floating point was created. We
+% define the floating points here as \enquote{exact}.
+% \begin{macrocode}
+\tl_const:Nn \c_zero_fp { \s_@@ \@@_chk:w 0 0 \s_@@_exact ; }
+\tl_const:Nn \c_minus_zero_fp { \s_@@ \@@_chk:w 0 2 \s_@@_exact ; }
+\tl_const:Nn \c_inf_fp { \s_@@ \@@_chk:w 2 0 \s_@@_exact ; }
+\tl_const:Nn \c_minus_inf_fp { \s_@@ \@@_chk:w 2 2 \s_@@_exact ; }
+\tl_const:Nn \c_nan_fp { \s_@@ \@@_chk:w 3 1 \s_@@_exact ; }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_@@_max_exponent_int}
+% Normal floating point numbers have an exponent at most
+% \texttt{max_exponent} in absolute value. Larger numbers are rounded
+% to $\pm\infty$. Smaller numbers are subnormal (not implemented yet),
+% and digits beyond
+% $10^{-\text{\texttt{max_exponent}}}$ are rounded away, hence the
+% true minimum exponent is $-\text{\texttt{max_exponent}}-16$;
+% beyond this, numbers are rounded to zero. Why this choice of
+% limits? When computing $(a\cdot 10^n)^(b\cdot 10^p)$, we need to
+% evaluate $\log(a\cdot 10^n) = \log(a) + n \log(10)$ as a fixed point
+% number, which we manipulate as blocks of $4$ digits. Multiplying
+% such a fixed point number by $n<10000$ is much cheaper than larger
+% $n$, because we can multiply $n$ with each block safely.
+% \begin{macrocode}
+\int_const:Nn \c_@@_max_exponent_int { 10000 }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[int, EXP]{\@@_zero_fp:N, \@@_inf_fp:N}
+% In case of overflow or underflow, we have to output
+% a zero or infinity with a given sign.
+% \begin{macrocode}
+\cs_new:Npn \@@_zero_fp:N #1 { \s_@@ \@@_chk:w 0 #1 \s_@@_underflow ; }
+\cs_new:Npn \@@_inf_fp:N #1 { \s_@@ \@@_chk:w 2 #1 \s_@@_overflow ; }
+% \end{macrocode}
+% \end{macro}
+%
+%^^A todo: currently unused.
+% \begin{macro}[int, EXP]{\@@_max_fp:N, \@@_min_fp:N}
+% In some cases, we need to output the smallest or biggest positive or
+% negative finite numbers.
+% \begin{macrocode}
+\cs_new:Npn \@@_min_fp:N #1
+ {
+ \s_@@ \@@_chk:w 1 #1
+ { \int_eval:n { - \c_@@_max_exponent_int } }
+ {1000} {0000} {0000} {0000} ;
+ }
+\cs_new:Npn \@@_max_fp:N #1
+ {
+ \s_@@ \@@_chk:w 1 #1
+ { \int_use:N \c_@@_max_exponent_int }
+ {9999} {9999} {9999} {9999} ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_exponent:w}
+% For normal numbers, the function expands to the exponent, otherwise
+% to $0$.
+% \begin{macrocode}
+\cs_new:Npn \@@_exponent:w \s_@@ \@@_chk:w #1
+ {
+ \if_meaning:w 1 #1
+ \exp_after:wN \@@_use_ii_until_s:nnw
+ \else:
+ \exp_after:wN \@@_use_i_until_s:nw
+ \exp_after:wN 0
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Overflow, underflow, and exact zero}
+%
+%^^A todo: the sign of exact zeros should depend on the rounding mode.
+%
+% \begin{macro}[int, EXP]{\@@_sanitize:Nw, \@@_sanitize:wN}
+% \begin{macro}[aux, EXP]{\@@_sanitize_zero:w}
+% Expects the sign and the exponent in some order, then the
+% significand (which we don't touch). Outputs the corresponding
+% floating point number, possibly underflowed to $\pm 0$ or overflowed
+% to $\pm\infty$. The functions \cs{@@_underflow:w} and
+% \cs{@@_overflow:w} are defined in \pkg{l3fp-traps}.
+% \begin{macrocode}
+\cs_new:Npn \@@_sanitize:Nw #1 #2;
+ {
+ \if_case:w \if_int_compare:w #2 > \c_@@_max_exponent_int \c_one \else:
+ \if_int_compare:w #2 < - \c_@@_max_exponent_int \c_two \else:
+ \if_meaning:w 1 #1 \c_three \else: \c_zero \fi: \fi: \fi:
+ \or: \exp_after:wN \@@_overflow:w
+ \or: \exp_after:wN \@@_underflow:w
+ \or: \exp_after:wN \@@_sanitize_zero:w
+ \fi:
+ \s_@@ \@@_chk:w 1 #1 {#2}
+ }
+\cs_new:Npn \@@_sanitize:wN #1; #2 { \@@_sanitize:Nw #2 #1; }
+\cs_new:Npn \@@_sanitize_zero:w \s_@@ \@@_chk:w #1 #2 #3; { \c_zero_fp }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Expanding after a floating point number}
+%
+% \begin{macro}[int, EXP]{\@@_exp_after_o:w}
+% \begin{macro}[int, EXP]{\@@_exp_after_o:nw, \@@_exp_after_f:nw}
+% \begin{syntax}
+% \cs{@@_exp_after_o:nw} \Arg{tokens} \meta{floating point} \meta{more tokens}
+% \end{syntax}
+% Places \meta{tokens} (empty in the case of \cs{@@_exp_after_o:w})
+% between the \meta{floating point} and the \meta{more tokens}, then
+% hits those tokens with either \texttt{o}-expansion (one
+% \cs{exp_after:wN}) or \texttt{f}-expansion, and leaves the floating
+% point number unchanged.
+%
+% We first distinguish normal floating points, which have a mantissa,
+% from the much simpler special floating points.
+% \begin{macrocode}
+\cs_new:Npn \@@_exp_after_o:w \s_@@ \@@_chk:w #1
+ {
+ \if_meaning:w 1 #1
+ \exp_after:wN \@@_exp_after_normal:nNNw
+ \else:
+ \exp_after:wN \@@_exp_after_special:nNNw
+ \fi:
+ { }
+ #1
+ }
+\cs_new:Npn \@@_exp_after_o:nw #1 \s_@@ \@@_chk:w #2
+ {
+ \if_meaning:w 1 #2
+ \exp_after:wN \@@_exp_after_normal:nNNw
+ \else:
+ \exp_after:wN \@@_exp_after_special:nNNw
+ \fi:
+ { #1 }
+ #2
+ }
+\cs_new:Npn \@@_exp_after_f:nw #1 \s_@@ \@@_chk:w #2
+ {
+ \if_meaning:w 1 #2
+ \exp_after:wN \@@_exp_after_normal:nNNw
+ \else:
+ \exp_after:wN \@@_exp_after_special:nNNw
+ \fi:
+ { \tex_romannumeral:D -`0 #1 }
+ #2
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_exp_after_special:nNNw}
+% \begin{syntax}
+% \cs{@@_exp_after_special:nNNw} \Arg{after} \meta{case} \meta{sign} \meta{scan mark} |;|
+% \end{syntax}
+% Special floating point numbers are easy to jump over since they
+% contain few tokens.
+% \begin{macrocode}
+\cs_new:Npn \@@_exp_after_special:nNNw #1#2#3#4;
+ {
+ \exp_after:wN \s_@@
+ \exp_after:wN \@@_chk:w
+ \exp_after:wN #2
+ \exp_after:wN #3
+ \exp_after:wN #4
+ \exp_after:wN ;
+ #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_exp_after_normal:nNNw}
+% For normal floating point numbers, life is slightly harder, since we
+% have many tokens to jump over. Here it would be slightly better if
+% the digits were not braced but instead were delimited arguments (for
+% instance delimited by |,|). That may be changed some day.
+% \begin{macrocode}
+\cs_new:Npn \@@_exp_after_normal:nNNw #1 1 #2 #3 #4#5#6#7;
+ {
+ \exp_after:wN \@@_exp_after_normal:Nwwwww
+ \exp_after:wN #2
+ \__int_value:w #3 \exp_after:wN ;
+ \__int_value:w 1 #4 \exp_after:wN ;
+ \__int_value:w 1 #5 \exp_after:wN ;
+ \__int_value:w 1 #6 \exp_after:wN ;
+ \__int_value:w 1 #7 \exp_after:wN ; #1
+ }
+\cs_new:Npn \@@_exp_after_normal:Nwwwww
+ #1 #2; 1 #3 ; 1 #4 ; 1 #5 ; 1 #6 ;
+ { \s_@@ \@@_chk:w 1 #1 {#2} {#3} {#4} {#5} {#6} ; }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Packing digits}
+%
+% When a positive integer |#1| is known to be less than $10^8$, the
+% following trick will split it into two blocks of $4$ digits, padding
+% with zeros on the left.
+% \begin{verbatim}
+% \cs_new:Npn \pack:NNNNNw #1 #2#3#4#5 #6; { {#2#3#4#5} {#6} }
+% \exp_after:wN \pack:NNNNNw
+% \int_use:N \__int_eval:w 1 0000 0000 + #1 ;
+% \end{verbatim}
+% The idea is that adding $10^8$ to the number ensures that it has
+% exactly $9$ digits, and can then easily find which digits correspond
+% to what position in the number. Of course, this can be modified
+% for any number of digits less or equal to~$9$ (we are limited by
+% \TeX{}'s integers). This method is very heavily relied upon in
+% \texttt{l3fp-basics}.
+%
+% More specifically, the auxiliary inserts |+ #1#2#3#4#5 ; {#6}|, which
+% allows us to compute several blocks of $4$ digits in a nested manner,
+% performing carries on the fly. Say we want to compute $1\,2345 \times
+% 6677\,8899$. With simplified names, we would do
+% \begin{verbatim}
+% \exp_after:wN \post_processing:w
+% \int_use:N \__int_eval:w - 5 0000
+% \exp_after:wN \pack:NNNNNw
+% \int_use:N \__int_eval:w 4 9995 0000
+% + 12345 * 6677
+% \exp_after:wN \pack:NNNNNw
+% \int_use:N \__int_eval:w 5 0000 0000
+% + 12345 * 8899 ;
+% \end{verbatim}
+% The \cs{exp_after:wN} triggers |\int_use:N \__int_eval:w|, which
+% starts a first computation, whose initial value is $- 5\,0000$ (the
+% \enquote{leading shift}). In that computation appears an
+% \cs{exp_after:wN}, which triggers the nested computation
+% |\int_use:N \__int_eval:w| with starting value $4\,9995\,0000$ (the
+% \enquote{middle shift}). That, in turn, expands \cs{exp_after:wN}
+% which triggers the third computation. The third computation's value
+% is $5\,0000\,0000 + 12345 \times 8899$, which has $9$ digits. Adding
+% $5\cdot 10^{8}$ to the product allowed us to know how many digits to
+% expect as long as the numbers to multiply are not too big; it will
+% also work to some extent with negative results. The \texttt{pack}
+% function puts the last $4$ of those $9$ digits into a brace group,
+% moves the semi-colon delimiter, and inserts a |+|, which combines the
+% carry with the previous computation. The shifts nicely combine into
+% $5\,0000\,0000 / 10^{4} + 4\,9995\,0000 = 5\,0000\,0000$. As long as
+% the operands are in some range, the result of this second computation
+% will have $9$ digits. The corresponding \texttt{pack} function,
+% expanded after the result is computed, braces the last $4$ digits, and
+% leaves |+| \meta{5 digits} for the initial computation. The
+% \enquote{leading shift} cancels the combination of the other shifts,
+% and the |\post_processing:w| takes care of packing the last few
+% digits.
+%
+% Admittedly, this is quite intricate. It is probably the key in making
+% \pkg{l3fp} as fast as other pure \TeX{} floating point units despite
+% its increased precision. In fact, this is used so much that we
+% provide different sets of packing functions and shifts, depending on
+% ranges of input.
+%
+% \begin{macro}[int, EXP]{\@@_pack:NNNNNw}
+% \begin{variable}
+% {
+% \c_@@_trailing_shift_int ,
+% \c_@@_middle_shift_int ,
+% \c_@@_leading_shift_int ,
+% }
+% This set of shifts allows for computations involving results in the
+% range $[-4\cdot 10^{8}, 5\cdot 10^{8}-1]$. Shifted values all have
+% exactly $9$ digits.
+% \begin{macrocode}
+\int_const:Nn \c_@@_leading_shift_int { - 5 0000 }
+\int_const:Nn \c_@@_middle_shift_int { 5 0000 * 9999 }
+\int_const:Nn \c_@@_trailing_shift_int { 5 0000 * 10000 }
+\cs_new:Npn \@@_pack:NNNNNw #1 #2#3#4#5 #6; { + #1#2#3#4#5 ; {#6} }
+% \end{macrocode}
+% \end{variable}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_pack_big:NNNNNNw}
+% \begin{variable}
+% {
+% \c_@@_big_trailing_shift_int ,
+% \c_@@_big_middle_shift_int ,
+% \c_@@_big_leading_shift_int ,
+% }
+% This set of shifts allows for computations involving results in the
+% range $[-5\cdot 10^{8}, 6\cdot 10^{8}-1]$ (actually a bit more).
+% Shifted values all have exactly $10$ digits. Note that the upper
+% bound is due to \TeX{}'s limit of $2^{31}-1$ on integers. The
+% shifts are chosen to be roughly the mid-point of $10^{9}$ and
+% $2^{31}$, the two bounds on $10$-digit integers in \TeX{}.
+% \begin{macrocode}
+\int_const:Nn \c_@@_big_leading_shift_int { - 15 2374 }
+\int_const:Nn \c_@@_big_middle_shift_int { 15 2374 * 9999 }
+\int_const:Nn \c_@@_big_trailing_shift_int { 15 2374 * 10000 }
+\cs_new:Npn \@@_pack_big:NNNNNNw #1#2 #3#4#5#6 #7;
+ { + #1#2#3#4#5#6 ; {#7} }
+% \end{macrocode}
+% \end{variable}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_pack_twice_four:wNNNNNNNN}
+% \begin{syntax}
+% \cs{@@_pack_twice_four:wNNNNNNNN} \meta{tokens} |;| \meta{$\geq 8$ digits}
+% \end{syntax}
+% Grabs two sets of $4$ digits and places them before the semi-colon
+% delimiter. Putting several copies of this function before a
+% semicolon will pack more digits since each will take the digits
+% packed by the others in its first argument.
+% \begin{macrocode}
+\cs_new:Npn \@@_pack_twice_four:wNNNNNNNN #1; #2#3#4#5 #6#7#8#9
+ { #1 {#2#3#4#5} {#6#7#8#9} ; }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Decimate (dividing by a power of 10)}
+%
+% ^^A begin[todo]
+% \begin{macro}[int, EXP]{\@@_decimate:nNnnnn}
+% \begin{syntax}
+% \cs{@@_decimate:nNnnnn} \Arg{shift} \Arg{f_1}
+% ~~\Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4}
+% \end{syntax}
+% Each \meta{X_i} consists in $4$ digits exactly,
+% and $1000\leq\meta{X_1}<9999$. The first argument determines
+% by how much we shift the digits. \meta{f_1} is called as follows:
+% \begin{syntax}
+% \meta{f_1} \meta{rounding} \Arg{X'_1} \Arg{X'_2} \meta{extra-digits} |;|
+% \end{syntax}
+% where $0\leq\meta{X'_i}<10^{8}-1$ are $8$ digit numbers,
+% forming the truncation of our number. In other words,
+% \[
+% \left(
+% \sum_{i=1}^{4} \meta{X_i} \cdot 10^{-4i} \cdot 10^{-\meta{shift}}
+% - \meta{X'_1} \cdot 10^{-8} + \meta{X'_2} \cdot 10^{-16}
+% \right)
+% \in [0,10^{-16}).
+% \]
+% To round properly later, we need to remember some information
+% about the difference. The \meta{rounding} digit is $0$ if and
+% only if the difference is exactly $0$, and $5$ if and only if
+% the difference is exactly $0.5\cdot 10^{-16}$. Otherwise, it
+% is the (non-$0$, non-$5$) digit closest to $10^{17}$ times the
+% difference. In particular, if the shift is $17$ or more, all
+% the digits are dropped, \meta{rounding} is $1$ (not $0$), and
+% \meta{X'_1} \meta{X'_2} are both zero.
+%
+% If the shift is $1$, the \meta{rounding} digit is simply the
+% only digit that was pushed out of the brace groups (this is
+% important for subtraction). It would be more natural for the
+% \meta{rounding} digit to be placed after the \meta{X_i},
+% but the choice we make involves less reshuffling.
+%
+% Note that this function fails for negative \meta{shift}.
+% \begin{macrocode}
+\cs_new:Npn \@@_decimate:nNnnnn #1
+ {
+ \cs:w
+ @@_decimate_
+ \if_int_compare:w \__int_eval:w #1 > \c_sixteen
+ tiny
+ \else:
+ \tex_romannumeral:D \__int_eval:w #1
+ \fi:
+ :Nnnnn
+ \cs_end:
+ }
+% \end{macrocode}
+% Each of the auxiliaries see the function \meta{f_1},
+% followed by $4$ blocks of $4$ digits.
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_decimate_:Nnnnn, \@@_decimate_tiny:Nnnnn}
+% If the \meta{shift} is zero, or too big, life is very easy.
+% \begin{macrocode}
+\cs_new:Npn \@@_decimate_:Nnnnn #1 #2#3#4#5
+ { #1 0 {#2#3} {#4#5} ; }
+\cs_new:Npn \@@_decimate_tiny:Nnnnn #1 #2#3#4#5
+ { #1 1 { 0000 0000 } { 0000 0000 } 0 #2#3#4#5 ; }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]
+% {
+% \@@_decimate_i:Nnnnn, \@@_decimate_ii:Nnnnn,
+% \@@_decimate_iii:Nnnnn, \@@_decimate_iv:Nnnnn,
+% \@@_decimate_v:Nnnnn, \@@_decimate_vi:Nnnnn,
+% \@@_decimate_vii:Nnnnn, \@@_decimate_viii:Nnnnn,
+% \@@_decimate_ix:Nnnnn, \@@_decimate_x:Nnnnn,
+% \@@_decimate_xi:Nnnnn, \@@_decimate_xii:Nnnnn,
+% \@@_decimate_xiii:Nnnnn, \@@_decimate_xiv:Nnnnn,
+% \@@_decimate_xv:Nnnnn, \@@_decimate_xvi:Nnnnn
+% }
+% \begin{syntax}
+% \cs{@@_decimate_i:Nnnnn} \meta{f_1} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4}
+% \end{syntax}
+% Shifting happens in two steps: compute the \meta{rounding} digit,
+% and repack digits into two blocks of $8$. The sixteen functions
+% are very similar, and defined through \cs{@@_tmp:w}.
+% The arguments are as follows: |#1| indicates which function is
+% being defined; after one step of expansion, |#2| yields the
+% \enquote{extra digits} which are then converted by
+% \cs{@@_decimate_round:Nw} to the \meta{rounding} digit.
+% This triggers the \texttt{f}-expansion of
+% \cs{@@_decimate_pack:nnnnnnnnnnw},\footnote{No, the argument
+% spec is not a mistake: the function calls an auxiliary to
+% do half of the job.} responsible for building two blocks of
+% $8$ digits, and removing the rest. For this to work, |#3|
+% alternates between braced and unbraced blocks of $4$ digits,
+% in such a way that the $5$ first and $5$ next token groups
+% yield the correct blocks of $8$ digits.
+% \begin{macrocode}
+\cs_new:Npn \@@_tmp:w #1 #2 #3
+ {
+ \cs_new:cpn { @@_decimate_ #1 :Nnnnn } ##1 ##2##3##4##5
+ {
+ \exp_after:wN ##1
+ \__int_value:w
+ \exp_after:wN \@@_decimate_round:Nw #2 ;
+ \@@_decimate_pack:nnnnnnnnnnw #3 ;
+ }
+ }
+\@@_tmp:w {i} {\use_none:nnn #50} { 0{#2}#3{#4}#5 }
+\@@_tmp:w {ii} {\use_none:nn #5 } { 00{#2}#3{#4}#5 }
+\@@_tmp:w {iii} {\use_none:n #5 } { 000{#2}#3{#4}#5 }
+\@@_tmp:w {iv} { #5 } { {0000}#2{#3}#4 #5 }
+\@@_tmp:w {v} {\use_none:nnn #4#5 } { 0{0000}#2{#3}#4 #5 }
+\@@_tmp:w {vi} {\use_none:nn #4#5 } { 00{0000}#2{#3}#4 #5 }
+\@@_tmp:w {vii} {\use_none:n #4#5 } { 000{0000}#2{#3}#4 #5 }
+\@@_tmp:w {viii}{ #4#5 } { {0000}0000{#2}#3 #4 #5 }
+\@@_tmp:w {ix} {\use_none:nnn #3#4+#5} { 0{0000}0000{#2}#3 #4 #5 }
+\@@_tmp:w {x} {\use_none:nn #3#4+#5} { 00{0000}0000{#2}#3 #4 #5 }
+\@@_tmp:w {xi} {\use_none:n #3#4+#5} { 000{0000}0000{#2}#3 #4 #5 }
+\@@_tmp:w {xii} { #3#4+#5} { {0000}0000{0000}#2 #3 #4 #5 }
+\@@_tmp:w {xiii}{\use_none:nnn#2#3+#4#5} { 0{0000}0000{0000}#2 #3 #4 #5 }
+\@@_tmp:w {xiv} {\use_none:nn #2#3+#4#5} { 00{0000}0000{0000}#2 #3 #4 #5 }
+\@@_tmp:w {xv} {\use_none:n #2#3+#4#5} { 000{0000}0000{0000}#2 #3 #4 #5 }
+\@@_tmp:w {xvi} { #2#3+#4#5} {{0000}0000{0000}0000 #2 #3 #4 #5 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, aux]
+% {\@@_decimate_round:Nw, \@@_decimate_pack:nnnnnnnnnnw}
+% \cs{@@_decimate_round:Nw} will receive the \enquote{extra digits}
+% as its argument, and its expansion is triggered by \cs{__int_value:w}.
+% If the first digit is neither $0$ nor $5$, then it is the \meta{rounding}
+% digit. Otherwise, if the remaining digits are not all zero, we need
+% to add $1$ to that leading digit to get the rounding digit. Some caution
+% is required, though, because there may be more than $10$
+% \enquote{extra digits}, and this may overflow \TeX{}'s integers.
+% Instead of feeding the digits directly to \cs{@@_decimate_round:Nw},
+% they come split into several blocks, separated by $+$. Hence the first
+% \cs{__int_eval:w} here.
+% \begin{macrocode}
+\cs_new:Npn \@@_decimate_round:Nw #1 #2;
+ {
+ \if_int_odd:w \if_meaning:w 0 #1 \c_one \else:
+ \if_meaning:w 5 #1 \c_one \else:
+ \c_zero \fi: \fi:
+ \if_int_compare:w \__int_eval:w #2 > \c_zero
+ \__int_eval:w 1 +
+ \fi:
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% The computation of the \meta{rounding} digit leaves an unfinished
+% \cs{__int_value:w}, which expands the following functions. This
+% allows us to repack nicely the digits we keep. Those digits come
+% as an alternation of unbraced and braced blocks of $4$ digits,
+% such that the first $5$ groups of token consist in $4$ single digits,
+% and one brace group (in some order), and the next $5$ have the same
+% structure. This is followed by some digits and a semicolon.
+% \begin{macrocode}
+\cs_new:Npn \@@_decimate_pack:nnnnnnnnnnw #1#2#3#4#5
+ { \@@_decimate_pack_ii:nnnnnnw { #1#2#3#4#5 } }
+\cs_new:Npn \@@_decimate_pack_ii:nnnnnnw #1 #2#3#4#5#6
+ { {#1} {#2#3#4#5#6} }
+% \end{macrocode}
+% \end{macro}
+% ^^A end[todo]
+%
+% \subsection{Functions for use within primitive conditional branches}
+%
+% The functions described in this section are not pretty and can easily
+% be misused. When correctly used, each of them removes one \cs{fi:} as
+% part of its parameter text, and puts one back as part of its
+% replacement text.
+%
+% Many computation functions in \pkg{l3fp} must perform tests on the
+% type of floating points that they receive. This is often done in an
+% \cs{if_case:w} statement or another conditional statement, and only a
+% few cases lead to actual computations: most of the special cases are
+% treated using a few standard functions which we define now. A typical
+% use context for those functions would be
+% \begin{syntax}
+% |\if_case:w| \meta{integer} |\exp_stop_f:|
+% | \@@_case_return_o:Nw| \meta{fp var}
+% |\or: \@@_case_use:nw| \Arg{some computation}
+% |\or: \@@_case_return_same_o:w|
+% |\or: \@@_case_return:nw| \Arg{something}
+% |\fi:|
+% \meta{junk}
+% \meta{floating point}
+% \end{syntax}
+% In this example, the case $0$ will return the floating point
+% \meta{fp~var}, expanding once after that floating point. Case $1$
+% will do \meta{some computation} using the \meta{floating point}
+% (presumably compute the operation requested by the user in that
+% non-trivial case). Case $2$ will return the \meta{floating point}
+% without modifying it, removing the \meta{junk} and expanding once
+% after. Case $3$ will close the conditional, remove the \meta{junk}
+% and the \meta{floating point}, and expand \meta{something} next. In
+% other cases, the \enquote{\meta{junk}} is expanded, performing some
+% other operation on the \meta{floating point}. We provide similar
+% functions with two trailing \meta{floating points}.
+%
+% \begin{macro}[int, EXP]{\@@_case_use:nw}
+% This function ends a \TeX{} conditional, removes junk until the next
+% floating point, and places its first argument before that floating
+% point, to perform some operation on the floating point.
+% \begin{macrocode}
+\cs_new:Npn \@@_case_use:nw #1#2 \fi: #3 \s_@@ { \fi: #1 \s_@@ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_case_return:nw}
+% This function ends a \TeX{} conditional, removes junk and a floating
+% point, and places its first argument in the input stream. A quirk
+% is that we don't define this function requiring a floating point to
+% follow, simply anything ending in a semicolon. This, in turn, means
+% that the \meta{junk} may not contain semicolons.
+% \begin{macrocode}
+\cs_new:Npn \@@_case_return:nw #1#2 \fi: #3 ; { \fi: #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_case_return_o:Nw}
+% This function ends a \TeX{} conditional, removes junk and a floating
+% point, and returns its first argument, a \meta{fp~var}, expanding
+% once after it.
+% \begin{macrocode}
+\cs_new:Npn \@@_case_return_o:Nw #1#2 \fi: #3 \s_@@ #4 ;
+ { \fi: \exp_after:wN #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_case_return_same_o:w}
+% This function ends a \TeX{} conditional, removes junk, and returns
+% the following floating point, expanding once after it.
+% \begin{macrocode}
+\cs_new:Npn \@@_case_return_same_o:w #1 \fi: #2 \s_@@
+ { \fi: \@@_exp_after_o:w \s_@@ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_case_return_o:Nww}
+% Same as \cs{@@_case_return_o:Nw} but with two trailing floating
+% points.
+% \begin{macrocode}
+\cs_new:Npn \@@_case_return_o:Nww #1#2 \fi: #3 \s_@@ #4 ; #5 ;
+ { \fi: \exp_after:wN #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_case_return_ii_o:ww}
+% Similar to \cs{@@_case_return_same_o:w}, but this returns the second
+% of two trailing floating point numbers, expanding once after it.
+% \begin{macrocode}
+\cs_new:Npn \@@_case_return_ii_o:ww #1 \fi: #2 \s_@@ #3 ;
+ { \fi: \@@_exp_after_o:w }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Small integer floating points}
+%
+% \begin{macro}[int, EXP]{\@@_small_int:wTF}
+% \begin{macro}[aux, EXP]
+% {
+% \@@_small_int_true:wTF,
+% \@@_small_int_normal:NnwTF,
+% \@@_small_int_test:NnnwNTF
+% }
+% This function tests if its floating point argument is an integer in
+% the range $[-99999999,99999999]$. If it is, the result of the
+% conversion is fed as a braced argument to the \meta{true code}.
+% Otherwise, the \meta{false code} is performed. First filter special
+% cases: neither \texttt{nan} nor infinities are integers. Normal
+% numbers with a non-positive exponent are never integers. When the
+% exponent is greater than $8$, the number is too large for the range.
+% Otherwise, decimate, and test the digits after the decimal
+% separator. The \cs{use_iii:nnn} remove a trailing |;| and the true
+% branch, leaving only the false branch. The \cs{__int_value:w}
+% appearing in the case where the normal floating point is an integer
+% takes care of expanding all the conditionals until the trailing |;|.
+% That integer is fed to \cs{@@_small_int_true:wTF} which places it as
+% a braced argument of the true branch.
+% \begin{macrocode}
+\cs_new:Npn \@@_small_int:wTF \s_@@ \@@_chk:w #1
+ {
+ \if_case:w #1 \exp_stop_f:
+ \@@_case_return:nw { \@@_small_int_true:wTF 0 ; }
+ \or: \exp_after:wN \@@_small_int_normal:NnwTF
+ \else: \@@_case_return:nw \use_ii:nn
+ \fi:
+ }
+\cs_new:Npn \@@_small_int_true:wTF #1; #2#3 { #2 {#1} }
+\cs_new:Npn \@@_small_int_normal:NnwTF #1#2#3;
+ {
+ \if_int_compare:w #2 > \c_zero
+ \if_int_compare:w #2 > \c_eight
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \use_iii:nnn
+ \else:
+ \@@_decimate:nNnnnn { \c_sixteen - #2 }
+ \@@_small_int_test:NnnwNTF
+ #3 #1
+ \fi:
+ \else:
+ \exp_after:wN \use_iii:nnn
+ \fi:
+ ;
+ }
+\cs_new:Npn \@@_small_int_test:NnnwNTF #1#2#3#4; #5
+ {
+ \if_meaning:w 0 #1
+ \exp_after:wN \@@_small_int_true:wTF
+ \__int_value:w \if_meaning:w 2 #5 - \fi: #3
+ \else:
+ \exp_after:wN \use_iii:nnn
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Length of a floating point array}
+%
+% \begin{macro}[int, EXP]{\@@_array_count:w}
+% \begin{macro}[aux, EXP]{\@@_array_count_loop:Nw}
+% Count the number of items in an array of floating points. The
+% technique is very similar to \cs{tl_count:n}, but with the loop
+% built-in. Checking for the end of the loop is done with the
+% |\use_none:n #1| construction.
+% \begin{macrocode}
+\cs_new:Npn \@@_array_count:w #1 @
+ {
+ \int_use:N \__int_eval:w \c_zero
+ \@@_array_count_loop:Nw #1 { ? \__prg_break: } ;
+ \__prg_break_point:
+ \__int_eval_end:
+ }
+\cs_new:Npn \@@_array_count_loop:Nw #1#2;
+ { \use_none:n #1 + \c_one \@@_array_count_loop:Nw }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Messages}
+%
+% Using a floating point directly is an error.
+% \begin{macrocode}
+\__msg_kernel_new:nnnn { kernel } { misused-fp }
+ { A~floating~point~with~value~'#1'~was~misused. }
+ {
+ To~obtain~the~value~of~a~floating~point~variable,~use~
+ '\token_to_str:N \fp_to_decimal:N',~
+ '\token_to_str:N \fp_to_scientific:N',~or~other~
+ conversion~functions.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
new file mode 100644
index 00000000000..0b06d377232
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-basics.dtx
@@ -0,0 +1,1634 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-basics.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-basics.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Floating-point arithmetic}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-basics} package\thanks{This file
+% has version number \ExplFileVersion, last
+% revised \ExplFileDate.}\\
+% Floating point arithmetic}
+% \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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-basics} Implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% All operations implemented in this module yield the outcome of
+% rounding the infinitely precise result of the operation to the
+% nearest representable number.
+%
+% ^^A begin[todo]: move
+% \section{Internal storage of floating points numbers}
+%
+% A floating point number \meta{X} is stored as
+% \begin{quote}
+% \cs{s_@@} \cs{@@_chk:w} \meta{case} \meta{sign} \meta{body} |;|
+% \end{quote}
+% Here, \meta{case} is 0 for $\pm 0$, 1 for normal numbers, 2 for $\pm
+% \infty$, and 3 for \texttt{nan}, and \meta{sign} is $0$ for positive
+% numbers, $1$ for \texttt{nan}s, and $2$ for negative numbers. The
+% \meta{body} of normal numbers is \Arg{exponent} \Arg{X_1} \Arg{X_2}
+% \Arg{X_3} \Arg{X_4}, with
+% \[
+% \meta{X} = (-1)^{\meta{sign}} 10^{-\meta{exponent}} \sum_i
+% \meta{X_i} 10^{-4i}.
+% \]
+% Calculations are done in base $10000$, \emph{i.e.} one myriad. The
+% \meta{exponent} lies between $\pm\cs{c_@@_max_exponent_int} = \pm
+% \the\csname\detokenize{c__fp_max_exponent_int}\endcsname$ inclusive.
+%
+% Additionally, positive and negative floating point numbers may only be
+% stored with $1000\leq\meta{X_1}<10000$. This requirement is necessary
+% in order to preserve accuracy and speed.
+%
+% ^^A end[todo]
+%
+% ^^A begin[todo]
+%
+% Some algorithms used below end up being quite similar to some
+% described in \enquote{What Every Computer Scientist Should Know About
+% Floating Point Arithmetic}, by David Goldberg, which can be found at
+% \texttt{http://cr.yp.to/2005-590/goldberg.pdf}. I need to compare them
+% very carefully.
+%
+% ^^A end[todo]
+%
+%^^A todo sanitize, pack.
+%
+% \subsection{Common to several operations}
+%
+% \begin{macro}[EXP]
+% {
+% \@@_basics_pack_low:NNNNNw ,
+% \@@_basics_pack_high:NNNNNw ,
+% \@@_basics_pack_high_carry:w
+% }
+% Addition and multiplication of mantissas are done in two steps:
+% first compute a (more or less) exact result,
+% then round and pack digits in the final (braced) form.
+% These functions take care of the packing, with special attention
+% given to the case where rounding has caused a carry.
+% In \cs{@@_basics_pack_high_carry:w}, |#1| should
+% always be $0000$.
+% \begin{macrocode}
+\cs_new:Npn \@@_basics_pack_low:NNNNNw #1 #2#3#4#5 #6;
+ {
+ \if_meaning:w 2 #1
+ + \c_one
+ \fi:
+ ; {#2#3#4#5} {#6} ;
+ }
+\cs_new:Npn \@@_basics_pack_high:NNNNNw #1 #2#3#4#5 #6;
+ {
+ \if_meaning:w 2 #1
+ \@@_basics_pack_high_carry:w
+ \fi:
+ ; {#2#3#4#5} {#6}
+ }
+\cs_new:Npn \@@_basics_pack_high_carry:w \fi: ; #1
+ { \fi: + \c_one ; {1000} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \@@_basics_return_nan_nan:NNww ,
+% \@@_basics_return_zero:NNww ,
+% \@@_basics_return_inf:NNww ,
+% \@@_basics_return_i:NNNNww ,
+% \@@_basics_return_ii:NNNNww ,
+% \@@_basics_return_nan:NNNNww
+% }
+% \begin{syntax}
+% \cs{@@_basics_return_...:NNww}
+% ~~\meta{sign_1} \meta{sign_2} \meta{body_1} |;| \meta{body_2} |;|
+% \end{syntax}
+% Used for binary operations, to return a value for some special
+% cases (common to several operations). All functions expand once
+% after their arguments.
+%
+% ^^A todo: redoc, changed.
+% The \texttt{nan_nan} function combines the \texttt{info} fields
+% of the two \texttt{nan}.\footnote{Bruno: check that messages are
+% kept.}
+% The \texttt{zero} and \texttt{inf} functions return $\pm 0$ or
+% $\pm\infty$ with a sign equal to the product of the two signs:
+% three \cs{exp_after:wN} are needed to escape out of the
+% conditional, and expand once after.
+% The \texttt{i} and \texttt{ii} functions return one of their
+% operands and expand after using \cs{@@_exp_after_o:w}.
+% In some cases, this could be optimized, since we know in advance
+% what case of number we have. However, it seems better to keep the
+% number of control sequences low: these functions are called only
+% in special cases anyways, so performance is not an issue.
+% \begin{macrocode}
+\cs_new:Npn \@@_basics_return_nan_nan:NNww #1#2 #3; #4;
+ { \@@_exp_after_o:w \s_@@ \@@_chk:w 3 1 #3 ; }
+\cs_new:Npn \@@_basics_return_zero:NNww #1#2 #3; #4;
+ {
+ \if_meaning:w #1 #2
+ \exp_after:wN \exp_after:wN \exp_after:wN \c_zero_fp
+ \else:
+ \exp_after:wN \exp_after:wN \exp_after:wN \c_minus_zero_fp
+ \fi:
+ }
+\cs_new:Npn \@@_basics_return_inf:NNww #1#2 #3; #4;
+ {
+ \if_meaning:w #1 #2
+ \exp_after:wN \exp_after:wN \exp_after:wN \c_inf_fp
+ \else:
+ \exp_after:wN \exp_after:wN \exp_after:wN \c_minus_inf_fp
+ \fi:
+ }
+\cs_new:Npn \@@_basics_return_i:NNNNww #1#2 #3#4 #5; #6;
+ { \@@_exp_after_o:w \s_@@ \@@_chk:w #1 #3 #5; }
+\cs_new:Npn \@@_basics_return_ii:NNNNww #1#2 #3#4 #5; #6;
+ { \@@_exp_after_o:w \s_@@ \@@_chk:w #2 #4 #6; }
+\cs_new:Npn \@@_basics_return_nan:NNww #1#2
+ {
+ \if_meaning:w 1 #1
+ \exp_after:wN \@@_basics_return_i:NNNNww
+ \else:
+ \exp_after:wN \@@_basics_return_ii:NNNNww
+ \fi:
+ 3 3 #1 #2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Addition and subtraction}
+%
+% \begin{macro}[int, EXP]{\@@_+_o:ww}
+% For addition, everything is easy. No need to grab the
+% \meta{body_2}.
+% \begin{macrocode}
+\cs_new:cpn { @@_+_o:ww }
+ \s_@@ \@@_chk:w #1 #2 #3 ; \s_@@ \@@_chk:w #4 #5
+ { \@@_add_cases:NN #1 #4 #2 #5 #3 ; }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_-_o:ww}
+% Change the sign of the second argument.
+% \begin{macrocode}
+\cs_new:cpn { @@_-_o:ww }
+ \s_@@ \@@_chk:w #1 #2 #3 ; \s_@@ \@@_chk:w #4 #5
+ {
+ \exp_after:wN \@@_add_cases:NN
+ \exp_after:wN #1
+ \exp_after:wN #4
+ \exp_after:wN #2
+ \int_use:N \__int_eval:w \c_two - #5 \__int_eval_end:
+ #3 ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Sign, exponent, and special numbers}
+%
+% \begin{macro}[EXP,aux]{\@@_add_cases:NN}
+% \begin{syntax}
+% \cs{@@_add_cases:NN} \meta{case_1} \meta{case_2}
+% ~~\meta{sign_1} \meta{sign_2} \meta{body_1} |;| \meta{body_2} |;|
+% \end{syntax}
+% This performs the addition. it also expands the following tokens
+% on the input stream once.
+%
+% Whenever \meta{case_1} is different from \meta{case_2}, the result
+% is simply the floating point number with the highest \meta{case}.
+% For instance, adding a normal number to a zero gives the normal
+% number, and adding a \texttt{nan} to any non-\texttt{nan} gives
+% that \texttt{nan}. Optimizing for addition of normal numbers,
+% we test for equality and then separate the \enquote{greater than}
+% and \enquote{less than} branches.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_cases:NN #1 #2
+ {
+ \if_int_compare:w #1 = #2 \exp_stop_f:
+ \exp_after:wN \@@_add_cases_eq:N
+ \else:
+ \if_int_compare:w #1 < #2 \exp_stop_f:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_basics_return_ii:NNNNww
+ \else:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_basics_return_i:NNNNww
+ \fi:
+ \exp_after:wN #1
+ \fi:
+ #2
+ }
+% \end{macrocode}
+% If the first \meta{case} is larger, then the first number remains
+% untouched, while the second number is ignored. On the other hand,
+% if the second \meta{case} is larger, the opposite happens: we retain
+% the second number. In both cases, there needs to be one step of
+% expansion after.
+% \begin{macrocode}
+% \end{macrocode}
+% We are then ready for the equality case: we split according
+% to the \meta{case}.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_cases_eq:N #1
+ {
+ \if_case:w #1 \exp_stop_f:
+ \exp_after:wN \@@_add_zeros:NNww
+ \or: \exp_after:wN \@@_add_normal:NNww
+ \or: \exp_after:wN \@@_add_inf:NNww
+ \or: \exp_after:wN \@@_basics_return_nan_nan:NNww
+ \fi:
+ }
+% \end{macrocode}
+% Adding two zeros yields \cs{c_zero_fp}, except if both
+% zeros were $-0$.\footnote{Bruno: this should depend on the
+% rounding mode.}
+% \begin{macrocode}
+\cs_new:Npn \@@_add_zeros:NNww #1#2 #3;
+ {
+ \if_int_compare:w #1 #2 = 02 \exp_stop_f:
+ \@@_case_return_o:Nw \c_zero_fp
+ \else:
+ \@@_case_return_same_o:w
+ \fi:
+ \s_@@ \@@_chk:w 0 #2
+ }
+% \end{macrocode}
+% If both infinities have the same sign, just return that infinity,
+% otherwise, it is an invalid operation.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_inf:NNww #1#2 #3;
+ {
+ \if_meaning:w #1 #2
+ \@@_case_return_same_o:w
+ \else:
+ \@@_case_use:nw
+ {
+ \@@_invalid_operation:Nnww \c_nan_fp { + }
+ \s_@@ \@@_chk:w 2 #1 #3 ;
+ }
+ \fi:
+ \s_@@ \@@_chk:w 2 #2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_normal:NNww}
+% \begin{syntax}
+% \cs{@@_add_normal:NNww} \meta{sign_1} \meta{sign_2}
+% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;|
+% \end{syntax}
+% We now have two normal numbers to add, and we have to check signs
+% and exponents more carefully before performing the addition.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_normal:NNww #1#2
+ {
+ \if_meaning:w #1#2
+ \exp_after:wN \@@_add_npos:Nnwnw
+ \else:
+ \exp_after:wN \@@_sub_npos:Nnwnw
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Absolute addition}
+%
+% In this subsection, we perform the addition
+% of two positive normal numbers.
+%
+% \begin{macro}[EXP]{\@@_add_npos:Nnwnw}
+% \begin{syntax}
+% \cs{@@_add_npos:Nnwnw} \meta{sign}
+% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;|
+% \end{syntax}
+% Since we are doing an addition, \meta{sign} will be the final sign.
+% The only special case which may arise is the case of an overflow.
+% This will be checked by \cs{@@_sanitize:Nw} at the end of
+% the calculation. We start an \cs{__int_eval:w}, responsible for
+% computing the exponent, which may receive a contribution of |+1|
+% in case of carry. The exponent should be stopped by |;| followed by
+% the overall \meta{sign} for the sanitizing to work properly.
+%
+% Grab and compare the exponents. The smaller number is decimated until
+% its exponent reaches that of the bigger number. We need to bring the
+% final sign down in the midst of the calculation to do the rounding
+% correctly.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_npos:Nnwnw #1 #2#3; #4
+ {
+ \exp_after:wN \@@_sanitize:Nw
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w
+ \if_int_compare:w #2 > #4 \exp_stop_f:
+ #2
+ \exp_after:wN \@@_add_big_i:wNww \__int_value:w -
+ \else:
+ #4
+ \exp_after:wN \@@_add_big_ii:wNww \__int_value:w
+ \fi:
+ \__int_eval:w #4 - #2 ; #1 #3;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_big_i:wNww,
+% \@@_add_big_ii:wNww}
+% \begin{syntax}
+% \cs{@@_add_big_i:wNww} \meta{shift} |;| \meta{sign}
+% ~~\meta{body_1} |;| \meta{body_2} |;|
+% \end{syntax}
+% Shift the mantissa of the small number, and then add with
+% \cs{@@_add_mantissa:NnnwnnnnN}.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_big_i:wNww #1; #2 #3; #4;
+ {
+ \@@_decimate:nNnnnn {#1}
+ \@@_add_mantissa:NnnwnnnnN
+ #4
+ #3
+ #2
+ }
+\cs_new:Npn \@@_add_big_ii:wNww #1; #2 #3; #4;
+ {
+ \@@_decimate:nNnnnn {#1}
+ \@@_add_mantissa:NnnwnnnnN
+ #3
+ #4
+ #2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_add_mantissa:NnnwnnnnN}
+% \begin{syntax}
+% \cs{@@_add_mantissa:NnnwnnnnN}
+% ~~\meta{rounding}
+% ~~\Arg{Y'_1} \Arg{Y'_2} \meta{extra-digits} |;|
+% ~~\Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4}
+% ~~\meta{final sign}
+% \end{syntax}
+% To round properly, we must know at which digit the rounding
+% should occur. This requires to know whether the addition
+% produces an overall carry or not. Thus, we do the computation
+% now and check for a carry, then go back and do the rounding.
+% The rounding may cause a carry in very rare cases such as
+% $0.99\cdots 95 \to 1.00\cdots 0$, but this situation always
+% give an exact power of $10$, for which it is easy to correct
+% the result at the end.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_mantissa:NnnwnnnnN #1 #2#3 #4; #5#6#7#8
+ {
+ \exp_after:wN \@@_add_mantissa_test:N
+ \int_use:N \__int_eval:w 1#5#6 + #2
+ \exp_after:wN \@@_add_mantissa_pack:NNNNNNN
+ \int_use:N \__int_eval:w 1#7#8 + #3 ; #1
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_add_mantissa_pack:NNNNNNN #1 #2#3#4#5#6#7
+ {
+ \if:w 2 #1
+ + \c_one
+ \fi:
+ ; #2 #3 #4 #5 #6 #7 ;
+ }
+\cs_new:Npn \@@_add_mantissa_test:N #1
+ {
+ \if:w 2 #1
+ \exp_after:wN \@@_add_mantissa_carry:wwNNNN
+ \else:
+ \exp_after:wN \@@_add_mantissa_no_carry:wwNNNN
+ \fi:
+ }
+% \end{macrocode}
+%
+% \begin{quote}
+% \cs{@@_add_mantissa_no_carry:wwNNNN}
+% ~~\meta{8d} |;| \meta{6d} |;| \meta{2d} |;|
+% ~~\meta{rounding} \meta{sign}
+% \end{quote}
+% If there's no carry, grab all the digits again, and just
+% set the rounding correctly.\footnote{Bruno: an optimization
+% would be to compute whether we need rounding or not,
+% and only grab digits if there is rounding.}
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_add_mantissa_no_carry:wwNNNN
+ #1; #2; #3#4 ; #5#6
+ {
+ \exp_after:wN \@@_basics_pack_high:NNNNNw
+ \int_use:N \__int_eval:w 1 #1
+ \exp_after:wN \@@_basics_pack_low:NNNNNw
+ \int_use:N \__int_eval:w 1 #2 #3#4
+ + \@@_round:NNN #6 #4 #5
+ \exp_after:wN ;
+ }
+% \end{macrocode}
+%
+% The case where there is a carry is very similar: rounding can even
+% raise the first digit from $1$ to $2$ (but we don't need to check that).
+% \begin{quote}
+% \cs{@@_add_mantissa_carry:wwNNNN}
+% ~~\meta{8d} |;| \meta{6d} |;| \meta{2d} |;|
+% ~~\meta{rounding} \meta{sign}
+% \end{quote}
+% \begin{macrocode}
+\cs_new:Npn \@@_add_mantissa_carry:wwNNNN
+ #1; #2; #3#4; #5#6
+ {
+ + \c_one
+ \exp_after:wN \@@_add_mantissa_carry_pack:NNNNNNNNw
+ \int_use:N \__int_eval:w 1 #1
+ \exp_after:wN \@@_add_mantissa_carry_pack_ii:NNNNw
+ \int_use:N \__int_eval:w 1 #2#3
+ + \@@_round:NNNN #6 #3 #4 #5
+ \exp_after:wN ;
+ }
+\cs_new:Npn \@@_add_mantissa_carry_pack_ii:NNNNw #1 #2#3#4 #5;
+ {
+ \if:w 2 #1
+ + \c_one
+ \fi:
+ \__int_eval_end:
+ #2#3#4; {#5} ;
+ }
+\cs_new:Npn \@@_add_mantissa_carry_pack:NNNNNNNNw
+ #1#2#3#4 #5#6#7#8 #9; { ; {#1#2#3#4} {#5#6#7#8} {#9} }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Absolute subtraction}
+%
+% \begin{macro}[EXP]{\@@_sub_npos:Nnwnw}
+% \begin{syntax}
+% \cs{@@_sub_npos:Nnwnw} \meta{sign}
+% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;|
+% \end{syntax}
+% Rounding properly in some modes requires to know what the sign
+% of the result will be. For addition, this was easy. Here, besides
+% comparing the exponents to know how to decimate, we need to
+% check carefully which number is bigger when they have the same
+% exponent.
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_npos:Nnwnw #1 #2#3; #4 #5;
+ {
+ \exp_after:wN \@@_sanitize:wN
+ \int_use:N \__int_eval:w
+ \if_int_compare:w #2 > #4 \exp_stop_f:
+ #2
+ \exp_after:wN \@@_sub_big_i:wNww \__int_value:w -
+ \else:
+ #4
+ \if_int_compare:w #2 = #4 \exp_stop_f:
+ \@@_sub_exponent_eq:nnnnnnnn #3 #5
+ \else:
+ \exp_after:wN \@@_sub_big_ii:wNww \__int_value:w
+ \fi:
+ \fi:
+ \__int_eval:w #4 - #2 ; #1 #3; #5;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_sub_exponent_eq:nnnnnnnn}
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_exponent_eq:nnnnnnnn #1#2#3#4 #5#6#7#8
+ {
+ \if_int_compare:w #1#2 > #5#6 \exp_stop_f:
+ \exp_after:wN \@@_sub_big_i:wNww \__int_value:w
+ \else:
+ \if_int_compare:w #1#2 < #5#6 \exp_stop_f:
+ \exp_after:wN \@@_sub_big_ii:wNww \__int_value:w
+ \else:
+ \if_int_compare:w #3#4 > #7#8 \exp_stop_f:
+ \exp_after:wN \@@_sub_big_i:wNww \__int_value:w
+ \else:
+ \if_int_compare:w #3#4 < #7#8 \exp_stop_f:
+ \exp_after:wN \@@_sub_big_ii:wNww \__int_value:w
+ \else:
+ \exp_after:wN \@@_sub_eq:wNww \__int_value:w
+ \fi:
+ \fi:
+ \fi:
+ \fi:
+ }
+\cs_new:Npn \@@_sub_eq:wNww #1; #2 #3; #4;
+ { \exp_after:wN ; \exp_after:wN 1 \exp_after:wN ; }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_sub_big_i:wNww,\@@_sub_big_ii:wNww}
+% \begin{syntax}
+% \cs{@@_sub_big_i:wNww} \meta{shift} |;| \meta{sign}
+% ~~\meta{body_1} |;| \meta{body_2} |;|
+% \end{syntax}
+% Shift the mantissa of the small number, and then subtract with
+% \cs{@@_sub_back_mantissa:NnnwNnnnn}.
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_big_i:wNww #1; #2 #3; #4;
+ {
+ \@@_decimate:nNnnnn {#1}
+ \@@_sub_back_mantissa:NnnwNnnnn
+ #4
+ #2
+ #3
+ }
+\cs_new:Npn \@@_sub_big_ii:wNww #1; #2 #3; #4;
+ {
+ \exp_after:wN \@@_sub_big_i:wNww
+ \__int_value:w #1 \exp_after:wN ;
+ \int_use:N \__int_eval:w 2 - #2 \__int_eval_end:
+ #4; #3;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_sub_back_mantissa:NnnwNnnnn}
+% \begin{syntax}
+% \cs{@@_sub_back_mantissa:NnnwNnnnn}
+% ~~\meta{rounding} \Arg{Y'_1} \Arg{Y'_2} \meta{extra-digits}
+% ~~\meta{final sign}
+% ~~\Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4}
+% \end{syntax}
+% At this stage, we know that \meta{Y} is less than \meta{X},
+% and we know the final sign.
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_back_mantissa:NnnwNnnnn #1 #2#3 #4; #5 #6#7#8#9
+ {
+ \exp_after:wN \@@_sub_back_mantissa_i:NNwNNNNwN
+ \exp_after:wN #1
+ \exp_after:wN #5
+ \int_use:N \__int_eval:w 2#6#7 - #2 - \c_two +
+ \exp_after:wN \@@_sub_back_mantissa_round:wNN
+ \int_use:N \__int_eval:w 2#8#9 - #3 ; #1 #5
+ }
+% \end{macrocode}
+% After the computation, we need to check whether the first digit of
+% the result is zero. This can only happen if the two numbers had the
+% same exponent, or exponents differing by $1$. In the latter case,
+% the \meta{rounding} digit is not quite enough to let us retrieve
+% the exact result (consider $\cdots25$ and $\cdots15$, both rounded
+% to $\cdots2$ in the usual mode), so we also move the result of
+% \cs{@@_round_neg:NNN} upstream as the digit $0$ or $1$.
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_back_mantissa_round:wNN #1; #2 #3
+ {
+ \exp_after:wN \@@_sub_back_mantissa_iii:N
+ \__int_value:w
+ \exp_after:wN \@@_round_neg:NNN
+ \exp_after:wN #3
+ \use_none:nnnnnnnn #1 #2
+ + #1
+ \exp_after:wN ;
+ }
+\cs_new:Npn \@@_sub_back_mantissa_iii:N #1
+ {
+ \exp_after:wN \@@_sub_back_mantissa_ii:NNNNNNw
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w
+ - #1
+ }
+\cs_new:Npn \@@_sub_back_mantissa_ii:NNNNNNw #1 #2 #3#4#5#6 #7;
+ { #2 ; #1 {#3#4#5#6} {#7} ; }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_sub_back_mantissa_i:NNwNNNNwN}
+% Here, |#3| should always be $2$, but we have to take is
+% as a normal undelimited argument since that would break
+% if |#2| is $2$.
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_back_mantissa_i:NNwNNNNwN #1#2 #3 #4#5#6#7 #8; #9
+ {
+ \if:w 0 #4
+ \exp_after:wN \@@_sub_back_carry:NNwNnnnn
+ \exp_after:wN #1
+ \exp_after:wN #9
+ \fi:
+ ; #2
+ {#4#5#6#7} {#8}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_sub_back_carry:NNwNnnnn}
+% \begin{syntax}
+% \cs{@@_sub_back_carry:NNwNnnnn}
+% ~~\meta{rounding} \meta{0 or 1} |;| \meta{final sign}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} |;|
+% \end{syntax}
+% This function is called when $\meta{Z_1}\leq 999$. We revert
+% the carry, which is given by \meta{0 or 1}, and subtract the
+% \meta{rounding} digit as appropriate, then feed the result,
+% of the form \meta{$\leq$ 7d} |;| \meta{9d} |;| to
+% \cs{@@_sub_back_carry_i:wwN}. The result is always exact.
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_back_carry:NNwNnnnn #1#2 ; #3 #4#5#6#7 ;
+ {
+ \exp_after:wN \@@_sub_back_carry_i:wwN
+ \int_use:N \__int_eval:w #4 #5 - 1 + \exp_after:wN \@@_use_s:n
+ \int_use:N \__int_eval:w 1 #6 #7 0 + #2 0 - #1 ; #3
+ }
+% \end{macrocode}
+% Unless the first block is zero, check how many digits is has,
+% and shift the exponent down by the corresponding amount. Then
+% pack digits into blocks of $4$ (there are between $10$ and $16$
+% digits in front of \cs{@@_sub_back_carry_large:NNNNNNNNw}).
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_back_carry_i:wwN #1 ;
+ {
+ \if:w 0 #1
+ - 8
+ \exp_after:wN \@@_sub_back_carry_small:wN \__int_value:w
+ \else:
+ - \@@_sub_back_carry_ii:NNNNNNNNw #1 1234567;
+ \exp_after:wN \@@_sub_back_carry_large:NNNNNNNNw
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% The case where the number is non-zero is slightly easier.
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_back_carry_ii:NNNNNNNNw #1#2#3#4#5#6#7#8#9; {#8}
+\cs_new:Npn \@@_sub_back_carry_large:NNNNNNNNw #1#2#3#4 #5#6#7#8 #9;
+ {
+ \@@_sub_back_carry_large_ii:NNNNNNNNw
+ #9 000000 ; {#1#2#3#4} {#5#6#7#8}
+ }
+\cs_new:Npn \@@_sub_back_carry_large_ii:NNNNNNNNw #1#2#3#4 #5#6#7#8 #9;
+ { \@@_sub_back_carry_large_iii:nnnnN {#1#2#3#4} {#5#6#7#8} }
+\cs_new:Npn \@@_sub_back_carry_large_iii:nnnnN #1#2 #3#4 #5
+ { ; #5 {#3}{#4} {#1}{#2} ; }
+% \end{macrocode}
+% In the case of a \enquote{small} result, what comes after
+% \cs{@@_sub_back_carry_small:wN} has between $1$
+% and $9$ digits, and is not zero.
+% \begin{macrocode}
+\cs_new:Npn \@@_sub_back_carry_small:wN #1;
+ {
+ - \exp_after:wN \@@_use_i_until_s:nw
+ \use_none:nnnnnnnnn #1 012345678;
+ \@@_sub_back_carry_small_ii:NNNNNNNN #1 00000000 ;
+ }
+\cs_new:Npn \@@_sub_back_carry_small_ii:NNNNNNNN #1#2#3#4 #5#6#7#8
+ { \@@_sub_back_carry_small_iii:nnNwN {#1#2#3#4} {#5#6#7#8} }
+\cs_new:Npn \@@_sub_back_carry_small_iii:nnNwN #1 #2 #3 #4; #5
+ { ; #5 {#1} {#2} {#3000} {0000} ; }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Multiplication}
+%
+% \begin{macro}[int, EXP]{\@@_*_o:ww}
+% For multiplication, everything is easy. No need to grab the
+% \meta{body_2}.
+% \begin{macrocode}
+\cs_new:cpn { @@_*_o:ww }
+ \s_@@ \@@_chk:w #1 #2 #3 ; \s_@@ \@@_chk:w #4 #5
+ { \@@_mul_cases:NN #1 #4 #2 #5 #3 ; }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Signs, and special numbers}
+%
+% \begin{macro}[EXP,aux]{\@@_mul_cases:NN}
+% \begin{syntax}
+% \cs{@@_mul_cases:NN} \meta{case_1} \meta{case_2}
+% ~~\meta{sign_1} \meta{sign_2} \meta{body_1} |;| \meta{body_2} |;|
+% \end{syntax}
+% Expands the following tokens on the input stream once.
+% The special cases are coded at the start of this module,
+% and identical to the ones for division.\footnote{Bruno: \texttt{nan}
+% are not treated properly: $\infty\times 0$ should signal.}
+%^^A todo: use the faster \if_meaning:w.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_cases:NN #1 #2
+ {
+ \if_case:w \if_meaning:w 1 #1 #2 \else:
+ \if_meaning:w 1 #2 #1 \else:
+ \if_meaning:w #1#2 #1 \else:
+ \if_int_compare:w \__int_eval:w #1 + #2 > \c_two
+ 3 \else: 4 \fi: \fi: \fi: \fi:
+ \exp_stop_f:
+ \exp_after:wN \@@_basics_return_zero:NNww
+ \or: \exp_after:wN \@@_mul_normal:NNww
+ \or: \exp_after:wN \@@_basics_return_inf:NNww
+ \or: \exp_after:wN \@@_basics_return_nan:NNww
+ \or:
+ \exp_after:wN \@@_mul_invalid:NNNNww
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \fi:
+ }
+\cs_new:Npn \@@_mul_invalid:NNNNww #1#2#3#4#5; #6;
+ {
+ \@@_invalid_operation:Nnww \c_nan_fp { * }
+ \s_@@ \@@_chk:w #1 #3 #5 ;
+ \s_@@ \@@_chk:w #2 #4 #6 ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_mul_normal:NNww}
+% \begin{syntax}
+% \cs{@@_mul_normal:NNww} \meta{sign_1} \meta{sign_2}
+% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;|
+% \end{syntax}
+% We now have two normal numbers to multiply. Combine the signs.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_normal:NNww #1#2
+ {
+ \if:w #1#2
+ \exp_after:wN \@@_mul_npos:Nnwnw
+ \exp_after:wN 0
+ \else:
+ \exp_after:wN \@@_mul_npos:Nnwnw
+ \exp_after:wN 2
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Absolute multiplication}
+%
+% In this subsection, we perform the multiplication
+% of two positive normal numbers.
+%
+% \begin{macro}[EXP]{\@@_mul_npos:Nnwnw}
+% \begin{syntax}
+% \cs{@@_mul_npos:Nnwnw} \meta{sign}
+% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;|
+% \end{syntax}
+% As for addition, \meta{sign} is the final sign. After the computation,
+% \cs{@@_sanitize:Nw} checks for overflow or underflow.
+% As before, \cs{__int_eval:w} computes the exponent, catching any
+% shift coming from the computation in the mantissa. Again, the
+% \meta{sign} is needed for rounding to be done properly, so we move
+% it around with us. We setup the post-expansion here, triggered by
+% \cs{@@_mul_mantissa:nnnnNnnnn}.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_npos:Nnwnw #1 #2#3; #4 #5;
+ {
+ \exp_after:wN \@@_sanitize:Nw
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w
+ #2 + #4
+ \@@_mul_mantissa:nnnnNnnnn #3 #1 #5
+ \exp_after:wN ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_mul_mantissa:nnnnNnnnn}
+% \begin{syntax}
+% \cs{@@_mul_mantissa:nnnnNnnnn}
+% ~~\Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \meta{sign}
+% ~~\Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} \meta{;}
+% \end{syntax}
+% After one expansion, the token following \meta{Y_4} must be a semicolon
+% (represented by \meta{;}).
+%
+% The product of two $16$ digit integers has $31$ or $32$ digits,
+% but it is impossible to know which one before computing. The place
+% where we round depends on that number of digits, and may depend
+% on all digits until the last in some rare cases. The approach is
+% thus to compute the $5$ first blocks of $4$ digits (the first one
+% is between $100$ and $9999$ inclusive), and a compact version of
+% the remaining $3$ blocks. Afterwards, the number of digits is
+% known, and we can do the rounding within yet another set of
+% \cs{__int_eval:w}.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_mantissa:nnnnNnnnn #1#2#3#4 #5 #6#7#8#9
+ {
+ \exp_after:wN \@@_mul_mantissa_after:NNN
+ \exp_after:wN #5
+ \int_use:N \__int_eval:w 99990000 + #1*#6 +
+ \exp_after:wN \@@_mul_mantissa_keep:NNNNNw
+ \int_use:N \__int_eval:w 99990000 + #1*#7 + #2*#6 +
+ \exp_after:wN \@@_mul_mantissa_keep:NNNNNw
+ \int_use:N \__int_eval:w 99990000 + #1*#8 + #2*#7 + #3*#6 +
+ \exp_after:wN \@@_mul_mantissa_drop:NNNNNw
+ \int_use:N \__int_eval:w 99990000 + #1*#9 + #2*#8 + #3*#7 + #4*#6 +
+ \exp_after:wN \@@_mul_mantissa_drop:NNNNNw
+ \int_use:N \__int_eval:w 99990000 + #2*#9 + #3*#8 + #4*#7 +
+ \exp_after:wN \@@_mul_mantissa_drop:NNNNNw
+ \int_use:N \__int_eval:w 99990000 + #3*#9 + #4*#8 +
+ \exp_after:wN \@@_mul_mantissa_drop:NNNNNw
+ \int_use:N \__int_eval:w 100000000 + #4*#9 \exp_after:wN ;
+ }
+\cs_new:Npn \@@_mul_mantissa_drop:NNNNNw #1#2#3#4#5 #6;
+ { #1#2#3#4#5 ; + #6 }
+\cs_new:Npn \@@_mul_mantissa_keep:NNNNNw #1#2#3#4#5 #6;
+ { #1#2#3#4#5 ; #6 ; }
+% \end{macrocode}
+% Once the first \cs{int_use:N} \cs{__int_eval:w}, and all the
+% \cs{@@_mul_mantissa_...:NNNNNw} have been expanded,
+% we get
+% \begin{quote}
+% \cs{@@_mul_mantissa_after:NNN} \meta{sign} |1|
+% ~~\meta{digits 1--8} |;| \meta{digits 9--12} |;| \meta{digits 13--16} |;|
+% ~~|+| \meta{digits 17--20} |+| \meta{digits 21--24}
+% ~~|+| \meta{digits 25--28} |+| \meta{digits 29--32} |;|
+% \end{quote}
+% If the \meta{digit 1} is non-zero, then for rounding we only care
+% about the digits $16$ and $17$, and whether all other digits are zero
+% or not (check for exact ties). On the other hand, if \meta{digit 1}
+% is zero, we care about digits $17$ and $18$, and whether all others are
+% zero.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_mantissa_after:NNN #1 #2 #3
+ {
+ \if:w 0 #3
+ \exp_after:wN \@@_mul_mantissa_small:NNwwwN
+ \else:
+ \exp_after:wN \@@_mul_mantissa_large:NwwNNNN
+ \fi:
+ #1 #3
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_mul_mantissa_large:NwwNNNN}
+% In this branch, \meta{digit 1} is non-zero. The result is thus
+% \meta{digits 1--16}, plus some rounding which depends on the digits
+% $16$, $17$, and whether all subsequent digits are zero or not.
+% Here, \cs{@@_round_s:NNNw} takes the \meta{sign}, followed by
+% digits $16$, $17$, and an integer expression which is zero if and
+% only if all further digits are zero.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_mantissa_large:NwwNNNN #1 #2; #3; #4#5#6#7; +
+ {
+ \exp_after:wN \@@_basics_pack_high:NNNNNw
+ \int_use:N \__int_eval:w 1#2
+ \exp_after:wN \@@_basics_pack_low:NNNNNw
+ \int_use:N \__int_eval:w 1#3#4#5#6#7 + \@@_round_s:NNNw #1 #7
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_mul_mantissa_small:NNwwwN}
+% In this branch, \meta{digit 1} is zero. Our result will thus be
+% \meta{digits 2--17}, plus some rounding which depends on the digits
+% $17$, $18$, and whether all subsequent digits are zero or not.
+% The $8$ digits |1#3| are followed, after expansion of the
+% \texttt{small_pack} auxiliary, by the next digit, to form a $9$
+% digit number. Also, rounding may have caused a carry, which is
+% then converted to \cs{c_ten} rather than the usual \cs{c_one},
+% because of the shift.
+% \begin{macrocode}
+\cs_new:Npn \@@_mul_mantissa_small:NNwwwN #1 #2#3; #4; #5; + #6
+ {
+ - \c_one
+ \exp_after:wN \@@_basics_pack_high:NNNNNw
+ \int_use:N \__int_eval:w 1#3
+ \exp_after:wN \@@_mul_mantissa_small_pack:NNNNNNw
+ \int_use:N \__int_eval:w 1#4#5#6 + \@@_round_s:NNNw #1 #6
+ }
+\cs_new:Npn \@@_mul_mantissa_small_pack:NNNNNNw #1#2 #3#4#5#6 #7;
+ {
+ #2
+ \if:w 2 #1
+ + \c_ten
+ \fi:
+ ; {#3#4#5#6} {#7} ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Division}
+%
+% Time is now ripe to tackle the hardest of the four elementary
+% operations: division.
+%
+% \begin{macro}[EXP]{\@@_/_o:ww}
+% For division we swap the two floating point numbers.
+% \begin{macrocode}
+\cs_new:cpn { @@_/_o:ww }
+ \s_@@ \@@_chk:w #1 #2 #3 ; \s_@@ \@@_chk:w #4 #5 #6 ;
+ { \@@_div_back_cases:NN #4 #1 #5 #2 #6 ; #3 ; }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Signs, and special numbers}
+%
+% In the case of division, the order of the operands matters,
+% and it turns out to be slightly simpler if we internally
+% compute the \enquote{backwards} division.
+%
+% \begin{macro}[EXP,aux]{\@@_div_back_cases:NN}
+% \begin{syntax}
+% \cs{@@_div_back_cases:NN} \meta{case_2} \meta{case_1}
+% ~~\meta{sign_2} \meta{sign_1} \meta{body_2} |;| \meta{body_1} |;|
+% \end{syntax}
+% Expands the following tokens on the input stream once.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_back_cases:NN #1 #2
+ {
+ \if_case:w \if_int_compare:w #1 = #2 \exp_stop_f:
+ #1 \exp_stop_f:
+ \else:
+ \if_int_compare:w #1 < #2 \exp_stop_f:
+ \if:w 3 #2 \c_four \else: \c_five \fi:
+ \else:
+ \if:w 3 #1 \c_six \else: \c_seven \fi:
+ \fi:
+ \fi:
+ \exp_after:wN \@@_div_back_invalid:NNNww \exp_after:wN 0
+ \or: \exp_after:wN \@@_div_back_normal:NNww
+ \or: \exp_after:wN \@@_div_back_invalid:NNNww \exp_after:wN 2
+ \or: \exp_after:wN \@@_basics_return_nan_nan:NNww
+ \or:
+ \exp_after:wN \@@_basics_return_ii:NNNNww
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \or: \exp_after:wN \@@_basics_return_inf:NNww
+ \or:
+ \exp_after:wN \@@_basics_return_i:NNNNww
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \or: \exp_after:wN \@@_basics_return_zero:NNww
+ \fi:
+ }
+% \end{macrocode}
+% Most of the special cases are common with some
+% previous operations. We only need to write the cases of
+% $0/0$ and $\infty/\infty$.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_back_invalid:NNNww #1#2#3 #4; #5;
+ {
+ \@@_invalid_operation:Nnww \c_nan_fp { / }
+ \s_@@ \@@_chk:w #1 #3 #5 ;
+ \s_@@ \@@_chk:w #1 #2 #4 ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_div_back_normal:NNww}
+% \begin{syntax}
+% \cs{@@_div_back_normal:NNww} \meta{sign_1} \meta{sign_2}
+% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;|
+% \end{syntax}
+% We now have two normal numbers to divide. Combine the signs.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_back_normal:NNww #1#2
+ {
+ \if:w #1#2
+ \exp_after:wN \@@_div_back_npos:Nnwnw
+ \exp_after:wN 0
+ \else:
+ \exp_after:wN \@@_div_back_npos:Nnwnw
+ \exp_after:wN 2
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Absolute (backwards) division}
+%
+% In this subsection, we perform the division
+% of two positive normal numbers.
+%
+% \begin{macro}[EXP]{\@@_div_back_npos:Nnwnw}
+% \begin{syntax}
+% \cs{@@_div_back_npos:Nnwnw} \meta{sign}
+% ~~\Arg{exp Z} \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} |;|
+% ~~\Arg{exp A} \Arg{A_1} \Arg{A_2} \Arg{A_3} \Arg{A_4} |;|
+% \end{syntax}
+% We want to compute $A/Z$. As for addition and multiplication,
+% \meta{sign} is the final sign. Checking for underflow and
+% overflow is done using the same auxiliary as for multiplication.
+% As explained just below, we first compute $y$, which is
+% the $5$ first digits of $Z$, plus $1$, and then compute pieces
+% of the quotient roughly $4$ digits at a time. Here, |#1| is
+% a single digit, |#2| and |#7| are the exponents (integers),
+% |#8| is three brace groups, and all others are each $4$ digits.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_back_npos:Nnwnw #1 #2 #3#4#5#6; #7 #8;
+ {
+ \exp_after:wN \@@_sanitize:Nw
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w
+ #7 - #2
+ \@@_div_mantissa_i:wNwnn #3; #4;
+ #8 {#3}{#4}{#5}{#6} #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% We are given two numbers, $A=0.A_{1}A_{2}A_{3}A_{4}$
+% and $Z=0.Z_{1}Z_{2}Z_{3}Z_{4}$, in blocks of $4$ digits,
+% and we know that the first digits of $A_{1}$ and of $Z_{1}$
+% are non-zero. To compute $A/Z$, we proceed as follows.
+% \begin{itemize}
+% \item Find an integer $Q_{1} \simeq 10^4 A / Z$.
+% \item Replace $A$ by $B = 10^4 A - Q_{1} Z$.
+% \item Find an integer $Q_{2} \simeq 10^4 B / Z$.
+% \item Replace $B$ by $C = 10^4 B - Q_{2} Z$.
+% \item Find an integer $Q_{3} \simeq 10^4 C / Z$.
+% \item Replace $C$ by $D = 10^4 C - Q_{3} Z$.
+% \item Find an integer $Q_{4} \simeq 10^4 D / Z$.
+% \item Consider $E = 10^4 D - Q_{4} Z$, and ensure
+% correct rounding.
+% \end{itemize}
+% The calculations of $B$, $C$, $D$, and $E$ can be done
+% exactly with only $16$ (or $17$) digits.
+%
+% Unfortunately, things are not as easy as they seem.
+% Firstly, we make sure that all intermediate steps are positive,
+% since negative results would require extra calculations at the end.
+% This requires that $Q_{1} \leq 10^4 A / Z$ etc. A reasonable
+% attempt would be to define $Q_{1}$ as
+% \[
+% \cs{int_eval:n} \left\{
+% \frac{ A_{1} A_{2} }{ Z_{1} + 1 } - 1 \right\}.
+% \]
+% Subtracting $1$ at the end takes care of the fact that e\TeX{}'s
+% \cs{__int_eval:w} rounds instead of truncating. We add $1$ to $Z_{1}$
+% because $ Z_{1} \leq 10^4 Z < Z_{1}+1$ and we need $Q_{1}$
+% to be an underestimate. However, we are now underestimating
+% $Q_{1}$ too much: it can be wrong by up to $100$, for instance
+% when $Z = 0.1$ and $A \simeq 1$. Then $B$ could take values up to
+% $10$ (maybe more), and a few steps down the line, we would run into
+% arithmetic overflow, since \TeX{} can only handle integers less than
+% roughly $2\cdot 10^9$.
+%
+% A better formula is to take
+% \[
+% Q_{1} = \cs{int_eval:n} \left\{
+% \frac{ 10 \cdot A_{1} A_{2} }
+% { \left\lfloor 10^{-3} \cdot Z_{1} Z_{2} \right\rfloor + 1 }
+% - 1 \right\}.
+% \]
+% This is always less than $10^9 A / (10^5 Z)$, as we wanted.
+% In words, we take the $5$ first digits of $Z$ into account,
+% and the $8$ first digits of $A$, using $0$ as a $9$-th digit
+% rather than the true digit for efficiency reasons. We shall
+% prove that using this formula to define all the $Q_{i}$
+% leads to no overflow. For convenience, let us denote
+% \[
+% y = \left\lfloor 10^{-3} \cdot Z_{1} Z_{2} \right\rfloor + 1,
+% \]
+% so that, taking into account the fact that e\TeX{} rounds ties
+% away from zero,
+% \[
+% Q_{1} = \left\lfloor A_{1}A_{2}0/y - 1/2 \right\rfloor.
+% \]
+% Note that $10^4<y\leq 10^5$, and $999 \leq Q_{1} \leq 99989$.
+% Also note that this formula does not cause an overflow as long as
+% $A<2.147\cdots$, since the numerator involves an integer slightly
+% smaller than $10^9A$.
+%
+% Let us bound $B$:
+% \begin{align*}
+% 10^5 B
+% &=
+% A_{1}A_{2}0 + 10 \cdot 0.A_{3}A_{4}
+% - 10 \cdot Z_{1}.Z_{2}Z_{3}Z_{4}
+% \cdot \left\lfloor A_{1}A_{2}0/y - 1/2 \right\rfloor
+% \\
+% &<
+% A_{1}A_{2}0
+% \cdot \left( 1 - 10 \frac{Z_{1}.Z_{2}Z_{3}Z_{4}}{y} \right)
+% + \frac{3}{2} \cdot 10 \cdot Z_{1}.Z_{2}Z_{3}Z_{4} + 10
+% \\
+% &\leq
+% \frac{A_{1}A_{2}0 \cdot (y - 10 Z_{1}.Z_{2}Z_{3}Z_{4})}{y}
+% + \frac{3}{2} y + 10
+% \\
+% &\leq
+% \frac{A_{1}A_{2}0}{y} + \frac{3}{2} y + 10
+% \leq
+% \frac{10^9 A}{y} + 1.6 y
+% \end{align*}
+% At the last step, we hide $10$ into the second term
+% for later convenience. The same reasoning yields\footnote{Bruno:
+% I need to find much better notations. These are not great.}
+% \begin{align*}
+% 10^5 B &< 10^9 A/y + 1.6 y, \\
+% 10^5 C &< 10^9 B/y + 1.6 y, \\
+% 10^5 D &< 10^9 C/y + 1.6 y, \\
+% 10^5 E &< 10^9 D/y + 1.6 y. \\
+% \end{align*}
+% The goal is now to prove that none of $B$, $C$, $D$, and $E$
+% can go beyond $2.147\cdots$. Simply bounding each term on the
+% right-hand side separately will not be tight enough: for instance,
+% we would get $10^5 B < 10^5 + 1.6\cdot 10^5 = 2.6 \cdot 10^5$,
+% which is too large.
+%
+% Combining the various inequalities together with $A<1$, we get
+% \begin{align*}
+% 10^5 B &< 10^9/y + 1.6 y, \\
+% 10^5 C &< 10^{13}/y^2 + 1.6 (y + 10^4), \\
+% 10^5 D &< 10^{17}/y^3 + 1.6 (y + 10^4 + 10^8/y), \\
+% 10^5 E &< 10^{21}/y^4 + 1.6 (y + 10^4 + 10^8/y + 10^{12}/y^2). \\
+% \end{align*}
+% All of those bounds are convex functions of $y$ (since every power
+% of $y$ involved is convex, and hte coefficients are positive), and
+% thus maximal at one of the end-points of the allowed range
+% $10^4<y\leq 10^5$. Thus,
+% \begin{align*}
+% 10^5 B &< \mathrm{max} ( 1.16\cdot 10^5, 1.7 \cdot 10^5), \\
+% 10^5 C &< \mathrm{max} ( 1.32\cdot 10^5, 1.77 \cdot 10^5), \\
+% 10^5 D &< \mathrm{max} ( 1.48\cdot 10^5, 1.777 \cdot 10^5), \\
+% 10^5 E &< \mathrm{max} ( 1.64\cdot 10^5, 1.7777 \cdot 10^5). \\
+% \end{align*}
+% All of those bounds are less than $2.147\cdot 10^5$, and
+% we are thus within \TeX{}'s bounds in all cases!\footnote{Bruno:
+% but I need to check this very carefully again.}
+%
+% We will later need to have a bound on the $Q_{i}$. Their
+% definitions imply that $Q_{1} < 10^9 A/y - 1/2 < 10^5 A$ and
+% similarly for the other $Q_{i}$. Thus each of them is at most
+% $177770$.
+%
+% The last step is to ensure correct rounding. We have
+% \[
+% A/Z = \sum_{i=1}^4 \left(10^{-4i} Q_{i}\right) + 10^{-16} E/Z
+% \]
+% exactly. Furthermore, we know that the result will be between
+% $0.1$ (inclusive) and $10$, so we only need to know the integer
+% part of $E/Z$, and a \enquote{rounding} digit encoding the rest
+% (see maybe addition for an explanation of why). Equivalently,
+% we need to find the integer part of $2E/Z$, and determine whether
+% it was an exact integer or not (this serves to detect ties). Since
+% \[
+% \frac{2E}{Z} = 2\frac{10^5 E}{10^5 Z}
+% \leq 2\frac{10^5 E}{10^4} < 36,
+% \]
+% this integer part is between $0$ and $35$ inclusive. We let
+% e\TeX{} round
+% \[
+% P = \cs{int_eval:n} \left\{
+% 2 \frac{E_{1}E_{2}}{Z_{1}Z_{2}} \right\},
+% \]
+% which differs from $2E/Z$ by at most
+% \[
+% \frac{1}{2}
+% + 2 \left\lvert \frac{E}{Z} - \frac{E}{10^{-8} Z_{1}Z_{2}}\right\rvert
+% + 2 \left\lvert \frac{10^8 E - E_{1}E_{2}}{Z_{1}Z_{2}}\right\rvert
+% < 1,
+% \]
+% ($1/2$ comes from e\TeX{}'s rounding) because each absolute value
+% is less than $10^{-7}$. Thus $P$ is either the correct integer part,
+% or an overestimate by $1$ (impossible if $2E/Z$ is an integer). It
+% then suffices to compare $PZ$ with $2E$ to get the integer part of
+% $2E/Z$ and the information of whether it was an exact quotient or not.
+%
+% \begin{macro}[EXP]{\@@_div_mantissa_i:wNwnn}
+% \begin{syntax}
+% \cs{@@_div_mantissa_i:wNwnn}
+% ~~\meta{Z_1} |;| \meta{Z_2} |;|
+% ~~\Arg{A_1} \Arg{A_2} \Arg{A_3} \Arg{A_4}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign}
+% \end{syntax}
+% First compute $y$ from the first $5$ digits of $Z$, and
+% unbrace \meta{A_1} and \meta{A_2}.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_i:wNwnn #1; #2 #3; #4 #5
+ {
+ \exp_after:wN \@@_div_mantissa_ii:ww
+ \int_use:N \__int_eval:w #1#2 + \c_one ;
+ #4 #5 ;
+ }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_ii:ww}
+% ~~\meta{y} |;| \meta{A_1} \meta{A_2} |;| \Arg{A_3} \Arg{A_4}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign}
+% \end{quote}
+% Compute $Q_{1}$ by evaluating $\meta{A_1}\meta{A_2}0/y - 1$.
+% The result will be output to the left, in an \cs{__int_eval:w}
+% which we start now.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_ii:ww #1; #2;
+ {
+ \exp_after:wN \@@_div_mantissa_iii:www
+ \__int_value:w #1 \exp_after:wN ;
+ \__int_value:w
+ \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn
+ \int_use:N \__int_eval:w #20/#1 + 999999 ; #2 ;
+ }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_calc:Nwwnnnnnn} \meta{$10^6+{}$Q_1} |;|
+% ~~\meta{A_1} \meta{A_2} |;| \Arg{A_3} \Arg{A_4}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign}
+% \end{quote}
+% The goal here is to expand to
+% \begin{quote}
+% \meta{$10^6+{}$Q_1} |;| \meta{B_1} \meta{B_2} |;| \Arg{B_3} \Arg{B_4}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign}
+% \end{quote}
+% where $B = 10^4 A - Q_{1} \cdot Z$. More generally, this function
+% is used with $A\to B$, $B\to C$ and $Q_{1} \to Q_{2}$, etc.
+%
+% Computing the product $Q_{1} \cdot Z$ is almost simple, since
+% $Q_{1}$ is rather small, but not quite:
+% the product of $Q_{1}$ with each block of four digits $Z_{i}$
+% is within \TeX{}'s bounds, but we wouldn't be able to use the
+% usual trick of adding a large power of $10$ to ensure that the
+% number of digits is fixed (see other operations for many examples
+% of this). Instead, we split off the digit of $10^5$ in $Q_{1}$
+% (and more generally $Q_{i}$), and do something similar to the
+% case of the full multiplication.
+%
+% We know that $0<Q_{i}<1.8\cdot 10^5$, so $10^6+Q_{i}$ starts
+% with the digit $1$, followed by $\#1 = 1$ or $0$, then |#2|, which
+% is $5$ more digits. It would be somewhat simpler if we got |#1|
+% to be two digits, and |#2| four, but we are constrained by the $9$
+% arguments limit.
+%
+% The result we want is then (the overall power of $10$ is arbitrary):
+% \begin{align*}
+% &10^{-4} ( \#3 - \#2 \cdot \#6 - 10 \cdot \#1 \cdot \#6\#7 )
+% + 10^{-8} ( \#4 - \#2 \cdot \#7 - 10 \cdot \#1 \cdot \#8 ) \\
+% &+ 10^{-12}( \#5 - \#2 \cdot \#8 - 10 \cdot \#1 \cdot \#9 )
+% + 10^{-16}( - \#2 \cdot \#9 ).
+% \end{align*}
+% The factors of $10$ come from the fact that
+% $Q_{i} = 10\cdot 10^4 \cdot \#1 + \#2$. As usual, to combine
+% all the terms, we need to choose some shifts which must ensure
+% that the number of digits of the second, third, and fourth terms
+% are each fixed. Here, a good choice is $2\cdot 10^9$.
+% We are flirting with \TeX{}'s limits once more.
+%
+% If $\#1=0$, then each term in parentheses (omitting the first)
+% is in the open interval $(-10^9, 10^4)$. Thus, adding
+% $2\cdot 10^9$ to it gives a $10$ digits number.\footnote{Bruno:
+% check that the carry from below does not screw that up. This
+% requires slightly tighter bounds.}
+%
+% If $\#1=1$, then $\#2 < 7.8 \cdot 10^4$, and each term
+% in parentheses (omitting the first) is in the interval
+% $(-8\cdot 10^8, 10^4)$, and we are even safer.
+%
+% We add the terms containing $\#1$ in a slightly tricky way
+% for efficiency reasons: if $\#1=0$, no need to do any computation,
+% while if $\#1=1$ we want $10$ times some number, simply obtained
+% by appending a $0$ digit.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_calc:Nwwnnnnnn 1#1#2; #3;#4#5 #6#7#8#9
+ {
+ 1 #1 #2 \exp_after:wN ;
+ \int_use:N \__int_eval:w
+ - 200000 + #3 - #2 * #6
+ \if_meaning:w 1 #1
+ - #6#70
+ \fi:
+ +
+ \exp_after:wN \@@_div_mantissa_calc_last:NNNNNN
+ \int_use:N \__int_eval:w
+ 1999800000 + #4 - #2*#7
+ \if_meaning:w 1 #1
+ - #80
+ \fi:
+ +
+ \exp_after:wN \@@_div_mantissa_calc_pack:NNNNNNw
+ \int_use:N \__int_eval:w
+ 1999800000 + #5 - #2*#8
+ \if_meaning:w 1 #1
+ - #90
+ \fi:
+ +
+ \exp_after:wN \@@_div_mantissa_calc_pack:NNNNNNw
+ \int_use:N \__int_eval:w 2000000000 - #2*#9 ;
+ {#6}{#7}{#8}{#9}
+ }
+\cs_new:Npn \@@_div_mantissa_calc_pack:NNNNNNw #1#2#3#4#5#6 #7;
+ { #1#2#3#4#5#6 ; {#7} }
+\cs_new:Npn \@@_div_mantissa_calc_last:NNNNNN #1#2#3#4#5#6
+ { #1#2#3#4#5#6 \__int_eval_end: }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_iii:www} \meta{y} |;| \meta{$10^6+{}$Q_1} |;|
+% ~~\meta{B_1} \meta{B_2} |;| \Arg{B_3} \Arg{B_4}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign}
+% \end{quote}
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_iii:www #1; #2; #3;
+ {
+ \exp_after:wN \@@_div_mantissa_iii_after:w
+ \int_use:N \__int_eval:w #2
+ \exp_after:wN \@@_div_mantissa_iv:www
+ \__int_value:w #1 \exp_after:wN ;
+ \__int_value:w
+ \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn
+ \int_use:N \__int_eval:w #30/#1 + 999999 ;
+ #3 ;
+ }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_iv:www} \meta{y} |;| \meta{$10^6+{}$Q_2} |;|
+% ~~\meta{C_1} \meta{C_2} |;| \Arg{C_3} \Arg{C_4}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign}
+% \end{quote}
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_iv:www #1; #2; #3;
+ {
+ \exp_after:wN \@@_div_mantissa_pack:NNN
+ \int_use:N \__int_eval:w #2
+ \exp_after:wN \@@_div_mantissa_v:www
+ \__int_value:w #1 \exp_after:wN ;
+ \__int_value:w
+ \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn
+ \int_use:N \__int_eval:w #30/#1 + 999999 ;
+ #3 ;
+ }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_v:www} \meta{y} |;| \meta{$10^6+{}$Q_3} |;|
+% ~~\meta{D_1} \meta{D_2} |;| \Arg{D_3} \Arg{D_4}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign}
+% \end{quote}
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_v:www #1; #2; #3;
+ {
+ \exp_after:wN \@@_div_mantissa_pack:NNN
+ \int_use:N \__int_eval:w #2
+ \exp_after:wN \@@_div_mantissa_vi:wwnnnn
+ \__int_value:w
+ \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn
+ \int_use:N \__int_eval:w #30/#1 + 999999 ;
+ #3 ;
+ }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_vi:wwnnnn} \meta{$10^6+{}$Q_4} |;|
+% ~~\meta{E_1} \meta{E_2} |;| \Arg{E_3} \Arg{E_4}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign}
+% \end{quote}
+% We compute $P$ by rounding $2 E_{1} E_{2}/Z_{1}Z_{2}$.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_vi:wwnnnn #1; #2;#3#4 #5#6
+ {
+ \exp_after:wN \@@_div_mantissa_pack:NNN
+ \int_use:N \__int_eval:w #10
+ \exp_after:wN \@@_div_mantissa_vii:wwnnnnnn
+ \int_use:N \__int_eval:w (\c_two*#2)/#5#6 ; % <- P
+ #2;{#3}{#4}
+ {#5}{#6}
+ }
+% \end{macrocode}
+% Note that we used |#10| instead of |#2| which we had previously.
+% Two reasons: firstly, since we dropped $y$, the argument which
+% holds $Q_{i}$ has changed, and secondly, we will want the
+% fourth piece of the result to have $5$ digits, including the
+% \meta{rounding} digit, which we shall compute now from $P$.
+% \begin{quote}
+% \cs{@@_div_mantissa_vii:wwnnnnnn} \meta{P} |;|
+% ~~\meta{E_1} \meta{E_2} |;| \Arg{E_3} \Arg{E_4}
+% ~~\Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \meta{sign}
+% \end{quote}
+% Then compute $2E-PZ$. Once more, we need to be careful and show
+% that the calculation $\#1\cdot\#5\#6$ below does not cause an
+% overflow: naively, $P$ can be up to $35$, and $\#5\#6$ up to
+% $10^8$, but both cannot happen simultaneously. To show that things
+% are fine, we split in two (non-disjoint) cases.
+% \begin{itemize}
+% \item For small $P$, say, $P< 10$, the product obeys
+% $P\cdot\#5\#6 < 10^8 \cdot P < 10^9 $.
+% \item For large $P$, say, $P\geq 3$, the rounding error on $P$,
+% which is at most $1$, is less than a factor of $2$, hence
+% $P\leq 4E/Z$, and $P\cdot \#5\#6 \leq 4E\cdot 10^8 < 10^9$.
+% \end{itemize}
+% Both inequalities could be made tighter if needed.
+%
+% Note however that $P\cdot \#7\#8$ may overflow,
+% since the two factors are now independent, and the result may reach
+% $3.5\cdot 10^9$.
+%
+% Also, we add $10\cdot P/2$ to the \enquote{fourth piece} of the result
+% as a first estimate of $10$ times $E/Z$. The goal is that the last digit
+% (for now $0$ or $5$) should be the \meta{rounding} digit. More precisely,
+% it will be corrected later by adding or subtracting $1$ depending on
+% whether $F$ was the correct integer part, or an overestimate (and nothing
+% is added when the quotient was exact). This does not give the
+% \enquote{correct} \meta{rounding} digit, but it always gives a digit
+% in the right \enquote{class} ($0$, $[1,4]$, $5$, or $[6-9]$), enough
+% for rounding purposes.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_vii:wwnnnnnn #1; #2;#3#4 #5#6#7#8
+ {
+ + \c_five * #1
+ \exp_after:wN \@@_div_mantissa_ix:Nww
+ \int_use:N \__int_eval:w -20 + 2*#2 - #1*#5#6 +
+ \exp_after:wN \@@_div_mantissa_viii:NNw
+ \int_use:N \__int_eval:w 199980 + 2*#3 - #1*#7 +
+ \exp_after:wN \@@_div_mantissa_viii:NNw
+ \int_use:N \__int_eval:w 200000 + 2*#4 - #1*#8 ; ;
+ }
+\cs_new:Npn \@@_div_mantissa_viii:NNw #1#2#3; { #1#2 ; + #3 }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_ix:Nww}
+% ~~\meta{F_1} \meta{F_2} |;| |+| \meta{F_3} |+| \meta{F_4} |;| \meta{sign}
+% \end{quote}
+% where $F=2E-PZ$. We only need to know whether it is positive,
+% negative, or exactly zero.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_ix:Nww #1#2;#3;
+ {
+ \if_meaning:w 0 #1
+ \exp_after:wN \@@_div_mantissa_x:w
+ \int_use:N \__int_eval:w #3
+ \else:
+ \if_meaning:w - #1
+ -
+ \else:
+ +
+ \fi:
+ \c_one
+ \fi:
+ ;
+ }
+\cs_new:Npn \@@_div_mantissa_x:w #1;
+ {
+ \if_int_compare:w #1 > \c_zero
+ + \c_one
+ \fi:
+ ;
+ }
+% \end{macrocode}
+% We now obtain the following code, where \TeX{} is in the process
+% of expanding each of the integer expressions, and thus expands
+% the function at the bottom before the ones above it.
+% \begin{quote}
+% \cs{@@_div_mantissa_iii_after:w} $10^6 + Q_{1}$
+% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{2}$
+% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{3}$
+% \cs{@@_div_mantissa_pack:NNN}
+% $10^7 + 10\cdot Q_{4} + 5 \cdot P + \varepsilon$ |;| \meta{sign}
+% \end{quote}
+% Here, $\varepsilon$ is $0$ in case $2E=PZ$ (\emph{i.e.}, $F=0$),
+% $1$ in case $2E>PZ$, which means that $P$ was the correct value,
+% but not with an exact quotient, and $-1$ if $2E<PZ$, \emph{i.e.},
+% $P$ was an overestimate.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_pack:NNN 1 #1 #2 { + #1 #2 ; }
+% \end{macrocode}
+% Once those have been expanded, we get
+% \begin{quote}
+% \cs{@@_div_mantissa_iii_after:w} |1| |0| \meta{5d} |;|
+% ~~\meta{4d} |;| \meta{4d} |;| \meta{5d} |;| \meta{sign}
+% \end{quote}
+% The reason we know that the first two digits are |1| and |0|
+% is that the final result is known to be between $0.1$ (inclusive)
+% and $10$, hence $\widetilde{Q_{1}}$ (the tilde denoting the
+% contribution from the other $Q_{i}$) is at most $99999$,
+% and $10^6+\widetilde{Q_{1}} = 10\cdots$.
+%
+% It is now time to round. This depends on how many digits
+% the final result will have.
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_iii_after:w 10 #1
+ {
+ \if_meaning:w 0 #1
+ \exp_after:wN \@@_div_mantissa_small:wwwNNNNwN
+ \else:
+ \exp_after:wN \@@_div_mantissa_large:wwwNNNNwN
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_small:wwwNNNNwN} |0| \meta{4d} |;|
+% ~~\meta{4d} |;| \meta{4d} |;| \meta{5d} |;| \meta{sign}
+% \end{quote}
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_small:wwwNNNNwN
+ 0 #1; #2; #3; #4#5#6#7#8; #9
+ {
+ \exp_after:wN \@@_basics_pack_high:NNNNNw
+ \int_use:N \__int_eval:w 1 #1#2
+ \exp_after:wN \@@_basics_pack_low:NNNNNw
+ \int_use:N \__int_eval:w 1 #3#4#5#6#7
+ + \@@_round:NNN #9 #7 #8
+ \exp_after:wN ;
+ }
+% \end{macrocode}
+% \begin{quote}
+% \cs{@@_div_mantissa_large:wwwNNNNwN} \meta{5d} |;|
+% ~~\meta{4d} |;| \meta{4d} |;| \meta{5d} |;| \meta{sign}
+% \end{quote}
+% \footnote{Bruno: rename the \enquote{add mantissa carry pack} function.}
+% \begin{macrocode}
+\cs_new:Npn \@@_div_mantissa_large:wwwNNNNwN
+ #1; #2; #3; #4#5#6#7#8; #9
+ {
+ + \c_one
+ \exp_after:wN \@@_div_mantissa_large_pack:NNNNNNNNw
+ \int_use:N \__int_eval:w 1 #1 #2 %<- 1+9d
+ \exp_after:wN \@@_add_mantissa_carry_pack_ii:NNNNw
+ \int_use:N \__int_eval:w 1 #3 #4 #5 #6
+ + \@@_round:NNNN #9 #6 #7 #8
+ \exp_after:wN ;
+ }
+\cs_new:Npn \@@_div_mantissa_large_pack:NNNNNNNNw
+ 1 #1#2#3#4 #5#6#7#8 #9; { ; {#1#2#3#4} {#5#6#7#8} {#9} }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Unary operations}
+%
+% \begin{macro}{\@@_neg:w}
+% This function flips the sign of the \meta{floating point}
+% and expands after it in the input stream, just like
+% \cs{@@_+_o:ww} etc.
+% \begin{macrocode}
+\cs_new:Npn \@@_neg:w \s_@@ \@@_chk:w #1 #2
+ {
+ \exp_after:wN \@@_exp_after_o:w
+ \exp_after:wN \s_@@
+ \exp_after:wN \@@_chk:w
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w \c_two - #2 \__int_eval_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_abs:w}
+% This function sets the sign of the \meta{floating point} to be
+% positive, and expands after itself in the input stream, just like
+% \cs{@@_neg:w}.
+% \begin{macrocode}
+\cs_new:Npn \@@_abs:w \s_@@ \@@_chk:w #1 #2
+ { \@@_exp_after_o:w \s_@@ \@@_chk:w #1 0 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
new file mode 100644
index 00000000000..057cef4b176
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-convert.dtx
@@ -0,0 +1,476 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-convert.dtx Copyright(C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-convert.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Floating-point conversion}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \textsf{l3fp-convert} package\\ Floating point conversion^^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}
+%
+% ^^A todo: tests
+% ^^A todo: doc functions
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\texttt{l3fp-convert} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{Trimming trailing zeros}
+%
+% \begin{macro}[int, EXP]{\@@_trim_zeros:w}
+% \begin{macro}[aux, EXP]
+% {\@@_trim_zeros_loop:w, \@@_trim_zeros_dot:w, \@@_trim_zeros_end:w}
+% If |#1| ends with a $0$, the \texttt{loop} auxiliary takes that zero
+% as an end-delimiter for its first argument, and the second argument
+% is the same \texttt{loop} auxiliary. Once the last trailing zero is
+% reached, the second argument will be the \texttt{dot} auxiliary,
+% which removes a trailing dot if any. We then cleanup with the
+% \texttt{end} auxiliary, keeping only the number.
+% \begin{macrocode}
+\cs_new:Npn \@@_trim_zeros:w #1 ;
+ {
+ \@@_trim_zeros_loop:w #1
+ ; \@@_trim_zeros_loop:w 0; \@@_trim_zeros_dot:w .; \s__stop
+ }
+\cs_new:Npn \@@_trim_zeros_loop:w #1 0; #2 { #2 #1 ; #2 }
+\cs_new:Npn \@@_trim_zeros_dot:w #1 .; { \@@_trim_zeros_end:w #1 ; }
+\cs_new:Npn \@@_trim_zeros_end:w #1 ; #2 \s__stop { #1 }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Scientific notation}
+%
+% \begin{variable}{\c_@@_scientific_inf_tl}
+% Result of converting $\infty$ to a scientific representation: after
+% triggering an \enquote{invalid operation} exception,
+% \cs{fp_to_scientific:n} yields that result, larger than any finite
+% floating point number.
+% \begin{macrocode}
+\tl_const:Nx \c_@@_scientific_inf_tl
+ { 1e \int_use:N \c_@@_max_exponent_int }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}
+% {\fp_to_scientific:N, \fp_to_scientific:c, \fp_to_scientific:n}
+% The three public functions evaluate their argument, then pass it to
+% \cs{@@_to_scientific:w}.
+% \begin{macrocode}
+\cs_new:Npn \fp_to_scientific:N #1 { \exp_after:wN \@@_to_scientific:w #1 }
+\cs_generate_variant:Nn \fp_to_scientific:N { c }
+\cs_new:Npn \fp_to_scientific:n #1
+ {
+ \exp_after:wN \@@_to_scientific:w
+ \tex_romannumeral:D -`0 \@@_parse:n {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]
+% {
+% \@@_to_scientific:w,
+% \@@_to_scientific_normal:wnnnnn,
+% \@@_to_scientific_normal:wNw
+% }
+% Expressing an internal floating point number in scientific notation
+% is quite easy: no rounding, and the format is very well defined.
+% First cater for the sign: negative numbers (|#2=2|) start with |-|.
+% Then filter the special cases: we insert \cs{prg_do_nothing:}
+% because \cs{@@_invalid_operation:Nnw} expands after taking one
+% floating point argument. In the normal case, decrement the exponent
+% and unbrace the $4$ brace groups, then in a second step grab the
+% first digit (previously hidden in braces) to order the various parts
+% correctly. Finally trim zeros.
+% \begin{macrocode}
+\cs_new:Npn \@@_to_scientific:w \s_@@ \@@_chk:w #1#2#3 ;
+ {
+ \if_meaning:w 2 #2 \exp_after:wN - \tex_romannumeral:D -`0 \fi:
+ \if_case:w #1 \exp_stop_f:
+ \@@_case_return:nw { \exp_after:wN 0 }
+ \or: \exp_after:wN \@@_to_scientific_normal:wnnnnn
+ \or:
+ \@@_case_use:nw
+ {
+ \@@_invalid_operation:Nnw
+ \c_@@_scientific_inf_tl { fp_to_scientific }
+ }
+ \or:
+ \@@_case_use:nw
+ { \@@_invalid_operation:Nnw 0 { fp_to_scientific } }
+ \fi:
+ \s_@@ \@@_chk:w #1 #2 #3 ; \prg_do_nothing:
+ }
+\cs_new:Npn \@@_to_scientific_normal:wnnnnn
+ \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; \prg_do_nothing:
+ {
+ \if_int_compare:w #2 = \c_one
+ \exp_after:wN \@@_to_scientific_normal:wNw
+ \else:
+ \exp_after:wN \@@_to_scientific_normal:wNw
+ \exp_after:wN e
+ \int_use:N \__int_eval:w #2 - \c_one
+ \fi:
+ ; #3 #4 #5 #6 ;
+ }
+\cs_new:Npn \@@_to_scientific_normal:wNw #1 ; #2#3;
+ { \@@_trim_zeros:w #2.#3 ; #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Decimal representation}
+%
+% \begin{variable}{\c_@@_decimal_inf_tl}
+% Result of converting $\infty$ to a decimal representation: after
+% triggering an \enquote{invalid operation} exception,
+% \cs{fp_to_decimal:n} yields a~$1$ followed by $\ExplSyntaxOn
+% \int_use:N \c__fp_max_exponent_int$~$0$, larger than any finite
+% floating point number. Since the expanded token list is very long,
+% we use an \texttt{n}-type assignment.
+% \begin{macrocode}
+\tl_const:Nn \c_@@_decimal_inf_tl
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN 1
+ \prg_replicate:nn \c_@@_max_exponent_int 0
+ }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[EXP]
+% {\fp_to_decimal:N, \fp_to_decimal:c, \fp_to_decimal:n}
+% All three public variants are based on the same \cs{@@_to_decimal:w}
+% after evaluating their argument to an internal floating point.
+% \begin{macrocode}
+\cs_new:Npn \fp_to_decimal:N #1 { \exp_after:wN \@@_to_decimal:w #1 }
+\cs_generate_variant:Nn \fp_to_decimal:N { c }
+\cs_new_nopar:Npn \fp_to_decimal:n
+ {
+ \exp_after:wN \@@_to_decimal:w
+ \tex_romannumeral:D -`0 \@@_parse:n
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, aux]
+% {
+% \@@_to_decimal:w,
+% \@@_to_decimal_normal:wnnnnn,
+% \@@_to_decimal_large:Nnnw,
+% \@@_to_decimal_huge:wnnnn,
+% }
+% The structure is similar to \cs{@@_to_scientific:w}. Insert |-| for
+% negative numbers. Zero gives $0$, $\pm\infty$ and \nan{} yield an
+% \enquote{invalid operation} exception. Normal numbers with an
+% exponent in the range $[1,15]$ have that number of digits before the
+% decimal separator: \enquote{decimate} them, and remove leading zeros
+% with \cs{__int_value:w}, then trim trailing zeros and dot. Normal
+% numbers with an exponent $16$ or larger have no decimal separator,
+% we only need to add trailing zeros. When the exponent is
+% non-positive, the result should be $0.\meta{zeros}\meta{digits}$,
+% trimmed.
+% \begin{macrocode}
+\cs_new:Npn \@@_to_decimal:w \s_@@ \@@_chk:w #1#2#3 ;
+ {
+ \if_meaning:w 2 #2 \exp_after:wN - \tex_romannumeral:D -`0 \fi:
+ \if_case:w #1 \exp_stop_f:
+ \@@_case_return:nw { \exp_after:wN 0 }
+ \or: \exp_after:wN \@@_to_decimal_normal:wnnnnn
+ \or:
+ \@@_case_use:nw
+ {
+ \@@_invalid_operation:Nnw
+ \c_@@_decimal_inf_tl { fp_to_decimal }
+ }
+ \or:
+ \@@_case_use:nw
+ { \@@_invalid_operation:Nnw 0 { fp_to_decimal } }
+ \fi:
+ \s_@@ \@@_chk:w #1 #2 #3 ; \prg_do_nothing:
+ }
+\cs_new:Npn \@@_to_decimal_normal:wnnnnn
+ \s_@@ \@@_chk:w 1 #1 #2 #3#4#5#6 ; \prg_do_nothing:
+ {
+ \int_compare:nNnTF {#2} > \c_zero
+ {
+ \int_compare:nNnTF {#2} < \c_sixteen
+ {
+ \@@_decimate:nNnnnn { \c_sixteen - #2 }
+ \@@_to_decimal_large:Nnnw
+ }
+ {
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_to_decimal_huge:wnnnn
+ \prg_replicate:nn { #2 - \c_sixteen } { 0 } ;
+ }
+ {#3} {#4} {#5} {#6}
+ }
+ {
+ \exp_after:wN \@@_trim_zeros:w
+ \exp_after:wN 0
+ \exp_after:wN .
+ \tex_romannumeral:D -`0 \prg_replicate:nn { - #2 } { 0 }
+ #3#4#5#6 ;
+ }
+ }
+\cs_new:Npn \@@_to_decimal_large:Nnnw #1#2#3#4;
+ {
+ \exp_after:wN \@@_trim_zeros:w \__int_value:w
+ \if_int_compare:w #2 > \c_zero
+ #2
+ \fi:
+ \exp_stop_f:
+ #3.#4 ;
+ }
+\cs_new:Npn \@@_to_decimal_huge:wnnnn #1; #2#3#4#5 { #2#3#4#5 #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Token list representation}
+%
+% \begin{macro}[EXP]{\fp_to_tl:N, \fp_to_tl:c, \fp_to_tl:n}
+% These three public functions evaluate their argument, then pass it
+% to \cs{@@_to_tl:w}.
+% \begin{macrocode}
+\cs_new:Npn \fp_to_tl:N #1 { \exp_after:wN \@@_to_tl:w #1 }
+\cs_generate_variant:Nn \fp_to_tl:N { c }
+\cs_new_nopar:Npn \fp_to_tl:n
+ {
+ \exp_after:wN \@@_to_tl:w
+ \tex_romannumeral:D -`0 \@@_parse:n
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, aux]{\@@_to_tl:w, \@@_to_tl_normal:nnnnn}
+% A structure similar to \cs{@@_to_scientific:w} and
+% \cs{@@_to_decimal:w}, but without the \enquote{invalid operation}
+% exception. First filter special cases. We express normal numbers
+% in decimal notation if the exponent is in the range $[-2,16]$, and
+% otherwise use scientific notation. The weird \cs{prg_do_nothing:}
+% is needed because the \texttt{decimal} and \texttt{scientific}
+% auxiliaries we use expect it.
+% \begin{macrocode}
+\cs_new:Npn \@@_to_tl:w \s_@@ \@@_chk:w #1#2
+ {
+ \if_meaning:w 2 #2 \exp_after:wN - \tex_romannumeral:D -`0 \fi:
+ \if_case:w #1 \exp_stop_f:
+ \@@_case_return:nw { 0 }
+ \or: \exp_after:wN \@@_to_tl_normal:nnnnn
+ \or: \@@_case_return:nw { inf }
+ \else: \@@_case_return:nw { nan }
+ \fi:
+ }
+\cs_new:Npn \@@_to_tl_normal:nnnnn #1#2 ;
+ {
+ \if_int_compare:w #1 > \c_sixteen
+ \exp_after:wN \@@_to_scientific_normal:wnnnnn
+ \else:
+ \if_int_compare:w #1 < - \c_two
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_to_scientific_normal:wnnnnn
+ \else:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_to_decimal_normal:wnnnnn
+ \fi:
+ \fi:
+ \s_@@ \@@_chk:w 1 0 {#1} #2 ; \prg_do_nothing:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Formatting}
+%
+% ^^A todo
+%
+% \subsection{Convert to dimension or integer}
+%
+% \begin{macro}[EXP]{\fp_to_dim:N, \fp_to_dim:c, \fp_to_dim:n}
+% These three public functions rely on \cs{fp_to_decimal:n}
+% internally.
+% \begin{macrocode}
+\cs_new:Npn \fp_to_dim:N #1 { \fp_to_decimal:N #1 pt }
+\cs_generate_variant:Nn \fp_to_dim:N { c }
+\cs_new:Npn \fp_to_dim:n #1 { \fp_to_decimal:n {#1} pt }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\fp_to_int:N, \fp_to_int:c, \fp_to_int:n}
+% These three public functions evaluate their argument, then pass it
+% to \cs{fp_to_int:w}.
+% \begin{macrocode}
+\cs_new:Npn \fp_to_int:N #1 { \exp_after:wN \@@_to_int:w #1 }
+\cs_generate_variant:Nn \fp_to_int:N { c }
+\cs_new_nopar:Npn \fp_to_int:n
+ {
+ \exp_after:wN \@@_to_int:w
+ \tex_romannumeral:D -`0 \@@_parse:n
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_to_int:w}
+% To convert to an integer, first round to $0$ places (to the nearest
+% integer), then express the result as a decimal number: the
+% definition of \cs{@@_to_decimal:w} is such that there will be no
+% trailing dot nor zero.
+% \begin{macrocode}
+\cs_new:Npn \@@_to_int:w #1;
+ {
+ \exp_after:wN \@@_to_decimal:w \tex_romannumeral:D -`0
+ \@@_round:Nwn \@@_round_to_nearest:NNN #1; { 0 } \prg_do_nothing:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Convert from a dimension}
+%
+% \begin{macro}[EXP]{\dim_to_fp:n}
+% \begin{macro}[aux, EXP]
+% {
+% \@@_from_dim_test:N,
+% \@@_from_dim:Nw,
+% \@@_from_dim_ii:wNNnnnnnn,
+% \@@_from_dim_iii:wnnnnwN,
+% }
+% The dimension expression (which can in fact be a glue expression)
+% is evaluated, converted to a number (\emph{i.e.}, expressed in
+% scaled points), then multiplied by $2^{-16} = 0.0000152587890625$
+% to give a value expressed in points. We use the auxiliary function
+% \begin{quote}
+% \cs{@@_mul_npos:Nnwnw} \meta{sign} \newline
+% ~~\Arg{exp_1} \meta{body_1} |;| \Arg{exp_2} \meta{body_2} |;|
+% \end{quote}
+% \begin{macrocode}
+\cs_new:Npn \dim_to_fp:n #1
+ {
+ \exp_after:wN \@@_from_dim_test:N
+ \__int_value:w \etex_glueexpr:D #1 ;
+ }
+\cs_new:Npn \@@_from_dim_test:N #1
+ {
+ \if_meaning:w 0 #1
+ \exp_after:wN \@@_use_i_until_s:nw
+ \exp_after:wN \c_zero_fp
+ \else:
+ \if_meaning:w - #1
+ \exp_after:wN \@@_from_dim:Nw
+ \exp_after:wN 2
+ \__int_value:w
+ \else:
+ \exp_after:wN \@@_from_dim:Nw
+ \exp_after:wN 0
+ \__int_value:w #1
+ \fi:
+ \fi:
+ }
+\cs_new:Npn \@@_from_dim:Nw #1 #2;
+ {
+ \@@_pack_twice_four:wNNNNNNNN \@@_from_dim_ii:wNNnnnnnn ;
+ #2 000 0000 00 {10}987654321; #1
+ }
+\cs_new:Npn \@@_from_dim_ii:wNNnnnnnn #1; #2#3#4#5#6#7#8#9
+ { \@@_from_dim_iii:wnnnnwN #1 {#2#300} {0000} ; }
+\cs_new:Npn \@@_from_dim_iii:wnnnnwN #1; #2#3#4#5#6; #7
+ {
+ \@@_mul_npos:Nnwnw #7 {#5} #1 ;
+ {-4} {1525} {8789} {0625} {0000} ;
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Use and eval}
+%
+% \begin{macro}[EXP]{\fp_use:N, \fp_use:c, \fp_eval:n}
+% Those public functions are simple copies of the decimal conversions.
+% \begin{macrocode}
+\cs_new_eq:NN \fp_use:N \fp_to_decimal:N
+\cs_generate_variant:Nn \fp_use:N { c }
+\cs_new_eq:NN \fp_eval:n \fp_to_decimal:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\fp_abs:n}
+% Trivial but useful.
+% \begin{macrocode}
+\cs_new:Npn \fp_abs:n #1 { \fp_to_decimal:n { abs ( #1 ) } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
new file mode 100644
index 00000000000..edf9ac2ad35
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-expo.dtx
@@ -0,0 +1,1252 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-expo.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-expo.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Floating-point exponential-related functions}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-expo} package\thanks{This file
+% has version number \ExplFileVersion, last
+% revised \ExplFileDate.}\\
+% Floating point exponential-related functions}
+% \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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-expo} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{General comments}
+%
+%^^A todo: redoc
+% The algorithm for computing the logarithm of the significand could be
+% made to use a $5$ terms Taylor series instead of $10$ terms by taking
+% $c = 2000/(\lfloor 200x\rfloor +1) \in [10,95]$ instead of $c\in
+% [1,10]$. Also, it would then be possible to simplify the computation
+% of $t$, using methods similar to \cs{@@_fixed_div_to_float:ww}.
+% However, we would then have to hard-code the logarithms of $44$ small
+% integers instead of $9$.
+%
+% \subsection{Some constants}
+%
+% ^^A todo: very odd: can I delete ln_ten?
+% \begin{variable}
+% {
+% \c_@@_ln_i_fixed_tl ,
+% \c_@@_ln_ii_fixed_tl ,
+% \c_@@_ln_iii_fixed_tl ,
+% \c_@@_ln_iv_fixed_tl ,
+% \c_@@_ln_vi_fixed_tl ,
+% \c_@@_ln_vii_fixed_tl ,
+% \c_@@_ln_viii_fixed_tl ,
+% \c_@@_ln_ix_fixed_tl ,
+% \c_@@_ln_x_fixed_tl,
+% \c_@@_ln_ten_fixed_tl,
+% }
+% A few values of the logarithm which are needed in the
+% implementation. It turns out that we don't need the value of
+% $\log(5)$.
+% \begin{macrocode}
+\tl_const:Nn \c_@@_ln_i_fixed_tl { {0000}{0000}{0000}{0000}{0000}{0000} }
+\tl_const:Nn \c_@@_ln_ii_fixed_tl { {6931}{4718}{0559}{9453}{0941}{7232} }
+\tl_const:Nn \c_@@_ln_iii_fixed_tl {{10986}{1228}{8668}{1096}{9139}{5245} }
+\tl_const:Nn \c_@@_ln_iv_fixed_tl {{13862}{9436}{1119}{8906}{1883}{4464} }
+ % \tl_const:Nn \c_@@_ln_v_fixed_tl {{16094}{3791}{2434}{1003}{7460}{0759} }
+\tl_const:Nn \c_@@_ln_vi_fixed_tl {{17917}{5946}{9228}{0550}{0081}{2477} }
+\tl_const:Nn \c_@@_ln_vii_fixed_tl {{19459}{1014}{9055}{3133}{0510}{5353} }
+\tl_const:Nn \c_@@_ln_viii_fixed_tl{{20794}{4154}{1679}{8359}{2825}{1696} }
+\tl_const:Nn \c_@@_ln_ix_fixed_tl {{21972}{2457}{7336}{2193}{8279}{0490} }
+\tl_const:Nn \c_@@_ln_x_fixed_tl {{23025}{8509}{2994}{0456}{8401}{7991} }
+ %\tl_const:Nn \c_@@_ln_ten_fixed_tl {{23025}{8509}{2994}{0456}{8401}{7991} }
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Logarithm}
+%
+% \subsubsection{Sign, exponent, and special numbers}
+%
+% \begin{macro}[EXP]{\@@_ln:w}
+% The logarithm of $\pm 0$ is $-\infty$, raising a division by zero
+% exception. The logarithm of negative numbers (including $-\infty$,
+% but not $-0$) raises the \enquote{invalid} exception. The logarithm
+% of $+\infty$ or a \texttt{nan} is itself. Positive normal numbers
+% call \cs{@@_ln_npos:w}.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln:w \s_@@ \@@_chk:w #1 #2
+ {
+ \if_meaning:w 0 #1
+ \@@_case_use:nw
+ { \@@_division_by_zero:Nnw \c_minus_inf_fp { ln } }
+ \fi:
+ \if_meaning:w 2 #2
+ \@@_case_use:nw
+ { \@@_invalid_operation:Nnw \c_nan_fp { ln } }
+ \fi:
+ \if_meaning:w 1 #1 \else:
+ \@@_case_return_same_o:w
+ \fi:
+ \@@_ln_npos:w \s_@@ \@@_chk:w #1#2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Absolute ln}
+%
+% We are given a positive normal number, of the form $a\cdot 10^{b}$
+% with $a\in[0.1,1)$. To compute its logarithm, we find a small integer
+% $5\leq c < 50$ such that $0.91 \leq a c / 5 < 1.1$, and use the
+% relation
+% \[
+% \ln (a \cdot 10^b) = b \cdot \ln (10) - \ln (c/5) + \ln (ac/5).
+% \]
+% The logarithms $\ln(10)$ and $\ln(c/5)$ are looked up in a table. The
+% last term is computed using the following Talor series of $\ln$ near
+% $1$:
+% \[
+% \ln\left(\frac{ac}{5}\right)
+% = \ln\left(\frac{1+t}{1-t}\right)
+% = 2t\left(1 + t^2 \left(\frac{1}{3} + t^2 \left(\frac{1}{5}
+% + t^2 \left(\frac{1}{7} + t^2 \left( \frac{1}{9} + \cdots
+% \right)\right)\right)\right)\right)
+% \]
+% where $t=1-10/(ac+5)$. We can now see one reason for the choice of
+% $ac\sim 5$: then $ac+5=10(1-\epsilon)$ with $-0.05<\epsilon\leq
+% 0.045$, hence
+% \[
+% t = \frac{\epsilon}{1-\epsilon}
+% = \epsilon (1+\epsilon)(1+\epsilon^2)(1+\epsilon^4)\ldots,
+% \]
+% is not too difficult to compute.
+%
+% \begin{macro}{\@@_ln_npos:w}
+% We catch the case of a significand very close to $0.1$ or to $1$.
+% In all other cases, the final result is at least $10^{-4}$, and
+% then an error of $0.5\cdot 10^{-20}$ is acceptable.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_npos:w \s_@@ \@@_chk:w 10#1#2#3;
+ { %^^A todo: ln(1) should be "exact zero", not "underflow"
+ \exp_after:wN \@@_sanitize:Nw
+ \__int_value:w % for the overall sign
+ \if_int_compare:w #1 < \c_one
+ 2
+ \else:
+ 0
+ \fi:
+ \exp_after:wN \exp_stop_f:
+ \int_use:N \__int_eval:w % for the exponent
+ \@@_ln_significand:NNNNnnnN #2#3
+ \@@_ln_exponent:wn {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_ln_significand:NNNNnnnN}
+% \begin{syntax}
+% \cs{@@_ln_significand:NNNNnnnN} \meta{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \meta{continuation}
+% \end{syntax}
+% This function expands to
+% \begin{quote}
+% \meta{continuation} \Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} \Arg{Y_5} \Arg{Y_6} |;|
+% \end{quote}
+% where $Y = - \log X$.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_significand:NNNNnnnN #1#2#3#4
+ {
+ \exp_after:wN \@@_ln_x_ii:wnnnn
+ \__int_value:w
+ \if_case:w #1 \exp_stop_f:
+ \or:
+ \if_int_compare:w #2 < \c_four
+ \__int_eval:w \c_ten - #2
+ \else:
+ 6
+ \fi:
+ \or: 4
+ \or: 3
+ \or: 2
+ \or: 2
+ \or: 2
+ \else: 1
+ \fi:
+ ; { #1 #2 #3 #4 }
+ }
+% \end{macrocode}
+% We have thus found $c$. It is chosen such that $0.7\leq ac < 1.4$
+% in all cases. Compute $ 1 + x = 1 + ac \in [1.7,2.4)$.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_x_ii:wnnnn #1; #2#3#4#5
+ {
+ \exp_after:wN \@@_ln_div_after:Nw
+ \cs:w c_@@_ln_ \tex_romannumeral:D #1 _fixed_tl \exp_after:wN \cs_end:
+ \__int_value:w
+ \exp_after:wN \@@_ln_x_iv:nnnnnnnn
+ \tex_romannumeral:D -`0
+ \exp_after:wN \@@_ln_x_iii_var:NNNNNw
+ \int_use:N \__int_eval:w 9999 9999 + #1*#2#3 +
+ \exp_after:wN \@@_ln_x_iii:NNNNNw
+ \int_use:N \__int_eval:w 1 0000 0000 + #1*#4#5 ;
+ {20000} {0000} {0000} {0000}
+ } %^^A todo: reoptimize (a generalization attempt failed).
+\cs_new:Npn \@@_ln_x_iii:NNNNNw #1 #2#3#4#5 #6; { #1; {#2#3#4#5} {#6} }
+\cs_new:Npn \@@_ln_x_iii_var:NNNNNw #1 #2#3#4#5 #6; { {#1#2#3#4#5} {#6} }
+% \end{macrocode}
+% The Taylor series will be expressed in terms of
+% $t = (x-1)/(x+1) = 1 - 2/(x+1)$. We now compute the
+% quotient with extended precision, reusing some code
+% from \cs{@@_/_o:ww}. Note that $1+x$ is known exactly.
+%
+% To reuse notations from \pkg{l3fp-basics}, we want to
+% compute $ A / Z $ with $ A = 2 $ and $ Z = x + 1 $.
+% In \pkg{l3fp-basics}, we considered the case where
+% both $A$ and $Z$ are arbitrary, in the range $[0.1,1)$,
+% and we had to monitor the growth of the sequence of
+% remainders $A$, $B$, $C$, etc. to ensure that no overflow
+% occured during the computation of the next quotient.
+% The main source of risk was our choice to define the
+% quotient as roughly $10^9 \cdot A / 10^5 \cdot Z$: then
+% $A$ was bound to be below $2.147\cdots$, and this limit
+% was never far.
+%
+% In our case, we can simply work with $10^8 \cdot A$ and
+% $10^4 \cdot Z$, because our reason to work with higher
+% powers has gone: we needed the integer $y \simeq 10^5 \cdot Z$
+% to be at least $10^4$, and now, the definition
+% $y \simeq 10^4 \cdot Z$ suffices.
+%
+% Let us thus define $y = \left\lfloor 10^4 \cdot Z \right\rfloor + 1
+% \in ( 1.7 \cdot 10^4, 2.4 \cdot 10^4 ] $, and
+% \[
+% Q_{1}
+% =
+% \left\lfloor
+% \frac {\left\lfloor 10^8 \cdot A\right\rfloor} {y} - \frac{1}{2}
+% \right\rfloor.
+% \]
+% (The $1/2$ comes from how e\TeX{} rounds.) As for division, it is
+% easy to see that $Q_{1} \leq 10^4 A / Z$, \emph{i.e.}, $Q_{1}$
+% is an underestimate.
+%
+% Exactly as we did for division, we set $B = 10^4 A - Q_{1}Z$. Then
+% \begin{align*}
+% 10^4 B
+% \leq
+% A_{1}A_{2}.A_{3}A_{4}
+% - \left( \frac{A_{1}A_{2}}{y} - \frac{3}{2} \right) 10^4 Z
+% \leq
+% A_{1}A_{2} \left( 1 - \frac{10^4 Z}{y} \right) + 1 + \frac{3}{2} y
+% \leq
+% 10^8 \frac{A}{y} + 1 + \frac{3}{2} y
+% \end{align*}
+% In the same way, and using $1.7\cdot 10^4\leq y\leq 2.4\cdot 10^4$,
+% and convexity, we get
+% \begin{align*}
+% 10^4 A &= 2\cdot 10^4 \\
+% 10^4 B &\leq 10^8 \frac{A}{y} + 1.6 y \leq 4.7\cdot 10^4\\
+% 10^4 C &\leq 10^8 \frac{B}{y} + 1.6 y \leq 5.8\cdot 10^4\\
+% 10^4 D &\leq 10^8 \frac{C}{y} + 1.6 y \leq 6.3\cdot 10^4\\
+% 10^4 E &\leq 10^8 \frac{D}{y} + 1.6 y \leq 6.5\cdot 10^4\\
+% 10^4 F &\leq 10^8 \frac{E}{y} + 1.6 y \leq 6.6\cdot 10^4\\
+% \end{align*}
+% Note that we compute more steps than for division: since $t$ is
+% not the end result, we need to know it with more accuracy
+% (on the other hand, the ending is much simpler, as we don't
+% need an exact rounding for transcendental functions, but just
+% a faithful rounding).\footnote{Bruno: to be completed.}
+%
+% \begin{quote}
+% \cs{@@_ln_x_iv:NNNNNwnn}
+% \meta{1 or 2} \meta{8d} |;| \Arg{4d} \Arg{4d} \meta{fixed-tl}
+% \end{quote}
+% The number is $x$. Compute $y$ by adding 1 to the five first digits.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_x_iv:nnnnnnnn #1#2#3#4 #5#6#7#8
+ {
+ \exp_after:wN \@@_ln_div_i:w
+ \int_use:N \__int_eval:w #1 + \c_one ;
+ #5 #6 ; {#7} {#8}
+ {#1} {#2} {#3} {#4}
+ }
+\cs_new:Npn \@@_ln_div_i:w #1;
+ {
+ \exp_after:wN \@@_ln_div_ii:www
+ \__int_value:w #1 \exp_after:wN ;
+ \__int_value:w
+ \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn
+ \int_use:N \__int_eval:w 999999 + 2 0000 0000 / #1 ; % Q1
+ }
+\cs_set_protected:Npn \@@_tmp:w #1#2
+ {
+ \cs_new:Npn #1 ##1; ##2; ##3; % y; Q1; B1B2; <- for k=1
+ {
+ \exp_after:wN \@@_div_mantissa_pack:NNN
+ \int_use:N \__int_eval:w ##2
+ \exp_after:wN #2
+ \__int_value:w ##1 \exp_after:wN ;
+ \__int_value:w
+ \exp_after:wN \@@_div_mantissa_calc:Nwwnnnnnn
+ \int_use:N \__int_eval:w 999999 + ##3 / ##1 ; % Q2
+ ##3 ;
+ }
+ }
+\@@_tmp:w \@@_ln_div_ii:www \@@_ln_div_iii:www
+\@@_tmp:w \@@_ln_div_iii:www \@@_ln_div_iv:www
+\@@_tmp:w \@@_ln_div_iv:www \@@_ln_div_v:www
+\@@_tmp:w \@@_ln_div_v:www \@@_ln_div_vi:www
+\cs_new:Npn \@@_ln_div_vi:www #1; #2; #3;#4#5 #6#7#8#9 %y;Q5;F1F2;F3F4x1x2x3x4
+ {
+ \exp_after:wN \@@_div_mantissa_pack:NNN
+ \int_use:N \__int_eval:w #2
+ \exp_after:wN \@@_div_mantissa_pack:NNN
+ \int_use:N \__int_eval:w 1000000 + #3 / #1 ; % Q6
+ }
+% \end{macrocode}
+% We now have essentially\footnote{Bruno: add a mention that
+% the error on $Q_{6}$ is bounded by $10$ (probably $6.7$),
+% and thus corresponds to an error of $10^{-23}$ on the final
+% result, small enough in all cases.}
+% \begin{quote}
+% \cs{@@_ln_div_after:Nw} \meta{fixed tl}
+% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{1}$
+% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{2}$
+% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{3}$
+% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{4}$
+% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{5}$
+% \cs{@@_div_mantissa_pack:NNN} $10^6 + Q_{6}$ |;|
+% \meta{exponent} |;| \meta{continuation}
+% \end{quote}
+% where \meta{fixed tl} holds the logarithm of a number
+% in $[1,10]$, and \meta{exponent} is
+% the exponent. Also, the expansion is done backwards. Then
+% \cs{@@_div_mantissa_pack:NNN} puts things in the
+% correct order to add the $Q_{i}$ together and put semicolons
+% between each piece. Once those have been expanded, we get
+% \begin{quote}
+% \cs{@@_ln_div_after:Nw} \meta{fixed-tl} \meta{1d} |;| \meta{4d} |;| \meta{4d} |;| \meta{4d} |;| \meta{4d} |;| \meta{4d} |;| \meta{4d} |;| \meta{exponent} |;|
+% \end{quote}
+% ^^A todo: redoc.
+% Just as with division, we know that the first two digits
+% are |1| and |0| because of bounds on the final result of
+% the division $2/(x+1)$, which is between roughly $0.8$ and $1.2$.
+% We then compute $1-2/(x+1)$, after testing whether $2/(x+1)$ is
+% greater than or smaller than $1$.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_div_after:Nw #1#2;
+ {
+ \if_meaning:w 0 #2
+ \exp_after:wN \@@_ln_t_small:Nw
+ \else:
+ \exp_after:wN \@@_ln_t_large:NNw
+ \exp_after:wN -
+ \fi:
+ #1
+ }
+\cs_new:Npn \@@_ln_t_small:Nw #1 #2; #3; #4; #5; #6; #7;
+ {
+ \exp_after:wN \@@_ln_t_large:NNw
+ \exp_after:wN + % <sign>
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w 9999 - #2 \exp_after:wN ;
+ \int_use:N \__int_eval:w 9999 - #3 \exp_after:wN ;
+ \int_use:N \__int_eval:w 9999 - #4 \exp_after:wN ;
+ \int_use:N \__int_eval:w 9999 - #5 \exp_after:wN ;
+ \int_use:N \__int_eval:w 9999 - #6 \exp_after:wN ;
+ \int_use:N \__int_eval:w 1 0000 - #7 ;
+ }
+% \end{macrocode}
+%
+% \begin{quote}
+% \cs{@@_ln_t_large:NNw} \meta{sign}\meta{fixed tl} \meta{t_1}|;| \meta{t_2} |;| \meta{t_3}|;| \meta{t_4}|;| \meta{t_5} |;| \meta{t_6}|;| \meta{exponent} |;| \meta{continuation}
+% \end{quote}
+% Compute the square $|t|^2$, and keep $|t|$ at the end with its
+% sign. We know that $|t|<0.1765$, so every piece has at most $4$
+% digits. However, since we were not careful in \cs{@@_ln_t_small:w},
+% they can have less than $4$ digits.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_t_large:NNw #1 #2 #3; #4; #5; #6; #7; #8;
+ {
+ \exp_after:wN \@@_ln_square_t_after:w
+ \int_use:N \__int_eval:w 9999 0000 + #3*#3
+ \exp_after:wN \@@_ln_square_t_pack:NNNNNw
+ \int_use:N \__int_eval:w 9999 0000 + 2*#3*#4
+ \exp_after:wN \@@_ln_square_t_pack:NNNNNw
+ \int_use:N \__int_eval:w 9999 0000 + 2*#3*#5 + #4*#4
+ \exp_after:wN \@@_ln_square_t_pack:NNNNNw
+ \int_use:N \__int_eval:w 9999 0000 + 2*#3*#6 + 2*#4*#5
+ \exp_after:wN \@@_ln_square_t_pack:NNNNNw
+ \int_use:N \__int_eval:w 1 0000 0000 + 2*#3*#7 + 2*#4*#6 + #5*#5
+ + (2*#3*#8 + 2*#4*#7 + 2*#5*#6) / 1 0000
+ % ; ; ;
+ \exp_after:wN \@@_ln_twice_t_after:w
+ \int_use:N \__int_eval:w -1 + 2*#3
+ \exp_after:wN \@@_ln_twice_t_pack:Nw
+ \int_use:N \__int_eval:w 9999 + 2*#4
+ \exp_after:wN \@@_ln_twice_t_pack:Nw
+ \int_use:N \__int_eval:w 9999 + 2*#5
+ \exp_after:wN \@@_ln_twice_t_pack:Nw
+ \int_use:N \__int_eval:w 9999 + 2*#6
+ \exp_after:wN \@@_ln_twice_t_pack:Nw
+ \int_use:N \__int_eval:w 9999 + 2*#7
+ \exp_after:wN \@@_ln_twice_t_pack:Nw
+ \int_use:N \__int_eval:w 10000 + 2*#8 ; ;
+ { \@@_ln_c:NwNw #1 }
+ #2
+ }
+\cs_new:Npn \@@_ln_twice_t_pack:Nw #1 #2; { + #1 ; {#2} }
+\cs_new:Npn \@@_ln_twice_t_after:w #1; { ;;; {#1} }
+\cs_new:Npn \@@_ln_square_t_pack:NNNNNw #1 #2#3#4#5 #6;
+ { + #1#2#3#4#5 ; {#6} }
+\cs_new:Npn \@@_ln_square_t_after:w 1 0 #1#2#3 #4;
+ { \@@_ln_Taylor:wwNw {0#1#2#3} {#4} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_ln_Taylor:wwNw}
+% Denoting $T=t^2$, we get
+% \begin{quote}
+% \cs{@@_ln_Taylor:wwNw}
+% \Arg{T_1} \Arg{T_2} \Arg{T_3} \Arg{T_4} \Arg{T_5} \Arg{T_6} |;| |;|
+% \Arg{(2t)_1} \Arg{(2t)_2} \Arg{(2t)_3} \Arg{(2t)_4} \Arg{(2t)_5} \Arg{(2t)_6} |;|
+% |{| \cs{@@_ln_c:NwNn} \meta{sign} |}|
+% \meta{fixed tl} \meta{exponent} |;| \meta{continuation}
+% \end{quote}
+% And we want to compute
+% \[
+% \ln\left(\frac{1+t}{1-t}\right)
+% = 2t\left(1 + T \left(\frac{1}{3} + T \left(\frac{1}{5}
+% + T \left(\frac{1}{7} + T \left( \frac{1}{9} + \cdots
+% \right)\right)\right)\right)\right)
+% \]
+% The process looks as follows
+% \begin{verbatim}
+% \loop 5; A;
+% \div_int 5; 1.0; \add A; \mul T; {\loop \eval 5-2;}
+% \add 0.2; A; \mul T; {\loop \eval 5-2;}
+% \mul B; T; {\loop 3;}
+% \loop 3; C;
+% \end{verbatim}
+% \footnote{Bruno: add explanations.}
+%
+% This uses the routine for dividing a number by a small integer
+% (${}<10^4$).
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_Taylor:wwNw
+ { \@@_ln_Taylor_loop:www 21 ; {0000}{0000}{0000}{0000}{0000}{0000} ; }
+\cs_new:Npn \@@_ln_Taylor_loop:www #1; #2; #3;
+ {
+ \if_int_compare:w #1 = \c_one
+ \@@_ln_Taylor_break:w
+ \fi:
+ \exp_after:wN \@@_fixed_div_int:wwN \c_@@_one_fixed_tl ; #1;
+ \@@_fixed_add:wwN #2;
+ \@@_fixed_mul:wwn #3;
+ {
+ \exp_after:wN \@@_ln_Taylor_loop:www
+ \int_use:N \__int_eval:w #1 - \c_two ;
+ }
+ #3;
+ }
+\cs_new:Npn \@@_ln_Taylor_break:w \fi: #1 \@@_fixed_add:wwN #2#3; #4 ;;
+ {
+ \fi:
+ \exp_after:wN \@@_fixed_mul:wwn
+ \exp_after:wN { \int_use:N \__int_eval:w 10000 + #2 } #3;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_ln_c:NwNw}
+% \begin{quote}
+% \cs{@@_ln_c:NwNw} \meta{sign}
+% \Arg{r_1} \Arg{r_2} \Arg{r_3} \Arg{r_4} \Arg{r_5} \Arg{r_6} |;|
+% \meta{fixed tl} \meta{exponent} |;| \meta{continuation}
+% \end{quote}
+% We are now reduced to finding $\ln c$ and $\meta{exponent}\ln 10$
+% in a table, and adding it to the mixture. The first step is to
+% get $\ln c - \ln x = - \ln a$, then we get $|b|\ln 10$ and add
+% or subtract.
+%
+% For now, $\ln x$ is given as $\cdot 10^0$. Unless both the exponent
+% is $1$ and $c=1$, we shift to working in units of $\cdot 10^4$,
+% since the final result will be at least $\ln 10/7 \simeq
+% 0.35$.\footnote{Bruno: that was wrong at some point, I must check.}
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_c:NwNw #1 #2; #3
+ {
+ \if_meaning:w + #1
+ \exp_after:wN \exp_after:wN \exp_after:wN \@@_fixed_sub:wwN
+ \else:
+ \exp_after:wN \exp_after:wN \exp_after:wN \@@_fixed_add:wwN
+ \fi:
+ #3 ; #2 ;
+ }
+% \end{macrocode}
+% \footnote{Bruno: this \emph{\textbf{must}} be updated with correct values!}
+% \end{macro}
+%
+% \begin{macro}{\@@_ln_exponent:wn}
+% \begin{quote}
+% \cs{@@_ln_exponent:wn}
+% \Arg{s_1} \Arg{s_2} \Arg{s_3} \Arg{s_4} \Arg{s_5} \Arg{s_6} |;|
+% \Arg{exponent}
+% \end{quote}
+% Compute \meta{exponent} times $\ln 10$. Apart from the cases where
+% \meta{exponent} is $0$ or $1$, the result will necessarily be at
+% least $\ln 10 \simeq 2.3$ in magnitude. We can thus drop the least
+% significant $4$ digits. In the case of a very large (positive or
+% negative) exponent, we can (and we need to) drop $4$ additional
+% digits, since the result is of order $10^4$. Naively, one would
+% think that in both cases we can drop $4$ more digits than we do,
+% but that would be slightly too tight for rounding to happen correctly.
+% Besides, we already have addition and subtraction for $24$ digits
+% fixed point numbers.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_exponent:wn #1; #2
+ {
+ \if_case:w #2 \exp_stop_f:
+ \c_zero \@@_case_return:nw { \@@_fixed_to_float:Nw 2 }
+ \or:
+ \exp_after:wN \@@_ln_exponent_one:ww \__int_value:w
+ \else:
+ \if_int_compare:w #2 > \c_zero
+ \exp_after:wN \@@_ln_exponent_small:NNww
+ \exp_after:wN 0
+ \exp_after:wN \@@_fixed_sub:wwN \__int_value:w
+ \else:
+ \exp_after:wN \@@_ln_exponent_small:NNww
+ \exp_after:wN 2
+ \exp_after:wN \@@_fixed_add:wwN \__int_value:w -
+ \fi:
+ \fi:
+ #2; #1;
+ }
+% \end{macrocode}
+% Now we painfully write all the cases.\footnote{Bruno: do rounding.}
+% No overflow nor underflow can happen, except when computing \texttt{ln(1)}.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_exponent_one:ww 1; #1;
+ {
+ \c_zero
+ \exp_after:wN \@@_fixed_sub:wwN \c_@@_ln_x_fixed_tl ; #1;
+ \@@_fixed_to_float:wN 0
+ }
+% \end{macrocode}
+% For small exponents, we just drop one block of digits, and set the
+% exponent of the log to $4$ (minus any shift coming from leading zeros
+% in the conversion from fixed point to floating point). Note that here
+% the exponent has been made positive.
+% \begin{macrocode}
+\cs_new:Npn \@@_ln_exponent_small:NNww #1#2#3; #4#5#6#7#8#9;
+ {
+ \c_four
+ \exp_after:wN \@@_fixed_mul:wwn
+ \c_@@_ln_x_fixed_tl ;
+ {#3}{0000}{0000}{0000}{0000}{0000} ;
+ #2
+ {0000}{#4}{#5}{#6}{#7}{#8};
+ \@@_fixed_to_float:wN #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Exponential}
+%
+% \subsubsection{Sign, exponent, and special numbers}
+%
+% \begin{macro}[int, EXP]{\@@_exp:w}
+% \begin{macrocode}
+\cs_new:Npn \@@_exp:w \s_@@ \@@_chk:w #1#2
+ {
+ \if_case:w #1 \exp_stop_f:
+ \@@_case_return_o:Nw \c_one_fp
+ \or:
+ \exp_after:wN \@@_exp_normal:w
+ \or:
+ \if_meaning:w 0 #2
+ \exp_after:wN \@@_case_return_o:Nw
+ \exp_after:wN \c_inf_fp
+ \else:
+ \exp_after:wN \@@_case_return_o:Nw
+ \exp_after:wN \c_zero_fp
+ \fi:
+ \or:
+ \@@_case_return_same_o:w
+ \fi:
+ \s_@@ \@@_chk:w #1#2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_exp_normal:w, \@@_exp_pos:Nnwnw}
+% \begin{macrocode}
+\cs_new:Npn \@@_exp_normal:w \s_@@ \@@_chk:w 1#1
+ {
+ \if_meaning:w 0 #1
+ \@@_exp_pos:NNwnw + \@@_fixed_to_float:wN
+ \else:
+ \@@_exp_pos:NNwnw - \@@_fixed_inv_to_float:wN
+ \fi:
+ }
+\cs_new:Npn \@@_exp_pos:NNwnw #1#2#3 \fi: #4#5;
+ {
+ \fi:
+ \exp_after:wN \@@_sanitize:Nw
+ \exp_after:wN 0
+ \__int_value:w #1 \__int_eval:w
+ \if_int_compare:w #4 < - \c_eight
+ \c_one
+ \exp_after:wN \@@_add_big_i:wNww
+ \int_use:N \__int_eval:w \c_one - #4 ;
+ 0 {1000}{0000}{0000}{0000} ; #5;
+ \tex_romannumeral:D
+ \else:
+ \if_int_compare:w #4 > \c_five % cf \c_@@_max_exponent_int
+ \exp_after:wN \@@_exp_overflow:
+ \tex_romannumeral:D
+ \else:
+ \if_int_compare:w #4 < \c_zero
+ \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \use_ii:nn
+ \fi:
+ {
+ \c_zero
+ \@@_decimate:nNnnnn { - #4 }
+ \@@_exp_Taylor:Nnnwn
+ }
+ {
+ \@@_decimate:nNnnnn { \c_sixteen - #4 }
+ \@@_exp_pos_large:NnnNwn
+ }
+ #5
+ {#4}
+ #2 0
+ \tex_romannumeral:D
+ \fi:
+ \fi:
+ \exp_after:wN \c_zero
+ }
+\cs_new:Npn \@@_exp_overflow:
+ { + \c_two * \c_@@_max_exponent_int ; {1000} {0000} {0000} {0000} ; }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_exp_Taylor:Nnnwn}
+% \begin{macro}[aux, EXP]{\@@_exp_Taylor_loop:www, \@@_exp_Taylor_break:Nww}
+% This function is called for numbers in the range $[10^{-9},
+% 10^{-1})$. Our only task is to compute the Taylor series. The
+% first argument is irrelevant (rounding digit used by some other
+% functions). The next three arguments, at least $16$ digits,
+% delimited by a semicolon, form a fixed point number, so we pack it
+% in blocks of $4$ digits.
+% \begin{macrocode}
+\cs_new:Npn \@@_exp_Taylor:Nnnwn #1#2#3 #4; #5
+ {
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_exp_Taylor_ii:ww
+ ; #2#3#4 0000 0000 ;
+ }
+\cs_new:Npn \@@_exp_Taylor_ii:ww #1; #2;
+ { \@@_exp_Taylor_loop:www 10 ; #1 ; #1 ; \s__stop }
+\cs_new:Npn \@@_exp_Taylor_loop:www #1; #2; #3;
+ {
+ \if_int_compare:w #1 = \c_one
+ \exp_after:wN \@@_exp_Taylor_break:Nww
+ \fi:
+ \@@_fixed_div_int:wwN #3 ; #1 ;
+ \@@_fixed_add_one:wN
+ \@@_fixed_mul:wwn #2 ;
+ {
+ \exp_after:wN \@@_exp_Taylor_loop:www
+ \int_use:N \__int_eval:w #1 - 1 ;
+ #2 ;
+ }
+ }
+\cs_new:Npn \@@_exp_Taylor_break:Nww #1 #2; #3 \s__stop
+ { \@@_fixed_add_one:wN #2 ; }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]
+% {
+% \@@_exp_pos_large:NnnNwn ,
+% \@@_exp_large_after:wwn ,
+% \@@_exp_large:w ,
+% \@@_exp_large_v:wN,
+% \@@_exp_large_iv:wN,
+% \@@_exp_large_iii:wN,
+% \@@_exp_large_ii:wN,
+% \@@_exp_large_i:wN,
+% \@@_exp_large_:wN,
+% }
+% The first two arguments are irrelevant (a rounding digit, and a
+% brace group with $8$ zeros). The third argument is the integer part
+% of our number, then we have the decimal part delimited by a
+% semicolon, and finally the exponent, in the range $[0,5]$. Remove
+% leading zeros from the integer part: putting |#4| in there too
+% ensures that an integer part of $0$ is also removed. Then read
+% digits one by one, looking up $\exp(\meta{digit}\cdot
+% 10^{\meta{exponent}})$ in a table, and multiplying that to the
+% current total. The loop is done by having the auxiliary for one
+% exponent call the auxiliary for the next exponent. The current
+% total is expressed by leaving the exponent behind in the input
+% stream (we are currently within an \cs{__int_eval:w}), and keeping
+% track of a fixed point number, |#1| for the numbered auxiliaries.
+% Our usage of \cs{if_case:w} is somewhat dirty for optimization:
+% \TeX{} jumps to the appropriate case, but we then lose the
+% \cs{if_case:w} \enquote{by hand}, using \cs{or:} and \cs{fi:} as
+% delimiters.
+% \begin{macrocode}
+\cs_new:Npn \@@_exp_pos_large:NnnNwn #1#2#3 #4#5; #6
+ {
+ \exp_after:wN \exp_after:wN
+ \cs:w @@_exp_large_\tex_romannumeral:D #6:wN \exp_after:wN \cs_end:
+ \exp_after:wN \c_@@_one_fixed_tl
+ \exp_after:wN ;
+ \__int_value:w #3 #4 \exp_stop_f:
+ #5 00000 ;
+ }
+\cs_new:Npn \@@_exp_large:w #1 \or: #2 \fi:
+ { \fi: \@@_fixed_mul:wwn #1; }
+\cs_new:Npn \@@_exp_large_v:wN #1; #2
+ {
+ \if_case:w #2 ~ \exp_after:wN \@@_fixed_continue:wn \or:
+ + 4343 \@@_exp_large:w {8806}{8182}{2566}{2921}{5872}{6150} \or:
+ + 8686 \@@_exp_large:w {7756}{0047}{2598}{6861}{0458}{3204} \or:
+ + 13029 \@@_exp_large:w {6830}{5723}{7791}{4884}{1932}{7351} \or:
+ + 17372 \@@_exp_large:w {6015}{5609}{3095}{3052}{3494}{7574} \or:
+ + 21715 \@@_exp_large:w {5297}{7951}{6443}{0315}{3251}{3576} \or:
+ + 26058 \@@_exp_large:w {4665}{6719}{0099}{3379}{5527}{2929} \or:
+ + 30401 \@@_exp_large:w {4108}{9724}{3326}{3186}{5271}{5665} \or:
+ + 34744 \@@_exp_large:w {3618}{6973}{3140}{0875}{3856}{4102} \or:
+ + 39087 \@@_exp_large:w {3186}{9209}{6113}{3900}{6705}{9685} \or:
+ \fi:
+ #1;
+ \@@_exp_large_iv:wN
+ }
+\cs_new:Npn \@@_exp_large_iv:wN #1; #2
+ {
+ \if_case:w #2 ~ \exp_after:wN \@@_fixed_continue:wn \or:
+ + 435 \@@_exp_large:w {1970}{0711}{1401}{7046}{9938}{8888} \or:
+ + 869 \@@_exp_large:w {3881}{1801}{9428}{4368}{5764}{8232} \or:
+ + 1303 \@@_exp_large:w {7646}{2009}{8905}{4704}{8893}{1073} \or:
+ + 1738 \@@_exp_large:w {1506}{3559}{7005}{0524}{9009}{7592} \or:
+ + 2172 \@@_exp_large:w {2967}{6283}{8402}{3667}{0689}{6630} \or:
+ + 2606 \@@_exp_large:w {5846}{4389}{5650}{2114}{7278}{5046} \or:
+ + 3041 \@@_exp_large:w {1151}{7900}{5080}{6878}{2914}{4154} \or:
+ + 3475 \@@_exp_large:w {2269}{1083}{0850}{6857}{8724}{4002} \or:
+ + 3909 \@@_exp_large:w {4470}{3047}{3316}{5442}{6408}{6591} \or:
+ \fi:
+ #1;
+ \@@_exp_large_iii:wN
+ }
+\cs_new:Npn \@@_exp_large_iii:wN #1; #2
+ {
+ \if_case:w #2 ~ \exp_after:wN \@@_fixed_continue:wn \or:
+ + 44 \@@_exp_large:w {2688}{1171}{4181}{6135}{4484}{1263} \or:
+ + 87 \@@_exp_large:w {7225}{9737}{6812}{5749}{2581}{7748} \or:
+ + 131 \@@_exp_large:w {1942}{4263}{9524}{1255}{9365}{8421} \or:
+ + 174 \@@_exp_large:w {5221}{4696}{8976}{4143}{9505}{8876} \or:
+ + 218 \@@_exp_large:w {1403}{5922}{1785}{2837}{4107}{3977} \or:
+ + 261 \@@_exp_large:w {3773}{0203}{0092}{9939}{8234}{0143} \or:
+ + 305 \@@_exp_large:w {1014}{2320}{5473}{5004}{5094}{5533} \or:
+ + 348 \@@_exp_large:w {2726}{3745}{7211}{2566}{5673}{6478} \or:
+ + 391 \@@_exp_large:w {7328}{8142}{2230}{7421}{7051}{8866} \or:
+ \fi:
+ #1;
+ \@@_exp_large_ii:wN
+ }
+\cs_new:Npn \@@_exp_large_ii:wN #1; #2
+ {
+ \if_case:w #2 ~ \exp_after:wN \@@_fixed_continue:wn \or:
+ + 5 \@@_exp_large:w {2202}{6465}{7948}{0671}{6516}{9579} \or:
+ + 9 \@@_exp_large:w {4851}{6519}{5409}{7902}{7796}{9107} \or:
+ + 14 \@@_exp_large:w {1068}{6474}{5815}{2446}{2146}{9905} \or:
+ + 18 \@@_exp_large:w {2353}{8526}{6837}{0199}{8540}{7900} \or:
+ + 22 \@@_exp_large:w {5184}{7055}{2858}{7072}{4640}{8745} \or:
+ + 27 \@@_exp_large:w {1142}{0073}{8981}{5684}{2836}{6296} \or:
+ + 31 \@@_exp_large:w {2515}{4386}{7091}{9167}{0062}{6578} \or:
+ + 35 \@@_exp_large:w {5540}{6223}{8439}{3510}{0525}{7117} \or:
+ + 40 \@@_exp_large:w {1220}{4032}{9431}{7840}{8020}{0271} \or:
+ \fi:
+ #1;
+ \@@_exp_large_i:wN
+ }
+\cs_new:Npn \@@_exp_large_i:wN #1; #2
+ {
+ \if_case:w #2 ~ \exp_after:wN \@@_fixed_continue:wn \or:
+ + 1 \@@_exp_large:w {2718}{2818}{2845}{9045}{2353}{6029} \or:
+ + 1 \@@_exp_large:w {7389}{0560}{9893}{0650}{2272}{3043} \or:
+ + 2 \@@_exp_large:w {2008}{5536}{9231}{8766}{7740}{9285} \or:
+ + 2 \@@_exp_large:w {5459}{8150}{0331}{4423}{9078}{1103} \or:
+ + 3 \@@_exp_large:w {1484}{1315}{9102}{5766}{0342}{1116} \or:
+ + 3 \@@_exp_large:w {4034}{2879}{3492}{7351}{2260}{8387} \or:
+ + 4 \@@_exp_large:w {1096}{6331}{5842}{8458}{5992}{6372} \or:
+ + 4 \@@_exp_large:w {2980}{9579}{8704}{1728}{2747}{4359} \or:
+ + 4 \@@_exp_large:w {8103}{0839}{2757}{5384}{0077}{1000} \or:
+ \fi:
+ #1;
+ \@@_exp_large_:wN
+ }
+\cs_new:Npn \@@_exp_large_:wN #1; #2
+ {
+ \if_case:w #2 ~ \exp_after:wN \@@_fixed_continue:wn \or:
+ + 1 \@@_exp_large:w {1105}{1709}{1807}{5647}{6248}{1171} \or:
+ + 1 \@@_exp_large:w {1221}{4027}{5816}{0169}{8339}{2107} \or:
+ + 1 \@@_exp_large:w {1349}{8588}{0757}{6003}{1039}{8374} \or:
+ + 1 \@@_exp_large:w {1491}{8246}{9764}{1270}{3178}{2485} \or:
+ + 1 \@@_exp_large:w {1648}{7212}{7070}{0128}{1468}{4865} \or:
+ + 1 \@@_exp_large:w {1822}{1188}{0039}{0508}{9748}{7537} \or:
+ + 1 \@@_exp_large:w {2013}{7527}{0747}{0476}{5216}{2455} \or:
+ + 1 \@@_exp_large:w {2225}{5409}{2849}{2467}{6045}{7954} \or:
+ + 1 \@@_exp_large:w {2459}{6031}{1115}{6949}{6638}{0013} \or:
+ \fi:
+ #1;
+ \@@_exp_large_after:wwn
+ }
+\cs_new:Npn \@@_exp_large_after:wwn #1; #2;
+ {
+ \@@_exp_Taylor:Nnnwn ? { } { } 0 #2; {}
+ \@@_fixed_mul:wwn #1;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Power}
+%
+% Raising a number $a$ to a power $b$ leads to many distinct situations.
+% \begin{center}
+% \begin{tabular}{>{$}c<{$}|*8{>{$}l<{$}}}
+% a^b &-\infty&-y &-n &\pm 0&+n &+y &+\infty&\nan \\
+% \hline
+% +\infty&+0 &+0 &+0 &+1&+\infty &+\infty&+\infty&\nan \\
+% 1<x &+0 &+x^{-y}&+x^{-n} &+1&+x^{n} &+x^{y} &+\infty&\nan \\
+% +1 &+1 &+1 &+1 &+1&+1 &+1 &+1 &+1 \\
+% 0<x<1 &+\infty&+x^{-y}&+x^{-n} &+1&+x^{n} &+x^{y} &+0 &\nan \\
+% +0 &+\infty&+\infty&+\infty &+1&+0 &+0 &+0 &\nan \\
+% -0 &\nan &\nan &\pm\infty &+1&\pm 0 &+0 &+0 &\nan \\
+% -1<-x<0&\nan &\nan &\pm x^{-n}&+1&\pm x^{n}&\nan &+0 &\nan \\
+% -1 &\nan &\nan &\pm 1 &+1&\pm 1 &\nan &\nan &\nan \\
+% -x<-1 &+0 &\nan &\pm x^{-n}&+1&\pm x^{n}&\nan &\nan &\nan \\
+% -\infty&+0 &+0 &\pm 0 &+1&\pm\infty&\nan &\nan &\nan \\
+% \nan &\nan &\nan &\nan &+1&\nan &\nan &\nan &\nan \\
+% \end{tabular}
+% \end{center}
+% One peculiarity of this operation is that $\nan^0 = 1^\nan = 1$,
+% because this relation is obeyed for any number, even $\pm\infty$.
+%
+% \begin{macro}[int, EXP]+\@@_^_o:ww+
+% We cram a most of the tests into a single function to save csnames.
+% First treat the case $b=0$: $a^0=1$ for any $a$, even \texttt{nan}.
+% Then test the sign of $a$.
+% \begin{itemize}
+% \item If it is positive, and $a$ is a normal number, call
+% \cs{@@_pow_normal:ww} followed by the two \texttt{fp} $a$ and $b$.
+% For $a=+0$ or $+\inf$, call \cs{@@_pow_zero_or_inf:ww} instead, to
+% return either $+0$ or $+\infty$ as appropriate.
+% \item If $a$ is a \texttt{nan}, then skip to the next semicolon
+% (which happens to be conveniently the end of $b$) and return
+% \texttt{nan}.
+% \item Finally, if $a$ is negative, compute $|a|^b$
+% (\cs{@@_pow_normal:ww} which ignores the sign of its first
+% operand), and keep an extra copy of $a$ and $b$ (the second brace
+% group, containing \{~$b$~$a$~\}, is inserted between $a$ and $b$).
+% Then do some tests to find the final sign of the result if it
+% exists.
+% \end{itemize}
+% \begin{macrocode}
+\cs_new:cpn { @@_ \iow_char:N \^ _o:ww }
+ \s_@@ \@@_chk:w #1#2#3; \s_@@ \@@_chk:w #4#5#6;
+ {
+ \if_meaning:w 0 #4
+ \@@_case_return_o:Nw \c_one_fp
+ \fi:
+ \if_case:w #2 \exp_stop_f:
+ \exp_after:wN \use_i:nn
+ \or:
+ \@@_case_return_o:Nw \c_nan_fp
+ \else:
+ \exp_after:wN \@@_pow_neg:www
+ \tex_romannumeral:D -`0 \exp_after:wN \use:nn
+ \fi:
+ {
+ \if_meaning:w 1 #1
+ \exp_after:wN \@@_pow_normal:ww
+ \else:
+ \exp_after:wN \@@_pow_zero_or_inf:ww
+ \fi:
+ \s_@@ \@@_chk:w #1#2#3;
+ }
+ { \s_@@ \@@_chk:w #4#5#6; \s_@@ \@@_chk:w #1#2#3; }
+ \s_@@ \@@_chk:w #4#5#6;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_pow_zero_or_inf:ww}
+% Raising $-0$ or $-\infty$ to \texttt{nan} yields \texttt{nan}. For
+% other powers, the result is $+0$ if $0$ is raised to a positive
+% power or $\infty$ to a negative power, and $+\infty$ otherwise. We
+% can thus know the result by comparing the type of $a$ with the sign
+% of $b$, since those conveniently take the same possible values, $0$
+% and~$2$.
+% \begin{macrocode}
+\cs_new:Npn \@@_pow_zero_or_inf:ww \s_@@ \@@_chk:w #1#2; \s_@@ \@@_chk:w #3#4
+ {
+ \if_meaning:w 1 #4
+ \@@_case_return_same_o:w
+ \fi:
+ \if_meaning:w #1 #4
+ \@@_case_return_o:Nw \c_zero_fp
+ \else:
+ \@@_case_return_o:Nw \c_inf_fp
+ \fi:
+ \s_@@ \@@_chk:w #3#4
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_pow_normal:ww}
+% We have in front of us $a$, and $b\neq 0$, we know that $a$ is a
+% normal number, and we wish to compute $\lvert a\rvert^{b}$. If
+% $\lvert a\rvert=1$, we return $1$, unless $a=-1$ and $b$ is
+% \texttt{nan}. Indeed, returning $1$ at this point would wrongly
+% raise \enquote{invalid} when the sign is considered. If $\lvert
+% a\rvert\neq 1$, test the type of $b$:
+% \begin{itemize}
+% \item[0] Impossible, we already filtered $b=\pm 0$.
+% \item[1] Call \cs{@@_pow_npos:ww}.
+% \item[2] Return $+\infty$ or $+0$ depending on the sign of $b$ and
+% whether the exponent of $a$ is positive or not.
+% \item[3] Return $b$.
+% \end{itemize}
+% \begin{macrocode}
+\cs_new:Npn \@@_pow_normal:ww \s_@@ \@@_chk:w 1 #1#2#3; \s_@@ \@@_chk:w #4#5
+ {
+ \if_int_compare:w \pdftex_strcmp:D { #2 #3 }
+ { 1 {1000} {0000} {0000} {0000} } = \c_zero
+ \if_int_compare:w #4 #1 = 32 \exp_stop_f:
+ \exp_after:wN \@@_case_return_ii_o:ww
+ \fi:
+ \@@_case_return_o:Nww \c_one_fp
+ \fi:
+ \if_case:w #4 ~
+ \or:
+ \exp_after:wN \@@_pow_npos:Nww
+ \exp_after:wN #5
+ \or:
+ \if_meaning:w 2 #5 \exp_after:wN \reverse_if:N \fi:
+ \if_int_compare:w #2 > \c_zero
+ \exp_after:wN \@@_case_return_o:Nww
+ \exp_after:wN \c_inf_fp
+ \else:
+ \exp_after:wN \@@_case_return_o:Nww
+ \exp_after:wN \c_zero_fp
+ \fi:
+ \or:
+ \@@_case_return_ii_o:ww
+ \fi:
+ \s_@@ \@@_chk:w 1 #1 {#2} #3 ;
+ \s_@@ \@@_chk:w #4 #5
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% ^^A todo: check that we compute ln to 21 digits!
+% \begin{macro}[aux, EXP]{\@@_pow_npos:Nww}
+% We now know that $a\neq\pm 1$ is a normal number, and $b$ is a
+% normal number too. We want to compute $\lvert a\rvert^{b} = (\lvert
+% x\rvert\cdot 10^{n})^{y\cdot 10^{p}} = \exp((\log\lvert x\rvert + n
+% \log 10)\cdot y \cdot 10^{p}) = \exp(z)$. To compute the
+% exponential accurately, we need to know the digits of $z$ up to the
+% $16$-th position. Since the exponential of $10^{5}$ is infinite, we
+% only need at most $21$ digits, hence the fixed point result of
+% \cs{@@_ln:w} is precise enough for our needs. Start an integer
+% expression for the decimal exponent of $e^{\lvert z\rvert}$. If $z$
+% is negative, negate that decimal exponent, and prepare to take the
+% inverse when converting from the fixed point to the floating point result.
+% \begin{macrocode}
+\cs_new:Npn \@@_pow_npos:Nww #1 \s_@@ \@@_chk:w 1#2#3
+ {
+ \exp_after:wN \@@_sanitize:Nw
+ \exp_after:wN 0
+ \__int_value:w
+ \if:w #1 \if_int_compare:w #3 > \c_zero 0 \else: 2 \fi:
+ \exp_after:wN \@@_pow_npos_aux:Nnww
+ \exp_after:wN \@@_fixed_to_float:wN
+ \else:
+ -
+ \exp_after:wN \@@_pow_npos_aux:Nnww
+ \exp_after:wN \@@_fixed_inv_to_float:wN
+ \fi:
+ {#3}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%^^A begin[todo]
+% \begin{macro}[aux, EXP]{\@@_pow_npos_aux:Nnww}
+% The first argument is the conversion function from fixed point to
+% float. Then comes an exponent and the $4$ brace groups of $x$,
+% followed by $b$. Compute $-\log x$.
+% \begin{macrocode}
+\cs_new:Npn \@@_pow_npos_aux:Nnww #1#2#3#4; \s_@@ \@@_chk:w 1#5#6#7;
+ {
+ \__int_eval:w
+ \@@_ln_significand:NNNNnnnN #3#4
+ \@@_pow_exponent:wnN {#2}
+ \@@_fixed_mul:wwn #7 {0000}{0000} ;
+ \@@_pow_B:wwN #6;
+ #1 0 % fixed_to_float:wN
+ }
+\cs_new:Npn \@@_pow_exponent:wnN #1; #2
+ {
+ \if_int_compare:w #2 > \c_zero
+ \exp_after:wN \@@_pow_exponent:Nwnnnnnn % n\log 10 - (-\log x)
+ \exp_after:wN +
+ \else:
+ \exp_after:wN \@@_pow_exponent:Nwnnnnnn % -( |n|\log 10 + (-\log x) )
+ \exp_after:wN -
+ \fi:
+ #2; #1;
+ }
+\cs_new:Npn \@@_pow_exponent:Nwnnnnnn #1#2; #3#4#5#6#7#8;
+ { %^^A todo: use that in ln. %^^A todo: log(1.00...) too inaccurate?
+ \exp_after:wN \@@_fixed_mul_after:wwn
+ \int_use:N \__int_eval:w -5 0000
+ \exp_after:wN \@@_fixed_mul_pack:NNNNNw
+ \int_use:N \__int_eval:w 4 9995 0000 #1#2*23025 - #1 #3
+ \exp_after:wN \@@_fixed_mul_pack:NNNNNw
+ \int_use:N \__int_eval:w 4 9995 0000 #1 #2*8509 - #1 #4
+ \exp_after:wN \@@_fixed_mul_pack:NNNNNw
+ \int_use:N \__int_eval:w 4 9995 0000 #1 #2*2994 - #1 #5
+ \exp_after:wN \@@_fixed_mul_pack:NNNNNw
+ \int_use:N \__int_eval:w 4 9995 0000 #1 #2*0456 - #1 #6
+ \exp_after:wN \@@_fixed_mul_pack:NNNNNw
+ \int_use:N \__int_eval:w 5 0000 0000 #1 #2*8401 - #1 #7
+ #1 ( #2*7991 - #8 ) / 1 0000 ; ;
+ }
+\cs_new:Npn \@@_pow_B:wwN #1#2#3#4#5#6; #7;
+ {
+ \if_int_compare:w #7 < \c_zero
+ \exp_after:wN \@@_pow_C_neg:w \__int_value:w -
+ \else:
+ \if_int_compare:w #7 < 22 \exp_stop_f:
+ \exp_after:wN \@@_pow_C_pos:w \__int_value:w
+ \else:
+ \exp_after:wN \@@_pow_C_overflow:w \__int_value:w
+ \fi:
+ \fi:
+ #7 \exp_after:wN ;
+ \int_use:N \__int_eval:w 10 0000 + #1 \__int_eval_end:
+ #2#3#4#5#6 0000 0000 0000 0000 0000 0000 ; %^^A todo: how many 0?
+ }
+\cs_new:Npn \@@_pow_C_overflow:w #1; #2;
+ {
+ + \c_two * \c_@@_max_exponent_int
+ \exp_after:wN \@@_fixed_continue:wn \c_@@_one_fixed_tl ;
+ }
+\cs_new:Npn \@@_pow_C_neg:w #1 ; 1
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \@@_pow_C_pack:w
+ \prg_replicate:nn {#1} {0}
+ }
+\cs_new:Npn \@@_pow_C_pos:w #1; 1
+ { \@@_pow_C_pos_loop:wN #1; }
+\cs_new:Npn \@@_pow_C_pos_loop:wN #1; #2
+ {
+ \if_meaning:w 0 #1
+ \exp_after:wN \@@_pow_C_pack:w
+ \exp_after:wN #2
+ \else:
+ \if_meaning:w 0 #2
+ \exp_after:wN \@@_pow_C_pos_loop:wN \__int_value:w
+ \else:
+ \exp_after:wN \@@_pow_C_overflow:w \__int_value:w
+ \fi:
+ \__int_eval:w #1 - \c_one \exp_after:wN ;
+ \fi:
+ }
+\cs_new:Npn \@@_pow_C_pack:w
+ { \exp_after:wN \@@_exp_large_v:wN \c_@@_one_fixed_tl ; }
+% \end{macrocode}
+% \end{macro}
+%^^A end[todo]
+%
+% \begin{macro}[aux, EXP]{\@@_pow_neg:www, \@@_pow_neg_neg:w}
+% This function is followed by three floating point numbers: $|a|^b$,
+% $a\in[-\infty,-0]$, and $b$. If $b$ is an even integer (case $-1$),
+% $a^b=|a|^b$. If $b$ is an odd integer (case $0$), $a^b=-|a|^b$,
+% obtained by a call to \cs{@@_pow_neg_neg:w}. Otherwise, the sign is
+% undefined. This is invalid, unless $|a|^b$ turns out to be $+0$ or
+% \texttt{nan}, in which case we return that as $a^b$. In particular,
+% since the underflow detection occurs before \cs{@@_pow_neg:www} is
+% called, |(-0.1)**(12345.6)| will give $+0$ rather than complaining
+% that the sign is not defined.
+% \begin{macrocode}
+\cs_new:Npn \@@_pow_neg:www \s_@@ \@@_chk:w #1#2; #3; #4;
+ {
+ \if_case:w \@@_pow_neg_case:w #4 ;
+ \exp_after:wN \@@_pow_neg_neg:w
+ \or:
+ \if_int_compare:w \__int_eval:w #1 / \c_two = \c_one
+ \@@_invalid_operation:Nnww \c_nan_fp { ^ } #3; #4;
+ \tex_romannumeral:D -`0
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_use_none_until_s:w
+ \fi:
+ \fi:
+ \@@_exp_after_o:w
+ \s_@@ \@@_chk:w #1#2;
+ }
+\cs_new:Npn \@@_pow_neg_neg:w \@@_exp_after_o:w \s_@@ \@@_chk:w #1#2
+ {
+ \exp_after:wN \@@_exp_after_o:w
+ \exp_after:wN \s_@@
+ \exp_after:wN \@@_chk:w
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w \c_two - #2 \__int_eval_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]
+% {
+% \@@_pow_neg_case:w, \@@_pow_neg_case_aux:nnnnn,
+% \@@_pow_neg_case_aux:NNNNNNNNw
+% }
+% This function expects a floating point number, and \enquote{returns}
+% $-1$ if it is an even integer, $0$ if it is an odd integer, and $1$
+% if it is not an integer. Zeros are even, $\pm\infty$ and
+% \texttt{nan} are non-integers. The sign of normal numbers is
+% irrelevant to parity. If the exponent is greater than sixteen, then
+% the number is even. If the exponent is non-positive, the number
+% cannot be an integer. We also separate the ranges of exponent
+% $[1,8]$ and $[9,16]$. In the former case, check that the last $8$
+% digits are zero (otherwise we don't have an integer). In both
+% cases, consider the appropriate $8$ digits, either |#4#5| or |#2#3|,
+% remove the first few: we are then left with \meta{digit}
+% \meta{digits} |;| which would be the digits surrounding the decimal
+% period. If the \meta{digits} are non-zero, the number is not an
+% integer. Otherwise, check the parity of the \meta{digit} and return
+% \cs{c_zero} or \cs{c_minus_one}.
+% \begin{macrocode}
+\cs_new:Npn \@@_pow_neg_case:w \s_@@ \@@_chk:w #1#2#3;
+ {
+ \if_case:w #1 \exp_stop_f:
+ \c_minus_one
+ \or: \@@_pow_neg_case_aux:nnnnn #3
+ \else: \c_one
+ \fi:
+ }
+\cs_new:Npn \@@_pow_neg_case_aux:nnnnn #1#2#3#4#5
+ {
+ \if_int_compare:w #1 > \c_eight
+ \if_int_compare:w #1 > \c_sixteen
+ \c_minus_one
+ \else:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_pow_neg_case_aux:NNNNNNNNw
+ \prg_replicate:nn { \c_sixteen - #1 } { 0 } #4#5 ;
+ \fi:
+ \else:
+ \if_int_compare:w #1 > \c_zero
+ \if_int_compare:w #4#5 = \c_zero
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_pow_neg_case_aux:NNNNNNNNw
+ \prg_replicate:nn { \c_eight - #1 } { 0 } #2#3 ;
+ \else:
+ \c_one
+ \fi:
+ \else:
+ \c_one
+ \fi:
+ \fi:
+ }
+\cs_new:Npn \@@_pow_neg_case_aux:NNNNNNNNw #1#2#3#4#5#6#7#8#9;
+ {
+ \if_int_compare:w 0 #9 = \c_zero
+ \if_int_odd:w #8 \exp_stop_f:
+ \c_zero
+ \else:
+ \c_minus_one
+ \fi:
+ \else:
+ \c_one
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
new file mode 100644
index 00000000000..d38c6de8e17
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-extended.dtx
@@ -0,0 +1,674 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-extended.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-extended.dtx 2474 2011-06-17 12:54:02Z bruno $
+ {L3 Floating-point extended precision fixed-points}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-extended} package\thanks{This file
+% has version number \ExplFileVersion, last
+% revised \ExplFileDate.}\\
+% Fixed points with extended precision for internal use}
+% \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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-extended} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% In this module, we work on (almost) fixed-point numbers with
+% extended ($24$ digits) precision. This is used in the computation of
+% Taylor series for the logarithm, exponential, and trigonometric
+% functions. Since we eventually only care about the $16$ first digits
+% of the final result, some of the calculations are not performed with
+% the full $24$-digit precision. In other words, the last two blocks of
+% each fixed point number may be wrong as long as the error is small
+% enough to be rounded away when converting back to a floating point
+% number. The fixed point numbers are expressed as
+% \begin{quote}
+% \Arg{a_1} \Arg{a_2} \Arg{a_3} \Arg{a_4} \Arg{a_5} \Arg{a_6} |;|
+% \end{quote}
+% where each \meta{a_i} is exactly $4$ digits, except
+% \meta{a_1}, which may be any positive \TeX{} integer. The fixed point
+% number $a$ corresponding to the representation above is $a =
+% \sum_{i=1}^{6} \meta{a_i} \cdot 10^{-4i}$.
+%
+% Most functions we define here have the form
+% \begin{syntax}
+% \cs{@@_fixed_\meta{calculation}:wwN} \meta{operand_1} |;| \meta{operand_2} |;| \meta{continuation}
+% \end{syntax}
+% They perform the \meta{calculation} on the two \meta{operands}, then
+% feed the result ($6$ brace groups followed by a semicolon) to the
+% \meta{continuation}, responsible for the next step of the calculation.
+% This allows constructions such as
+% \begin{quote}
+% \cs{@@_fixed_add:wwN} \meta{X_1} |;| \meta{X_2} |;| \\
+% \cs{@@_fixed_mul:wwn} \meta{X_3} |;| \\
+% \cs{@@_fixed_add:wwN} \meta{X_4} |;| \\
+% \end{quote}
+% to compute $(X_1+X_2)\cdot X_3 + X_4$. This turns out to be very
+% appropriate for computing continued fractions and Taylor series.
+%
+% At the end of the calculation, the result is turned back to a floating
+% point number using \cs{@@_fixed_to_float:Nw}. This function has to
+% change the exponent of the floating point number: it must be used
+% after starting an integer expression for the overall exponent of the
+% result.
+%
+% \begin{variable}{\c_@@_one_fixed_tl}
+% \begin{macrocode}
+\tl_const:Nn \c_@@_one_fixed_tl
+ { {10000} {0000} {0000} {0000} {0000} {0000} }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[int, EXP]{\@@_fixed_continue:wn}
+% This function does nothing.
+% \begin{macrocode}
+\cs_new:Npn \@@_fixed_continue:wn #1; #2 { #2 #1; }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_fixed_div_int:wwN}
+% \begin{macro}[aux, EXP]
+% {
+% \@@_fixed_div_int_i:wnN, \@@_fixed_div_int_ii:wnn,
+% \@@_fixed_div_int_end:wnn, \@@_fixed_div_int_pack:Nw,
+% \@@_fixed_div_int_after:Nw
+% }
+% \begin{syntax}
+% \cs{@@_fixed_div_int:wwN} \meta{a} |;| \meta{n} |;| \meta{function}
+% \end{syntax}
+% Divides the fixed point number \meta{a} by the (small) integer
+% $0<\meta{n}<10^4$ and feeds the result to the \meta{function}. The
+% \texttt{wnN} auxiliary receives $a_{i}$, $n$, and a continuation
+% function as arguments, and computes a (rather tight) lower bound
+% $Q_{i}$ for the quotient. The \texttt{wnn} auxiliary receives
+% $Q_{i}$, $n$, and $a_{i}$. It adds $Q_{i}$ to a surrounding integer
+% expression, and starts a new one. It also computes $a_{i}-n\cdot
+% Q_{i}$, putting the result in front of $a_{i+1}$ to serve as the
+% first argument for a new call to the \texttt{wnN} auxiliary. At the
+% end, the path we took to the lowest levels rewinds: the
+% \texttt{pack} auxiliary receives $5$ digits, braces the last $4$,
+% and carries the leading digit to the level above. The offsets used
+% to ensure a given number of digits are as follows: we first subtract
+% $1$ from the top-level, then add $9999$ at every subsequent level,
+% and add $2$ to the last level. This last number is not $1$, because
+% it compensates for the |- \c_one| in the \texttt{wnN} auxiliary.
+% \begin{macrocode}
+\cs_new:Npn \@@_fixed_div_int:wwN #1#2#3#4#5#6 ; #7 ; #8
+ {
+ \exp_after:wN \@@_fixed_div_int_after:Nw
+ \exp_after:wN #8
+ \int_use:N \__int_eval:w \c_minus_one
+ \@@_fixed_div_int_i:wnN
+ #1; {#7} \@@_fixed_div_int_ii:wnn
+ #2; {#7} \@@_fixed_div_int_ii:wnn
+ #3; {#7} \@@_fixed_div_int_ii:wnn
+ #4; {#7} \@@_fixed_div_int_ii:wnn
+ #5; {#7} \@@_fixed_div_int_ii:wnn
+ #6; {#7} \@@_fixed_div_int_end:wnn ;
+ }
+\cs_new:Npn \@@_fixed_div_int_i:wnN #1; #2 #3
+ {
+ \exp_after:wN #3
+ \int_use:N \__int_eval:w #1 / #2 - \c_one ;
+ {#2}
+ {#1}
+ }
+\cs_new:Npn \@@_fixed_div_int_ii:wnn #1; #2 #3
+ {
+ + #1
+ \exp_after:wN \@@_fixed_div_int_pack:Nw
+ \int_use:N \__int_eval:w 9999
+ \exp_after:wN \@@_fixed_div_int_i:wnN
+ \int_use:N \__int_eval:w #3 - #1*#2 \__int_eval_end:
+ }
+\cs_new:Npn \@@_fixed_div_int_end:wnn #1; #2 #3 { + #1 + \c_two ; }
+\cs_new:Npn \@@_fixed_div_int_pack:Nw #1 #2; { + #1; {#2} }
+\cs_new:Npn \@@_fixed_div_int_after:Nw #1 #2; { #1 {#2} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_fixed_add_one:wN}
+% \begin{syntax}
+% \cs{@@_fixed_add_one:wN} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \Arg{X_5} \Arg{X_6} |;| \meta{function}
+% \end{syntax}
+% \begin{macrocode}
+\cs_new:Npn \@@_fixed_add_one:wN #1#2; #3
+ {
+ \exp_after:wN #3 \exp_after:wN
+ { \int_use:N \__int_eval:w 10000 + #1 } #2 ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]
+% {\@@_fixed_add:wwN, \@@_fixed_sub:wwN, \@@_fixed_sub_back:wwN}
+%^^A todo: remove sub_back.
+% \begin{macro}[aux, EXP]
+% {
+% \@@_fixed_add_i:NNnnnnwnn,
+% \@@_fixed_add_ii:NnnNnnnnw,
+% \@@_fixed_add_pack:NNNNNwN,
+% \@@_fixed_add_after:NNNNNwN
+% }
+% \begin{syntax}
+% \cs{@@_fixed_add:wwN} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \Arg{X_5} \Arg{X_6} |;| \Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} \Arg{Y_5} \Arg{Y_6} |;| \meta{function}
+% \end{syntax}
+% Computes $X+Y$ (resp.\ $X-Y$ and $Y-X$) and feeds the result to
+% \meta{function}. The three functions only differ by some signs and
+% use a common auxiliary. It would be nice to grab the $12$ brace
+% groups in one go, only $9$ arguments are allowed. Start by grabbing
+% the two signs, $X_{1}, \ldots, X_{4}$, the rest of $X$, and $Y_{1}$
+% and $Y_{2}$. The second auxiliary receives the sign of $X$, the
+% rest of $X$, the sign of $Y$, the rest of $Y$, and the
+% \meta{function}. After going down through the various level, we go
+% back up, packing digits and bringing the \meta{function} (|#9|, then
+% |#7|) from the end of the argument list to its start.
+% \begin{macrocode}
+\cs_new_nopar:Npn \@@_fixed_add:wwN { \@@_fixed_add_i:NNnnnnwnn + + }
+\cs_new_nopar:Npn \@@_fixed_sub:wwN { \@@_fixed_add_i:NNnnnnwnn + - }
+\cs_new_nopar:Npn \@@_fixed_sub_back:wwN { \@@_fixed_add_i:NNnnnnwnn - + }
+\cs_new:Npn \@@_fixed_add_i:NNnnnnwnn #1#2 #3#4#5#6 #7; #8#9
+ {
+ \exp_after:wN \@@_fixed_add_after:NNNNNwN
+ \int_use:N \__int_eval:w 1 9999 9998 #1 #3#4 #2 #8#9
+ \exp_after:wN \@@_fixed_add_pack:NNNNNwN
+ \int_use:N \__int_eval:w 1 9999 9998 #1 #5#6
+ \@@_fixed_add_ii:NnnNnnnnw #1 #7 #2
+ }
+\cs_new:Npn \@@_fixed_add_ii:NnnNnnnnw #1 #2#3 #4 #5#6 #7#8 ; #9
+ {
+ #4 #5#6
+ \exp_after:wN \@@_fixed_add_pack:NNNNNwN
+ \int_use:N \__int_eval:w 2 0000 0000 #4 #7#8 #1 #2#3 ; #9 ;
+ }
+\cs_new:Npn \@@_fixed_add_pack:NNNNNwN #1 #2#3#4#5 #6; #7
+ { + #1 ; #7 {#2#3#4#5} {#6} }
+\cs_new:Npn \@@_fixed_add_after:NNNNNwN #1 #2#3#4#5 #6; #7
+ {
+ \exp_after:wN #7
+ \exp_after:wN { \int_use:N \__int_eval:w - 2 0000 + #1#2#3#4#5 }
+ {#6}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_fixed_mul:wwn}
+% \begin{macro}[aux, EXP]
+% {
+% \@@_fixed_mul_i:nnnnnnnn ,
+% \@@_fixed_mul_pack:NNNNNw ,
+% \@@_fixed_mul_after:wwn
+% }
+% \begin{syntax}
+% \cs{@@_fixed_mul:wwn} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \Arg{X_5} \Arg{X_6} |;| \Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} \Arg{Y_5} \Arg{Y_6} |;| \Arg{tokens}
+% \end{syntax}
+% Computes $X\times Y$ and feeds the result to \meta{function}. It
+% would be nice to grab the $12$ brace groups in one go, but that's
+% not possible. On the other hand, we don't need to obtain an exact
+% rounding, contrarily to the case in \cs{@@_*_o:ww}, so things are
+% not quite as bad as they may seem. The parenthesis computing the
+% seventh group of digits (computed because we need to know its
+% potentially large carry) is closed by
+% \cs{@@_fixed_mul_i:nnnnnnnn}, once we access the last two brace
+% groups, which were not read before. Also, in
+% \cs{@@_fixed_mul_after:wwn}, |#3| is the continuation
+% tokens.\footnote{Bruno: insist on the difference compared to
+% \cs{@@_fixed_add:wwN}.}
+% \begin{macrocode}
+\cs_new:Npn \@@_fixed_mul:wwn #1#2#3#4 #5; #6#7#8#9
+ {
+ \exp_after:wN \@@_fixed_mul_after:wwn
+ \int_use:N \__int_eval:w \c_@@_leading_shift_int
+ \exp_after:wN \@@_pack:NNNNNw
+ \int_use:N \__int_eval:w \c_@@_middle_shift_int
+ + #1*#6
+ \exp_after:wN \@@_pack:NNNNNw
+ \int_use:N \__int_eval:w \c_@@_middle_shift_int
+ + #1*#7 + #2*#6
+ \exp_after:wN \@@_pack:NNNNNw
+ \int_use:N \__int_eval:w \c_@@_middle_shift_int
+ + #1*#8 + #2*#7 + #3*#6
+ \exp_after:wN \@@_pack:NNNNNw
+ \int_use:N \__int_eval:w \c_@@_middle_shift_int
+ + #1*#9 + #2*#8 + #3*#7 + #4*#6
+ \exp_after:wN \@@_pack:NNNNNw
+ \int_use:N \__int_eval:w \c_@@_trailing_shift_int
+ + #2*#9 + #3*#8 + #4*#7
+ + ( #3*#9 + #4*#8
+ + \@@_fixed_mul_i:nnnnnnnn #5 {#6}{#7} {#1}{#2}
+ }
+\cs_new:Npn \@@_fixed_mul_i:nnnnnnnn #1#2 #3#4 #5#6 #7#8
+ { #1*#4 + #2*#3 + #5*#8 + #6*#7 )/10000 + #1*#3 + #5*#7 ; }
+\cs_new:Npn \@@_fixed_mul_pack:NNNNNw
+ #1 #2#3#4#5 #6; { + #1#2#3#4#5 ; {#6} }
+\cs_new:Npn \@@_fixed_mul_after:wwn #1; #2; #3 { #3 {#1} #2 ; }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_fixed_mul_add:wwwn, \@@_fixed_mul_sub_back:wwwn}
+% \begin{syntax}
+% \cs{@@_fixed_mul_add:wwn} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \Arg{X_5} \Arg{X_6} |;| \Arg{Y_1} \Arg{Y_2} \Arg{Y_3} \Arg{Y_4} \Arg{Y_5} \Arg{Y_6} |;| \Arg{Z_1} \Arg{Z_2} \Arg{Z_3} \Arg{Z_4} \Arg{Z_5} \Arg{Z_6} |;| \Arg{tokens}
+% \end{syntax}
+% These functions compute $X\times Y + Z$ or $Z-X\times Y$ and feed
+% the result to the \meta{tokens}. This is tough because we have $18$
+% brace groups in front of us.
+% \begin{macrocode}
+\cs_new:Npn \@@_fixed_one_minus_mul:wwn #1; #2#3#4#5;
+ {
+ \exp_after:wN \@@_fixed_mul_after:wwn
+ \int_use:N \__int_eval:w \c_@@_big_leading_shift_int + \c_ten_thousand
+ \exp_after:wN \@@_pack_big:NNNNNNw
+ \int_use:N \__int_eval:w \c_@@_big_middle_shift_int
+ \@@_fixed_mul_add_i:Nnwnnwnnn
+ - 00; {#2}{#3}{#4}; #1; {#2}{#3}{#4}#5; - 00 ;
+ }
+\cs_new:Npn \@@_fixed_mul_add:wwwn #1; #2#3#4#5; #6#7#8#9
+ {
+ \exp_after:wN \@@_fixed_mul_after:wwn
+ \int_use:N \__int_eval:w \c_@@_big_leading_shift_int + #6
+ \exp_after:wN \@@_pack_big:NNNNNNw
+ \int_use:N \__int_eval:w \c_@@_big_middle_shift_int + #7
+ \@@_fixed_mul_add_i:Nnwnnwnnn
+ + {#8}{#9}; {#2}{#3}{#4}; #1; {#2}{#3}{#4}#5; +
+ }
+\cs_new:Npn \@@_fixed_mul_sub_back:wwwn #1; #2#3#4#5; #6#7#8#9
+ {
+ \exp_after:wN \@@_fixed_mul_after:wwn
+ \int_use:N \__int_eval:w \c_@@_big_leading_shift_int + #6
+ \exp_after:wN \@@_pack_big:NNNNNNw
+ \int_use:N \__int_eval:w \c_@@_big_middle_shift_int + #7
+ \@@_fixed_mul_add_i:Nnwnnwnnn
+ - {#8}{#9}; {#2}{#3}{#4}; #1; {#2}{#3}{#4}#5; -
+ }
+\cs_new:Npn \@@_fixed_mul_add_i:Nnwnnwnnn #1 #2#3; #4#5#6; #7#8#9
+ { % sg z3z4; y1y2y3; x1x2x3 x4x5x6; y1y2y3y4y5y6; sg z5z6;
+ #1 #7*#4
+ \exp_after:wN \@@_pack_big:NNNNNNw
+ \int_use:N \__int_eval:w \c_@@_big_middle_shift_int + #2
+ #1 #7*#5 #1 #8*#4
+ \exp_after:wN \@@_pack_big:NNNNNNw
+ \int_use:N \__int_eval:w \c_@@_big_middle_shift_int + #3
+ #1 #7*#6 #1 #8*#5 #1 #9*#4
+ \exp_after:wN \@@_pack_big:NNNNNNw
+ \int_use:N \__int_eval:w \c_@@_big_middle_shift_int
+ #1 \@@_fixed_mul_add_ii:nnnnwnnnn {#7}{#8}{#9}
+ }
+\cs_new:Npn \@@_fixed_mul_add_ii:nnnnwnnnn #1#2#3#4#5; #6#7#8#9
+ { % x1x2x3x4 x5x6; y1y2y3y4 y5y6; sg z5z6;
+ ( #1*#9 + #2*#8 + #3*#7 + #4*#6 )
+ \exp_after:wN \@@_pack_big:NNNNNNw
+ \int_use:N \__int_eval:w \c_@@_big_trailing_shift_int
+ \@@_fixed_mul_add_iii:nnnnwnnwN
+ { #6 + #4*#7 + #3*#8 + #2*#9 + #1 }
+ { #7 + #4*#8 + #3*#9 + #2 }
+ {#1} #5;
+ {#6}
+ }
+\cs_new:Npn \@@_fixed_mul_add_iii:nnnnwnnwN #1#2 #3#4#5; #6#7#8; #9
+ { % {y1+x4*y2+x3*y3+x2*y4+x1} {y2+x4*y3+x3*y4+x2}
+ % x1x5x6; y1y5y6; sg z5z6;
+ % =>
+ % sg (x5*y1+x4*y2+x3*y3+x2*y4+x1*y5)
+ % sg (x6*y1+x5*y2+x4*y3+x3*y4+x2*y5+x1*y6)/10000
+ % + z5z6;
+ #9 (#4* #1 *#7)
+ #9 (#5*#6+#4* #2 *#7+#3*#8) / \c_ten_thousand
+ + \@@_use_s:nn
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_fixed_to_float:Nw #1#2; { \@@_fixed_to_float:wN #2; #1 }
+% \end{macrocode}
+%
+% \begin{macro}[int, rEXP]{\@@_fixed_to_float:wN}
+% \begin{syntax}
+% \ldots{} \cs{__int_eval:w} \meta{exponent} \cs{@@_fixed_to_float:wN} \Arg{a_1} \Arg{a_2} \Arg{a_3} \Arg{a_4} \Arg{a_5} \Arg{a_6} |;| \meta{sign}
+% \end{syntax}
+% yields
+% \begin{quote}
+% \meta{exponent'} |;| \Arg{a'_1} \Arg{a'_2} \Arg{a'_3} \Arg{a'_4} |;|
+% \end{quote}
+% And the \texttt{to_fixed} version gives six brace groups instead of
+% $4$, ensuring that $1000\leq\meta{a'_1}\leq 9999$. At this stage, we
+% know that \meta{a_1} is positive (otherwise, it is sign of an error
+% before), and we assume that it is less than $10^8$.\footnote{Bruno:
+% I must double check this assumption.}
+%
+%^^A todo: round properly when rounding to infinity: I need to know the sign.
+% \begin{macrocode}
+\cs_new:Npn \@@_fixed_to_float:wN #1#2#3#4#5#6; #7
+ {
+ + \c_four % for the 8-digit-at-the-start thing.
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_fixed_to_loop:N
+ \exp_after:wN \use_none:n
+ \int_use:N \__int_eval:w
+ 1 0000 0000 + #1 \exp_after:wN \@@_use_none_stop_f:n
+ \__int_value:w 1#2 \exp_after:wN \@@_use_none_stop_f:n
+ \__int_value:w 1#3#4 \exp_after:wN \@@_use_none_stop_f:n
+ \__int_value:w 1#5#6
+ \exp_after:wN ;
+ \exp_after:wN ;
+ }
+\cs_new:Npn \@@_fixed_to_loop:N #1
+ {
+ \if_meaning:w 0 #1
+ - \c_one
+ \exp_after:wN \@@_fixed_to_loop:N
+ \else:
+ \exp_after:wN \@@_fixed_to_loop_end:w
+ \exp_after:wN #1
+ \fi:
+ }
+\cs_new:Npn \@@_fixed_to_loop_end:w #1 #2 ;
+ {
+ \if_meaning:w ; #1
+ \exp_after:wN \@@_fixed_to_float_zero:w
+ \else:
+ \exp_after:wN \@@_pack_twice_four:wNNNNNNNN
+ \exp_after:wN \@@_pack_twice_four:wNNNNNNNN
+ \exp_after:wN \@@_fixed_to_float_pack:ww
+ \exp_after:wN ;
+ \fi:
+ #1 #2 0000 0000 0000 0000 ;
+ }
+\cs_new:Npn \@@_fixed_to_float_zero:w ; 0000 0000 0000 0000 ;
+ {
+ - \c_two * \c_@@_max_exponent_int ;
+ {0000} {0000} {0000} {0000} ;
+ }
+\cs_new:Npn \@@_fixed_to_float_pack:ww #1 ; #2#3 ; ;
+ {
+ \if_int_compare:w #2 > \c_four
+ \exp_after:wN \@@_fixed_to_float_round_up:wnnnnw
+ \fi:
+ ; #1 ;
+ }
+\cs_new:Npn \@@_fixed_to_float_round_up:wnnnnw ; #1#2#3#4 ;
+ {
+ \exp_after:wN \@@_basics_pack_high:NNNNNw
+ \int_use:N \__int_eval:w 1 #1#2
+ \exp_after:wN \@@_basics_pack_low:NNNNNw
+ \int_use:N \__int_eval:w 1 #3#4 + \c_one ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[rEXP, int]{\@@_fixed_inv_to_float:wN, \@@_fixed_div_to_float:ww}
+% Starting from \texttt{fixed_dtf} $A$ |;| $B$ |;| we want to compute
+% $A/B$, and express it as a floating point number. Normalize both
+% numbers by removing leading brace groups of zeros and leaving the
+% appropriate exponent shift in the input stream.
+% \begin{macrocode}
+\cs_new:Npn \@@_fixed_inv_to_float:wN #1#2; #3
+ {
+ - \__int_eval:w
+ \if_int_compare:w #1 < \c_one_thousand
+ \@@_fixed_dtf_zeros:wNnnnnnn
+ \fi:
+ \@@_fixed_dtf_no_zero:Nwn + {#1} #2 \s_@@
+ \@@_fixed_dtf_approx:n
+ {10000} {0000} {0000} {0000} {0000} {0000} ;
+ }
+\cs_new:Npn \@@_fixed_div_to_float:ww #1#2; #3#4;
+ {
+ \if_int_compare:w #1 < \c_one_thousand
+ \@@_fixed_dtf_zeros:wNnnnnnn
+ \fi:
+ \@@_fixed_dtf_no_zero:Nwn - {#1} #2 \s_@@
+ {
+ \if_int_compare:w #3 < \c_one_thousand
+ \@@_fixed_dtf_zeros:wNnnnnnn
+ \fi:
+ \@@_fixed_dtf_no_zero:Nwn + {#3} #4 \s_@@
+ \@@_fixed_dtf_approx:n
+ }
+ }
+\cs_new:Npn \@@_fixed_dtf_no_zero:Nwn #1#2 \s_@@ #3 { #3 #2; }
+\cs_new:Npn \@@_fixed_dtf_zeros:wNnnnnnn
+ \fi: \@@_fixed_dtf_no_zero:Nwn #1#2#3#4#5#6#7
+ {
+ \fi:
+ #1 \c_minus_one
+ \exp_after:wN \use_i_ii:nnn
+ \exp_after:wN \@@_fixed_dtf_zeros:NN
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w 10 0000 + #2 \__int_eval_end: #3#4#5#6#7
+ ; 1 ;
+ }
+\cs_new:Npn \@@_fixed_dtf_zeros:NN #1#2
+ {
+ \if_meaning:w 0 #2
+ #1 \c_one
+ \else:
+ \@@_fixed_dtf_zeros_end:wNww #2
+ \fi:
+ \@@_fixed_dtf_zeros:NN #1
+ }
+\cs_new:Npn \@@_fixed_dtf_zeros_end:wNww
+ #1 \fi: \@@_fixed_dtf_zeros:NN #2 #3; #4 \s_@@
+ {
+ \fi:
+ \if_meaning:w ; #1
+ #2 \c_two * \c_@@_max_exponent_int
+ \use_i_ii:nnn
+ \fi:
+ \@@_fixed_dtf_zeros_ii:ww
+ #1#3 0000 0000 0000 0000 0000 0000 ;
+ }
+\cs_new:Npn \@@_fixed_dtf_zeros_ii:ww
+ {
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_fixed_dtf_zeros_iii:ww
+ ;
+ }
+\cs_new:Npn \@@_fixed_dtf_zeros_iii:ww #1; #2; #3 { #3 #1; }
+% \end{macrocode}
+% \newcommand{\eTeXfrac}[2]{\left[\frac{#1}{#2}\right]}
+% We get
+% \begin{quote}
+% \cs{@@_fixed_dtf_approx:n} \meta{B'} |;| \meta{A'} |;|
+% \end{quote}
+% where \meta{B'} and \meta{A'} are each $6$ brace groups,
+% representing fixed point numbers in the range $[0.1,1)$. Denote by
+% $x\in[1000,9999]$ and $y\in[0,9999]$ the first two groups of
+% \meta{B'}. We first find an estimate $a$ for the inverse of $B'$ by
+% computing
+% \begin{align*}
+% \alpha &= \eTeXfrac{10^{9}}{x+1} \\
+% \beta &= \eTeXfrac{10^{9}}{x} \\
+% a &= 10^{3} \alpha + (\beta-\alpha) \cdot
+% \left(10^{3}-\eTeXfrac{y}{10}\right) - 1750,
+% \end{align*}
+% where $\eTeXfrac{\bullet}{\bullet}$ denotes \eTeX{}'s rounding
+% division. The idea is to interpolate between $\alpha$ and $\beta$
+% with a parameter $y/10^{4}$. The shift by $1750$ helps to ensure
+% that $a$ is an underestimate of the correct value. We will prove
+% that
+% \[
+% 1 - 2.255\cdot 10^{-5} < \frac{B'a}{10^{8}} < 1 .
+% \]
+% We can then compute the inverse $B'a/10^{8}$ using $1/(1-\epsilon)
+% \simeq (1+\epsilon)(1+\epsilon^{2})$, which is correct up to a
+% relative error of $\epsilon^4 < 2.6\cdot 10^{-19}$. Since we target
+% a $16$-digit value, this is small enough.
+%
+% Let us prove the upper bound first.
+% \begin{align}\label{l3fp-fixed-eTeXfrac}
+% 10^{7} B'a
+% & < \left(10^{3} x + \eTeXfrac{y}{10} + \frac{3}{2}\right)
+% \left(\left(10^{3}-\eTeXfrac{y}{10}\right) \beta
+% + \eTeXfrac{y}{10} \alpha - 1750\right)
+% \\& < \left(10^{3} x + \eTeXfrac{y}{10} + \frac{3}{2}\right)
+% \left(\left(10^{3}-\eTeXfrac{y}{10}\right)
+% \left(\frac{10^{9}}{x} + \frac{1}{2} \right)
+% + \eTeXfrac{y}{10} \left(\frac{10^{9}}{x+1} + \frac{1}{2} \right)
+% - 1750\right)
+% \\& < \left(10^{3} x + \eTeXfrac{y}{10} + \frac{3}{2}\right)
+% \left(\frac{10^{12}}{x}
+% - \eTeXfrac{y}{10} \frac{10^{9}}{x(x+1)}
+% - 1250\right)
+% \end{align}
+% We recognize a quadratic polynomial in $[y/10]$ with a negative
+% leading coefficient, $([y/10]+a)(b-c[y/10]) \leq (b+ca)^2/(4c)$.
+% Hence,
+% \[
+% 10^{7} B'a
+% < \frac{10^{15}}{x(x+1)} \left(
+% x + \frac{1}{2} + \frac{3}{4} 10^{-3}
+% - 6.25\cdot 10^{-10} x(x+1) \right)^2
+% \]
+% We want to prove that the squared expression is less than $x(x+1)$,
+% which we do by simplifying the difference, and checking its sign,
+% \[
+% x(x+1) - \left(x + \frac{1}{2} + \frac{3}{4} 10^{-3}
+% - 6.25\cdot 10^{-10} x(x+1) \right)^2
+% > - \frac{1}{4} (1+1.5\cdot 10^{-3})^2 - 10^{-3} x
+% + 1.25\cdot 10^{-9} x(x+1)(x+0.5)
+% > 0.
+% \]
+%
+% Now, the lower bound. The same computation as
+% \eqref{l3fp-fixed-eTeXfrac} imply
+% \[
+% 10^{7} B'a
+% > \left(10^{3} x + \eTeXfrac{y}{10} - \frac{1}{2}\right)
+% \left(\frac{10^{12}}{x} - \eTeXfrac{y}{10} \frac{10^{9}}{x(x+1)}
+% - 2250\right)
+% \]
+% This time, we want to find the minimum of this quadratic polynomial.
+% Since the leading coefficient is still negative, the minimum is
+% reached for one of the extreme values $y=0$ or $y=9999$, and we
+% easily check the bound for those values.
+%
+% We have proven that the algorithm will give us a precise enough
+% answer. Incidentally, the upper bound that we derived tells us that
+% $a < 10^{8}/B \leq 10^{9}$, hence we can compute $a$ safely as a
+% \TeX{} integer, and even add $10^{9}$ to it to ease grabbing of all
+% the digits.
+% \begin{macrocode}
+\cs_new:Npn \@@_fixed_dtf_approx:n #1
+ {
+ \exp_after:wN \@@_fixed_dtf_approx_ii:wnn
+ \int_use:N \__int_eval:w 10 0000 0000 / ( #1 + \c_one ) ;
+ {#1}
+ }
+\cs_new:Npn \@@_fixed_dtf_approx_ii:wnn #1; #2#3
+ {
+%<assert> \assert:n { \tl_count:n {#1} = 6 }
+ \exp_after:wN \@@_fixed_dtf_approx_iii:NNNNNw
+ \int_use:N \__int_eval:w 10 0000 0000 - 1750
+ + #1000 + (10 0000 0000/#2-#1) * (1000-#3/10) ;
+ {#2}{#3}
+ }
+\cs_new:Npn \@@_fixed_dtf_approx_iii:NNNNNw 1#1#2#3#4#5#6; #7; #8;
+ {
+ + \c_four % because of the line below "dtf_epsilon" here.
+ \@@_fixed_mul:wwn {000#1}{#2#3#4#5}{#6}{0000}{0000}{0000} ; #7;
+ \@@_fixed_dtf_epsilon:wN
+ \@@_fixed_mul:wwn {000#1}{#2#3#4#5}{#6}{0000}{0000}{0000} ;
+ \@@_fixed_mul:wwn #8;
+ \@@_fixed_to_float:wN ?
+ }
+\cs_new:Npn \@@_fixed_dtf_epsilon:wN #1#2#3#4#5#6;
+ {
+%<assert> \assert:n { #1 = 0000 }
+%<assert> \assert:n { #2 = 9999 }
+ \exp_after:wN \@@_fixed_dtf_epsilon_ii:NNNNNww
+ \int_use:N \__int_eval:w 1 9999 9998 - #3#4 +
+ \exp_after:wN \@@_fixed_dtf_epsilon_pack:NNNNNw
+ \int_use:N \__int_eval:w 2 0000 0000 - #5#6 ; {0000} ;
+ }
+\cs_new:Npn \@@_fixed_dtf_epsilon_pack:NNNNNw #1#2#3#4#5#6;
+ { #1 ; {#2#3#4#5} {#6} }
+\cs_new:Npn \@@_fixed_dtf_epsilon_ii:NNNNNww #1#2#3#4#5#6; #7;
+ {
+ \@@_fixed_mul:wwn %^^A todo: optimize to use \@@_mul_mantissa.
+ {0000} {#2#3#4#5} {#6} #7 ;
+ {0000} {#2#3#4#5} {#6} #7 ;
+ \@@_fixed_add_one:wN
+ \@@_fixed_mul:wwn {10000} {#2#3#4#5} {#6} #7 ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
new file mode 100644
index 00000000000..2517236fb21
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-logic.dtx
@@ -0,0 +1,393 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-logic.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-logic.dtx 3504 2012-03-06 06:38:45Z bruno $
+ {L3 Floating-point conditionals}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-logic} package\thanks{This file
+% has version number \ExplFileVersion, last
+% revised \ExplFileDate.}\\
+% Floating point conditionals}
+% \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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-logic} Implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{Existence test}
+%
+% \begin{macro}[pTF]{\fp_if_exist:N, \fp_if_exist:c}
+% Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
+% \begin{macrocode}
+\cs_new_eq:NN \fp_if_exist:NTF \cs_if_exist:NTF
+\cs_new_eq:NN \fp_if_exist:NT \cs_if_exist:NT
+\cs_new_eq:NN \fp_if_exist:NF \cs_if_exist:NF
+\cs_new_eq:NN \fp_if_exist_p:N \cs_if_exist_p:N
+\cs_new_eq:NN \fp_if_exist:cTF \cs_if_exist:cTF
+\cs_new_eq:NN \fp_if_exist:cT \cs_if_exist:cT
+\cs_new_eq:NN \fp_if_exist:cF \cs_if_exist:cF
+\cs_new_eq:NN \fp_if_exist_p:c \cs_if_exist_p:c
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Comparison}
+%
+% \begin{macro}[int, EXP]{\@@_compare:ww}
+% \begin{macro}[aux, EXP]
+% {
+% \@@_compare_nan:w, \@@_compare_mantissa:ww,
+% \@@_compare_mantissa:nnnnnnnn
+% }
+% \begin{syntax}
+% \cs{@@_compare:ww} \meta{X} |;| \meta{Y} |;|
+% \end{syntax}
+% Expands (in the same way as \cs{int_eval:n}) to $-1$ if $x<y$, $0$
+% if $x=y$, $1$ if $x>y$, and $2$ otherwise (denoted as $x?y$). A
+% trick that will later be useful is that the character codes of |<|,
+% |=|, |>| and |?| are contiguous, and in the same order as the return
+% codes of \cs{@@_compare:ww}.
+% \begin{macrocode}
+\cs_new:Npn \@@_compare:ww \s_@@ \@@_chk:w #1#2#3; \s_@@ \@@_chk:w #4#5#6;
+ {
+ \__int_value:w
+ \if_meaning:w 3 #1 \exp_after:wN \@@_compare_nan:w \fi:
+ \if_meaning:w 3 #4 \exp_after:wN \@@_compare_nan:w \fi:
+ \if_meaning:w 2 #2 - \fi:
+ \if_meaning:w #2 #5
+ \if_meaning:w #1 #4
+ \if_meaning:w 1 #1
+ \@@_compare_mantissa:ww #3; #6;
+ \else:
+ 0
+ \fi:
+ \else:
+ \if_int_compare:w #1 < #4 - \fi: 1
+ \fi:
+ \else:
+ \if_meaning:w 0 #1
+ \if_meaning:w 0 #4
+ 0
+ \else:
+ 1
+ \fi:
+ \else:
+ 1
+ \fi:
+ \fi:
+ \exp_stop_f:
+ }
+\cs_new:Npn \@@_compare_nan:w #1 \exp_stop_f: { \c_two }
+\cs_new:Npn \@@_compare_mantissa:ww #1#2; #3#4;
+ {
+ \if_int_compare:w #1 = #3 \exp_stop_f:
+ \@@_compare_mantissa:nnnnnnnn #2 #4
+ \else:
+ \if_int_compare:w #1 < #3 - \fi: 1
+ \fi:
+ }
+\cs_new:Npn \@@_compare_mantissa:nnnnnnnn #1#2#3#4#5#6#7#8
+ {
+ \if_int_compare:w #1 = #5 \exp_stop_f:
+ \if_int_compare:w #2 = #6 \exp_stop_f:
+ \if_int_compare:w #3 = #7 \exp_stop_f:
+ \if_int_compare:w #4 = #8 \exp_stop_f:
+ 0
+ \else:
+ \if_int_compare:w #4 < #8 - \fi: 1
+ \fi:
+ \else:
+ \if_int_compare:w #3 < #7 - \fi: 1
+ \fi:
+ \else:
+ \if_int_compare:w #2 < #6 - \fi: 1
+ \fi:
+ \else:
+ \if_int_compare:w #1 < #5 - \fi: 1
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF, EXP]{\fp_compare:nNn}
+% \begin{macro}[aux, EXP]{\@@_compare_aux:wn}
+% Evaluate |#1| and |#3|, using an auxiliary to expand both, in the
+% correct order. Then compare this to |`#2-`=|, which is $-1$ for
+% |<|, $0$ for |=|, $1$ for |>| and $2$ for |?|.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \fp_compare:nNn #1#2#3 { p , T , F , TF }
+ {
+ \if_int_compare:w
+ \exp_after:wN \@@_compare_aux:wn
+ \tex_romannumeral:D -`0 \@@_parse:n {#3} {#1}
+ = \__int_eval:w `#2 - `= \__int_eval_end:
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+\cs_new:Npn \@@_compare_aux:wn #1; #2
+ {
+ \exp_after:wN \@@_compare:ww
+ \tex_romannumeral:D -`0 \@@_parse:n {#2} #1;
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP,pTF]{\fp_compare:n}
+% \begin{macro}[aux,EXP]{\@@_compare_aux:w}
+% For floating points the comparison operators are treated as
+% operations, so we simply evaluate then compare with \cs{c_zero_fp}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \fp_compare:n #1 { p , T , F , TF }
+ {
+ \exp_after:wN \@@_compare_aux:w
+ \tex_romannumeral:D -`0 \@@_parse:n {#1}
+ }
+\cs_new:Npn \@@_compare_aux:w \s_@@ \@@_chk:w #1#2;
+ {
+ \if_meaning:w 0 #1
+ \prg_return_false:
+ \else:
+ \prg_return_true:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Boolean operations}
+%
+% \begin{macro}[int, EXP]{\@@_not:w}
+% Return \texttt{true} or \texttt{false}, with two expansions, one to
+% exit the conditional, and one to please \pkg{l3fp-parse}.
+% \begin{macrocode}
+\cs_new:Npn \@@_not:w \s_@@ \@@_chk:w #1#2;
+ {
+ \if_meaning:w 0 #1
+ \exp_after:wN \exp_after:wN \exp_after:wN \c_one_fp
+ \else:
+ \exp_after:wN \exp_after:wN \exp_after:wN \c_zero_fp
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]+\@@_&_o:ww+
+% \begin{macro}[int, EXP]+\@@_|_o:ww+
+% \begin{macro}[aux, EXP]{\@@_and_return:wNw}
+% For \texttt{and}, if the first number is zero, return it (with the
+% same sign). Otherwise, return the second one. For \texttt{or}, the
+% logic is reversed: if the first number is non-zero, return it,
+% otherwise return the second number: we achieve that by hi-jacking
+% \cs{@@_\&_o:ww}, inserting an extra argument, \cs{else:}, before
+% \cs{s_@@}. In all cases, expand after the floating point number.
+% \begin{macrocode}
+\cs_new:cpn { @@_ \iow_char:N \& _o:ww } #1 \s_@@ \@@_chk:w #2#3;
+ {
+ \if_meaning:w 0 #2 #1
+ \@@_and_return:wNw \s_@@ \@@_chk:w #2#3;
+ \fi:
+ \@@_exp_after_o:w
+ }
+\cs_new_nopar:cpx { @@_ \iow_char:N \| _o:ww }
+ { \exp_not:c { @@_ \iow_char:N \& _o:ww } \exp_not:N \else: }
+\cs_new:Npn \@@_and_return:wNw #1; \fi: #2#3; { \fi: #2 #1; }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]
+% {\@@_ternary:NwwN, \@@_ternary_i:NwwN, \@@_ternary_ii:NwwN}
+% The first function receives the test and the true branch of the |?:|
+% ternary operator. It returns the true branch, unless the test
+% branch is zero. In that case, the function returns a very specific
+% \texttt{nan}. The second function receives the output of the first
+% function, and the false branch. It returns the previous input,
+% unless that is the special \texttt{nan}, in which case we return the
+% false branch.
+%^^A todo: optimize.
+% \begin{macrocode}
+\cs_new:Npn \@@_ternary:NwwN #1 #2@ #3@ #4
+ {
+ \if_meaning:w \@@_parse_infix_::N #4
+ \@@_ternary_loop:Nw
+ #2
+ \s_@@ \@@_chk:w { \@@_ternary_loop_break:w } ;
+ \@@_ternary_break_point:n { \exp_after:wN \@@_ternary_i:NwwN }
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \@@_parse_exp_after_array:wf #3 \s_@@_stop
+ \exp_after:wN @
+ \tex_romannumeral:D
+ \@@_parse_until:Nw \c_two
+ \@@_parse_expand:w
+ \else:
+ \@@_error:n { Missing~':'~clause~for~'?:'. }
+ \exp_after:wN \@@_parse_until_test:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \@@_parse_exp_after_array:wf #3 \s_@@_stop
+ \exp_after:wN #4
+ \exp_after:wN #1
+ \fi:
+ }
+\cs_new:Npn \@@_ternary_loop_break:w #1 \fi: #2 \@@_ternary_break_point:n #3
+ {
+ \c_zero = \c_zero \fi:
+ \exp_after:wN \@@_ternary_ii:NwwN
+ }
+\cs_new:Npn \@@_ternary_loop:Nw \s_@@ \@@_chk:w #1#2;
+ {
+ \if_int_compare:w #1 > \c_zero
+ \exp_after:wN \@@_ternary_map_break:
+ \fi:
+ \@@_ternary_loop:Nw
+ }
+\cs_new:Npn \@@_ternary_map_break: #1 \@@_ternary_break_point:n #2 {#2}
+\cs_new:Npn \@@_ternary_i:NwwN #1#2@#3@#4
+ {
+ \exp_after:wN \@@_parse_until_test:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \@@_parse_exp_after_array:wf #2 \s_@@_stop
+ #4 #1
+ }
+\cs_new:Npn \@@_ternary_ii:NwwN #1#2@#3@#4
+ {
+ \exp_after:wN \@@_parse_until_test:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \@@_parse_exp_after_array:wf #3 \s_@@_stop
+ #4 #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_max:w, \@@_min:w}
+% \begin{macrocode}
+\cs_new:Npn \@@_max:w #1@
+ {
+ \exp_after:wN \@@_minmax_loop:Nww
+ \exp_after:wN \c_minus_one
+ \c_minus_inf_fp
+ #1
+ \s_@@ \@@_chk:w { 3 \@@_minmax_break:w } ;
+ }
+\cs_new:Npn \@@_min:w #1@
+ {
+ \exp_after:wN \@@_minmax_loop:Nww
+ \exp_after:wN \c_one
+ \c_inf_fp
+ #1
+ \s_@@ \@@_chk:w { 3 \@@_minmax_break:w } ;
+ }
+\cs_new:Npn \@@_minmax_loop:Nww
+ #1 \s_@@ \@@_chk:w #2#3; \s_@@ \@@_chk:w #4#5;
+ {
+ \if_meaning:w 3 #4
+ \if_meaning:w 3 #2
+ \@@_minmax_i:ww
+ \else:
+ \@@_minmax_ii:ww
+ \fi:
+ \else:
+ \if_int_compare:w \@@_compare:ww \s_@@ \@@_chk:w #2#3;
+ \s_@@ \@@_chk:w #4#5; = #1
+ \@@_minmax_ii:ww
+ \else:
+ \@@_minmax_i:ww
+ \fi:
+ \fi:
+ \@@_minmax_loop:Nww #1
+ \s_@@ \@@_chk:w #2#3;
+ \s_@@ \@@_chk:w #4#5;
+ }
+\cs_new:Npn \@@_minmax_i:ww
+ #1 \@@_minmax_loop:Nww #2 \s_@@ #3; \s_@@ #4;
+ { #1 \@@_minmax_loop:Nww #2 \s_@@ #3; }
+\cs_new:Npn \@@_minmax_ii:ww
+ #1 \@@_minmax_loop:Nww #2 \s_@@ #3; \s_@@ #4;
+ { #1 \@@_minmax_loop:Nww #2 \s_@@ #4; }
+\cs_new:Npn \@@_minmax_break:w #1 \@@_minmax_loop:Nww #2 #3; #4;
+ {
+ \fi:
+ \@@_exp_after_o:w #3;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-old.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-old.dtx
new file mode 100644
index 00000000000..b195f766d52
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-old.dtx
@@ -0,0 +1,273 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-old.dtx Copyright (C) 2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-old.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Experimental floating-points (old)}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3fp-old} package\\ Floating-points (old)^^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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-old} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \subsection{Compatibility}
+%
+% \begin{variable}{\c_undefined_fp}
+% The old floating point number \cs{c_undefined_fp} is now implemented
+% as a \texttt{nan}.
+% \begin{macrocode}
+\fp_const:Nn \c_undefined_fp { nan }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[pTF]{\fp_if_undefined:N}
+% An old floating point is undefined if it is \texttt{inf} or
+% \texttt{nan}, \emph{i.e.}, if its type is $2$ or $3$.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \fp_if_undefined:N #1 { p , T , F , TF }
+ { \exp_after:wN \@@_if_undefined:w #1 }
+\cs_new:Npn \@@_if_undefined:w \s_@@ \@@_chk:w #1#2;
+ {
+ \if_int_compare:w #1 > \c_one
+ \prg_return_true: \else: \prg_return_false: \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\fp_if_zero:N}
+% An old floating point is zero if it is $\pm 0$, \emph{i.e.}, its
+% type is $0$.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \fp_if_zero:N #1 { p , T , F , TF }
+ { \exp_after:wN \@@_if_zero:w #1 }
+\cs_new:Npn \@@_if_zero:w \s_@@ \@@_chk:w #1#2;
+ { \if_meaning:w #1 0 \prg_return_true: \else: \prg_return_false: \fi: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \fp_abs:N , \fp_abs:c , \fp_gabs:N , \fp_gabs:c ,
+% \fp_neg:N , \fp_neg:c , \fp_gneg:N , \fp_gneg:c ,
+% }
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_abs:N { \@@_abs:NNN \tl_set:Nx \@@_abs:w }
+\cs_new_protected_nopar:Npn \fp_gabs:N { \@@_abs:NNN \tl_gset:Nx \@@_abs:w }
+\cs_new_protected_nopar:Npn \fp_neg:N { \@@_abs:NNN \tl_set:Nx \@@_neg:w }
+\cs_new_protected_nopar:Npn \fp_gneg:N { \@@_abs:NNN \tl_gset:Nx \@@_neg:w }
+\cs_new_protected:Npn \@@_abs:NNN #1#2#3
+ { #1 #3 { \exp_after:wN #2 #3 \prg_do_nothing: } }
+\cs_generate_variant:Nn \fp_abs:N { c }
+\cs_generate_variant:Nn \fp_gabs:N { c }
+\cs_generate_variant:Nn \fp_neg:N { c }
+\cs_generate_variant:Nn \fp_gneg:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \fp_mul:Nn, \fp_mul:cn, \fp_gmul:Nn, \fp_gmul:cn,
+% \fp_div:Nn, \fp_div:cn, \fp_gdiv:Nn, \fp_gdiv:cn,
+% \fp_pow:Nn, \fp_pow:cn, \fp_gpow:Nn, \fp_gpow:cn,
+% }
+% \begin{macro}[aux]{\@@_mul:NNNn}
+% See \cs{fp_add:Nn} for details.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_mul:Nn { \@@_mul:NNNn \fp_set:Nn * }
+\cs_new_protected_nopar:Npn \fp_gmul:Nn { \@@_mul:NNNn \fp_gset:Nn * }
+\cs_new_protected_nopar:Npn \fp_div:Nn { \@@_mul:NNNn \fp_set:Nn / }
+\cs_new_protected_nopar:Npn \fp_gdiv:Nn { \@@_mul:NNNn \fp_gset:Nn / }
+\cs_new_protected_nopar:Npn \fp_pow:Nn { \@@_mul:NNNn \fp_set:Nn ^ }
+\cs_new_protected_nopar:Npn \fp_gpow:Nn { \@@_mul:NNNn \fp_gset:Nn ^ }
+\cs_new_protected:Npn \@@_mul:NNNn #1#2#3#4 { #1 #3 { #3 #2 (#4) } }
+\cs_generate_variant:Nn \fp_mul:Nn { c }
+\cs_generate_variant:Nn \fp_gmul:Nn { c }
+\cs_generate_variant:Nn \fp_div:Nn { c }
+\cs_generate_variant:Nn \fp_gdiv:Nn { c }
+\cs_generate_variant:Nn \fp_pow:Nn { c }
+\cs_generate_variant:Nn \fp_gpow:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \fp_exp:Nn, \fp_exp:cn, \fp_gexp:Nn, \fp_gexp:cn,
+% \fp_ln:Nn , \fp_ln:cn , \fp_gln:Nn , \fp_gln:cn ,
+% \fp_sin:Nn, \fp_sin:cn, \fp_gsin:Nn, \fp_gsin:cn,
+% \fp_cos:Nn, \fp_cos:cn, \fp_gcos:Nn, \fp_gcos:cn,
+% \fp_tan:Nn, \fp_tan:cn, \fp_gtan:Nn, \fp_gtan:cn,
+% }
+% \begin{macro}[aux]
+% {\@@_assign_to:nNNNn, \@@_assign_to_i:wNNNn, \@@_assign_to_ii:NnNNN}
+% Here, an added twist
+% is that each value computed by these expensive unary operations is
+% stored as a constant floating point number.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1#2#3#4#5
+ {
+ \cs_new_protected_nopar:Npn #1 { #5 {#4} \tl_set_eq:NN #3 }
+ \cs_new_protected_nopar:Npn #2 { #5 {#4} \tl_gset_eq:NN #3 }
+ \cs_generate_variant:Nn #1 { c }
+ \cs_generate_variant:Nn #2 { c }
+ }
+\@@_tmp:w \fp_exp:Nn \fp_gexp:Nn \@@_exp:w {exp} \@@_assign_to:nNNNn
+\@@_tmp:w \fp_ln:Nn \fp_gln:Nn \@@_ln:w {ln } \@@_assign_to:nNNNn
+\@@_tmp:w \fp_sin:Nn \fp_gsin:Nn \@@_sin:w {sin} \@@_assign_to:nNNNn
+\@@_tmp:w \fp_cos:Nn \fp_gcos:Nn \@@_cos:w {cos} \@@_assign_to:nNNNn
+\@@_tmp:w \fp_tan:Nn \fp_gtan:Nn \@@_tan:w {tan} \@@_assign_to:nNNNn
+\cs_new_protected:Npn \@@_assign_to:nNNNn #1#2#3#4#5
+ {
+ \exp_after:wN \@@_assign_to_i:wNNNn
+ \tex_romannumeral:D -`0 \@@_parse:n {#5} {#1} #2#3#4
+ }
+\cs_new_protected:Npn \@@_assign_to_i:wNNNn \s_@@ \@@_chk:w #1#2#3; #4
+ {
+ \exp_args:Nc \@@_assign_to_ii:NnNNN
+ { c_@@_ #4 ( #2 \if_meaning:w 1 #1 #3 \fi: ) _fp }
+ { #1#2#3 }
+ }
+\cs_new_protected:Npn \@@_assign_to_ii:NnNNN #1#2#3#4#5
+ {
+ \cs_if_exist:NF #1
+ { \tl_const:Nx #1 { #4 \s_@@ \@@_chk:w #2; } }
+ #3 #5 #1
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF, EXP]{\fp_compare:NNN}
+% Comparisons used to be easier between floating points stored in
+% variables. No more.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_compare:NNNTF { \fp_compare:nNnTF }
+\cs_new_protected_nopar:Npn \fp_compare:NNNT { \fp_compare:nNnT }
+\cs_new_protected_nopar:Npn \fp_compare:NNNF { \fp_compare:nNnF }
+\cs_new_protected_nopar:Npn \fp_compare_p:NNN { \fp_compare_p:nNn }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\fp_round_places:Nn, \fp_ground_places:Nn}
+% \begin{macro}[aux]{\@@_round_places:NNn}
+% Rounding to a given number of places is easy, since it is provided
+% by the \pkg{l3fp-round} module.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \fp_round_places:Nn
+ { \@@_round_places:NNn \tl_set:Nx }
+\cs_new_protected_nopar:Npn \fp_ground_places:Nn
+ { \@@_round_places:NNn \tl_gset:Nx }
+\cs_new_protected:Npn \@@_round_places:NNn #1#2#3
+ {
+ #1 #2
+ {
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_round:Nwn
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_round_to_nearest:NNN
+ \exp_after:wN #2
+ \exp_after:wN { \int_use:N \__int_eval:w #3 }
+ }
+ }
+\cs_generate_variant:Nn \fp_round_places:Nn { c }
+\cs_generate_variant:Nn \fp_ground_places:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\fp_round_figures:Nn, \fp_ground_figures:Nn}
+% Rounding to a given number of figures is the same as rounding to a
+% number of places, after shifting by the exponent of the argument.
+% \begin{macrocode}
+\cs_new_protected:Npn \fp_round_figures:Nn #1#2
+ {
+ \@@_round_places:NNn \tl_set:Nx #1
+ { #2 - \exp_after:wN \@@_exponent:w #1 }
+ }
+\cs_new_protected:Npn \fp_ground_figures:Nn #1#2
+ {
+ \@@_round_places:NNn \tl_gset:Nx #1
+ { #2 - \exp_after:wN \@@_exponent:w #1 }
+ }
+\cs_generate_variant:Nn \fp_round_figures:Nn { c }
+\cs_generate_variant:Nn \fp_ground_figures:Nn { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
new file mode 100644
index 00000000000..11ec4e11b54
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-parse.dtx
@@ -0,0 +1,2601 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-parse.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-parse.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Floating-point expression parsing}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-parse} package\thanks{This file
+% has version number \fileversion, last
+% revised \filedate.}\\
+% Floating point expression parsing}
+% \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 \filedate}
+%
+% \maketitle
+%
+% ^^A begin[todo]
+%
+% ^^A To typeset the examples of expansion control, I'm using a hand-made
+% ^^A environment.
+% \newcommand{\fpOperation}[1]
+% {\textcolor[rgb]{.6,.2,.2}{\ttfamily#1}}
+% \newcommand{\fpPrecedence}[1]
+% {\textcolor[rgb]{.2,.2,.6}{\ttfamily#1}}
+% \newcommand{\fpExpand}[2]
+% {\underline{\textcolor{red}{#1{#2}}}}
+% \newenvironment{l3fp-code-example}
+% {\begin{quote}^^A
+% \edef\^{\string^}^^A
+% \let\*\fpExpand
+% \let\o\fpOperation
+% \let\p\fpPrecedence
+% \def\!{\begingroup\def\!{\endgroup\par}\color[gray]{0.5}}^^A
+% \ttfamily\frenchspacing
+% }{\end{quote}}
+%
+% \begin{documentation}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-parse} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% \section{Precedences}
+%
+% In order of evaluation (some distinctions are irrelevant for the order
+% of evaluation, but serve as signals).
+% \begin{itemize}
+% \item[32] Juxtaposition for implicit multiplication.
+% \item[16] Function calls with multiple arguments.
+% \item[15] Function calls expecting exactly one argument.
+% \item[14] Binary |**| and |^| (right to left).
+% \item[12] Unary |+|, |-|, |!| (right to left).
+% \item[10] Binary |*|, |/| and |%|.
+% \item[9] Binary |+| and |-|.
+% \item[7] Comparisons.
+% \item[5] Logical \texttt{and}, denoted by |&&|.
+% \item[4] Logical \texttt{or}, denoted by \verb*+||+.
+% \item[3] Ternary operator |?:|, piece |?|.
+% \item[2] Ternary operator |?:|, piece |:|.
+% \item[1] Commas, and parentheses accepting commas.
+% \item[0] Parentheses expecting exactly one argument.
+% \item[-1] Start and end of the expression.
+% \end{itemize}
+%
+% ^^A todo: change 'mantissa' => 'significand' everywhere.
+% ^^A todo: ask SO when sNaN can arise.
+%
+% \section{Evaluating an expression}
+%
+% \begin{macro}[EXP, int]{\@@_parse:n}
+% \begin{syntax}
+% \cs{@@_parse:n} \Arg{floating point expression}
+% \end{syntax}
+% This \texttt{f}-expands to the internal floating point number
+% obtained by evaluating the \meta{floating point expression}. During
+% this evaluation, each token is fully \texttt{f}-expanded.
+% \begin{texnote}
+% Registers (integers, toks, etc.) are automatically unpacked,
+% without requiring a function such as \cs{int_use:N}. Invalid
+% tokens remaining after \texttt{f}-expansion will lead to
+% unrecoverable low-level TeX errors.\footnote{Bruno: describe what
+% happens in cases like $2\cs{c_three} = 6$.}
+% \end{texnote}
+% \end{macro}
+%
+% \section{Work plan}\label{subsec:fp-parse-workplan}
+%
+% The task at hand is non-trivial, and some previous failed attempts have
+% shown me that the code ends up giving unreadable logs, so we'd better get
+% it (almost) right the first time. Let us thus first discuss precisely
+% the design before starting to write the code. To simplify matters,
+% we first consider expressions with integers only.
+%
+% \subsection{Storing results}
+%
+% The main issue in parsing expressions expandably is: \enquote{where
+% in the input stream should the result be put?}
+%
+% One option is to place the result at the end of the expression,
+% but this has several drawbacks:
+% \begin{itemize}
+% \item firstly it means that for long expressions we would be reaching
+% all the way to the end of the expression at every step of the
+% calculation, which can be rather expensive;
+% \item secondly, when parsing parenthesized sub-expressions, we would
+% naturally place the result after the corresponding closing parenthesis.
+% But since \cs{@@_parse:n} does not assume that its argument is expanded,
+% this closing parenthesis may be hidden in a macro, and not present yet,
+% causing havoc.
+% \end{itemize}
+%
+% The other natural option is to store the result at the start of the
+% expression, and carry it as an argument of each macro. This does not
+% really work either: in order to expand what follows on the input stream,
+% we need to skip at each step over all the tokens in the result using
+% \cs{exp_after:wN}. But this requires adding many \cs{exp_after:wN} to
+% the result at each step, also an expensive process.
+%
+% Hence, we need to go for some fine expansion control: the result is
+% stored \emph{before} the start\ldots{} A toy model that illustrates this
+% idea is to try and add some positive integers which may be hidden
+% within macros, or registers. Assume that one number has already been
+% found, and that we want to parse the next number. The current status
+% of the code may look as follows.
+% \begin{quote}\ttfamily
+% \cs{exp_after:wN} \cs{add:ww}
+% \cs{__int_value:w} 12345 \cs{exp_after:wN} ; \newline
+% \cs{tex_romannumeral:D} -`0 \cs{clean:w} \meta{stuff}
+% \end{quote}
+% Hitting this construction by one step of expansion expands
+% \cs{exp_after:wN}, which triggers the primitive \cs{__int_value:w},
+% which reads an integer, \texttt{12345}. This integer is unfinished,
+% causing the second \cs{exp_after:wN} to expand, and trigger
+% the construction \cs{tex_romannumeral:D} |-`0|, which f-expands
+% \cs{clean:w} (see \pkg{l3expan.dtx} for an explanation). Assume
+% then that \cs{clean:w} is such that it expands \meta{stuff} to
+% \emph{e.g.}, |333444;|. Once \cs{clean:w} is done expanding, we
+% will obtain essentially
+% \begin{quote}\ttfamily
+% \cs{exp_after:wN} \cs{add:ww} \cs{__int_value:w} 12345 ; 333444 ;
+% \end{quote}
+% where in fact \cs{exp_after:wN} has already been expanded, and
+% \cs{__int_value:w} has already seen \texttt{12345}. Now,
+% \cs{__int_value:w} sees the \texttt{;}, and stops expanding, and
+% we are left with
+% \begin{quote}\ttfamily
+% \cs{add:ww} 12345 ; 333444 ;
+% \end{quote}
+% which can safely perform the addition by grabbing two arguments
+% delimited by \texttt{;}.
+%
+% On this toy example, we could note that if we were to continue
+% parsing the expression, then the following number should also
+% be cleaned up before the next use of a binary operation such as
+% \cs{add:ww}. Just like \cs{__int_value:w} \texttt{12345}
+% \cs{exp_after:wN} \texttt{;} expanded what follows once, we need
+% \cs{add:ww} to do the calculation, and in the process to expand
+% the following once. This is also true in our real application:
+% all the functions of the form \cs{@@_..._o:ww} expand what
+% follows once. This comes at the cost of leaving tokens in the
+% input stack, and we will need to be careful to waste as little
+% as possible of this precious memory.
+%
+% \subsection{Precedence}
+%
+% A major point to keep in mind when parsing expressions is that
+% different operators have different precedence. The true analog
+% of our toy \cs{clean:w} macro must thus take care of that. For
+% definiteness, let us assume that the operation which prompted
+% \cs{clean:w} was a multiplication. Then \cs{clean:w} (expand
+% and) read digits until the number is ended by some operation.
+% If this is \texttt{+} or~\texttt{-}, then the multiplication
+% should be calculated next, so \cs{clean:w} can simply decide
+% that its job is done. However, if the operator we find is |^|,
+% then this operation must be performed before returning control
+% to the multiplication. This means that we need to \cs{clean:w}
+% the number following |^|, and perform the calculation, then just
+% end our job.
+%
+% Hence, each time a number is cleaned, the precedence of the
+% following operation must be compared to that of the previous
+% operation. The process of course has to happen recursively.
+% For instance, |1+2^3*4| would involve the following steps.
+% \begin{itemize}
+% \item |1| is cleaned up.
+% \item |2| is cleaned up.
+% \item The precedences of |+| and |^| are compared. Since the
+% latter is higher, the second operand of |^| should be cleaned.
+% \item |3| is cleaned up.
+% \item The precedences of |^| and |*| are compared. Since the
+% former is higher, the cleaning step stops.
+% \item Compute |2^3 = 8|.
+% \item We now have |1+8*4|, and the operation |+| is still
+% looking for a second operand. Clean |8|.
+% \item The precedences of |+| and |*| are compared. Since the
+% latter is higher, the second operand of |*| should be cleaned.
+% \item |4| is cleaned up, and the end of the expression is reached.
+% \item Compute |8*4 = 32|.
+% \item We now have |1+8*4|, and the operation |+| is still
+% looking for a second operand. Clean |32|, and reach the end
+% of the expression.
+% \item Compute |1+32 = 33|.
+% \end{itemize}
+% Here, there is some (expensive) redundant work: the results of
+% computations should not need to be cleaned again. Thus the true definition
+% is slightly more elaborate.
+%
+% The precedence of |(| and |)| are defined to be equal, and smaller than
+% the precedence of |+| and |-|, itself smaller than |*| and |/|, smaller,
+% finally, then the power operator |**| (or |^|).
+%
+%
+% \subsection{Infix operators}
+%
+% The implementation that was chosen is slightly wasteful: it causes
+% more nesting than necessary. ^^A todo: clarify.
+% However, it is simpler to implement and to explain than a slightly
+% optimized variant. ^^A todo: implement optimized version; compare.
+%
+% The cornerstone of that method is a pair of functions,
+% \cs{until} and \cs{one}, which both take as their first
+% argument the precedence (an integer) of the last operation.
+% The f-expansion of
+% \begin{quote}
+% \cs{until} \meta{prec} \cs{one} \meta{prec} \meta{stuff}
+% \end{quote}
+% is the internal floating point obtained by \enquote{cleaning}
+% numbers which follow in the input stream, and performing
+% computations until reaching an operation with a precedence
+% less than or equal to \meta{prec}. This is followed by a control
+% sequence of the form \cs{infix_?}, namely,
+% \begin{quote}
+% \meta{floating point} \cs{infix_?}
+% \end{quote}
+% where |?| is the operation following that number in the input
+% stream (we thus know that this operation has at most the
+% precedence \meta{prec}, otherwise it would have been performed
+% already).
+%
+% How is that expansion achieved? First, \cs{one} \meta{prec}
+% reads one \meta{floating point} number, and converts it to an
+% internal form, then the following operation, say |*|, is
+% packed in the form \cs{infix_*}, which is fed the \meta{prec}.
+% This function (one per infix operator) compares \meta{prec}
+% with the precedence of the operator we just read (here |*|).
+% If \meta{prec} is higher, our job is finished, and \cs{one}
+% leaves \cs{@@_parse_stop_until:N} so that \cs{until} knows to stop.
+% Otherwise, \cs{infix_*} triggers a new pair
+% \cs{until} \meta{prec(*)} \cs{one} \meta{prec(*)},
+% which produces the second operand \meta{floating point_2}
+% for the multiplication:
+% \begin{quote}
+% \cs{until} \meta{prec} \meta{floating point} \newline
+% \texttt{...} \meta{floating point_2} |;| \cs{infix_?}
+% \end{quote}
+% The dots are \cs{@@_parse_apply_binary:NwNwN} |*|. The boolean
+% tells \cs{until} that it is not done, and it expands
+% (essentially) to
+% \begin{quote}
+% \cs{until} \meta{prec}
+% \cs{@@_mul_o:ww} \meta{floating point} \meta{floating point_2}
+% \cs{tex_romannumeral:D} \texttt{-`0} \cs{infix_?} \meta{prec}
+% \end{quote}
+% making \TeX{} expand \cs{@@_mul_o:ww} before \cs{until}. As
+% implemented in \pkg{l3fp-basics}, this operation expands what follows
+% its result exactly once. This triggers \cs{tex_romannumeral:D},
+% which fully expands \cs{infix_?} \meta{prec}. This compares
+% the precedence of the next operation, |?|, and \meta{prec},
+% and leaves a boolean (and possibly more things), which is then
+% checked by \cs{until} \meta{prec} to know if the result
+% of the multiplication is the end of the story, or if |?|
+% should be computed as well before \cs{until} \meta{prec} ends.
+%
+% This should be easier to see on an example. To each infix
+% operator, for instance, |*|, is associated the following data:
+% \begin{itemize}
+% \item a test function, \cs{infix_*}, which conditionally continues
+% the calculation or waits to be hit again by expansion;
+% \item a function \fpOperation{*} (notation for \cs{@@_mul_o:ww})
+% which performs the actual calculation;
+% \item an integer, \fpPrecedence{*}, which encodes the precedence of
+% the operator.
+% \end{itemize}
+% The token that is currently being expanded is underlined,
+% and in red. Tokens that have not yet been read (and could
+% still be hidden in macros) are in gray.
+%
+% In a first reading, the disinction between the \meta{precedence}
+% \fpPrecedence{+}, the operation \fpOperation{+}, and the character
+% token |+| should not matter. It is only required to accomodate for
+% multi-token infix operators such as |**|: indeed, when controlling
+% expansion, we need to skip over those tokens using \cs{exp_after:wN},
+% and this only skips one token. Thus |**| needs to be replaced by a
+% single token (either its precedence or its calculating function,
+% depending on the place).
+%
+% To end the computation cleanly, we add a trailing right
+% parenthesis, and give |(| and |)| the lowest precedence,
+% so that \cs{until}\fpPrecedence{(} \cs{one}\fpPrecedence{(}
+% reads numbers and performs operations until meeting a right
+% parenthesis. This is discussed more precisely in the next section.
+%
+% \begin{l3fp-code-example}
+% \cs{until}\p( \*\cs{one}\p( \! 11 + 2**3 * 5 - 9 )\!
+% \cs{until}\p( 1 \*\cs{one}\p( \! 1 + 2**3 * 5 - 9 )\!
+% \cs{until}\p( 11 \*\cs{one}\p( \! + 2**3 * 5 - 9 )\!
+% \cs{until}\p( 11; \*\cs{infix_+}\p( \! 2**3 * 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ \*\cs{one}\p+ \! 2**3 * 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 2 \*\cs{one}\p+ \! **3 * 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 2; \*\cs{infix_**}\p+ \! 3 * 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 2;
+% F \o{**} \cs{until}\p{**} \*\cs{one}\p{**} \! 3 * 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 2;
+% F \o{**} \cs{until}\p{**} 3 \*\cs{one}\p{**} \! * 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 2;
+% F \o{**} \cs{until}\p{**} 3; \*\cs{infix_*}\p{**} \! 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 2;
+% F \o{**} \*\cs{until}\p{**} 3; T \cs{infix_*} \! 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \*\cs{until}\p+ 2;
+% F \o{**} 3; \cs{infix_*} \! 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ \*\o{**} 2; 3;
+% \cs{infix_*}\p+ \! 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 8; \*\cs{infix_*}\p+ \! 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 8;
+% F \o* \cs{until}\p* \*\cs{one}\p* \! 5 - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 8;
+% F \o* \cs{until}\p* 5 \*\cs{one}\p* \! - 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 8;
+% F \o* \cs{until}\p* 5; \*\cs{infix_-}\p* \! 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 8;
+% F \o* \*\cs{until}\p* 5; T \cs{infix_-} \! 9 )\!
+% \cs{until}\p( 11; F \o+ \*\cs{until}\p+ 8; F \o* 5; \cs{infix_-} \! 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ \*\o{*} 8; 5; \cs{infix_-}\p+ \! 9 )\!
+% \cs{until}\p( 11; F \o+ \cs{until}\p+ 40; \*\cs{infix_-}\p+ \! 9 )\!
+% \cs{until}\p( 11; F \o+ \*\cs{until}\p+ 40; T \cs{infix_-} \! 9 )\!
+% \*\cs{until}\p( 11; F \o+ 40; \cs{infix_-} \! 9 )\!
+% \cs{until}\p( \*\o{+} 11; 40; \cs{infix_-}\p( \! 9 )\!
+% \cs{until}\p( 51; \*\cs{infix_-}\p( \! 9 )\!
+% \cs{until}\p( 51; F \o- \cs{until}\p- \*\cs{one}\p- \! 9 )\!
+% \cs{until}\p( 51; F \o- \cs{until}\p- 9 \*\cs{one}\p- \! )\!
+% \cs{until}\p( 51; F \o- \cs{until}\p- 9; \*\cs{infix_)}\p- \!\!
+% \cs{until}\p( 51; F \o- \*\cs{until}\p- 9; T \cs{infix_)} \!\!
+% \*\cs{until}\p( 51; F \o- 9; \cs{infix_)} \!\!
+% \cs{until}\p( \*\o{-} 51; 9; \cs{infix_)}\p( \!\!
+% \cs{until}\p( 42; \*\cs{infix_)}\p( \!\!
+% \*\cs{until}\p( 42; T \cs{infix_)} \!\!
+% 42; \cs{infix_)} \!\!
+% \end{l3fp-code-example}
+%
+% The only missing step is to clean the output by removing \cs{infix_)},
+% and possibly checking that nothing else remains.
+%
+% \subsection{Prefix operators, parentheses, and functions}
+%
+% Prefix operators (typically the unary |-|) and parentheses are
+% taken care of by the same mechanism, and functions (\texttt{sin},
+% \texttt{exp}, etc.) as well. Finding the argument of the unary
+% |-|, for instance, is very similar to grabbing the second operand
+% of a binary infix operator, with a small subtelty on precedence
+% explained below. Once that argument is found, its sign can be
+% flipped. A left parenthesis is just a prefix operator which
+% removes the closing parenthesis (with some extra checks).
+%
+% Detecting prefix operators is done by \cs{one}. Before looking
+% for a number, it tests the first character. If it is a digit, a
+% dot, or a register, then we have a number. Otherwise, it is put
+% in a function, \cs{prefix_?} (where |?| is roughly that first
+% character), which is expanded. For instance, with a left
+% parenthesis we would have the following.
+% \begin{l3fp-code-example}
+% \*\cs{one}\p* \! ( 2 + 3 ) \!
+% \*\cs{prefix_(}\p* \! 2 + 3 ) \!
+% \o(\p* \cs{until}\p( \*\cs{one}\p( \! 2 + 3 ) \!
+% ... \!\!
+% \o(\p* 5; \cs{infix_)} \! \!
+% \end{l3fp-code-example}
+% As usual, the \cs{until}--\cs{one} pair reads and compute
+% until reaching an operator of precedence at most \fpPrecedence{(}.
+% Then \fpOperation{(} removes \cs{infix_)} and looks ahead for
+% the next operation, comparing its precedence with the precedence
+% \fpPrecedence{*} of the previous operation (in fact, this comparison
+% is done by the relevant \cs{infix_?} built from the next operation).
+%
+% To support multi-character function (and constant) names, we
+% may need to put more than one character in the \cs{prefix_?}
+% construction. See implementation for details.
+%
+% Note that contrarily to \cs{infix_?} functions, the \cs{prefix_?}
+% functions perform no test on their argument (which is once more
+% the previous precedence), since we know that we need a number,
+% and must never stop there.
+%
+% Functions are implemented as prefix operators with infinitely high
+% precedence, so that their argument is the first number that can
+% possibly be built. For instance, something like the following could
+% happen in a computation
+% \begin{l3fp-code-example}
+% \*\cs{one}\p* \! sqrt 4 + 3 ) \!
+% \*\cs{prefix_sqrt}\p* \! 4 + 3 ) \!
+% \o{sqrt}\p* \cs{until}\p{$\infty$} \*\cs{one}\p{$\infty$} \! 4 + 3 ) \!
+% ... \!\!
+% \o{sqrt}\p* 4; \cs{infix_+} \! 3 ) \!
+% 2; \*\cs{infix_+}\p* \! 3 ) \!
+% \end{l3fp-code-example}
+%
+% Lonely example, to be put somewhere: |2+sin 1 * 3| is $2+(\sin(1)\times 3)$.
+%
+% A further complication arises in the case of the unary |-| sign:
+% |-3**2| should be $-(3^2)=-9$, and not $(-3)^2=9$. Easy, just give
+% |-| a lower precedence, equal to that of the infix |+| and |-|.
+% Unfortunately, this fails in subtle cases such as |3**-2*4|,
+% yielding $3^{-2\times 4}$ instead of the correct $3^{-2}\times 4$.
+% In fact, a unary |-| should only perform operations whose precedence
+% is greater than that of the last operation, as well as
+% |-|.\footnote{Taking into account the precedence of \texttt{-} itself
+% only matters when it follows a left parenthesis:
+% \texttt{(-2*4+3)} should give \texttt{((-8)+3)}, not \texttt{(-(8+3))}.}
+% Thus, \cs{prefix_-} \meta{prec} expands to something like
+% \begin{l3fp-code-example}
+% \o- \meta{prec} \cs{until}\p? \*\cs{one} \p?
+% \end{l3fp-code-example}
+% where \fpPrecedence{?} is the maximum of \meta{prec} and the
+% precedence of |-|. Once the argument of |-| is found, \fpOperation{-}
+% gets its opposite, and leaves it for the previous operation to use.
+%
+% An example with parentheses.
+%
+% \begin{l3fp-code-example}
+% \cs{until}\p( \*\cs{one}\p( \! 11 * ( 2 + 3 ) - 9 )\!
+% \cs{until}\p( 1 \*\cs{one}\p( \! 1 * ( 2 + 3 ) - 9 )\!
+% \cs{until}\p( 11 \*\cs{one}\p( \! * ( 2 + 3 ) - 9 )\!
+% \cs{until}\p( 11; \*\cs{infix_*}\p( \! ( 2 + 3 ) - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \*\cs{one}\p* \! ( 2 + 3 ) - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \*\cs{prefix_(}\p* \! 2 + 3 ) - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \cs{until}\p( \*\cs{one}\p( \! 2 + 3 ) - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \cs{until}\p( 2 \*\cs{one}\p( \! + 3 ) - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \cs{until}\p( 2; \*\cs{infix_+}\p( \! 3 ) - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \cs{until}\p( 2; F \o+ \cs{until}\p+ \*\cs{one}\p+ \! 3)-9)\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \cs{until}\p( 2; F \o+ \cs{until}\p+ 3 \*\cs{one}\p+ \! )-9)\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \cs{until}\p( 2; F \o+ \cs{until}\p+ 3; \*\cs{infix_)}\p+ \! -9)\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \cs{until}\p( 2; F \o+ \*\cs{until}\p+ 3; T \cs{infix_)} \! -9)\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \*\cs{until}\p( 2; F \o+ 3; \cs{infix_)} \! - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \cs{until}\p( \*\o+ 2; 3; \cs{infix_)}\p( \! - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \cs{until}\p( 5; \*\cs{infix_)}\p( \! - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \o(\p* \*\cs{until}\p( 5; T \cs{infix_)} \! - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* \*\o(\p* 5; \cs{infix_)} \! - 9 )\!
+% \cs{until}\p( 11; F \o* \cs{until}\p* 5; \*\cs{infix_-}\p* \! 9 )\!
+% \cs{until}\p( 11; F \o* \*\cs{until}\p* 5; T \cs{infix_-} \! 9 )\!
+% \*\cs{until}\p( 11; F \o* 5; \cs{infix_-} \! 9 )\!
+% \cs{until}\p( \*\o* 11; 5; \cs{infix_-}\p( \! 9 )\!
+% \cs{until}\p( 55; \* \cs{infix_-}\p( \! 9 )\!
+% \cs{until}\p( 55; F \o- \cs{until}\p- \*\cs{one}\p- \! 9 )\!
+% \cs{until}\p( 55; F \o- \cs{until}\p- 9 \*\cs{one}\p- \! )\!
+% \cs{until}\p( 55; F \o- \cs{until}\p- 9; \*\cs{infix_)}\p- \!\!
+% \cs{until}\p( 55; F \o- \*\cs{until}\p- 9; T \cs{infix_)} \!\!
+% \*\cs{until}\p( 55; F \o- 9; \cs{infix_)} \!\!
+% \cs{until}\p( \*\o- 55; 9; \cs{infix_)}\p( \!\!
+% \cs{until}\p( 47; \*\cs{infix_)}\p( \!\!
+% \*\cs{until}\p( 47; T \cs{infix_)} \!\!
+% 47; \cs{infix_)} \!\!
+% \end{l3fp-code-example}
+%
+% The end of this (sub)section was not revised yet
+%
+% \begin{itemize}
+% \item If it is a sign (|-| or |+|), then any following sign will be
+% combined with this initial sign, forming \cs{prefix_+} or \cs{prefix_-}.
+% \item If it is a letter, then any following letter is grabbed, forming
+% for instance \cs{prefix_sin} or \cs{prefix_sinh}.
+% \item Otherwise, only one token\footnote{Some support for multi-character
+% prefix operator may be added in the future, but right now, I don't
+% see a use for it. Perhaps, for including comments inside
+% the computation itself??} is grabbed, for instance \cs{prefix_(}.
+% \end{itemize}
+%
+%^^A todo: make sure that's correct??
+%
+% Functions may take several arguments, possibly an unknown
+% number\footnote{Keyword argument support may be added later.},
+% for instance \texttt{round(1.23456,2)}.
+% \begin{itemize}
+% \item \texttt{round} is made into \cs{prefix_round}, which tries to
+% grab one number using \cs{one}.
+% \item This builds \cs{prefix_(}, which uses \cs{one} to grab one
+% number, calculating as necessary. The comma is given the same
+% precedence as parentheses, and thus ends the calculation of the
+% argument of \texttt{round}.
+% \item \texttt{round} now has its first argument. It can check whether
+% the argument was closed by |,| or |)|, and branch accordingly.
+% \item If it was a comma, then the first argument is skipped over,
+% through an expensive set of \cs{exp_after:wN}, and the second
+% argument can be grabbed. Here it is simply an integer, easier
+% to parse by building upon \cs{etex_numexpr:D}.
+% \item The closing parenthesis (or another comma) is seen, and the
+% control is given back to \cs{prefix_round}.
+% \end{itemize}
+%
+% \subsection{Type detection}
+%
+% The type of data should be detected by reading the first few tokens,
+% before calling a type-specific function to parse it. Or
+% should the type be obtained after the semicolon which indicates the
+% end of the thing? And placed there?
+%
+% ^^A todo: what did I mean in this paragraph?
+% Also to grab exponents correctly, build \cs{@@_<abc>:w} when seeing
+% some non-numeric |abc| while still looking to complete a number (or
+% other data). Then, if \cs{@@_postfix_<type>_<abc>:w} exists, use it.
+%
+% The internal representation of floating point numbers is quite
+% untypable, and we provide here the tools to convert from a more
+% user-friendly representation to internal floating point numbers,
+% and for various other conversions. Every floating point operation
+% calls those functions to normalize the input, so they must be
+% optimized.
+%
+% \section{Internal representation}
+%
+% Internally, a floating point number \meta{X} is a
+% token list containing
+% \begin{quote}
+% \cs{s_@@} \cs{@@_chk:w} \meta{case} \meta{sign} \meta{body} |;|
+% \end{quote}
+% Let us explain each piece separately.
+%
+% Internal floating point numbers will be used in expressions,
+% and in this context will be subject to f-expansion. They must
+% leave a recognizable mark after \texttt{f}-expansion, to prevent the
+% floating point number from being re-parsed. Thus, \cs{s_@@}
+% is simply another name for \tn{relax}.
+%
+% Since floating point numbers are always accessed by the various
+% operations using f-expansion, we can safely let them be protected:
+% \texttt{x}-expansion will then leave them untouched. However, when
+% used directly without an accessor function, floating points should
+% produce an error. \cs{s_@@} will do nothing, and \cs{@@_chk:w}
+% produces an error.
+%
+% The (decimal part of the) IEEE-754-2008 standard requires the
+% format to be able to represent special floating point numbers
+% besides the usual positive and negative cases. The various
+% possibilities will be distinguished by their \meta{case}, which
+% is a single digit:\footnote{Bruno: I need to implement subnormal
+% numbers. Also, quiet and signalling \texttt{nan} must be better
+% distinguished.}
+% \begin{itemize}
+% \item[0] zeros: |+0| and |-0|,
+% \item[1] \enquote{normal} numbers (positive and negative),
+% \item[2] infinities: |+inf| and |-inf|,
+% \item[3] quiet and signalling \texttt{nan}.
+% \end{itemize}
+% The \meta{sign} is |0| (positive) or |2| (negative),
+% except in the case of \texttt{nan}, which have $\meta{sign} = 1$.
+% This ensures that changing the \meta{sign} digit to $2-\meta{sign}$
+% is exactly equivalent to changing the sign of the number.
+%
+% Special floating point numbers have the form
+% \begin{quote}
+% \cs{s_@@} \cs{@@_chk:w} \meta{case} \meta{sign} \cs{s_@@_...} |;|
+% \end{quote}
+% where \cs{s_@@_...} is a scan mark carrying information about how the
+% number was formed (useful for debugging).
+%
+% Normal floating point numbers ($\meta{case} = 1$) have the form
+% \begin{quote}
+% \cs{s_@@} \cs{@@_chk:w} 1 \meta{sign} \Arg{exponent}
+% \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} |;|
+% \end{quote}
+% Here, the \meta{exponent} is an integer, at most
+% $\cs{c_@@_max_exponent_int} =
+% \the\csname\detokenize{c__fp_max_exponent_int}\endcsname$
+% in absolute value. The body consists in four
+% blocks of exactly $4$ digits, $ 0000 \leq \meta{X_i} \leq 9999$,
+% such that
+% \[
+% \meta{X}
+% = (-1)^{\meta{sign}} 10^{-\meta{exponent}}
+% \sum_{i=1}^{4} \meta{X_i} 10^{-4i}
+% \]
+% and such that the \meta{exponent} is minimal. This implies
+% $ 1000 \leq \meta{X_1} \leq 9999 $.
+%
+% \begin{table}\centering
+% \caption{Internal representation of floating point numbers.}
+% \label{tab:fp-convert-special}
+% \begin{tabular}{ll}
+% \toprule
+% \multicolumn{1}{c}{Representation} & Meaning \\
+% \midrule
+% 0 0 \cs{s_@@_...} \texttt{;} & Positive zero. \\
+% 0 2 \cs{s_@@_...} \texttt{;} & Negative zero. \\
+% 1 0 \Arg{exponent} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \texttt{;}
+% & Positive floating point. \\
+% 1 2 \Arg{exponent} \Arg{X_1} \Arg{X_2} \Arg{X_3} \Arg{X_4} \texttt{;}
+% & Negative floating point. \\
+% 2 0 \cs{s_@@_...} \texttt{;} & Positive infinity. \\
+% 2 2 \cs{s_@@_...} \texttt{;} & Negative infinity. \\
+% 3 1 \cs{s_@@_...} \texttt{;} & Quiet \texttt{nan}. \\
+% 3 1 \cs{s_@@_...} \texttt{;} & Signalling \texttt{nan}. \\
+% \bottomrule
+% \end{tabular}
+% \end{table}
+%
+% \section{Internal parsing functions}
+%
+% \begin{macro}[EXP, int]{\@@_parse_until:Nw}
+% \begin{syntax}
+% \cs{tex_romannumeral:D} \cs{@@_parse_until:Nw} \meta{precedence} \cs{@@_parse_expand:w} \meta{tokens}
+% \end{syntax}
+% Reads the \meta{tokens}, performing every computation with a
+% precedence higher than \meta{precedence}, then expands to
+% \begin{syntax}
+% \meta{objects} |@| \cs{@@_parse_infix_\meta{operation}:N} \ldots{}
+% \end{syntax}
+% where the \meta{op} is the first operation with a lower precedence,
+% possibly \texttt{end}.
+% \end{macro}
+%
+% \begin{macro}[EXP, int]{\@@_parse_operand:Nw}
+% \begin{syntax}
+% \cs{@@_parse_operand:Nw} \meta{precedence} \ldots{}
+% \end{syntax}
+% If the following \meta{operation} has a precedence higher than
+% \meta{precedence}, expands to
+% \begin{syntax}
+% \meta{object_1} |@| \cs{@@_parse_apply_binary:NwNwN} \meta{operation} \meta{object_2} |@| \cs{@@_parse_infix_\meta{operation_2}:N} \ldots{}
+% \end{syntax}
+% and otherwise expands to
+% \begin{syntax}
+% \meta{object} |@| \cs{@@_parse_stop_until:N} \cs{@@_parse_infix_\meta{operation}:N} \ldots{}
+% \end{syntax}
+% \end{macro}
+%
+% \begin{macro}[EXP, int]{\@@_parse_infix_\meta{operation}:N}
+% \begin{syntax}
+% \cs{@@_parse_infix_\meta{operation}:N} \meta{precedence}
+% \end{syntax}
+% If the \meta{op} has a precedence higher than \meta{precedence}, expands to
+% \begin{syntax}
+% |@| \cs{@@_parse_apply_binary:NwNwN} \meta{operation} \meta{object} |@| \cs{@@_parse_infix_\meta{operation_2}:N}
+% \end{syntax}
+% Otherwise expands to
+% \begin{syntax}
+% |@| \cs{@@_parse_stop_until:N} \cs{@@_parse_infix_\meta{operation}:N}
+% \end{syntax}
+% \end{macro}
+%
+% ^^A end[todo]
+%
+% \subsection{Expansion control}
+%
+% At each step in reading a floating point expression, we wish to
+% perform \texttt{f}-expansion. Normally, spaces stop this
+% \texttt{f}-expansion. This can be problematic: for instance, the
+% macro |\X| below will not be expanded if we simply do
+% \texttt{f}-expansion.
+% \begin{verbatim}
+% \DeclareDocumentCommand {\test} {m} { \fp_eval:n {#1} }
+% \ExplSyntaxOff
+% \test { 1 + \X }
+% \end{verbatim}
+% To avoid this problem, at every step, we do essentially what
+% \cs{use:f} would do: take an argument, put it back in the input
+% stream, then \texttt{f}-expand it. This is not a complete solution,
+% since a macro's expansion could contain leading spaces which will stop
+% the \texttt{f}-expansion before further macro calls are performed.
+% However, in practice it should be enough: in particular, floating
+% point numbers will correctly be expanded to the underlying \cs{s_@@}
+% \ldots{} structure.
+%
+%^^A begin[todo]
+% Floating point expressions should behave as much as possible like
+% \eTeX{}-based integer expressions and dimension expressions. In
+% particular, full-expansion should be performed as the expression is
+% read, token by token, forcing the expansion of protected macros, and
+% ignoring spaces.
+%
+% Full expansion can be done with \cs{tex_romannumeral:D} |-`0|.
+% Unfortunately, this expansion is stopped by spaces. Thus using simply
+% this will fail on |\fp_eval:n { 1 + ~ \l_tmpa_fp }| since the floating
+% point variable will not be expanded. Of course, spaces will not
+% appear in a code setting, but may very easily come in document-level
+% input, from which some expressions may come. We can avoid being
+% stopped by such explicit space characters (and by some braces) if we
+% add \cs{use:n} after~|-`0|.
+%
+% Testing if a character token |#1| is a digit can be done using
+% \begin{verbatim}
+% \if_int_compare:w \c_nine < 1 \token_to_str:N #1 \exp_stop_f:
+% true code
+% \else:
+% false code
+% \fi:
+% \end{verbatim}
+% To exclude |0|, replace \cs{c_nine} by \cs{c_ten}. The use of
+% \cs{token_to_str:N} ensures that a digit with any catcode is detected.
+%
+%^^A end[todo]
+%
+% \begin{macro}[rEXP, aux]{\@@_parse_expand:w}
+% \begin{syntax}
+% \cs{tex_romannumeral:D} \cs{@@_parse_expand:w} \meta{tokens}
+% \end{syntax}
+% This function must always come within a \tn{romannumeral} expansion.
+% The \meta{tokens} should be the part of the expression that we have
+% not yet read. This requires in particular closing all conditionals
+% properly before expanding.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_expand:w #1 { -`0 #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, aux]{\@@_parse_return_semicolon:w}
+% This very odd function swaps its position with the following
+% \cs{fi:} and removes \cs{@@_parse_expand:w} normally responsible for
+% expansion. That turns out to be useful.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_return_semicolon:w
+ #1 \fi: \@@_parse_expand:w { \fi: ; #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Fp object type}
+%
+% \begin{macro}[EXP, int]{\@@_type_from_scan:N}
+% \begin{syntax}
+% \cs{@@_type_from_scan:N} \meta{token}
+% \end{syntax}
+% Grabs the pieces of the stringified \meta{token} which lies after
+% the first |s__fp|. If the \meta{token} does not contain that
+% string, the result is empty.
+% \begin{macrocode}
+\group_begin:
+\char_set_catcode_other:N \S
+\char_set_catcode_other:N \F
+\char_set_catcode_other:N \P
+\char_set_lccode:nn { `\- } { `\_ }
+\tl_to_lowercase:n
+ {
+ \group_end:
+ \cs_new:Npn \@@_type_from_scan:N #1
+ {
+ \exp_after:wN \@@_type_from_scan:w
+ \token_to_str:N #1 \q_mark S--FP \q_mark \q_stop
+ }
+ \cs_new:Npn \@@_type_from_scan:w #1 S--FP #2 \q_mark #3 \q_stop {#2}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Reading digits}
+%
+% \begin{macro}[rEXP, aux]
+% {
+% \@@_parse_digits_vii:N ,
+% \@@_parse_digits_vi:N ,
+% \@@_parse_digits_v:N ,
+% \@@_parse_digits_iv:N ,
+% \@@_parse_digits_iii:N ,
+% \@@_parse_digits_ii:N ,
+% \@@_parse_digits_i:N
+% }
+% These functions must be called within an \cs{__int_value:w} or
+% \cs{__int_eval:w} construction. The first token which follows must be
+% \texttt{f}-expanded prior to calling those functions. The functions
+% read tokens one by one, and output digits into the input stream,
+% until meeting a non-digit, or up to a number of digits equal to
+% their index. The full expansion is
+% \begin{quote}
+% \meta{digits} |;| \meta{filling 0} |;| \meta{length}
+% \end{quote}
+% where \meta{filling 0} is a string of zeros such that \meta{digits}
+% \meta{filling 0} has the length given by the index of the function,
+% and \meta{length} is the number of zeros in the \meta{filling 0}
+% string. Each function puts a digit into the input stream and calls
+% the next function, until we find a non-digit. We are careful to
+% pass the tested tokens through \cs{token_to_str:N} to normalize
+% their category code.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1 #2 #3
+ {
+ \cs_new:cpn { @@_parse_digits_ #1 :N } ##1
+ {
+ \if_int_compare:w \c_nine < 1 \token_to_str:N ##1 \exp_stop_f:
+ \token_to_str:N ##1 \exp_after:wN #2 \tex_romannumeral:D
+ \else:
+ \@@_parse_return_semicolon:w #3 ##1
+ \fi:
+ \@@_parse_expand:w
+ }
+ }
+\@@_tmp:w {vii} \@@_parse_digits_vi:N { 0000000 ; 7 }
+\@@_tmp:w {vi} \@@_parse_digits_v:N { 000000 ; 6 }
+\@@_tmp:w {v} \@@_parse_digits_iv:N { 00000 ; 5 }
+\@@_tmp:w {iv} \@@_parse_digits_iii:N { 0000 ; 4 }
+\@@_tmp:w {iii} \@@_parse_digits_ii:N { 000 ; 3 }
+\@@_tmp:w {ii} \@@_parse_digits_i:N { 00 ; 2 }
+\@@_tmp:w {i} \@@_parse_digits_:N { 0 ; 1 }
+\cs_new_nopar:Npn \@@_parse_digits_:N { ; ; 0 }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Parsing one operand}
+%
+% At the start of an expression, or just following a binary operation or
+% a function call, we are looking for an operand. This can be an
+% explicit floating point number, a floating point variable, a \TeX{}
+% register, a function call such as \texttt{sin(3)}, a parenthesized
+% expression, \emph{etc.} We distinguish the various cases by their
+% first token after \texttt{f}-expansion:
+% \begin{itemize}
+% \item \cs{tex_relax:D} in some form. That can be an internal
+% floating point, a premature end, or an unitialized register.
+% \item A register. We interpret this as the significand of a floating
+% point number. This is subtely different from unpacking it, for
+% instance, \texttt{\cs{c_minus_one}**2} gives $1$, while
+% \texttt{-1**2} gives $-1$.
+% \item A digit, or a dot. That marks the start of the significand for
+% a floating point number.
+% \item A letter (lower or upper-case), which starts an identifier,
+% either a constant or a function (possibly unknown).
+% \item |+|, |-|, or |!|, unary operators, which resume looking for a
+% floating point number before acting on it.
+% \item |(|, which makes us parse a subexpression until the
+% matching~|)|.
+% \item Other characters such as |'| or |"| may be given a meaning
+% later. Characters such as |*| or |/| have a meaning as infix
+% operators but are not valid when we are looking for an operand: for
+% instance, |3+*4| is not valid.
+% \end{itemize}
+% A category code test separates the first two cases from the others,
+% and they are further distinguished with a meaning test. We then
+% single out digits. Letters are detected using their character code.
+% All other characters are taken care of by building a csname from that
+% character and using it to continue parsing. Unknown characters lead
+% to an error.
+%
+% \begin{macro}[int, EXP]{\@@_parse_operand:Nw}
+% Function called \cs{one} at other places. It grabs one operand, and
+% packs the symbol that follows in an \cs{infix_} csname. |#1| is the
+% previous \meta{precedence}, and |#2| the first character of the
+% operand (already \texttt{f}-expanded).
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_operand:Nw #1 #2
+ {
+ \if_catcode:w \tex_relax:D #2
+ \if_meaning:w \tex_relax:D #2
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_parse_operand_relax:NN
+ \else:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_parse_operand_register:NN
+ \fi:
+ \else:
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #2 \exp_stop_f:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_parse_operand_digit:NN
+ \else:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_parse_operand_other:NN
+ \fi:
+ \fi:
+ #1 #2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% ^^A todo: rounding of negative dimensions is probably wrong.
+% \begin{macro}[aux, EXP]
+% {\@@_parse_operand_register:NN, \@@_parse_operand_register_aux:www}
+% Find the exponent following the register |#2|, then combine the
+% value of |#2| (mapping |1pt| to $1$) with the exponent to produce a
+% floating point number.
+% \begin{macrocode}
+\group_begin:
+\char_set_catcode_other:N \P
+\char_set_catcode_other:N \T
+\tl_to_lowercase:n
+ {
+ \group_end:
+ \cs_new:Npn \@@_parse_operand_register:NN #1#2
+ {
+ \exp_after:wN \@@_parse_infix_after_operand:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \exp_after:wN \@@_parse_operand_register_aux:www
+ \tex_the:D
+ \exp_after:wN #2
+ \exp_after:wN P
+ \exp_after:wN T
+ \exp_after:wN \q_stop
+ \__int_value:w \@@_parse_exponent:N
+ }
+ \cs_new:Npn \@@_parse_operand_register_aux:www #1 PT #2 \q_stop #3 ;
+ { \@@_parse:n { #1 e #3 } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]
+% {\@@_parse_operand_relax:NN, \@@_parse_operand_relax_aux:wwnw} The
+% argument is a token equal to \cs{tex_relax:D}. This can be
+% \cs{s_@@}, \cs{s_@@_mark}, or a badly initialized register. We make
+% sure that the last argument of \cs{@@_parse_infix:NN} is
+% correctly expanded.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_operand_relax:NN #1#2
+ {
+ \@@_parse_operand_relax_aux:wwnw
+ #2 \s_@@_mark
+ {
+ \@@_exp_after_o:nw
+ {
+ \tex_romannumeral:D -`0
+ \exp_after:wN \@@_parse_infix:NN
+ \exp_after:wN #1 \tex_romannumeral:D \@@_parse_expand:w
+ }
+ \s_@@
+ }
+ \s_@@ #2
+ {
+ \@@_error:n { Premature~end~in~fp~expression. }
+ \exp_after:wN \c_nan_fp
+ \tex_romannumeral:D -`0
+ \@@_parse_infix:NN #1
+ \s_@@_mark
+ }
+ \s_@@_mark
+ {
+ \@@_error:n { Erroneous~variable~#2 used! }
+ \exp_after:wN \c_nan_fp
+ \tex_romannumeral:D -`0
+ \exp_after:wN \@@_parse_infix:NN
+ \exp_after:wN #1
+ \tex_romannumeral:D \@@_parse_expand:w
+ }
+ \s_@@_mark \s_@@_stop
+ }
+\cs_new:Npn \@@_parse_operand_relax_aux:wwnw
+ #1 \s_@@ #2 \s_@@_mark #3 #4 \s_@@_mark \s_@@_stop { #3 }
+% \end{macrocode}
+% \end{macro}
+%
+% ^^A begin[todo]
+%
+% \begin{macro}[aux, EXP]{\@@_parse_operand_other:NN}
+% The interesting bit is \cs{@@_parse_operand_other:NN}. It separates
+% letters from non-letters and builds the appropriate \cs{prefix}
+% function. If it is not defined (is \cs{tex_relax:D}), make it
+% a signalling \texttt{nan}. We don't look for an argument, as the
+% unknown \enquote{prefix} can also be a (mistyped) constant such
+% as \texttt{Inf}.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_operand_other:NN #1 #2
+ {
+ \if_int_compare:w
+ \__int_eval:w \tex_uccode:D `#2 / 26 = \c_three
+ \exp_after:wN \@@_parse_operand_other_word_aux:Nw
+ \exp_after:wN #1
+ \tex_romannumeral:D
+ \exp_after:wN \@@_parse_letters:NN
+ \exp_after:wN #2
+ \tex_romannumeral:D
+ \else:
+ \exp_after:wN \@@_parse_operand_other_prefix_aux:NNN
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \cs:w @@_parse_prefix_#2:Nw \exp_after:wN \cs_end:
+ \tex_romannumeral:D
+ \fi:
+ \@@_parse_expand:w
+ }
+
+\cs_new:Npn \@@_parse_letters:NN #1#2
+ {
+ \exp_after:wN \c_zero
+ \exp_after:wN #1
+ \tex_romannumeral:D
+ \if_int_compare:w
+ \if_catcode:w \tex_relax:D #2
+ \c_zero
+ \else:
+ \__int_eval:w \tex_uccode:D `#2 / 26
+ \fi:
+ = \c_three
+ \exp_after:wN \@@_parse_letters:NN
+ \exp_after:wN #2
+ \tex_romannumeral:D
+ \exp_after:wN \@@_parse_expand:w
+ \else:
+ \exp_after:wN \c_zero
+ \exp_after:wN ;
+ \exp_after:wN #2
+ \fi:
+ }
+\cs_new:Npn \@@_parse_operand_other_word_aux:Nw #1 #2;
+ {
+ \cs_if_exist_use:cF { @@_parse_word_#2:N }
+ {
+ \__msg_expandable_error:n { Unknown~word~#2. }
+ \exp_after:wN \c_nan_fp
+ \tex_romannumeral:D -`0
+ \@@_parse_infix:NN
+ }
+ #1
+ }
+\cs_new_eq:NN \s_@@_unknown \tex_relax:D
+\cs_new:Npn \@@_parse_operand_other_prefix_aux:NNN #1#2#3
+ {
+ \if_meaning:w \tex_relax:D #3
+ \exp_after:wN \@@_parse_operand_other_prefix_unknown:NNN
+ \exp_after:wN #2
+ \fi:
+ #3 #1
+ }
+\cs_new:Npn \@@_parse_operand_other_prefix_unknown:NNN #1#2#3
+ {
+ \cs_if_exist:cTF { @@_parse_infix_#1:N }
+ {
+ \@@_error:n { Missing~number~before~'#1'. }
+ \exp_after:wN \c_nan_fp
+ \tex_romannumeral:D -`0
+ \@@_parse_infix:NN #3 #1
+ }
+ {
+ \@@_error:n { Unknown~symbol~#1~ignored. }
+ \@@_parse_operand:Nw #3
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% The following forms are accepted:
+% \begin{itemize}
+% \item
+% \item \meta{floating point}
+% \item \meta{integer} |.| \meta{decimal} |e| \meta{exponent}
+% \end{itemize}
+% In both cases, \meta{signs} is a (possibly empty) string of
+% |+| and |-| (with any category code\footnote{Bruno: except
+% 1, 2, 4, 10, 13, and those which cannot be tokens (0, 5, 9),
+% so really, just 3, 6, 7, 8, 11, 12.}).\footnote{Bruno:
+% test (and implement) non-other digits.}
+%
+% In the second form, the \meta{integer} is a sequence of digits,
+% whose length is not limited by constraints \TeX{}'s integer
+% registers. It stops at the first non-digit character. The
+% \meta{decimal} part is formed by all digits from the dot
+% (if it exists) until the first non-digit character. The
+% \meta{exponent} part has the form \meta{exponent sign}
+% \meta{exponent body}, where \meta{exponent sign} is any string
+% of |+| or |-|, and \meta{exponent body} is a string of digits,
+% stopping, as usual, at the first non-digit.
+%
+% Any missing part will take the appropriate default value.
+% \begin{itemize}
+% \item A missing \meta{exponent} is considered to be zero.
+% \item A number with no dot has zero decimal part.
+% \item An empty \meta{integer} part or decimal part is zero.
+% \end{itemize}
+%
+% Border cases:
+% \begin{itemize}
+% \item \texttt{e1} is considered as invalid input, and gives
+% \texttt{qnan}.\footnote{Bruno: now just gives an error.}
+% This will be important once parsing expressions is
+% implemented, since \texttt{e-1} would be ambiguous otherwise.
+% \item \texttt{.e3} and \texttt{.} are zero.
+% \end{itemize}
+%
+% Bruno: expansion, not yet. Only f-expansion at the start, and
+% unpacking of registers after signs.
+%
+%
+% Work-plan.
+% \begin{itemize}
+% \item Remove any leading sign and build the \meta{sign} as we go.
+% If the next character is a letter, go to the \enquote{special}
+% branch, discussed later.
+% \item Drop leading zeros.
+% \item If the next character is a dot, drop some more zeros,
+% keeping track of how many were dropped after the dot.
+% Counting those gives $\meta{exp_1}<0$. Then read the decimal part
+% with the \cs{@@_from_str_small} functions.
+% \item Otherwise, $\meta{exp_1}=0$, and first read the integer part,
+% then the decimal part. This is implemented through the more
+% elaborate \cs{@@_from_str_large} functions.
+% \item Continuing in the same line of expansion, read the exponent
+% \meta{exp_2}.
+% \item Finally check that nothing is left.\footnote{Bruno: not done yet.}
+% \end{itemize}
+%
+% \begin{macro}[aux, EXP]{\@@_parse_operand_digit:NN}
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_operand_digit:NN #1
+ {
+ \exp_after:wN \@@_parse_infix_after_operand:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \exp_after:wN \@@_sanitize:wN
+ \int_use:N \__int_eval:w \c_zero \@@_parse_trim_zeros:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% ^^A end[todo]
+%
+% \subsubsection{Trimming leading zeros}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_trim_zeros:N, \@@_parse_trim_end:w}
+% This function expects an already expanded token. It removes any
+% leading zero, then distinguished three cases: if the first non-zero
+% token is a digit, then call \cs{@@_parse_large:N} (the significand is
+% $\geq 1$); if it is |.|, then continue trimming zeros with
+% \cs{@@_parse_strim_zeros:N}; otherwise, our number is exactly zero,
+% and we call \cs{@@_parse_zero:} to take care of that case.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_trim_zeros:N #1
+ {
+ \if:w 0 #1
+ \exp_after:wN \@@_parse_trim_zeros:N
+ \tex_romannumeral:D
+ \else:
+ \if:w . #1
+ \exp_after:wN \@@_parse_strim_zeros:N
+ \tex_romannumeral:D
+ \else:
+ \@@_parse_trim_end:w #1
+ \fi:
+ \fi:
+ \@@_parse_expand:w
+ }
+\cs_new:Npn \@@_parse_trim_end:w #1 \fi: \fi: \@@_parse_expand:w
+ {
+ \fi:
+ \fi:
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #1 \exp_stop_f:
+ \exp_after:wN \@@_parse_large:N
+ \else:
+ \exp_after:wN \@@_parse_zero:
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_strim_zeros:N, \@@_parse_strim_end:w}
+% If we have removed all digits until a period (or if the body started
+% with a period), then enter the \enquote{\texttt{small_trim}} loop
+% which outputs $-1$ for each removed $0$. Those $-1$ are added to an
+% integer expression waiting for the exponent. If the first non-zero
+% token is a digit, call \cs{@@_parse_small:N} (our significand is
+% smaller than~$1$), and otherwise, the number is an exact zero.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_strim_zeros:N #1
+ {
+ \if:w 0 #1
+ - \c_one
+ \exp_after:wN \@@_parse_strim_zeros:N
+ \tex_romannumeral:D
+ \else:
+ \@@_parse_strim_end:w #1
+ \fi:
+ \@@_parse_expand:w
+ }
+\cs_new:Npn \@@_parse_strim_end:w #1 \fi: \@@_parse_expand:w
+ {
+ \fi:
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #1 \exp_stop_f:
+ \exp_after:wN \@@_parse_small:N
+ \else:
+ \exp_after:wN \@@_parse_zero:
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Exact zero}
+%
+% \begin{macro}[aux, EXP]{\@@_parse_zero:}
+% After reading a significand of $0$, we need to remove any exponent,
+% then put a sign of |1| for \cs{@@_sanitize:wN}, denoting an
+% exact zero.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_zero:
+ {
+ \exp_after:wN ; \exp_after:wN 1
+ \__int_value:w \@@_parse_exponent:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Small significand}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_small:N}
+% This function is called after we have passed the decimal separator
+% and removed all leading zeros from the significand. It is followed
+% by a non-zero digit (with any catcode). The goal is to read up to
+% $16$ digits. But we can't do that all at once, because
+% \cs{__int_value:w} (which allows us to collect digits and continue
+% expanding) can only go up to $9$ digits. Hence we grab digits in
+% two steps of $8$ digits. Since |#1| is a digit, read seven more
+% digits using \cs{@@_parse_digits_vii:N}. The \texttt{small_leading}
+% auxiliary will leave those digits in the \cs{__int_value:w}, and grab
+% some more, or stop if there are no more digits. Then the
+% \texttt{pack_leading} auxiliary puts the various parts in the
+% appropriate order for the processing further up.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_small:N #1
+ {
+ \exp_after:wN \@@_parse_pack_leading:NNNNNww
+ \int_use:N \__int_eval:w 1 \token_to_str:N #1
+ \exp_after:wN \@@_parse_small_leading:wwNN
+ \__int_value:w 1
+ \exp_after:wN \@@_parse_digits_vii:N
+ \tex_romannumeral:D \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_small_leading:wwNN}
+% \begin{syntax}
+% \cs{@@_parse_small_leading:wwNN} |1| \meta{digits} |;| \meta{zeros} |;| \meta{number~of~zeros}
+% \end{syntax}
+% We leave \meta{digits} \meta{zeros} in the input stream: the
+% functions used to grab digits are such that this constitutes digits
+% $1$ through $8$ of the significand. Then prepare to pack $8$ more
+% digits, with an exponent shift of \cs{c_zero} (this shift is used in
+% the case of a large significand). If |#4| is a digit, leave it
+% behind for the packing function, and read $6$ more digits to reach a
+% total of $15$ digits: further digits are involved in the rounding.
+% Otherwise put $8$ zeros in to complete the significand, then look
+% for an exponent.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_small_leading:wwNN 1 #1 ; #2; #3 #4
+ {
+ #1 #2
+ \exp_after:wN \@@_parse_pack_trailing:NNNNNNww
+ \exp_after:wN \c_zero
+ \int_use:N \__int_eval:w 1
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #4 \exp_stop_f:
+ \token_to_str:N #4
+ \exp_after:wN \@@_parse_small_trailing:wwNN
+ \__int_value:w 1
+ \exp_after:wN \@@_parse_digits_vi:N
+ \tex_romannumeral:D
+ \else:
+ 0000 0000 \@@_parse_exponent:Nw #4
+ \fi:
+ \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_small_trailing:wwNN}
+% \begin{syntax}
+% \cs{@@_parse_small_trailing:wwNN} |1| \meta{digits} |;| \meta{zeros} |;| \meta{number~of~zeros} \meta{next~token}
+% \end{syntax}
+% Leave digits $10$ to $15$ (arguments |#1| and |#2|) in the input
+% stream. If the \meta{next~token} is a digit, it is the $16$th
+% digit, we keep it, then the \texttt{small_round} auxiliary considers
+% this digit and all further digits to perform the rounding: the
+% function expands to nothing or to |+1|. Otherwise, there is no
+% $16$-th digit, so we put a $0$, and look for an exponent.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_small_trailing:wwNN 1 #1 ; #2; #3 #4
+ {
+ #1 #2
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #4 \exp_stop_f:
+ \token_to_str:N #4
+ \exp_after:wN \@@_parse_small_round:NN
+ \exp_after:wN #4
+ \tex_romannumeral:D
+ \else:
+ 0 \@@_parse_exponent:Nw #4
+ \fi:
+ \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]
+% {
+% \@@_parse_pack_trailing:NNNNNNww ,
+% \@@_parse_pack_leading:NNNNNww ,
+% \@@_parse_pack_carry:w
+% }
+% Those functions are expanded after all the digits are found, we took
+% care of the rounding, as well as the exponent. The last argument is
+% the exponent. The previous five arguments are $8$ digits which we
+% pack in groups of $4$, and the argument before that is $1$, except
+% in the rare case where rounding lead to a carry, in which case the
+% argument is $2$. The \texttt{trailing} function has an exponent
+% shift as its first argument, which we add to the exponent found in
+% the |e...| syntax. If the trailing digits cause a carry, the
+% integer expression for the leading digits is incremented (|+ \c_one|
+% in the code below). If the leading digits propagte this carry all
+% the way up, the function \cs{@@_parse_pack_carry:w} increments the
+% exponent, and changes the mantissa from |0000...| to |1000...|: this
+% is simple because such a carry can only occur to give rise to a
+% power of $10$.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_pack_trailing:NNNNNNww #1 #2 #3#4#5#6 #7; #8 ;
+ {
+ \if_meaning:w 2 #2 + \c_one \fi:
+ ; #8 + #1 ; {#3#4#5#6} {#7};
+ }
+\cs_new:Npn \@@_parse_pack_leading:NNNNNww #1 #2#3#4#5 #6; #7;
+ {
+ + #7
+ \if_meaning:w 2 #1 \@@_parse_pack_carry:w \fi:
+ ; 0 {#2#3#4#5} {#6}
+ }
+\cs_new:Npn \@@_parse_pack_carry:w \fi: ; 0 #1
+ { \fi: + \c_one ; 0 {1000} }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Large significand}
+%
+% Parsing a significand larger than $1$ is a little bit more difficult
+% than parsing small significands. We need to count the number of
+% digits before the decimal separator, and add that to the final
+% exponent. We also need to test for the presence of a dot each time we
+% run out of digits, and branch to the appropriate \texttt{parse_small}
+% function in those cases.
+%
+% \begin{macro}[aux, EXP]{\@@_parse_large:N}
+% This function is followed by the first non-zero digit of a
+% \enquote{large} significand ($\geq 1$). It is called within an
+% integer expression for the exponent. Grab up to $7$ more digits,
+% for a total of $8$ digits.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_large:N #1
+ {
+ \exp_after:wN \@@_parse_large_leading:wwNN
+ \__int_value:w 1 \token_to_str:N #1
+ \exp_after:wN \@@_parse_digits_vii:N
+ \tex_romannumeral:D \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_large_leading:wwNN}
+% \begin{syntax}
+% \cs{@@_parse_large_leading:wwNN} |1| \meta{digits} |;| \meta{zeros} |;| \meta{number~of~zeros} \meta{next~token}
+% \end{syntax}
+% We shift the exponent by the number of digits in |#1|, namely the
+% target number, $8$, minus the \meta{number of zeros} (number of
+% digits missing). Then prepare to pack the $8$ first digits. If the
+% \meta{next token} is a digit, read up to $6$ more digits (digits
+% $10$ to $15$). If it is a period, try to grab the end of our $8$
+% first digits, branching to the \texttt{small} functions since the
+% number of digit does not affect the exponent anymore. Finally, if
+% this is the end of the significand, insert the \meta{zeros} to
+% complete the $8$ first digits, insert $8$ more, and look for an
+% exponent.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_large_leading:wwNN 1 #1 ; #2; #3 #4
+ {
+ + \c_eight - #3
+ \exp_after:wN \@@_parse_pack_leading:NNNNNww
+ \int_use:N \__int_eval:w 1 #1
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #4 \exp_stop_f:
+ \exp_after:wN \@@_parse_large_trailing:wwNN
+ \__int_value:w 1 \token_to_str:N #4
+ \exp_after:wN \@@_parse_digits_vi:N
+ \tex_romannumeral:D
+ \else:
+ \if:w . #4
+ \exp_after:wN \@@_parse_small_leading:wwNN
+ \__int_value:w 1
+ \cs:w
+ @@_parse_digits_
+ \tex_romannumeral:D #3
+ :N \exp_after:wN
+ \cs_end:
+ \tex_romannumeral:D
+ \else:
+ #2
+ \exp_after:wN \@@_parse_pack_trailing:NNNNNNww
+ \exp_after:wN \c_zero
+ \__int_value:w 1 0000 0000
+ \@@_parse_exponent:Nw #4
+ \fi:
+ \fi:
+ \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_parse_large_trailing:wwNN}
+% \begin{syntax}
+% \cs{@@_parse_large_trailing:wwNN} |1| \meta{digits} |;| \meta{zeros} |;| \meta{number~of~zeros} \meta{next~token}
+% \end{syntax}
+% We have just read $15$ digits. If the \meta{next token} is a digit,
+% then the exponent shift caused by this block of $8$ digits is $8$,
+% first argument to the \texttt{pack_trailing} function. We keep the
+% \meta{digits} and this $16$-th digit, and find how this should be
+% rounded using \cs{@@_parse_large_round:NN}. Otherwise, the exponent
+% shift is the number of \meta{digits}, $7$ minus the \meta{number of
+% zeros}, and we test for a decimal point. This case happens in
+% |123451234512345.67| with exactly $15$ digits before the decimal
+% separator. Then branch to the appropriate \texttt{small} auxiliary,
+% grabbing a few more digits to complement the digits we already
+% grabbed. Finally, if this is truly the end of the significand, look
+% for an exponent after using the \meta{zeros} and providing a $16$-th
+% digit of $0$.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_large_trailing:wwNN 1 #1 ; #2; #3 #4
+ {
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #4 \exp_stop_f:
+ \exp_after:wN \@@_parse_pack_trailing:NNNNNNww
+ \exp_after:wN \c_eight
+ \int_use:N \__int_eval:w 1 #1 \token_to_str:N #4
+ \exp_after:wN \@@_parse_large_round:NN
+ \exp_after:wN #4
+ \tex_romannumeral:D
+ \else:
+ \exp_after:wN \@@_parse_pack_trailing:NNNNNNww
+ \int_use:N \__int_eval:w \c_seven - #3 \exp_stop_f:
+ \int_use:N \__int_eval:w 1 #1
+ \if:w . #4
+ \exp_after:wN \@@_parse_small_trailing:wwNN
+ \__int_value:w 1
+ \cs:w
+ @@_parse_digits_
+ \tex_romannumeral:D #3
+ :N \exp_after:wN
+ \cs_end:
+ \tex_romannumeral:D
+ \else:
+ #2 0 \@@_parse_exponent:Nw #4
+ \fi:
+ \fi:
+ \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Finding the exponent}
+%
+% Expansion is a little bit tricky here, in part because we accept input
+% where multiplication is implicit.
+% \begin{verbatim}
+% \@@_parse:n { 3.2 erf(0.1) }
+% \@@_parse:n { 3.2 e\l_my_int }
+% \@@_parse:n { 3.2 \c_pi_fp }
+% \end{verbatim}
+% The first case indicates that just looking one character ahead for an
+% \enquote{\texttt{e}} is not enough, since we would mistake the
+% function \texttt{erf} for an exponent of \enquote{\texttt{rf}}. An
+% alternative would be to look two tokens ahead and check if what
+% follows is a sign or a digit, considering in that case that we must be
+% finding an exponent. But taking care of the second case requires that
+% we unpack registers after \texttt{e}. However, blindly expanding the
+% two tokens ahead completely would break the third example (unpacking
+% is even worse). Indeed, in the course of reading $3.2$, \cs{c_pi_fp}
+% is expanded to \cs{s_@@} \cs{@@_chk:w} |1| |0| |{-1}| |{3141}|
+% $\cdots$ |;| and \cs{s_@@} stops the expansion. Expanding two tokens
+% ahead would then force the expansion of \cs{@@_chk:w} (despite it
+% being protected), and that function tries to produce an error.
+%
+% What can we do? Really, the reason why this last case breaks is that
+% just as \TeX{} does, we should read ahead as little as possible.
+% Here, the only case where there may be an exponent is if the first
+% token ahead is |e|. Then we expand (and possibly unpack) the second
+% token --- and hopefully that is safe.
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_exponent:Nw}
+% This auxiliary is convenient to smuggle some material through
+% \cs{fi:} ending conditional processing. We place those \cs{fi:}
+% (argument |#2|) at a very odd place becase this allows us to insert
+% \cs{__int_eval:w} \ldots{} there if needed.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_exponent:Nw #1 #2 \@@_parse_expand:w
+ {
+ \exp_after:wN ;
+ \__int_value:w #2 \@@_parse_exponent:N #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_exponent:N, \@@_parse_exponent_ii:N}
+% This function should be called within an \cs{__int_value:w} expansion
+% (or within an integer expression. It leaves digits of the exponent
+% behind it in the input stream, and terminates the expansion with a
+% semicolon. If there is no \texttt{e}, leave an exponent of $0$. If
+% there is an \texttt{e}, expand the next token to run some tests on
+% it. Namely, if the character code of |#1| is greater than that of
+% |9| (largest code valid for an exponent, less than any code valid
+% for an identifier), there was in fact no exponent; otherwise, we
+% search for the sign of the exponent.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_exponent:N #1
+ {
+ \if:w e #1
+ \exp_after:wN \@@_parse_exponent_ii:N
+ \tex_romannumeral:D
+ \else:
+ 0 \@@_parse_return_semicolon:w #1
+ \fi:
+ \@@_parse_expand:w
+ }
+\cs_new:Npn \@@_parse_exponent_ii:N #1
+ {
+ \if_int_compare:w \if_catcode:w \tex_relax:D #1
+ \c_zero \else: `#1 \fi: > `9 \exp_stop_f:
+ 0 \exp_after:wN ; \exp_after:wN e
+ \else:
+ \exp_after:wN \@@_parse_exponent_sign:N
+ \fi:
+ #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_exponent_sign:N}
+% Read signs one by one (if there is any).
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_exponent_sign:N #1
+ {
+ \if:w + \if:w - #1 + \fi: \token_to_str:N #1
+ \exp_after:wN \@@_parse_exponent_sign:N
+ \tex_romannumeral:D \exp_after:wN \@@_parse_expand:w
+ \else:
+ \exp_after:wN \@@_parse_exponent_body:N
+ \exp_after:wN #1
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_exponent_body:N}
+% An exponent can be an explicit integer (most common case), or
+% various other things (most of which are invalid).
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_exponent_body:N #1
+ {
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #1 \exp_stop_f:
+ \token_to_str:N #1
+ \exp_after:wN \@@_parse_exponent_digits:N
+ \tex_romannumeral:D
+ \else:
+ \@@_parse_exponent_keep:NTF #1
+ { \@@_parse_return_semicolon:w #1 }
+ {
+ \exp_after:wN ;
+ \tex_romannumeral:D
+ }
+ \fi:
+ \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_exponent_digits:N}
+% Read digits one by one, and leave them behind in the input stream.
+% When finding a non-digit, stop, and insert a semicolon. Note that
+% we don't check for overflow of the exponent, hence there can be a
+% TeX error. It is mostly harmless, except when parsing
+% |0e9876543210|, which should be a valid representation of $0$, but
+% is not.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_exponent_digits:N #1
+ {
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #1 \exp_stop_f:
+ \token_to_str:N #1
+ \exp_after:wN \@@_parse_exponent_digits:N
+ \tex_romannumeral:D
+ \else:
+ \@@_parse_return_semicolon:w #1
+ \fi:
+ \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, rEXP]{\@@_parse_exponent_keep:NTF}
+% This is the last building block for parsing exponents. The argument
+% |#1| is already fully expanded, and neither |+| nor |-| nor a digit.
+% It can be:
+% \begin{itemize}
+% \item \cs{s_@@}, marking the start of an internal floating point,
+% invalid here;
+% \item another control sequence equal to \tn{relax}, probably a bad
+% variable;
+% \item a register: in this case we make sure that it is an integer
+% register, not a dimension;
+% \item a character other than |+|, |-| or digits, again, an error.
+% \end{itemize}
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_parse_exponent_keep:N #1 { TF }
+ {
+ \if_catcode:w \tex_relax:D #1
+ \if_meaning:w \tex_relax:D #1
+ \if_int_compare:w \pdftex_strcmp:D { \s_@@ } { #1 } = \c_zero
+ 0 \@@_error:n { Cannot~use~floating~point~after~'e'. }
+ \prg_return_true:
+ \else:
+ 0 \@@_error:n { Erroneous~variable~#1 used. }
+ \prg_return_false:
+ \fi:
+ \else:
+ \if_int_compare:w
+ \pdftex_strcmp:D { \__int_value:w #1 } { \tex_the:D #1 }
+ = \c_zero
+ \__int_value:w #1
+ \else:
+ 0 \@@_error:n { Cannot~use~a~dimension~(#1)~after~'e'. }
+ \fi:
+ \prg_return_false:
+ \fi:
+ \else:
+ 0 \@@_error:n { Missing~exponent~after~'e'. }
+ \prg_return_true:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% ^^A begin[todo]
+% ^^A todo: \@@_sin:Nn should first _set, then \@@_sin:w,
+% ^^A both for speed, and error reporting.
+% ^^A todo: word 'e' == 'invalid syntax', word 'E' == "use 'e' instead"
+%
+% \subsubsection{Beyond 16 digits: rounding}
+%
+% \begin{macro}[int]{\@@_cfs_round_loop:N}
+% Used both for \cs{@@_parse_small_round:NN} and
+% \cs{@@_parse_large_round:NN}.
+% Should appear after a \cs{__int_eval:w} |0|. Reads digits one by one,
+% until reaching a non-digit. Adds |+1| for each digit. If all digits
+% found are |0|, ends the \cs{__int_eval:w} by |;\c_zero|, otherwise
+% by |;\c_one|. This is done by switching the loop to |round_up|
+% at the first non-zero digit.
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_cfs_round_loop:N #1
+ {
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #1 \exp_stop_f:
+ + \c_one
+ \if:w 0 #1
+ \exp_after:wN \@@_cfs_round_loop:N
+ \tex_romannumeral:D
+ \else:
+ \exp_after:wN \@@_cfs_round_up:N
+ \tex_romannumeral:D
+ \fi:
+ \else:
+ \@@_parse_return_semicolon:w \c_zero #1
+ \fi:
+ \@@_parse_expand:w
+ }
+\cs_new:Npn \@@_cfs_round_up:N #1
+ {
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #1 \exp_stop_f:
+ + 1
+ \exp_after:wN \@@_cfs_round_up:N
+ \tex_romannumeral:D
+ \else:
+ \@@_parse_return_semicolon:w \c_one #1
+ \fi:
+ \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}[int]{\@@_parse_large_round:NN}
+% \begin{syntax}
+% \cs{@@_parse_large_round:NN} \meta{digit} \meta{more digits}
+% \end{syntax}
+% \meta{digit} is the digit that we are currently rounding (we only
+% care whether it is even or odd).
+%
+% The goal is to get \cs{c_zero} or \cs{c_one}, check for an exponent
+% afterwards, and combine it to the number of digits before the decimal
+% point (which we thus need to keep track of).
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_large_round:NN #1#2
+ {
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #2 \exp_stop_f:
+ +
+ \exp_after:wN \@@_round_s:NNNw
+ \exp_after:wN 0
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \int_use:N \__int_eval:w
+ \exp_after:wN \@@_parse_large_round_after:wNN
+ \int_use:N \__int_eval:w \c_one
+ \exp_after:wN \@@_cfs_round_loop:N
+ \else: %^^A could be dot, or e, or other
+ \exp_after:wN \@@_parse_large_round_dot_test:NNw
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \fi:
+ }
+\cs_new:Npn \@@_parse_large_round_dot_test:NNw #1#2
+ {
+ \if:w . #2
+ \exp_after:wN \@@_parse_small_round:NN
+ \exp_after:wN #1
+ \tex_romannumeral:D
+ \else:
+ \@@_parse_exponent:Nw #2
+ \fi:
+ \@@_parse_expand:w
+ }
+% \end{macrocode}
+% \begin{syntax}
+% \cs{@@_parse_large_round_after:wNN} \meta{exp} |;|
+% ~~\meta{0 or 1} \meta{next~token}
+% \end{syntax}
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_large_round_after:wNN #1 ; #2 #3
+ {
+ \if:w . #3
+ \exp_after:wN \@@_parse_large_round_after_ii:wN
+ \int_use:N \__int_eval:w #1 +
+ \c_zero * \__int_eval:w \c_zero
+ \exp_after:wN \@@_cfs_round_loop:N
+ \tex_romannumeral:D \exp_after:wN \@@_parse_expand:w
+ \else:
+ + #2
+ \exp_after:wN ;
+ \int_use:N \__int_eval:w #1 +
+ \exp_after:wN \@@_parse_exponent:N
+ \exp_after:wN #3
+ \fi:
+ }
+\cs_new:Npn \@@_parse_large_round_after_ii:wN #1 ; #2
+ {
+ + #2
+ \exp_after:wN ;
+ \int_use:N \__int_eval:w #1 +
+ \@@_parse_exponent:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}[int]{\@@_parse_small_round:NN}
+% \begin{syntax}
+% \cs{@@_parse_small_round:NN} \meta{digit} \meta{more digits}
+% \end{syntax}
+% \meta{digit} is the digit that we are currently rounding (we only
+% care whether it is even or odd).
+%
+% The goal is to get \cs{c_zero} or \cs{c_one}
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_small_round:NN #1#2
+ {
+ \if_int_compare:w \c_nine < 1 \token_to_str:N #2 \exp_stop_f:
+ +
+ \exp_after:wN \@@_round_s:NNNw
+ \exp_after:wN 0
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \int_use:N \__int_eval:w
+ \exp_after:wN \@@_parse_small_round_after:wN
+ \int_use:N \__int_eval:w \c_zero
+ \exp_after:wN \@@_cfs_round_loop:N
+ \tex_romannumeral:D
+ \else:
+ \@@_parse_exponent:Nw #2
+ \fi:
+ \@@_parse_expand:w
+ }
+\cs_new:Npn \@@_parse_small_round_after:wN #1; #2
+ {
+ + #2 \exp_after:wN ;
+ \__int_value:w \@@_parse_exponent:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Main functions}
+%
+% \begin{macro}[int, EXP]{\@@_parse:n}
+% \begin{macro}[aux, EXP]{\@@_parse_after:ww}
+% Start a \tn{romannumeral} expansion so that \cs{@@_parse:n} expands
+% in two steps. The \cs{@@_parse_until:Nw} function will perform
+% computations until reaching an operation with precedence
+% \cs{c_minus_one} or less. Then check that there was indeed nothing
+% left (this cannot happen), and stop the initial expansion with
+% \cs{c_zero}.%^^A todo: simplify a bit.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse:n #1
+ {
+ \tex_romannumeral:D
+ \exp_after:wN \@@_parse_after:ww
+ \tex_romannumeral:D
+ \@@_parse_until:Nw \c_minus_one
+ \@@_parse_expand:w #1 \s_@@_mark
+ \s_@@_stop
+ }
+\cs_new:Npn \@@_parse_after:ww #1@ #2 \s_@@_stop
+ {
+%<assert> \assert_str_eq:nn { #2 } { \@@_parse_infix_end:N \s_@@_mark }
+ \c_zero #1
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_parse_until:Nw}
+% \begin{macro}[aux, EXP]{\@@_parse_until_test:NwN}
+% The \cs{@@_parse_until}
+% This is just a shorthand which sets up both \cs{@@_parse_until_test}
+% and \cs{@@_parse_operand} with the same precedence. Note the
+% trailing \cs{tex_romannumeral:D}. This function should be
+% used with much care.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_until:Nw #1
+ {
+ -`0
+ \exp_after:wN \@@_parse_until_test:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \exp_after:wN \@@_parse_operand:Nw
+ \exp_after:wN #1
+ \tex_romannumeral:D
+ }
+\cs_new:Npn \@@_parse_until_test:NwN #1 #2 @ #3 { #3 #1 #2 @ }
+\cs_new:Npn \@@_parse_stop_until:N #1 { }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_parse_until_test:NwN}
+% \begin{syntax}
+% \cs{@@_parse_until_test:NwN} \meta{prec} \meta{fp} \meta{bool}
+% \end{syntax}
+% If \meta{bool} is true, then \meta{fp} is the floating
+% point number that we are looking for (it ends with |;|),
+% and this expands to \meta{fp}. If \meta{bool} is false,
+% then the input stream actually looks like
+% \begin{quote}
+% \cs{@@_parse_until_test:NwN} \meta{prec} \meta{fp_1} \meta{false}
+% \meta{oper} \meta{fp_2} \cs{infix_?}
+% \end{quote}
+% and we must feed \meta{prec} to \cs{infix_?}, and perform
+% \meta{oper} on \meta{fp_1} and \meta{fp_2}: this
+% triggers the expansion of \cs{infix_?} \meta{prec}, continuing
+% the computation (or stopping). In that case, the function \cs{until}
+% yields
+% \begin{quote}
+% \cs{@@_parse_until_test:NwN} \meta{prec}
+% \meta{oper} \meta{fp_1} \meta{fp_2}
+% \cs{tex_romannumeral:D} |-`0| \cs{infix_?} \meta{prec}
+% \end{quote}
+% expanding \meta{oper} next.
+% \begin{macrocode}
+% \end{macrocode}
+% \end{macro}
+%
+% ^^A 3.5\mydim e4**2
+% ^^A todo: add tests that catcode changes don't mess things up.
+%
+% \subsection{Main functions}
+%
+% \begin{macro}[aux, EXP]{\@@_parse_infix_after_operand:NwN}
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_infix_after_operand:NwN #1 #2;
+ {
+ \@@_exp_after_f:nw { \@@_parse_infix:NN #1 }
+ #2;
+ }
+\group_begin:
+ \char_set_catcode_letter:N \*
+ \cs_new:Npn \@@_parse_infix:NN #1 #2
+ {
+ \if_catcode:w \tex_relax:D #2
+ \if_int_compare:w
+ \pdftex_strcmp:D { \s_@@_mark } { #2 }
+ = \c_zero
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_parse_infix_end:N
+ \else:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_parse_infix_juxtapose:N
+ \fi:
+ \else:
+ \if_int_compare:w
+ \__int_eval:w \tex_uccode:D `#2 / 26
+ = \c_three
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_parse_infix_juxtapose:N
+ \else:
+ \exp_after:wN \@@_parse_infix_check:NNN
+ \cs:w
+ @@_parse_infix_#2:N
+ \exp_after:wN \exp_after:wN \exp_after:wN
+ \cs_end:
+ \fi:
+ \fi:
+ #1
+ #2
+ }
+ \cs_new:Npn \@@_parse_infix_check:NNN #1#2#3
+ {
+ \if_meaning:w \tex_relax:D #1
+ \__msg_expandable_error:n { Missing~*~inserted. }
+ \exp_after:wN \@@_parse_infix_*:N
+ \exp_after:wN #2
+ \exp_after:wN #3
+ \else:
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \tex_romannumeral:D \exp_after:wN \@@_parse_expand:w
+ \fi:
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_parse_apply_binary:NwNwN}
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_apply_binary:NwNwN #1 #2#3@ #4 #5#6@ #7
+ {
+ \exp_after:wN \@@_parse_until_test:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \cs:w
+ @@
+ \@@_type_from_scan:N #2
+ \@@_type_from_scan:N #5
+ _ #4 _o:ww
+ \cs_end:
+ #2#3 #5#6
+ \tex_romannumeral:D -`0 #7 #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]
+% {\@@_parse_apply_unary_array:NNwN, \@@_parse_apply_unary:NNwN}
+% Here, |#2| is \emph{e.g.}, \cs{@@_neg_@@:w}, and expands once after the
+% calculation.\footnote{Bruno: explain.} The argument |#3| may be an
+% array, so either we map through all its items, or we feed all items
+% at once to the custom function.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_apply_unary_array:NNwN #1#2#3@#4
+ {
+ #2 #3 @
+ \tex_romannumeral:D -`0 #4 #1
+ }
+\cs_new:Npn \@@_parse_apply_unary:NNwN #1#2#3@#4
+ {
+ #2 #3
+ \tex_romannumeral:D -`0 #4 #1
+ }
+\cs_new:Npn \@@_parse_unary_type:N #1
+ { \@@_type_from_scan:N #1 :w \cs_end: #1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Prefix operators}
+%
+% \subsubsection{Identifiers}
+%
+% \begin{macro}[aux, EXP]
+% {
+% \@@_parse_word_inf:N, \@@_parse_word_nan:N, \@@_parse_word_pi:N ,
+% \@@_parse_word_deg:N, \@@_parse_word_em:N ,
+% \@@_parse_word_ex:N , \@@_parse_word_in:N , \@@_parse_word_pt:N ,
+% \@@_parse_word_pc:N , \@@_parse_word_cm:N , \@@_parse_word_mm:N ,
+% \@@_parse_word_dd:N , \@@_parse_word_cc:N , \@@_parse_word_nd:N ,
+% \@@_parse_word_nc:N , \@@_parse_word_bp:N , \@@_parse_word_sp:N ,
+% \@@_parse_word_true:N , \@@_parse_word_false:N ,
+% }
+% A whole bunch of floating point numbers.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1 #2
+ {
+ \cs_new_nopar:cpn { @@_parse_word_#1:N }
+ { \exp_after:wN #2 \tex_romannumeral:D -`0 \@@_parse_infix:NN }
+ }
+\@@_tmp:w { inf } \c_inf_fp
+\@@_tmp:w { nan } \c_nan_fp
+\@@_tmp:w { pi } \c_pi_fp
+\@@_tmp:w { deg } \c_one_degree_fp
+\@@_tmp:w { true } \c_one_fp
+\@@_tmp:w { false } \c_zero_fp
+\@@_tmp:w { pt } \c_one_fp
+\cs_set_protected:Npn \@@_tmp:w #1 #2
+ {
+ \cs_new_nopar:cpn { @@_parse_word_#1:N }
+ {
+ \@@_exp_after_f:nw { \@@_parse_infix:NN }
+ \s_@@ \@@_chk:w 10 #2 ;
+ }
+ }
+\@@_tmp:w {in} { {2} {7227} {0000} {0000} {0000} }
+\@@_tmp:w {pc} { {2} {1200} {0000} {0000} {0000} }
+\@@_tmp:w {cm} { {2} {2845} {2755} {9055} {1181} }
+\@@_tmp:w {mm} { {1} {2845} {2755} {9055} {1181} }
+\@@_tmp:w {dd} { {1} {1070} {0085} {6496} {0630} }
+\@@_tmp:w {cc} { {2} {1284} {0102} {7795} {2756} }
+\@@_tmp:w {nd} { {1} {1066} {9783} {4645} {6693} }
+\@@_tmp:w {nc} { {2} {1280} {3740} {1574} {8031} }
+\@@_tmp:w {bp} { {1} {1003} {7500} {0000} {0000} }
+\@@_tmp:w {sp} { {-4} {1525} {8789} {0625} {0000} }
+\tl_map_inline:nn { {em} {ex} }
+ {
+ \cs_new_nopar:cpn { @@_parse_word_#1:N }
+ {
+ \exp_after:wN \dim_to_fp:n \exp_after:wN
+ { \dim_use:N \__dim_eval:w 1 #1 \exp_after:wN }
+ \tex_romannumeral:D -`0 \@@_parse_infix:NN
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]
+% {
+% \@@_parse_word_abs:N ,
+% \@@_parse_word_cos:N ,
+% \@@_parse_word_cot:N ,
+% \@@_parse_word_exp:N ,
+% \@@_parse_word_ln:N ,
+% \@@_parse_word_sin:N ,
+% \@@_parse_word_tan:N ,
+% }
+% Unary functions, which are applied to all of their arguments when
+% receiving an array.
+% \begin{macrocode}
+\tl_map_inline:nn { {abs} {cos} {cot} {exp} {ln} {sin} {tan} }
+ {
+ \cs_new:cpn { @@_parse_word_#1:N } ##1
+ {
+ \exp_after:wN \@@_parse_apply_unary:NNwN
+ \exp_after:wN ##1
+ \cs:w @@_ #1 \exp_after:wN \@@_parse_unary_type:N
+ \tex_romannumeral:D
+ \@@_parse_until:Nw \c_fifteen
+ \@@_parse_expand:w
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]
+% {
+% \@@_parse_word_max:N , \@@_parse_word_min:N ,
+% \@@_parse_word_mod:N ,
+% }
+% Those functions are also unary, but need to mix all of their
+% arguments together.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1#2
+ {
+ \cs_new:Npn #1 ##1
+ {
+ \exp_after:wN \@@_parse_apply_unary_array:NNwN
+ \exp_after:wN ##1
+ \exp_after:wN #2
+ \tex_romannumeral:D
+ \@@_parse_until:Nw \c_sixteen \@@_parse_expand:w
+ }
+ }
+\@@_tmp:w \@@_parse_word_max:N \@@_max:w
+\@@_tmp:w \@@_parse_word_min:N \@@_min:w
+ % \@@_tmp:w \@@_parse_word_mod:N \@@_mod:w %^^A todo: not implemented!
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_parse_word_round:N}
+% This function expects one or two arguments.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_word_round:N #1#2
+ {
+ \if_meaning:w + #2
+ \@@_parse_round:Nw \@@_round_to_pinf:NNN
+ \else:
+ \if_meaning:w 0 #2
+ \@@_parse_round:Nw \@@_round_to_zero:NNN
+ \else:
+ \if_meaning:w - #2
+ \@@_parse_round:Nw \@@_round_to_ninf:NNN
+ \fi:
+ \fi:
+ \fi:
+ \exp_after:wN \@@_parse_apply_round:NNwN
+ \exp_after:wN #1
+ \exp_after:wN \@@_round_to_nearest:NNN
+ \tex_romannumeral:D
+ \@@_parse_until:Nw \c_sixteen \@@_parse_expand:w #2
+ }
+\cs_new:Npn \@@_parse_round:Nw
+ #1 #2 \@@_round_to_nearest:NNN #3 \@@_parse_expand:w #4
+ { #2 #1 #3 \@@_parse_expand:w }
+\cs_new:Npn \@@_parse_apply_round:NNwN #1#2#3@#4
+ {
+ \if_case:w \__int_eval:w \@@_array_count:w #3@ - \c_one \__int_eval_end:
+ \@@_round:Nwn #2 #3 {0} \tex_romannumeral:D
+ \or: \@@_round:Nww #2 #3 \tex_romannumeral:D
+ \else:
+ \@@_error:n { round()~expects~1~or~2~arguments. }
+ \exp_after:wN \c_nan_fp \tex_romannumeral:D
+ \fi:
+ -`0 #4 #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Unary minus, plus, not}
+%
+% \begin{macro}[EXP, aux]{\@@_parse_prefix_+:Nw}
+% A unary |+| does nothing.
+% \begin{macrocode}
+\cs_new_eq:cN { @@_parse_prefix_+:Nw } \@@_parse_operand:Nw
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP, aux]{\@@_parse_prefix_-:Nw, \@@_parse_prefix_!:Nw}
+% Unary |-| is harder.
+% Boolean not.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1#2
+ {
+ \cs_new:cpn { @@_parse_prefix_#1:Nw } ##1
+ {
+ \exp_after:wN \@@_parse_apply_unary:NNwN
+ \exp_after:wN ##1
+ \cs:w @@_ #2 \exp_after:wN \@@_parse_unary_type:N
+ \tex_romannumeral:D
+ \if_int_compare:w \c_twelve < ##1
+ \@@_parse_until:Nw ##1
+ \else:
+ \@@_parse_until:Nw \c_twelve
+ \fi:
+ \@@_parse_expand:w
+ }
+ }
+\@@_tmp:w - { neg }
+\@@_tmp:w ! { not }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Other prefixes}
+%
+% \begin{macro}[int]{\@@_parse_prefix_(:Nw}
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_letter:N \)
+ \cs_new:cpn { @@_parse_prefix_(:Nw } #1
+ {
+ \exp_after:wN \@@_parse_lparen_after:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D
+ \if_int_compare:w #1 = \c_sixteen
+ \@@_parse_until:Nw \c_one
+ \else:
+ \@@_parse_until:Nw \c_zero
+ \fi:
+ \@@_parse_expand:w
+ }
+ \cs_new:Npn \@@_parse_lparen_after:NwN #1#2@#3
+ {
+ \token_if_eq_meaning:NNTF #3 \@@_parse_infix_):N
+ {
+ \@@_parse_exp_after_array:wf #2 \s_@@_stop
+ \exp_after:wN \@@_parse_infix:NN
+ \exp_after:wN #1
+ \tex_romannumeral:D \@@_parse_expand:w
+ }
+ {
+ \@@_error:n { Missing~')'~inserted. }
+ #2 @ \@@_parse_stop_until:N #3
+ }
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+%
+%^^A todo: rename to exp_after_array_f:w
+% \begin{macro}[int, EXP]{\@@_parse_exp_after_array:wf}
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_exp_after_array:wf #1
+ {
+ \cs:w @@ \@@_type_from_scan:N #1 _exp_after_f:nw \cs_end:
+ { \@@_parse_exp_after_array:wf }
+ #1
+ }
+\cs_new:Npn \@@_stop_exp_after_f:nw #1#2 { }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_parse_prefix_.:Nw}
+% This function is called when a number starts with a dot.
+% \begin{macrocode}
+\cs_new:cpn {@@_parse_prefix_.:Nw} #1
+ {
+ \exp_after:wN \@@_parse_infix_after_operand:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \exp_after:wN \@@_sanitize:wN
+ \int_use:N \__int_eval:w \c_zero \@@_parse_strim_zeros:N
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Infix operators}
+%
+% As described in the \enquote{work plan}, each infix operator has an
+% associated \cs{infix} function, a computing function, and
+% precedence, given as arguments to \cs{@@_tmp:w}. The
+% latter two are only needed when defining the \cs{infix} function.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1#2#3#4
+ {
+ \cs_new:Npn #1 ##1
+ {
+ \if_int_compare:w ##1 < #3
+ \exp_after:wN @
+ \exp_after:wN \@@_parse_apply_binary:NwNwN
+ \exp_after:wN #2
+ \tex_romannumeral:D
+ \@@_parse_until:Nw #4
+ \exp_after:wN \@@_parse_expand:w
+ \else:
+ \exp_after:wN @
+ \exp_after:wN \@@_parse_stop_until:N
+ \exp_after:wN #1
+ \fi:
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macro}[int, EXP]
+% {
+% \@@_parse_infix_+:N, \@@_parse_infix_-:N,
+% \@@_parse_infix_/:N, \@@_parse_infix_mul:N,
+% \@@_parse_infix_and:N, \@@_parse_infix_or:N,
+% }
+% Using the general mechanism for arithmetic operations.
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_other:N \&
+ \@@_tmp:w \@@_parse_infix_juxtapose:N * \c_thirty_two \c_thirty_two
+ \exp_args:Nc \@@_tmp:w { @@_parse_infix_ / :N } / \c_ten \c_ten
+ \exp_args:Nc \@@_tmp:w { @@_parse_infix_mul:N } * \c_ten \c_ten
+ \exp_args:Nc \@@_tmp:w { @@_parse_infix_ - :N } - \c_nine \c_nine
+ \exp_args:Nc \@@_tmp:w { @@_parse_infix_ + :N } + \c_nine \c_nine
+ \exp_args:Nc \@@_tmp:w { @@_parse_infix_and:N } & \c_five \c_five
+ \exp_args:Nc \@@_tmp:w { @@_parse_infix_ or:N } | \c_four \c_four
+\group_end:
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_parse_infix_*:N}
+% \begin{macro}[int, EXP]+\@@_parse_infix_^:N+
+% The power operation must be associative in the opposite order from
+% all others. For this, we reverse the test, hence treating a
+% \enquote{previous precedence} of \cs{c_fourteen} as less binding
+% than |^|.
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_letter:N ^
+ \@@_tmp:w \@@_parse_infix_^:N ^ \c_fifteen \c_fourteen
+ \cs_new:cpn { @@_parse_infix_*:N } #1#2
+ {
+ \if:w * #2
+ \exp_after:wN \@@_parse_infix_^:N
+ \exp_after:wN #1
+ \else:
+ \exp_after:wN \@@_parse_infix_mul:N
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \fi:
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]+\@@_parse_infix_|:Nw+
+% \begin{macro}[int, EXP]+\@@_parse_infix_&:Nw+
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_letter:N \|
+ \char_set_catcode_letter:N \&
+ \cs_new:Npn \@@_parse_infix_|:N #1#2
+ {
+ \if:w | #2
+ \exp_after:wN \@@_parse_infix_|:N
+ \exp_after:wN #1
+ \tex_romannumeral:D \exp_after:wN \@@_parse_expand:w
+ \else:
+ \exp_after:wN \@@_parse_infix_or:N
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \fi:
+ }
+ \cs_new:Npn \@@_parse_infix_&:N #1#2
+ {
+ \if:w & #2
+ \exp_after:wN \@@_parse_infix_&:N
+ \exp_after:wN #1
+ \tex_romannumeral:D \exp_after:wN \@@_parse_expand:w
+ \else:
+ \exp_after:wN \@@_parse_infix_and:N
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \fi:
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]
+% {
+% \@@_parse_infix_<:N, \@@_parse_infix_=:N,
+% \@@_parse_infix_>:N, \@@_parse_infix_!:N
+% }
+% \begin{macro}[aux, EXP]
+% {
+% \@@_parse_infix_excl_aux:NN,
+% \@@_parse_infix_excl_error:,
+% \@@_infix_compare:N,
+% \@@_parse_compare:NNNNNw,
+% \@@_parse_compare_expand:NNNNNw,
+% \@@_parse_compare_end:NNNN,
+% \@@_compare:wNNNNw,
+% }
+% \begin{macrocode}
+\cs_new:cpn { @@_parse_infix_<:N } #1
+ {
+ \@@_infix_compare:N #1 \c_one_fp
+ \c_zero_fp \c_zero_fp \c_zero_fp \c_zero_fp <
+ }
+\cs_new:cpn { @@_parse_infix_=:N } #1
+ {
+ \@@_infix_compare:N #1 \c_one_fp
+ \c_zero_fp \c_zero_fp \c_zero_fp \c_zero_fp =
+ }
+\cs_new:cpn { @@_parse_infix_>:N } #1
+ {
+ \@@_infix_compare:N #1 \c_one_fp
+ \c_zero_fp \c_zero_fp \c_zero_fp \c_zero_fp >
+ }
+\cs_new:cpn { @@_parse_infix_!:N } #1
+ {
+ \exp_after:wN \@@_parse_infix_excl_aux:NN
+ \exp_after:wN #1 \tex_romannumeral:D \@@_parse_expand:w
+ }
+\cs_new:Npn \@@_parse_infix_excl_aux:NN #1#2
+ {
+ \if_catcode:w \tex_relax:D #2
+ \@@_parse_infix_excl_error:
+ \else:
+ \if_int_compare:w `#2 > `? \exp_stop_f:
+ \@@_parse_infix_excl_error:
+ \else:
+ \if_int_compare:w `#2 < `< \exp_stop_f:
+ \@@_parse_infix_excl_error:
+ \fi:
+ \fi:
+ \fi:
+ \@@_infix_compare:N #1 \c_zero_fp
+ \c_one_fp \c_one_fp \c_one_fp \c_one_fp #2
+ }
+\cs_new:Npn \@@_parse_infix_excl_error:
+ { \__msg_expandable_error:n { Missing~relation~symbol~after~'!'. } }
+\cs_new:Npn \@@_infix_compare:N #1
+ {
+ \if_int_compare:w #1 < \c_seven
+ \exp_after:wN \@@_parse_compare:NNNNNw
+ \else:
+ \exp_after:wN @
+ \exp_after:wN \@@_parse_stop_until:N
+ \exp_after:wN \@@_infix_compare:N
+ \fi:
+ }
+\cs_new:Npn \@@_parse_compare:NNNNNw #1#2#3#4#5#6
+ {
+ \if_case:w
+ \if_catcode:w \tex_relax:D #6
+ \c_minus_one
+ \else:
+ \__int_eval:w `#6 - `< \__int_eval_end:
+ \fi:
+ \@@_parse_compare_expand:NNNNNw #1#1#3#4#5
+ \or: \@@_parse_compare_expand:NNNNNw #1#2#1#4#5
+ \or: \@@_parse_compare_expand:NNNNNw #1#2#3#1#5
+ \or: \@@_parse_compare_expand:NNNNNw #1#2#3#4#1
+ \else: \@@_parse_compare_end:NNNN #2#3#4#5#6
+ \fi:
+ }
+\cs_new:Npn \@@_parse_compare_expand:NNNNNw #1#2#3#4#5
+ {
+ \exp_after:wN \@@_parse_compare:NNNNNw
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \exp_after:wN #3
+ \exp_after:wN #4
+ \exp_after:wN #5
+ \tex_romannumeral:D \exp_after:wN \@@_parse_expand:w
+ }
+\cs_new:Npn \@@_parse_compare_end:NNNN #1#2#3#4#5 \fi:
+ {
+ \fi:
+ \exp_after:wN @
+ \exp_after:wN \@@_parse_apply_compare:NwNNNNwN
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \exp_after:wN #3
+ \exp_after:wN #4
+ \tex_romannumeral:D
+ \@@_parse_until:Nw \c_seven \@@_parse_expand:w #5
+ }
+\cs_new:Npn \@@_parse_apply_compare:NwNNNNwN #1 #2@ #3#4#5#6 #7@ #8
+ {
+ \exp_after:wN \@@_parse_until_test:NwN
+ \exp_after:wN #1
+ \tex_romannumeral:D -`0
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \exp_after:wN
+ \if_case:w \@@_compare:ww #2 #7 \exp_stop_f:
+ #4
+ \or: #5
+ \or: #6
+ \else: #3
+ \fi:
+ \tex_romannumeral:D -`0 #8 #1
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_parse_infix_?:N, \@@_parse_infix_::N}
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_letter:N \?
+ \cs_new:Npn \@@_parse_infix_?:N #1
+ {
+ \if_int_compare:w #1 < \c_three
+ \exp_after:wN @
+ \exp_after:wN \@@_ternary:NwwN
+ \tex_romannumeral:D
+ \@@_parse_until:Nw \c_three
+ \exp_after:wN \@@_parse_expand:w
+ \else:
+ \exp_after:wN @
+ \exp_after:wN \@@_parse_stop_until:N
+ \exp_after:wN \@@_parse_infix_?:N
+ \fi:
+ }
+ \cs_new:Npn \@@_parse_infix_::N #1
+ {
+ \if_int_compare:w #1 < \c_three
+ \__msg_expandable_error:n { Missing~'?'~inserted~for~'?:'. }
+ \exp_after:wN @
+ \exp_after:wN \@@_ternary_ii:NwwN
+ \tex_romannumeral:D
+ \@@_parse_until:Nw \c_two
+ \exp_after:wN \@@_parse_expand:w
+ \else:
+ \exp_after:wN @
+ \exp_after:wN \@@_parse_stop_until:N
+ \exp_after:wN \@@_parse_infix_::N
+ \fi:
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]+\@@_parse_infix_):N+
+% This one is a little bit odd: force every previous operator to end,
+% regardless of the precedence. This is very similar to
+% \cs{@@_parse_infix_end:N}.
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_letter:N \)
+ \cs_new:Npn \@@_parse_infix_):N #1
+ {
+ \if_int_compare:w #1 < \c_zero
+ \@@_error:n { Extra~')'~ignored. }
+ \exp_after:wN \@@_parse_infix:NN
+ \exp_after:wN #1
+ \tex_romannumeral:D \exp_after:wN \@@_parse_expand:w
+ \else:
+ \exp_after:wN @
+ \exp_after:wN \@@_parse_stop_until:N
+ \exp_after:wN \@@_parse_infix_):N
+ \fi:
+ }
+\group_end:
+\cs_new:Npn \@@_parse_infix_end:N #1
+ { @ \@@_parse_stop_until:N \@@_parse_infix_end:N }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]+\@@_parse_infix_,:N+
+% \begin{macrocode}
+\group_begin:
+ \char_set_catcode_letter:N \,
+ \cs_new:Npn \@@_parse_infix_,:N #1
+ {
+ \if_int_compare:w #1 > \c_one
+ \exp_after:wN @
+ \exp_after:wN \@@_parse_stop_until:N
+ \exp_after:wN \@@_parse_infix_,:N
+ \else:
+ \if_int_compare:w #1 = \c_one
+ \exp_after:wN \@@_parse_infix_comma:w
+ \tex_romannumeral:D
+ \else:
+ \exp_after:wN \@@_parse_infix_comma_gobble:w
+ \tex_romannumeral:D
+ \fi:
+ \@@_parse_until:Nw \c_one
+ \exp_after:wN \@@_parse_expand:w
+ \fi:
+ }
+ \cs_new:Npn \@@_parse_infix_comma:w #1 @
+ { #1 @ \@@_parse_stop_until:N }
+ \cs_new:Npn \@@_parse_infix_comma_gobble:w #1 @
+ {
+ \@@_error:n { Unexpected~comma:~extra~arguments~ignored. }
+ @ \@@_parse_stop_until:N
+ }
+\group_end:
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
new file mode 100644
index 00000000000..68df5e1ac17
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-round.dtx
@@ -0,0 +1,424 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-round.dtx Copyright(C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-round.dtx 3549 2012-03-13 20:54:30Z bruno $
+ {L3 Floating-point rounding}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \textsf{l3fp-round} package\\ Rounding floating points^^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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-round} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% ^^A todo: provide an interface for rounding modes.
+% ^^A todo: provide a \l_@@_rounding_mode_int giving the current mode.
+% ^^A todo: make transcendental function obey the correct rounding mode.
+% ^^A todo: optimize all rounding functions for various rounding modes.
+% ^^A todo: reduce the number of almost identical functions.
+%
+% \subsection{Rounding tools}
+%
+% Floating point operations often yield a result that cannot be exactly
+% represented in a mantissa with $16$ digits. In that case, we need to
+% round the exact result to a representable number. The \textsc{ieee}
+% standard defines four rounding modes:
+% \begin{itemize}
+% \item Round to nearest: round to the representable floating point
+% number whose absolute difference with the exact result is the
+% smallest. If the exact result lies exactly at the mid-point
+% between two consecutive representable floating point numbers,
+% round to the floating point number whose last digit is even.
+% \item Round towards negative infinity: round to the greatest
+% floating point number not larger than the exact result.
+% \item Round towards zero: round to a floating point number with the
+% same sign as the exact result, with the largest absolute value not
+% larger than the absolute value of the exact result.
+% \item Round towards positive infinity: round to the least floating
+% point number not smaller than the exact result.
+% \end{itemize}
+% This is not fully implemented in \pkg{l3fp} yet, and transcendental
+% functions fall back on the \enquote{round to nearest} mode. All
+% rounding for basic algebra is done through the functions defined in
+% this module, which can be redefined to change their rounding behaviour
+% (but there is not interface for that yet).
+%
+% The rounding tools available in this module are many variations on a
+% base function \cs{@@_round:NNN}, which expands to \cs{c_zero} or
+% \cs{c_one} depending on whether the final result should be rounded up
+% or down.
+% \begin{itemize}
+% \item \cs{@@_round:NNN} \meta{sign} \meta{digit_1} \meta{digit_2}
+% can expand to \cs{c_zero} or \cs{c_one}.
+% \item \cs{@@_round:NNNN} \meta{sign} \meta{digit_1} \meta{digit_2}
+% \meta{digit_3} can expand to \cs{c_zero} or \cs{c_one}.
+% \item \cs{@@_round_s:NNNw} \meta{sign} \meta{digit_1} \meta{digit_2}
+% \meta{more digits} |;| can expand to |\c_zero ;| or |\c_one ;|.
+% \item \cs{@@_round_neg:NNN} \meta{sign} \meta{digit_1} \meta{digit_2}
+% can expand to \cs{c_zero} or \cs{c_one}.
+% \end{itemize}
+% See implementation comments for details on the syntax.
+%
+% \begin{macro}[int, rEXP]{\@@_round:NNN}
+% \begin{macro}[aux, rEXP]
+% {
+% \@@_round_to_nearest:NNN,
+% \@@_round_to_ninf:NNN,
+% \@@_round_to_zero:NNN,
+% \@@_round_to_pinf:NNN
+% }
+% \begin{syntax}
+% \cs{@@_round:NNN} \meta{final sign} \meta{digit_1} \meta{digit_2}
+% \end{syntax}
+% If rounding the number $\meta{final sign}
+% \meta{digit_1}.\meta{digit_2}$ to an integer rounds it towards zero
+% (truncates it), this function expands to \cs{c_zero}, and otherwise
+% to \cs{c_one}. Typically used within the scope of an
+% \cs{__int_eval:w}, to add~$1$ if needed, and thereby round
+% correctly. The result depends on the rounding mode.
+%
+% It is very important that \meta{final sign} be the final sign of the
+% result. Otherwise, the result will be incorrect in the case of
+% rounding towards~$-\infty$ or towards~$+\infty$. Also recall that
+% \meta{final sign} is~$0$ for positive, and~$2$ for negative.
+%
+% By default, the functions below return \cs{c_zero}, but this is
+% superseded by \cs{@@_round_return_one:}, which instead returns
+% \cs{c_one}, expanding everything and removing \cs{c_zero} in the
+% process. In the case of rounding towards~$\pm\infty$ or
+% towards~$0$, this is not really useful, but it prepares us for the
+% \enquote{round to nearest, ties to even} mode.
+%
+% The \enquote{round to nearest} mode is the default. If the
+% \meta{digit_2} is larger than~$5$, then round up. If it is less
+% than~$5$, round down. If it is exactly $5$, then round such that
+% \meta{digit_1} plus the result is even. In other words, round up if
+% \meta{digit_1} is odd.
+% \begin{macrocode}
+\cs_new:Npn \@@_round_return_one:
+ { \exp_after:wN \c_one \tex_romannumeral:D }
+\cs_new:Npn \@@_round_to_ninf:NNN #1 #2 #3
+ {
+ \if_meaning:w 2 #1
+ \if_int_compare:w #3 > \c_zero
+ \@@_round_return_one:
+ \fi:
+ \fi:
+ \c_zero
+ }
+\cs_new:Npn \@@_round_to_zero:NNN #1 #2 #3 { \c_zero }
+\cs_new:Npn \@@_round_to_pinf:NNN #1 #2 #3
+ {
+ \if_meaning:w 0 #1
+ \if_int_compare:w #3 > \c_zero
+ \@@_round_return_one:
+ \fi:
+ \fi:
+ \c_zero
+ }
+\cs_new:Npn \@@_round_to_nearest:NNN #1 #2 #3
+ {
+ \if_int_compare:w #3 > \c_five
+ \@@_round_return_one:
+ \else:
+ \if_meaning:w 5 #3
+ \if_int_odd:w #2 \exp_stop_f:
+ \@@_round_return_one:
+ \fi:
+ \fi:
+ \fi:
+ \c_zero
+ }
+\cs_new_eq:NN \@@_round:NNN \@@_round_to_nearest:NNN
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP, int]{\@@_round_s:NNNw}
+% \begin{syntax}
+% \cs{@@_round_s:NNNw} \meta{final sign} \meta{digit} \meta{more digits} |;|
+% \end{syntax}
+% Similar to \cs{@@_round:NNN}, but with an extra semicolon, this
+% function expands to |\c_zero ;| if rounding $\meta{final sign}
+% \meta{digit}.\meta{more digits}$ to an integer truncates, and to
+% |\c_one ;| otherwise. The \meta{more digits} part must be a digit,
+% followed by something that does not overflow a \cs{int_use:N}
+% \cs{__int_eval:w} construction. The only relevant information about
+% this piece is whether it is zero or not.
+% \begin{macrocode}
+\cs_new:Npn \@@_round_s:NNNw #1 #2 #3 #4;
+ {
+ \exp_after:wN \@@_round:NNN
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \int_use:N \__int_eval:w
+ \if_int_odd:w 0 \if_meaning:w 0 #3 1 \fi:
+ \if_meaning:w 5 #3 1 \fi:
+ \exp_stop_f:
+ \if_int_compare:w \__int_eval:w #4 > \c_zero
+ 1 +
+ \fi:
+ \fi:
+ #3
+ ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_round:NNNN}
+% \begin{syntax}
+% \cs{@@_round:NNNN} \meta{final sign} \meta{digit} \meta{2d}
+% \end{syntax}
+% Identical to \cs{@@_round_s:NNNw} except for a trailing semicolon.
+% \begin{macrocode}
+\cs_new:Npn \@@_round:NNNN #1 #2 #3 #4
+ {
+ \exp_after:wN \@@_round:NNN
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \int_use:N \__int_eval:w
+ \if_int_odd:w 0 \if_meaning:w 0 #3 1 \fi:
+ \if_meaning:w 5 #3 1 \fi:
+ \exp_stop_f:
+ \if_int_compare:w #4 > \c_zero
+ 1 +
+ \fi:
+ \fi:
+ #3
+ \__int_eval_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_round_neg:NNN}
+% \begin{macro}[aux, EXP]
+% {
+% \@@_round_to_nearest_neg:NNN,
+% \@@_round_to_ninf_neg:NNN,
+% \@@_round_to_zero_neg:NNN,
+% \@@_round_to_pinf_neg:NNN
+% }
+% \begin{syntax}
+% \cs{@@_round_neg:NNN} \meta{final sign} \meta{digit_1} \meta{digit_2}
+% \end{syntax}
+% This expands to \cs{c_zero} or \cs{c_one}. Consider a number of
+% the form $ \meta{final sign}.X\ldots X\meta{digit_1} $ with exactly
+% $15$ (non-all-zero) digits before \meta{digit_1}, and subtract from it
+% $\meta{final sign}.0\ldots0\meta{digit_2}$, where there are $16$ zeros.
+% If in the current rounding mode the result should be rounded down,
+% then this function returns \cs{c_one}. Otherwise, \emph{i.e.},
+% if the result is rounded back to the first operand, then this function
+% returns \cs{c_zero}.
+%
+% It turns out that this negative \enquote{round to nearest}
+% is identical to the positive one. And this is the default mode.
+% \begin{macrocode}
+\cs_new:Npn \@@_round_to_ninf_neg:NNN #1 #2 #3
+ {
+ \if_meaning:w 0 #1
+ \if_int_compare:w #3 > \c_zero
+ \@@_round_return_one:
+ \fi:
+ \fi:
+ \c_zero
+ }
+\cs_new:Npn \@@_round_to_zero_neg:NNN #1 #2 #3
+ {
+ \if_int_compare:w #3 > \c_zero
+ \@@_round_return_one:
+ \fi:
+ \c_zero
+ }
+\cs_new:Npn \@@_round_to_pinf_neg:NNN #1 #2 #3
+ {
+ \if_meaning:w 2 #1
+ \if_int_compare:w #3 > \c_zero
+ \@@_round_return_one:
+ \fi:
+ \fi:
+ \c_zero
+ }
+\cs_new_eq:NN \@@_round_to_nearest_neg:NNN \@@_round_to_nearest:NNN
+\cs_new_eq:NN \@@_round_neg:NNN \@@_round_to_nearest_neg:NNN
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{The \texttt{round} function}
+%
+% ^^A todo: This macro is intermingled with l3fp-parse.
+% ^^A todo: Add explanations.
+% \begin{macro}[int, EXP]{\@@_round:Nww, \@@_round:Nwn}
+% \begin{macro}[aux, EXP]
+% {
+% \@@_round_normal:NwNNnw ,
+% \@@_round_normal_ii:NnnwNNnn ,
+% \@@_round_pack:Nw ,
+% \@@_round_normal_iii:NNwNnn ,
+% \@@_round_normal_end:wwNnn ,
+% \@@_round_special:NwwNnn ,
+% \@@_round_special_aux:Nw
+% }
+% \begin{macrocode}
+\cs_new:Npn \@@_round:Nww #1#2 ; #3 ;
+ {
+ \@@_small_int:wTF #3; { \@@_round:Nwn #1#2; }
+ {
+ \@@_error:x { {round(x,n)~with~n=} \@@_to_tl:w #3; }
+ \exp_after:wN \c_nan_fp
+ }
+ }
+\cs_new:Npn \@@_round:Nwn #1 \s_@@ \@@_chk:w #2#3#4; #5
+ {
+ \if_meaning:w 1 #2
+ \exp_after:wN \@@_round_normal:NwNNnw
+ \exp_after:wN #1
+ \__int_value:w #5
+ \else:
+ \exp_after:wN \@@_exp_after_o:w
+ \fi:
+ \s_@@ \@@_chk:w #2#3#4;
+ }
+\cs_new:Npn \@@_round_normal:NwNNnw #1#2 \s_@@ \@@_chk:w 1#3#4#5;
+ {
+ \@@_decimate:nNnnnn { \c_sixteen - #4 - #2 }
+ \@@_round_normal_ii:NnnwNNnn #5 #1 #3 {#4} {#2}
+ }
+\cs_new:Npn \@@_round_normal_ii:NnnwNNnn #1#2#3#4; #5#6
+ {
+ \exp_after:wN \@@_round_normal_iii:NNwNnn
+ \int_use:N \__int_eval:w
+ \if_int_compare:w #2 > \c_zero
+ 1 \__int_value:w #2
+ \exp_after:wN \@@_round_pack:Nw
+ \int_use:N \__int_eval:w 1#3 +
+ \else:
+ \if_int_compare:w #3 > \c_zero
+ 1 \__int_value:w #3 +
+ \fi:
+ \fi:
+ \exp_after:wN #5
+ \exp_after:wN #6
+ \use_none:nnnnnnn #3
+ #1
+ \__int_eval_end:
+ 0000 0000 0000 0000 ; #6
+ }
+\cs_new:Npn \@@_round_pack:Nw #1
+ { \if_meaning:w 2 #1 + \c_one \fi: \__int_eval_end: }
+\cs_new:Npn \@@_round_normal_iii:NNwNnn #1 #2
+ {
+ \if_meaning:w 0 #2
+ \exp_after:wN \@@_round_special:NwwNnn
+ \exp_after:wN #1
+ \fi:
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_round_normal_end:wwNnn
+ ; #2
+ }
+\cs_new:Npn \@@_round_normal_end:wwNnn #1;#2;#3#4#5
+ {
+ \exp_after:wN \@@_exp_after_o:w \tex_romannumeral:D -`0
+ \@@_sanitize:Nw #3 #4 ; #1 ;
+ }
+\cs_new:Npn \@@_round_special:NwwNnn #1#2;#3;#4#5#6
+ {
+ \if_meaning:w 0 #1
+ \@@_case_return:nw
+ { \exp_after:wN \@@_zero_fp:N \exp_after:wN #4 }
+ \else:
+ \exp_after:wN \@@_round_special_aux:Nw
+ \exp_after:wN #4
+ \int_use:N \__int_eval:w \c_one
+ \if_meaning:w 1 #1 -#6 \else: +#5 \fi:
+ \fi:
+ ;
+ }
+\cs_new:Npn \@@_round_special_aux:Nw #1#2;
+ {
+ \exp_after:wN \@@_exp_after_o:w \tex_romannumeral:D -`0
+ \@@_sanitize:Nw #1#2; {1000}{0000}{0000}{0000};
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
new file mode 100644
index 00000000000..2e3a5e262ba
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-traps.dtx
@@ -0,0 +1,418 @@
+% \iffalse meta-comment
+%%
+%% File: l3fp-traps.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-traps.dtx 2479 2011-06-19 21:57:25Z bruno $
+ {L3 Floating-point exception trapping}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-traps} package\thanks{This file
+% has version number \ExplFileVersion, last
+% revised \ExplFileDate.}\\
+% Trapping floating-point exceptions}
+% \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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3fp-traps} Implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+% Exceptions should be accessed by an \texttt{n}-type argument, among
+% \begin{itemize}
+% \item \texttt{invalid_operation}
+% \item \texttt{division_by_zero}
+% \item \texttt{overflow}
+% \item \texttt{underflow}
+% \item \texttt{inexact} (actually never used).
+% \end{itemize}
+%
+% \subsection{Flags}
+%
+% \begin{macro}{\@@_flag_off:n}
+% Function to turn a flag off. Simply undefine it.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_flag_off:n #1
+ { \cs_set_eq:cN { l_@@_ #1 _flag_token } \c_undefined:D }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_flag_on:n}
+% Function to turn a flag on expandably: use \TeX{}'s automatic
+% assignment to \cs{scan_stop:}.
+% \begin{macrocode}
+\cs_new:Npn \@@_flag_on:n #1
+ { \exp_args:Nc \use_none:n { l_@@_ #1 _flag_token } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP,pTF]{\@@_if_flag_on:n}
+% Returns true if the flag is on, false otherwise.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_flag_on:n #1 { p , T , F , TF }
+ {
+ \if_cs_exist:w l_@@_ #1 _flag_token \cs_end:
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}
+% {
+% \l_@@_invalid_operation_flag_token ,
+% \l_@@_division_by_zero_flag_token ,
+% \l_@@_overflow_flag_token ,
+% \l_@@_underflow_flag_token ,
+% }
+% The \textsc{ieee} standard defines five exceptions. We currently
+% don't support the \enquote{inexact} exception.
+% \begin{macrocode}
+\cs_new_eq:NN \l_@@_invalid_operation_flag_token \c_undefined:D
+\cs_new_eq:NN \l_@@_division_by_zero_flag_token \c_undefined:D
+\cs_new_eq:NN \l_@@_overflow_flag_token \c_undefined:D
+\cs_new_eq:NN \l_@@_underflow_flag_token \c_undefined:D
+% \end{macrocode}
+% \end{variable}
+%
+% \subsection{Traps}
+%
+% Exceptions can be trapped to obtain custom behaviour. When an invalid
+% operation or a division by zero is trapped, the trap receives as
+% arguments the result as an $N$-type floating point number, the
+% function name (multiple letters for prefix operations, or a single
+% symbol for infix operations), and the operand(s). When an overflow or
+% underflow is trapped, the trap receives the resulting overly large or
+% small floating point number if it is not too big, otherwise it
+% receives $+\infty$. Currently, the inexact exception is entirely
+% ignored.
+%
+% The behaviour when an exception occurs is controlled by the
+% definitions of the functions
+% \begin{itemize}
+% \item \cs{@@_invalid_operation:Nnw},
+% \item \cs{@@_invalid_operation:Nnww},
+% \item \cs{@@_division_by_zero:Nnw},
+% \item \cs{@@_division_by_zero:Nnww},
+% \item \cs{@@_overflow:w},
+% \item \cs{@@_underflow:w}.
+% \end{itemize}
+% Rather than changing them directly, we provide a user interface as
+% \cs{@@_trap:nn} \Arg{exception} \Arg{way of trapping}, where the
+% \meta{way of trapping} is one of \texttt{error}, \texttt{flag}, or
+% \texttt{none}.
+%
+% \begin{macro}{\@@_trap:nn} %^^A todo: user command => document
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_trap:nn #1#2
+ {
+ \cs_if_exist_use:cF { @@_trap_#1_set_#2: }
+ {
+ \clist_if_in:nnTF
+ { invalid_operation , division_by_zero , overflow , underflow }
+ {#1}
+ {
+ \__msg_kernel_error:nnxx { kernel }
+ { unknown-fpu-trap-type } {#1} {#2}
+ }
+ { \__msg_kernel_error:nnx { kernel } { unknown-fpu-exception } {#1} }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux]
+% {
+% \@@_trap_invalid_operation_set_error: ,
+% \@@_trap_invalid_operation_set_flag: ,
+% \@@_trap_invalid_operation_set_none: ,
+% \@@_trap_invalid_operation_set:N ,
+% }
+% \begin{macro}[aux]
+% {
+% \@@_trap_division_by_zero_set_error: ,
+% \@@_trap_division_by_zero_set_flag: ,
+% \@@_trap_division_by_zero_set_none: ,
+% \@@_trap_division_by_zero_set:N ,
+% }
+% \begin{macro}[aux]{\@@_trap_invalid_operation_set:Nnn}
+% We provide three types of trapping for invalid operations and
+% division by zero: either produce an error and raise the relevant
+% flag; or only raise the flag; or don't even raise the flag. In all
+% cases, the function must produce a result, namely its first
+% argument, $\pm\infty$ or \nan{}.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_trap_invalid_operation_set_error:
+ { \@@_trap_invalid_operation_set:N \prg_do_nothing: }
+\cs_new_protected_nopar:Npn \@@_trap_invalid_operation_set_flag:
+ { \@@_trap_invalid_operation_set:N \use_none:nn }
+\cs_new_protected_nopar:Npn \@@_trap_invalid_operation_set_none:
+ { \@@_trap_invalid_operation_set:N \use_none:nnnn }
+\cs_new_protected:Npn \@@_trap_invalid_operation_set:N #1
+ {
+ \@@_trap_invalid_operation_set:Nnn #1
+ { invalid_operation } { Invalid~operation~ }
+ }
+\cs_new_protected_nopar:Npn \@@_trap_division_by_zero_set_error:
+ { \@@_trap_division_by_zero_set:N \prg_do_nothing: }
+\cs_new_protected_nopar:Npn \@@_trap_division_by_zero_set_flag:
+ { \@@_trap_division_by_zero_set:N \use_none:nn }
+\cs_new_protected_nopar:Npn \@@_trap_division_by_zero_set_none:
+ { \@@_trap_division_by_zero_set:N \use_none:nnnn }
+\cs_new_protected:Npn \@@_trap_division_by_zero_set:N #1
+ {
+ \@@_trap_invalid_operation_set:Nnn #1
+ { division_by_zero } { Division~by~zero~in~ }
+ }
+\cs_new_protected:Npn \@@_trap_invalid_operation_set:Nnn #1#2#3
+ {
+ \exp_args:Nno \use:n
+ { \cs_set:cpn { @@_ #2 :Nnw } ##1##2##3; }
+ {
+ #1
+ \@@_error:x { { #3 ##2 } ( \@@_to_tl:w ##3; ) }
+ \@@_flag_on:n {#2}
+ \exp_after:wN ##1
+ }
+ \exp_args:Nno \use:n
+ { \cs_set:cpn { @@_ #2 :Nnww } ##1##2##3; ##4; }
+ {
+ #1
+ \@@_error:x
+ {
+ {#3}
+ \tl_if_single:nTF {##2}
+ { ( \@@_to_tl:w ##3; ) ##2 ( \@@_to_tl:w ##4; ) }
+ { { ##2 ( } \@@_to_tl:w ##3; { , ~ } \@@_to_tl:w ##4; ) }
+ }
+ \@@_flag_on:n {#2}
+ \exp_after:wN ##1
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux]
+% {
+% \@@_trap_overflow_set_error: ,
+% \@@_trap_overflow_set_flag: ,
+% \@@_trap_overflow_set_none: ,
+% \@@_trap_overflow_set:N ,
+% }
+% \begin{macro}[aux]
+% {
+% \@@_trap_underflow_set_error: ,
+% \@@_trap_underflow_set_flag: ,
+% \@@_trap_underflow_set_none: ,
+% \@@_trap_underflow_set:N ,
+% }
+% \begin{macro}[aux]{\@@_trap_overflow_set:NnNn}
+% Just as for invalid operations and division by zero, the three
+% different behaviours are obtained by feeding \cs{prg_do_nothing:},
+% \cs{use_none:nn} or \cs{use_none:nnnn} to an auxiliary, with a
+% further auxiliary common to overflow and underflow functions. In
+% most cases, the argument of the \cs{@@_overflow:w} and
+% \cs{@@_underflow:w} functions will be an (almost) normal number
+% (with an exponent outside the allowed range), and the error message
+% thus displays that number together with the result to which it
+% overflowed or underflowed. For extreme cases such as \texttt{10 **
+% 1e9999}, the exponent would be too large for \TeX{}, and
+% \cs{@@_overflow:w} receives $\pm \infty$ (\cs{@@_underflow:w} would
+% receive $\pm 0$); then we cannot do better than simply say an
+% overflow or underflow occurred.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_trap_overflow_set_error:
+ { \@@_trap_overflow_set:N \prg_do_nothing: }
+\cs_new_protected_nopar:Npn \@@_trap_overflow_set_flag:
+ { \@@_trap_overflow_set:N \use_none:nn }
+\cs_new_protected_nopar:Npn \@@_trap_overflow_set_none:
+ { \@@_trap_overflow_set:N \use_none:nnnn }
+\cs_new_protected:Npn \@@_trap_overflow_set:N #1
+ { \@@_trap_overflow_set:NnNn #1 { overflow } \@@_inf_fp:N { inf } }
+\cs_new_protected_nopar:Npn \@@_trap_underflow_set_error:
+ { \@@_trap_underflow_set:N \prg_do_nothing: }
+\cs_new_protected_nopar:Npn \@@_trap_underflow_set_flag:
+ { \@@_trap_underflow_set:N \use_none:nn }
+\cs_new_protected_nopar:Npn \@@_trap_underflow_set_none:
+ { \@@_trap_underflow_set:N \use_none:nnnn }
+\cs_new_protected:Npn \@@_trap_underflow_set:N #1
+ { \@@_trap_overflow_set:NnNn #1 { underflow } \@@_zero_fp:N { 0 } }
+\cs_new_protected:Npn \@@_trap_overflow_set:NnNn #1#2#3#4
+ {
+ \exp_args:Nno \use:n
+ { \cs_set:cpn { @@_ #2 :w } \s_@@ \@@_chk:w ##1##2##3; }
+ {
+ #1
+ \@@_error:x
+ {
+ \token_if_eq_meaning:NNTF 1 ##1
+ {
+ \@@_to_tl:w \s_@@ \@@_chk:w ##1##2##3; ~ #2 ed ~ to ~
+ \token_if_eq_meaning:NNF 0 ##2 { - } #4 .
+ }
+ { An~#2~occurred. }
+ }
+ \@@_flag_on:n {#2}
+ #3 ##2
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]
+% {
+% \@@_invalid_operation:Nnw, \@@_invalid_operation:Nnww,
+% \@@_division_by_zero:Nnw, \@@_division_by_zero:Nnww,
+% \@@_overflow:w , \@@_underflow:w
+% }
+% Initialize the two control sequences (to log properly their
+% existence). Then set invalid operations to trigger an error, and
+% division by zero, overflow, and underflow to act silently on their
+% flag.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \@@_invalid_operation:Nnw { }
+\cs_new_protected_nopar:Npn \@@_invalid_operation:Nnww { }
+\cs_new_protected_nopar:Npn \@@_division_by_zero:Nnw { }
+\cs_new_protected_nopar:Npn \@@_division_by_zero:Nnww { }
+\cs_new_protected_nopar:Npn \@@_overflow:w { }
+\cs_new_protected_nopar:Npn \@@_underflow:w { }
+\@@_trap:nn { invalid_operation } { error }
+\@@_trap:nn { division_by_zero } { flag }
+\@@_trap:nn { overflow } { flag }
+\@@_trap:nn { underflow } { flag }
+% \end{macrocode}
+% \end{macro}
+%
+%^^A todo: first arg of @@_invalid_operation:Nnw(w) should be an 'invalid' nan.
+%
+% \subsection{Errors}
+%
+%^^A begin[todo]
+% \begin{macro}[int, EXP]{\@@_error:n, \@@_error:x}
+% The argument is fully expanded in a way similar to \texttt{x}-type
+% expansion, but braced groups are simply copied, \cs{exp_not:n} does
+% not work, spaces are ignored unless braced. The result of that
+% weird (but useful) expansion is fed to \cs{__msg_expandable_error:n}.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_error:n \__msg_expandable_error:n
+\cs_new:Npn \@@_error:x #1
+ {
+ \exp_args:Nf \__msg_expandable_error:n
+ {
+ \@@_error_loop:nwnN { \exp_stop_f: } #1 \prg_do_nothing:
+ \s_@@_mark { } \@@_error_loop:nwnN \s_@@_mark { } \@@_error_end:nw
+ }
+ }
+\cs_new:Npn \@@_error_end:nw #1#2 \@@_error_end:nw { #1 }
+\cs_new:Npn \@@_error_loop:nwnN #1#2 \s_@@_mark #3 #4
+ {
+ \exp_after:wN #4 \tex_romannumeral:D -`0
+ #2
+ \s_@@_mark { #3 #1 } #4
+ }
+% \end{macrocode}
+% \end{macro}
+% ^^A end[todo]
+%
+% \subsection{Messages}
+%
+% Some messages.
+% \begin{macrocode}
+\msg_new:nnnn { kernel } { unknown-fpu-exception }
+ { The~FPU~exception~'#1'~is~not~known:~that~trap~will~never~be~triggered. }
+ {
+ The~only~exceptions~to~which~traps~can~be~attached~are \\
+ \iow_indent:n
+ {
+ * ~ invalid_operation \\
+ * ~ division_by_zero \\
+ * ~ overflow \\
+ * ~ underflow
+ }
+ }
+\msg_new:nnnn { kernel } { unknown-fpu-trap-type }
+ { The~FPU~trap~type~'#2'~is~not~known. }
+ {
+ The~trap~type~must~be~one~of \\
+ \iow_indent:n
+ {
+ * ~ error \\
+ * ~ flag \\
+ * ~ none
+ }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
new file mode 100644
index 00000000000..16a3fb465f6
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp-trig.dtx
@@ -0,0 +1,581 @@
+% \iffalse meta-comment
+%
+%% File: l3fp-trig.dtx Copyright (C) 2011-2012 The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "l3kernel bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The 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 LaTeX Project Team.
+%%
+%% -----------------------------------------------------------------------
+%%
+%
+%<*driver>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3fp-trig.dtx 3514 2012-03-08 06:14:48Z bruno $
+ {L3 Floating-point trigonometric functions}
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{The \textsf{l3fp-trig} package\thanks{This file
+% has version number \ExplFileVersion, last
+% revised \ExplFileDate.}\\
+% Floating point trigonometric functions}
+% \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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{Implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=fp>
+% \end{macrocode}
+%
+%^^A todo: check EXP/rEXP everywhere.
+%
+% \subsection{Inverting a floating point number}
+%
+% \begin{macro}[int, EXP]{\@@_one_over:w}
+% Expects a floating point of the form \cs{s_@@} \ldots{} |;| and
+% computes its multiplicative inverse. This is used to compute the
+% cotangent function very near $0$.
+% \begin{macrocode}
+\cs_new_nopar:Npx \@@_one_over:w
+ {
+ \exp_not:N \exp_after:wN
+ \exp_not:c { @@_/_o:ww }
+ \exp_not:N \c_one_fp
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Direct trigonometric functions}
+%
+% The approach for all trigonometric functions (sine, cosine, tangent,
+% and cotangent) is the same.
+% \begin{itemize}
+% \item Filter out special cases ($\pm 0$, $\pm\inf$ and \nan{}).
+% \item Keep the sign for later, and work with the absolute value $|x|$
+% of the argument.
+% \item For numbers less than $1$, shift the mantissa to convert them to
+% fixed point numbers. Very small numbers take a slightly different
+% route.
+% \item For numbers $\geq 1$, subtract a multiple of $\pi/2$ to bring
+% them to the range to $[0, \pi/2]$.
+% \item Reduce further to $[0, \pi/4]$ using $\sin x = \cos (\pi/2-x)$.
+% \item Use the appropriate power series depending on the octant
+% $\lfloor\frac{|x|}{\pi/4}\rfloor \mod 8$, the sign, and the function
+% to compute.
+% \end{itemize}
+%
+% \subsubsection{Sign and special numbers}
+%
+% \begin{macro}[int, EXP]{\@@_sin:w}
+% The sine of $\pm 0$ or \nan{} is the same floating point number.
+% The sine of $\pm\infty$ raises an invalid operation exception.
+% Otherwise, check the exponent, preparing to use
+% \cs{@@_sin_series:NNwww} for the calculation, with a sign |#2|, and
+% an initial octant of $0$. The question mark is an argument which is
+% not used in this case.
+% \begin{macrocode}
+\cs_new:Npn \@@_sin:w \s_@@ \@@_chk:w #1#2
+ {
+ \if_case:w #1 \exp_stop_f:
+ \@@_case_return_same_o:w
+ \or:
+ \exp_after:wN \@@_trig_exponent:NNNNwn
+ \exp_after:wN \@@_sin_series:NNwww
+ \exp_after:wN ?
+ \exp_after:wN #2
+ \exp_after:wN \c_zero
+ \or:
+ \@@_case_use:nw
+ { \@@_invalid_operation:Nnw \c_nan_fp { sin } }
+ \else: \@@_case_return_same_o:w
+ \fi:
+ \s_@@ \@@_chk:w #1#2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_cos:w}
+% The cosine of $\pm 0$ is $1$. The cosine of $\pm\infty$ raises an
+% invalid operation exception. The cosine of \nan{} is itself.
+% Otherwise, check the exponent, preparing to use
+% \cs{@@_sin_series:NNwww} for the calculation, with a positive sign
+% ($0$), and an initial octant of $2$, because $\cos x = \sin ( \pi/2
+% + |x|)$. The question mark is an argument which is not used in this
+% case.
+% \begin{macrocode}
+\cs_new:Npn \@@_cos:w \s_@@ \@@_chk:w #1#2
+ {
+ \if_case:w #1 \exp_stop_f:
+ \@@_case_return_o:Nw \c_one_fp
+ \or:
+ \@@_case_use:nw %^^A todo: is that faster than the exp_after route?
+ {
+ \@@_trig_exponent:NNNNwn
+ \@@_sin_series:NNwww
+ ?
+ 0
+ \c_two
+ }
+ \or:
+ \@@_case_use:nw
+ { \@@_invalid_operation:Nnw \c_nan_fp { cos } }
+ \else: \@@_case_return_same_o:w
+ \fi:
+ \s_@@ \@@_chk:w #1#2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_tan:w}
+% The tangent of $\pm 0$ or \nan{} is the same floating point number.
+% The tangent of $\pm\infty$ raises an invalid operation exception.
+% Otherwise, check the exponent, preparing to use
+% \cs{@@_tan_series:NNwww} for the calculation, with a positive sign
+% ($0$), and an initial octant of $1$, chosen to be distinct from the
+% octants for sine and cosine. See \cs{@@_cot:w} for an
+% explanation of the $0$ argument.
+% \begin{macrocode}
+\cs_new:Npn \@@_tan:w \s_@@ \@@_chk:w #1#2
+ {
+ \if_case:w #1 \exp_stop_f:
+ \@@_case_return_same_o:w
+ \or:
+ \exp_after:wN \@@_trig_exponent:NNNNwn
+ \exp_after:wN \@@_tan_series:NNwww
+ \exp_after:wN 0
+ \exp_after:wN #2
+ \exp_after:wN \c_one
+ \or:
+ \@@_case_use:nw
+ { \@@_invalid_operation:Nnw \c_nan_fp { tan } }
+ \else: \@@_case_return_same_o:w
+ \fi:
+ \s_@@ \@@_chk:w #1#2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int, EXP]{\@@_cot:w}
+% The cotangent of $\pm 0$ is $\pm \infty$ with the same sign,
+% produced by \cs{@@_one_over:w}. The cotangent of $\pm\infty$ raises
+% an invalid operation exception. The cotangent of \nan{} is itself.
+% We use $\cot x = - \tan (\pi/2 + x)$, and the initial octant for the
+% tangent was chosen to be $1$, so the octant here starts at $3$. The
+% change in sign is obtained by feeding \cs{@@_tan_series:NNwww} two
+% signs rather than just the sign of the argument: the first of those
+% indicates whether we compute tangent or cotangent. Those signs are
+% eventually combined.
+% \begin{macrocode}
+\cs_new:Npn \@@_cot:w \s_@@ \@@_chk:w #1#2
+ {
+ \if_case:w #1 \exp_stop_f:
+ \exp_after:wN \@@_one_over:w
+ \or:
+ \exp_after:wN \@@_trig_exponent:NNNNwn
+ \exp_after:wN \@@_tan_series:NNwww
+ \exp_after:wN 2
+ \exp_after:wN #2
+ \exp_after:wN \c_three
+ \or:
+ \@@_case_use:nw
+ { \@@_invalid_operation:Nnw \c_nan_fp { cot } }
+ \else: \@@_case_return_same_o:w
+ \fi:
+ \s_@@ \@@_chk:w #1#2
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Small and tiny arguments}
+%
+% \begin{macro}[aux, EXP]{\@@_trig_exponent:NNNNwn}
+% The first four arguments control what trigonometric function we
+% compute, then follows a normal floating point number. If the
+% floating point is smaller than $10^{-8}$, then call the appropriate
+% \texttt{_epsilon} auxiliary. Otherwise, call the function |#1|,
+% with arguments |#2|, |#3|, the octant, computed in an integer
+% expression starting with |#4|, and a fixed point number obtained
+% from the floating point number by argument reduction. Numbers less
+% than $1$ are converted using \cs{@@_trig_small:w} which simply
+% shifts the mantissa, while large numbers need argument reduction.
+% \begin{macrocode}
+\cs_new:Npn \@@_trig_exponent:NNNNwn #1#2#3#4 \s_@@ \@@_chk:w 1#5#6
+ {
+ \if_int_compare:w #6 > - \c_eight
+ \exp_after:wN #1
+ \exp_after:wN #2
+ \exp_after:wN #3
+ \int_use:N \__int_eval:w #4
+ \if_int_compare:w #6 > \c_zero
+ \exp_after:wN \@@_trig_large:w \__int_value:w
+ \else:
+ \exp_after:wN \@@_trig_small:w \__int_value:w
+ \fi:
+ \else:
+ \if_case:w #4
+ \@@_sin_epsilon:w
+ \or: \@@_sin_epsilon:w
+ \or: \@@_cos_epsilon:w
+ \else: \@@_cot_epsilon:w
+ \fi:
+ #5
+ \fi:
+ #6 ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]
+% {\@@_sin_epsilon:w, \@@_cos_epsilon:w, \@@_cot_epsilon:w}
+% Sine and tangent of tiny numbers give the number itself: the
+% relative error is less than $5 \cdot 10^{-17}$, which is
+% appropriate. Cosine simply gives $1$. Cotangent computes the
+% inverse. This is actually slightly wrong because further terms in
+% the power series could affect the rounding for cotangent.
+% \begin{macrocode}
+\cs_new:Npn \@@_sin_epsilon:w #1 \fi: #2 \fi: #3 ;
+ { \fi: \fi: \@@_exp_after_o:w \s_@@ \@@_chk:w 1 #2 {#3} }
+\cs_new:Npn \@@_cos_epsilon:w #1 \fi: #2 \fi: #3 ; #4 ;
+ { \fi: \fi: \exp_after:wN \c_one_fp }
+\cs_new:Npn \@@_cot_epsilon:w \fi: #1 \fi: #2 ;
+ { \fi: \fi: \@@_one_over:w \s_@@ \@@_chk:w 1 #1 {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_trig_small:w, \@@_trig_small_aux:wwNN}
+% Floating point numbers less than $1$ are converted to fixed point
+% numbers by shifting the mantissa. Since we have already filtered
+% out numbers less than $10^{-8}$, no digit is lost in converting to
+% a fixed point number.
+% \begin{macrocode}
+\cs_new:Npn \@@_trig_small:w #1;
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \@@_trig_small_aux:wwNN
+ \prg_replicate:nn { - #1 } { 0 } ;
+ }
+\cs_new:Npn \@@_trig_small_aux:wwNN #1; #2#3#4#5;
+ {
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_pack_twice_four:wNNNNNNNN
+ \@@_pack_twice_four:wNNNNNNNN
+ .
+ ;
+ #1#2#3#4#5 0000 0000;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Reduction of large arguments}
+%
+% In the case of a floating point argument greater or equal to $1$, we
+% need to perform argument reduction.
+%
+% \begin{macro}[aux, rEXP]
+% {
+% \@@_trig_large:w, \@@_trig_large_i:www,
+% \@@_trig_large_ii:wnnnnnn, \@@_trig_large_break:w
+% }
+% We shift the mantissa by one digit at a time, subtracting a multiple
+% of $2\pi$ at each step. We use a value of $2\pi$ rounded up,
+% consistent with the choice of \cs{c_pi_fp}. This is not quite
+% correct from an accuracy perspective, but has the nice property that
+% $\sin(180\mathrm{deg}) = 0$ exactly. The arguments of
+% \cs{@@_trig_large_i:www} are a leading block of up to $5$ digits,
+% three brace groups of $4$ digits each, and the exponent, decremented
+% at each step. The multiple of $2\pi$ to subtract is estimated as
+% $\lfloor |#1| / 6283\rfloor$ (the formula chosen always gives a
+% non-negative integer). The subtraction has a form similar to our
+% usual multiplications (see \pkg{l3fp-basics} or
+% \pkg{l3fp-extended}). Once the exponent reaches $0$, we are done
+% subtracting $2\pi$, and we call \cs{@@_trig_octant_loop:nw} to do
+% the reduction by $\pi/2$.
+% \begin{macrocode}
+\cs_new:Npn \@@_trig_large:w #1; #2#3;
+ { \@@_trig_large_i:www #2; #3 ; #1; }
+\cs_new:Npn \@@_trig_large_i:www #1; #2; #3;
+ {
+ \if_meaning:w 0 #3 \@@_trig_large_break:w \fi:
+ \exp_after:wN \@@_trig_large_ii:wnnnnnn
+ \int_use:N \__int_eval:w ( #1 - 3141 ) / 6283 ;
+ {#1} #2;
+ \int_use:N \__int_eval:w \c_minus_one + #3;
+ }
+\cs_new:Npn \@@_trig_large_ii:wnnnnnn #1; #2#3#4#5;
+ {
+ \exp_after:wN \@@_trig_large_i:www
+ \int_use:N \__int_eval:w -5 0000 + #20 - #1*62831
+ \exp_after:wN \@@_fixed_mul_pack:NNNNNw
+ \int_use:N \__int_eval:w 4 9995 0000 + #30 - #1*8530
+ \exp_after:wN \@@_fixed_mul_pack:NNNNNw
+ \int_use:N \__int_eval:w 4 9995 0000 + #40 - #1*7179
+ \exp_after:wN \@@_fixed_mul_pack:NNNNNw
+ \int_use:N \__int_eval:w 5 0000 0000 + #50 - #1*5880
+ \exp_after:wN ;
+ \exp_after:wN ;
+ }
+\cs_new:Npn \@@_trig_large_break:w \fi: #1; #2;
+ { \fi: \@@_trig_octant_loop:nw #2 {0000} {0000} ; }
+% \end{macrocode}
+% \end{macro}
+%
+%^^A todo: optimize: we don't need 6x4 digits here, only 4x4.
+%
+% \begin{macro}[aux, rEXP]
+% {
+% \@@_trig_octant_loop:nw, \@@_trig_octant_break:w,
+% \@@_trig_octant_neg:w
+% }
+% We receive a fixed point number as argument. As long as it is
+% greater than $1.5707$ (a slight underestimate of $\pi/2$), subtract
+% $\pi/2$, and leave |+ \c_two| in the integer expression for the
+% octant. Once it becomes smaller, if it is greater than $0.7854$
+% (overestimate of $\pi/4$), then compute $\pi/2 - x$ and increment
+% the octant. If it is negative, correct this by changing the sign
+% and decrementing the octant (by adding $7$). The result is in all
+% cases in the range $[0, 0.7854]$, appropriate for a series
+% expansion.
+% \begin{macrocode}
+\cs_new:Npn \@@_trig_octant_loop:nw #1#2;
+ {
+ \if_int_compare:w #1 < 15707 \exp_stop_f:
+ \@@_trig_octant_break:w
+ \fi:
+ + \c_two
+ \@@_fixed_sub_back:wwN
+ {15707} {9632} {6794} {8970} {0000} {0000} ;
+ {#1} #2;
+ \@@_trig_octant_loop:nw
+ }
+\cs_new:Npn \@@_trig_octant_break:w #1 \fi: + #2#3 #4; #5#6; #7;
+ {
+ \fi:
+ \if_int_compare:w #5 < 7854 \exp_stop_f:
+ \if_int_compare:w #5 < \c_zero
+ \exp_after:wN \@@_trig_octant_neg:w
+ \fi:
+ \exp_after:wN \@@_use_i_until_s:nw
+ \exp_after:wN .
+ \fi:
+ + \c_one
+ \@@_fixed_sub:wwN
+ {15707} {9632} {6794} {8970} {0000} {0000} ;
+ {#5} #6 ; . ;
+ }
+\cs_new:Npn \@@_trig_octant_neg:w #1\fi: #2; #3#4#5#6#7#8; #9
+ {
+ \fi:
+ + \c_seven
+ \exp_after:wN \@@_fixed_add_after:NNNNNwN
+ \int_use:N \__int_eval:w 1 9999 9998 - #30000 - #4
+ \exp_after:wN \@@_fixed_add_pack:NNNNNwN
+ \int_use:N \__int_eval:w 1 9999 9998 - #5#6
+ \exp_after:wN \@@_fixed_add_pack:NNNNNwN
+ \int_use:N \__int_eval:w 2 0000 0000 - #7#8 ; {#9} ;
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Computing the power series}
+%
+% \begin{macro}[aux, EXP]{\@@_sin_series:NNwww, \@@_sin_series_aux:Nnww}
+% Here we receive an unused |?|, a \meta{sign} ($0$ or $2$), a
+% (non-negative) \meta{octant} delimited by a dot, a \meta{fixed
+% point} number, and junk delimited by a semicolon. The auxiliary
+% receives:
+% \begin{itemize}
+% \item The final sign, which depends on the octant |#3| and the
+% original sign |#2|,
+% \item The octant |#3|, which will control the series we use.
+% \item The square |#4 * #4| of the argument, computed with
+% \cs{@@_fixed_mul:wwn}.
+% \item The number itself.
+% \end{itemize}
+% If the octant is in $\{1,2,5,6,\ldots{}\}$, we are near an extremum
+% of the function and we use the series
+% \[
+% \cos(x) = 1 - x^2 \bigg( \frac{1}{2!} - x^2 \bigg( \frac{1}{4!}
+% - x^2 \bigg( \cdots \bigg) \bigg) \bigg) .
+% \]
+% Otherwise, the series
+% \[
+% \sin(x) = x \bigg( 1 - x^2 \bigg( \frac{1}{3!} - x^2 \bigg(
+% \frac{1}{5!} - x^2 \bigg( \cdots \bigg) \bigg) \bigg) \bigg)
+% \]
+% is used. Finally, the fixed point number is converted to a floating
+% point number with the given sign, and we check for overflow or
+% underflow. %^^A todo: can over/underflow really happen??
+% \begin{macrocode}
+\cs_new:Npn \@@_sin_series:NNwww #1#2#3 . #4; #5;
+ {
+ \@@_fixed_mul:wwn #4; #4;
+ {
+ \exp_after:wN \@@_sin_series_aux:Nnww
+ \__int_value:w
+ \if_int_odd:w \__int_eval:w ( #3 + \c_two ) / \c_four \__int_eval_end:
+ #2
+ \else:
+ \if_meaning:w #2 0 2 \else: 0 \fi:
+ \fi:
+ {#3}
+ }
+ #4 ;
+ }
+\cs_new:Npn \@@_sin_series_aux:Nnww #1#2 #3; #4;
+ {
+ \if_int_odd:w \__int_eval:w #2 / \c_two \__int_eval_end:
+ \exp_after:wN \use_i:nn
+ \else:
+ \exp_after:wN \use_ii:nn
+ \fi:
+ {
+ \@@_fixed_continue:wn {0000}{0000}{0000}{0001}{5619}{2070}; % 1/18!
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{0000}{0000}{0477}{9477}{3324};
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{0000}{0011}{4707}{4559}{7730};
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{0000}{2087}{6756}{9878}{6810};
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{0027}{5573}{1922}{3985}{8907};
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{2480}{1587}{3015}{8730}{1587};
+ \@@_fixed_mul_sub_back:wwwn #3; {0013}{8888}{8888}{8888}{8888}{8889};
+ \@@_fixed_mul_sub_back:wwwn #3; {0416}{6666}{6666}{6666}{6666}{6667};
+ \@@_fixed_mul_sub_back:wwwn #3; {5000}{0000}{0000}{0000}{0000}{0000};
+ \@@_fixed_mul_sub_back:wwwn #3;{10000}{0000}{0000}{0000}{0000}{0000};
+ }
+ {
+ \@@_fixed_continue:wn {0000}{0000}{0000}{0028}{1145}{7254}; % 1/17!
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{0000}{0000}{7647}{1637}{3182};
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{0000}{0160}{5904}{3836}{8216};
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{0002}{5052}{1083}{8544}{1719};
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{0275}{5731}{9223}{9858}{9065};
+ \@@_fixed_mul_sub_back:wwwn #3; {0001}{9841}{2698}{4126}{9841}{2698};
+ \@@_fixed_mul_sub_back:wwwn #3; {0083}{3333}{3333}{3333}{3333}{3333};
+ \@@_fixed_mul_sub_back:wwwn #3; {1666}{6666}{6666}{6666}{6666}{6667};
+ \@@_fixed_mul_sub_back:wwwn #3;{10000}{0000}{0000}{0000}{0000}{0000};
+ \@@_fixed_mul:wwn #4;
+ }
+ {
+ \exp_after:wN \@@_sanitize:Nw
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w \@@_fixed_to_float:wN
+ }
+ #1
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux, EXP]{\@@_tan_series:NNwww, \@@_tan_series_aux:Nnww}
+% Similar to \cs{@@_sin_series:NNwww}, but with slightly different
+% rules to find the sign. The result is expressed as a ratio of
+% polynomials, of the form
+% \[
+% \tan(x) \simeq
+% \frac{x (1 - x^2 (a_1 - x^2 (a_2 - x^2 (a_3 - x^2 (a_4 - x^2 a_5)))))}
+% {1 - x^2 (b_1 - x^2 (b_2 - x^2 (b_3 - x^2 (b_4 - x^2 b_5))))} .
+% \]
+% The ratio of the two fixed point numbers is converted to a floating
+% point number directly to avoid rounding issues. The two fixed
+% points may be exchanged before computing the ratio, depending on the
+% quadrant.
+% \begin{macrocode}
+\cs_new:Npn \@@_tan_series:NNwww #1#2#3. #4; #5;
+ {
+ \@@_fixed_mul:wwn #4; #4;
+ {
+ \exp_after:wN \@@_tan_series_aux:Nnww
+ \__int_value:w
+ \if_int_odd:w \__int_eval:w #3 / \c_two \__int_eval_end:
+ \exp_after:wN \reverse_if:N
+ \fi:
+ \if_meaning:w #1#2 2 \else: 0 \fi:
+ {#3}
+ }
+ #4 ;
+ }
+\cs_new:Npn \@@_tan_series_aux:Nnww #1 #2 #3; #4;
+ {
+ \@@_fixed_continue:wn {0000}{0000}{1527}{3493}{0856}{7059};
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{0159}{6080}{0274}{5257}{6472};
+ \@@_fixed_mul_sub_back:wwwn #3; {0002}{4571}{2320}{0157}{2558}{8481};
+ \@@_fixed_mul_sub_back:wwwn #3; {0115}{5830}{7533}{5397}{3168}{2147};
+ \@@_fixed_mul_sub_back:wwwn #3; {1929}{8245}{6140}{3508}{7719}{2982};
+ \@@_fixed_mul_sub_back:wwwn #3;{10000}{0000}{0000}{0000}{0000}{0000};
+ \@@_fixed_mul:wwn #4;
+ {
+ \@@_fixed_continue:wn {0000}{0007}{0258}{0681}{9408}{4706};
+ \@@_fixed_mul_sub_back:wwwn #3; {0000}{2343}{7175}{1399}{6151}{7670};
+ \@@_fixed_mul_sub_back:wwwn #3; {0019}{2638}{4588}{9232}{8861}{3691};
+ \@@_fixed_mul_sub_back:wwwn #3; {0536}{6357}{0691}{4344}{6852}{4252};
+ \@@_fixed_mul_sub_back:wwwn #3; {5263}{1578}{9473}{6842}{1052}{6315};
+ \@@_fixed_mul_sub_back:wwwn #3;{10000}{0000}{0000}{0000}{0000}{0000};
+ {
+ \exp_after:wN \@@_sanitize:Nw
+ \exp_after:wN #1
+ \int_use:N \__int_eval:w
+ \reverse_if:N \if_int_odd:w
+ \__int_eval:w (#2 - \c_one) / \c_two \__int_eval_end:
+ \exp_after:wN \@@_reverse_args:Nww
+ \fi:
+ \@@_fixed_div_to_float:ww
+ }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex \ No newline at end of file
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
index 64a6b39252f..68f71f540cc 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3fp.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3fp.dtx Copyright (C) 2010-2012 The LaTeX3 Project
+%% File: l3fp.dtx Copyright (C) 2011-2012 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
@@ -29,27 +29,31 @@
%% 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.
+%% prior consultation with the LaTeX3 Project Team.
%%
%% -----------------------------------------------------------------------
+%%
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3fp.dtx 3490 2012-03-04 01:00:53Z bruno $
- {L3 Experimental floating-point operations}
+\GetIdInfo$Id: l3fp.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Floating points}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
+\usepackage{amsmath}
+\providecommand\nan{\texttt{NaN}}
\begin{document}
\DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
%
+%
% \title{^^A
-% The \pkg{l3fp} package\\ Floating-point operations^^A
+% The \textsf{l3fp} package: floating points^^A
% \thanks{This file describes v\ExplFileVersion,
-% last revised \ExplFileDate.}^^A
+% last revised \ExplFileDate.}^^A
% }
%
% \author{^^A
@@ -67,5497 +71,868 @@
%
% \begin{documentation}
%
-% A floating point number is one which is stored as a mantissa and
-% a separate exponent. This module implements arithmetic using radix
-% $10$ floating point numbers. This means that the mantissa should
-% be a real number in the range $1 \le \expandafter\mathopen\string|
-% x \expandafter\mathclose\string| < 10$, with the
-% exponent given as an integer between $-99$ and $99$. In the
-% input, the exponent part is represented starting with an \texttt{e}.
-% As this is a low-level module, error-checking is minimal. Numbers
-% which are too large for the floating point unit to handle will result
-% in errors, either from \TeX{} or from \LaTeX{}. The \LaTeX{} code does not
-% check that the input will not overflow, hence the possibility of a
-% \TeX{} error. On the other hand, numbers which are too small will be
-% dropped, which will mean that extra decimal digits will simply be
-% lost.
-%
-% When parsing numbers, any missing parts will be interpreted as
-% zero. So for example
-%\begin{verbatim}
-% \fp_set:Nn \l_my_fp { }
-% \fp_set:Nn \l_my_fp { . }
-% \fp_set:Nn \l_my_fp { - }
+% A floating point number is one which is stored as a mantissa and a
+% separate exponent. The module implements expandably a wide set of
+% arithmetic, trigonometric, and other operations on floating point
+% numbers, to be used within floating point expressions. Floating point
+% expressions support the following operations with their usual
+% precedence.
+% \begin{itemize}
+% \item Basic arithmetic: addition $x+y$, subtraction $x-y$,
+% multiplication $x*y$, division $x/y$, and parentheses.
+% \item Trigonometry: $\sin x$, $\cos x$, $\tan x$, $\cot x$.
+% \item Exponentials: $\exp x$, $\ln x$, $x^y$.
+% \item Comparison operators: $x<y$, $x<=y$, $x>?y$, $x!=y$ \emph{etc.}
+% \item Boolean logic: negation $!x$, conjunction $\&\&$, disjunction
+% $\vert\vert$, ternary operator $x?y:z$.
+% \item [\emph{not yet}] Inverse trigonometric functions:
+% $\operatorname{asin} x$, $\operatorname{acos} x$,
+% $\operatorname{atan} x$, $\operatorname{acot} x$.
+% \item [\emph{not yet}] Hyperbolic functions and their inverse
+% functions: $\sinh x$, $\cosh x$, $\tanh x$, $\coth x$, and
+% $\operatorname{asinh} x$, $\operatorname{acosh} x$,
+% $\operatorname{atanh} x$, $\operatorname{acoth} x$.
+% \item Extrema: $\max(x,y,\ldots)$, $\min(x,y,\ldots)$,
+% $\operatorname{abs}(x)$.
+% \item Rounding functions: $\operatorname{round}(x,n)$ round to
+% closest, $\operatorname{round} 0(x,n)$ round towards zero,
+% $\operatorname{round}\pm(x,n)$ round towards $\pm\infty$. And
+% (\emph{not yet}) modulo, and \enquote{quantize}.
+% \item Constants: \texttt{pi}, \texttt{deg} (one degree in radians).
+% \item Dimensions, automatically expressed in points, \emph{e.g.},
+% \texttt{pc} is $12$.
+% \item Automatic conversion (no need for \cs{\meta{type}_use:N}) of
+% integer, dimension, and skip variables to floating points,
+% expressing dimensions in points and ignoring the stretch and
+% shrink components of skips.
+% \end{itemize}
+% Floating point numbers can be given either explicitly (in a form such
+% as |1.234e-34|, or |-.0001|), or as a stored floating point variable,
+% which is automatically replaced by its current value. See
+% section~\ref{sec:fp-floats} for a description of what a floating point is,
+% section~\ref{sec:fp-precedence} for details about how an expression is
+% parsed, and section~\ref{sec:fp-operations} to know what the various
+% operations do. Some operations may raise exceptions (error messages),
+% described in section~\ref{sec:fp-exceptions}.
+%
+% An example of use could be the following.
+% \begin{verbatim}
+% \LaTeX{} can now compute: $ \frac{\sin (3.5)}{2} + 2\cdot 10^{-3}
+% = \ExplSyntaxOn \fp_to_decimal:n {sin 3.5 /2 + 2e-3} $.
+% \end{verbatim}
+% But in all fairness, this module is mostly meant as an underlying tool
+% for higher-level commands. For example, one could provide a function
+% to typeset nicely the result of floating point computations.
+% \begin{verbatim}
+% \usepackage{xparse, siunitx}
+% \ExplSyntaxOn
+% \NewDocumentCommand { \calcnum } { m }
+% { \num { \fp_to_scientific:n {#1} } }
+% \ExplSyntaxOff
+% \calcnum { 2 pi * sin ( 2.3 ^ 5 ) }
% \end{verbatim}
-% will all be interpreted as zero values without raising an error.
-%
-% Operations which give an undefined result (such as division by
-% $0$) will not lead to errors. Instead special marker values are
-% returned, which can be tested for using for example
-% \cs{fp_if_undefined:N(TF)}. In this way it is possible to work with
-% asymptotic functions without first checking the input. If these
-% special values are carried forward in calculations they will be
-% treated as $0$.
-%
-% Floating point numbers are stored in the \texttt{fp} floating point
-% variable type. This has a standard range of functions for
-% variable management.
-%
-% \section{Floating-point variables}
%
-% \begin{function}{\fp_new:N, \fp_new:c}
-% \begin{syntax}
-% \cs{fp_new:N} \meta{floating point variable}
-% \end{syntax}
-% Creates a new \meta{floating point variable} or raises an error if
-% the name is already taken. The declaration is global. The
-% \meta{floating point} will initially be set to |+0.000000000e0|
-% (the zero floating point).
-% \end{function}
+% \section{Creating and initialising floating point variables}
%
-% \begin{function}{\fp_const:Nn, \fp_const:cn}
+% \begin{function}[updated = 2012-05-08]{\fp_new:N, \fp_new:c}
% \begin{syntax}
-% \cs{fp_const:Nn} \meta{floating point variable} \Arg{value}
+% \cs{fp_new:N} \meta{fp~var}
% \end{syntax}
-% Creates a new constant \meta{floating point variable} or raises an
-% error if the name is already taken. The value of the
-% \meta{floating point variable} will be set globally to the
-% \meta{value}.
+% Creates a new \meta{fp~var} or raises an error if the name is
+% already taken. The declaration is global. The \meta{fp~var} will
+% initially be $+0$.
% \end{function}
%
-% \begin{function}
-% {
-% \fp_set_eq:NN, \fp_set_eq:cN, \fp_set_eq:Nc, \fp_set_eq:cc,
-% \fp_gset_eq:NN, \fp_gset_eq:cN, \fp_gset_eq:Nc, \fp_gset_eq:cc
-% }
+% \begin{function}[updated = 2012-05-08]{\fp_const:Nn, \fp_const:cn}
% \begin{syntax}
-% \cs{fp_set_eq:NN} \meta{fp var1} \meta{fp var2}
+% \cs{fp_const:Nn} \meta{fp~var} \Arg{floating point expression}
% \end{syntax}
-% Sets the value of \meta{floating point variable1} equal to that of
-% \meta{floating point variable2}.
+% Creates a new constant \meta{fp~var} or raises an error if the name
+% is already taken. The \meta{fp~var} will be set globally equal to
+% the result of evaluating the \meta{floating point expression}.
% \end{function}
%
-% \begin{function}{\fp_zero:N, \fp_zero:c, \fp_gzero:N, \fp_gzero:c}
+% \begin{function}[updated = 2012-05-08]
+% {\fp_zero:N, \fp_zero:c, \fp_gzero:N, \fp_gzero:c}
% \begin{syntax}
-% \cs{fp_zero:N} \meta{floating point variable}
+% \cs{fp_zero:N} \meta{fp~var}
% \end{syntax}
-% Sets the \meta{floating point variable} to |+0.000000000e0|.
+% Sets the \meta{fp~var} to~$+0$.
% \end{function}
%
-% \begin{function}[added = 2012-01-07]
+% \begin{function}[updated = 2012-05-08]
% {\fp_zero_new:N, \fp_zero_new:c, \fp_gzero_new:N, \fp_gzero_new:c}
% \begin{syntax}
-% \cs{fp_zero_new:N} \meta{floating point variable}
+% \cs{fp_zero_new:N} \meta{fp~var}
% \end{syntax}
-% Ensures that the \meta{floating point variable} exists globally
+% Ensures that the \meta{fp~var} exists globally
% by applying \cs{fp_new:N} if necessary, then applies
-% \cs{fp_(g)zero:N} to leave the \meta{floating point variable}
-% set to zero.
+% \cs{fp_(g)zero:N} to leave the \meta{fp~var} set to zero.
% \end{function}
%
-% \begin{function}{\fp_set:Nn, \fp_set:cn, \fp_gset:Nn, \fp_gset:cn}
+% \section{Setting floating point variables}
+%
+% \begin{function}[updated = 2012-05-08]
+% {\fp_set:Nn, \fp_set:cn, \fp_gset:Nn, \fp_gset:cn}
% \begin{syntax}
-% \cs{fp_set:Nn} \meta{floating point variable} \Arg{value}
+% \cs{fp_set:Nn} \meta{fp~var} \Arg{floating point expression}
% \end{syntax}
-% Sets the \meta{floating point variable} variable to \meta{value}.
+% Sets \meta{fp~var} equal to the result of computing the
+% \meta{floating point expression}.
% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-05-08]
% {
-% \fp_set_from_dim:Nn, \fp_set_from_dim:cn,
-% \fp_gset_from_dim:Nn, \fp_gset_from_dim:cn
+% \fp_set_eq:NN , \fp_set_eq:cN , \fp_set_eq:Nc , \fp_set_eq:cc ,
+% \fp_gset_eq:NN, \fp_gset_eq:cN, \fp_gset_eq:Nc, \fp_gset_eq:cc
% }
% \begin{syntax}
-% \cs{fp_set_from_dim:Nn} \meta{floating point variable} \Arg{dimexpr}
+% \cs{fp_set_eq:NN} \meta{fp~var_1} \meta{fp~var_2}
% \end{syntax}
-% Sets the \meta{floating point variable} to the distance represented
-% by the \meta{dimension expression} in the units points. This means
-% that distances given in other units are first converted to points
-% before being assigned to the \meta{floating point variable}.
+% Sets the floating point variable \meta{fp~var_1} equal to the current
+% value of \meta{fp~var_2}.
% \end{function}
%
-% \begin{function}[rEXP]{\fp_use:N, \fp_use:c}
+% \begin{function}[updated = 2012-05-08]
+% {\fp_add:Nn, \fp_add:cn, \fp_gadd:Nn, \fp_gadd:cn}
% \begin{syntax}
-% \cs{fp_use:N} \meta{floating point variable}
+% \cs{fp_add:Nn} \meta{fp~var} \Arg{floating point expression}
% \end{syntax}
-% Inserts the value of the \meta{floating point variable} into the
-% input stream. The value will be given as a real number without any
-% exponent part, and will always include a decimal point. For example,
-% \begin{verbatim}
-% \fp_new:Nn \test
-% \fp_set:Nn \test { 1.234 e 5 }
-% \fp_use:N \test
-% \end{verbatim}
-% will insert |12345.00000| into the input stream.
-% As illustrated, a floating point will always be inserted with ten
-% significant digits given. Very large and very small values will
-% include additional zeros for place value.
+% Adds the result of computing the \meta{floating point expression} to
+% the \meta{fp~var}.
% \end{function}
%
-% \begin{function}{\fp_show:N, \fp_show:c}
+% \begin{function}[updated = 2012-05-08]
+% {\fp_sub:Nn, \fp_sub:cn, \fp_gsub:Nn, \fp_gsub:cn}
% \begin{syntax}
-% \cs{fp_show:N} \meta{floating point variable}
+% \cs{fp_sub:Nn} \meta{fp~var} \Arg{floating point expression}
% \end{syntax}
-% Displays the content of the \meta{floating point variable} on the
-% terminal.
+% Subtracts the result of computing the \meta{floating point
+% expression} from the \meta{fp~var}.
% \end{function}
%
-% \begin{function}[EXP, pTF, added=2012-03-03]{\fp_if_exist:N, \fp_if_exist:c}
+% \section{Using floating point numbers}
+%
+% \begin{function}[EXP, added = 2012-05-08, updated = 2012-07-08]{\fp_eval:n}
% \begin{syntax}
-% \cs{fp_if_exist_p:N} \meta{fp~var}
-% \cs{fp_if_exist:NTF} \meta{fp~var} \Arg{true code} \Arg{false code}
+% \cs{fp_eval:n} \Arg{floating point expression}
% \end{syntax}
-% Tests whether the \meta{fp~var} is currently defined. This does not
-% check that the \meta{fp~var} really is a floating point variable.
+% Evaluates the \meta{floating point expression} and expresses the
+% result as a decimal number with~$16$ significant figures and no
+% exponent. Leading or trailing zeros may be inserted to compensate
+% for the exponent. Non-significant trailing zeros are trimmed, and
+% integers are expressed without a decimal separator. The values
+% $\pm\infty$ and \texttt{nan} trigger an \enquote{invalid operation}
+% exception. This function is identical to \cs{fp_to_decimal:n}.
% \end{function}
%
-% \section{Conversion of floating point values to other formats}
-%
-% It is useful to be able to convert floating point variables to
-% other forms. These functions are expandable, so that the material
-% can be used in a variety of contexts. The \cs{fp_use:N} function
-% should also be consulted in this context, as it will insert the
-% value of the floating point variable as a real number.
-%
-% \begin{function}[rEXP]{\fp_to_dim:N, \fp_to_dim:c}
+% \begin{function}[EXP, added = 2012-05-08, updated = 2012-07-08]
+% {\fp_to_decimal:N, \fp_to_decimal:c, \fp_to_decimal:n}
% \begin{syntax}
-% \cs{fp_to_dim:N} \meta{floating point variable}
+% \cs{fp_to_decimal:N} \meta{fp~var}
+% \cs{fp_to_decimal:n} \Arg{floating point expression}
% \end{syntax}
-% Inserts the value of the \meta{floating point variable}
-% into the input stream converted into a dimension in points.
+% Evaluates the \meta{floating point expression} and expresses the
+% result as a decimal number with $16$ significant figures and no
+% exponent. Leading or trailing zeros may be inserted to compensate
+% for the exponent. Non-significant trailing zeros are trimmed, and
+% integers are expressed without a decimal separator. The values
+% $\pm\infty$ and \texttt{nan} trigger an \enquote{invalid operation}
+% exception.
% \end{function}
%
-% \begin{function}[rEXP]{\fp_to_int:N, \fp_to_int:c}
+% \begin{function}[EXP, updated = 2012-07-08]
+% {\fp_to_dim:N, \fp_to_dim:c, \fp_to_dim:n}
% \begin{syntax}
-% \cs{fp_to_int:N} \meta{floating point variable}
+% \cs{fp_to_dim:N} \meta{fp~var}
+% \cs{fp_to_dim:n} \Arg{floating point expression}
% \end{syntax}
-% Inserts the integer value of the \meta{floating point variable}
-% into the input stream. The decimal part of the number will not be
-% included, but will be used to round the integer.
+% Evaluates the \meta{floating point expression} and expresses the
+% result as a dimension (in \texttt{pt}) suitable for use in dimension
+% expressions. The output is identical to \cs{fp_to_decimal:n}, with
+% an additional trailing \texttt{pt}. In particular, floating point
+% numbers outside the range $[- 2^{14} + 2^{-17}, 2^{14} - 2^{-17}]$
+% overflow \TeX{}'s maximum dimension. The values $\pm\infty$ and
+% \texttt{nan} trigger an \enquote{invalid operation} exception.
% \end{function}
%
-% \begin{function}[rEXP]{\fp_to_tl:N, \fp_to_tl:c}
+% \begin{function}[EXP, updated = 2012-07-08]
+% {\fp_to_int:N, \fp_to_int:c, \fp_to_int:n}
% \begin{syntax}
-% \cs{fp_to_tl:N} \meta{floating point variable}
+% \cs{fp_to_int:N} \meta{fp~var}
+% \cs{fp_to_int:n} \Arg{floating point expression}
% \end{syntax}
-% Inserts a representation of the \meta{floating point variable} into
-% the input stream as a token list. The representation follows the
-% conventions of a pocket calculator:
-% \begin{center}
-% \ttfamily
-% \begin{tabular}{r@{.}lr@{.}l}
-% \toprule
-% \multicolumn{2}{l}{\rmfamily{Floating point value}} &
-% \multicolumn{2}{l}{\rmfamily{Representation}} \\
-% \midrule
-% 1 & 234000000000e0 & 1 & 234 \\
-% -1 & 234000000000e0 & -1 & 234 \\
-% 1 & 234000000000e3 & \multicolumn{2}{l}{1234} \\
-% 1 & 234000000000e13 & \multicolumn{2}{l}{1234e13} \\
-% 1 & 234000000000e-1 & 0 & 1234 \\
-% 1 & 234000000000e-2 & 0 & 01234 \\
-% 1 & 234000000000e-3 & 1 & 234e-3 \\
-% \bottomrule
-% \end{tabular}
-% \end{center}
-% Notice that trailing zeros are removed in this process, and that
-% numbers which do not require a decimal part do \emph{not} include
-% a decimal marker.
+% Evaluates the \meta{floating point expression}, and rounds the
+% result to the closest integer, with ties rounded to an even integer.
+% The result may be outside the range $[- 2^{31} + 1, 2^{31} - 1]$ of
+% valid \TeX{} integers, triggering \TeX{} errors if used in an
+% integer expression. The values $\pm\infty$ and \texttt{nan} trigger
+% an \enquote{invalid operation} exception.
% \end{function}
%
-% \section{Rounding floating point values}
-%
-% The module can round floating point values to either decimal places
-% or significant figures using the usual method in which exact halves
-% are rounded up.
+% \begin{function}[EXP, added = 2012-05-08, updated = 2012-07-08]
+% {\fp_to_scientific:N, \fp_to_scientific:c, \fp_to_scientific:n}
+% \begin{syntax}
+% \cs{fp_to_scientific:N} \meta{fp~var}
+% \cs{fp_to_scientific:n} \Arg{floating point expression}
+% \end{syntax}
+% Evaluates the \meta{floating point expression} and expresses the
+% result in scientific notation with $16$ significant figures:
+% \begin{quote}
+% \meta{optional \texttt{-}}\meta{digit}\texttt{.}\meta{15 digits}\texttt{e}\meta{optional sign}\meta{exponent}
+% \end{quote}
+% The leading \meta{digit} is non-zero except in the case of $\pm 0$.
+% The values $\pm\infty$ and \texttt{nan} trigger an \enquote{invalid
+% operation} exception.
+% \end{function}
%
-% \begin{function}
-% {
-% \fp_round_figures:Nn, \fp_round_figures:cn,
-% \fp_ground_figures:Nn, \fp_ground_figures:cn
-% }
+% \begin{function}[EXP, updated = 2012-07-08]
+% {\fp_to_tl:N, \fp_to_tl:c, \fp_to_tl:n}
% \begin{syntax}
-% \cs{fp_round_figures:Nn} \meta{floating point variable} \Arg{target}
+% \cs{fp_to_tl:N} \meta{fp~var}
+% \cs{fp_to_tl:n} \Arg{floating point expression}
% \end{syntax}
-% Rounds the \meta{floating point variable} to the \meta{target} number
-% of significant figures (an integer expression).
+% Evaluates the \meta{floating point expression} and expresses the
+% result in (almost) the shortest possible form. Numbers greater or
+% equal to $10^{16}$, or less than $10^{-3}$ are expressed in
+% scientific notation with trailing zeros trimmed (see
+% \cs{fp_to_scientific:n}). Numbers in the range $[10^{-3},10^{16})$
+% are expressed in a decimal notation without exponent, with trailing
+% zeros trimmed, and no decimal separator for integer values (see
+% \cs{fp_to_decimal:n}. The special values $\pm 0$, $\pm \inf$ and
+% \texttt{nan} are rendered as |0|, |-0|, \texttt{inf}, \texttt{-inf},
+% and \texttt{nan} respectively.
% \end{function}
%
-% \begin{function}
-% {
-% \fp_round_places:Nn, \fp_round_places:cn,
-% \fp_ground_places:Nn, \fp_ground_places:cn
-% }
+% \begin{function}[EXP, updated = 2012-07-08]{\fp_use:N, \fp_use:c}
% \begin{syntax}
-% \cs{fp_round_places:Nn} \meta{floating point variable} \Arg{target}
+% \cs{fp_use:N} \meta{fp~var}
% \end{syntax}
-% Rounds the \meta{floating point variable} to the \meta{target} number
-% of decimal places (an integer expression).
+% Inserts the value of the \meta{fp~var} into the input stream as a
+% decimal number with $16$ significant figures and no exponent.
+% Leading or trailing zeros may be inserted to compensate for the
+% exponent. Non-significant trailing zeros are trimmed. Integers are
+% expressed without a decimal separator. The values $\pm\infty$ and
+% \texttt{nan} trigger an \enquote{invalid operation} exception. This
+% function is identical to \cs{fp_to_decimal:N}.
% \end{function}
%
-% \section{Floating-point conditionals}
+% \section{Floating point conditionals}
%
-% \begin{function}[EXP,pTF]{\fp_if_undefined:N}
+% \begin{function}[EXP, pTF, updated = 2012-05-08]
+% {\fp_if_exist:N, \fp_if_exist:c}
% \begin{syntax}
-% \cs{fp_if_undefined_p:N} \meta{fixed-point} \\
-% \cs{fp_if_undefined:NTF} \meta{fixed-point} \Arg{true code} \Arg{false code}
+% \cs{fp_if_exist_p:N} \meta{fp~var}
+% \cs{fp_if_exist:NTF} \meta{fp~var} \Arg{true code} \Arg{false code}
% \end{syntax}
-% Tests if \meta{floating point} is undefined (\emph{i.e.}~equal to the
-% special \cs{c_undefined_fp} variable).
+% Tests whether the \meta{fp~var} is currently defined. This does not
+% check that the \meta{fp~var} really is a floating point variable.
% \end{function}
%
-% \begin{function}[EXP,pTF]{\fp_if_zero:N}
+% \begin{function}[EXP, pTF, updated = 2012-05-08]
+% {\fp_compare:nNn, \fp_compare:n}
% \begin{syntax}
-% \cs{fp_if_zero_p:N} \meta{fixed-point}
-% \cs{fp_if_zero:NTF} \meta{fixed-point} \Arg{true code} \Arg{false code}
+% \cs{fp_compare_p:nNn} \Arg{fpexpr_1} \meta{relation} \Arg{fpexpr_2}
+% \cs{fp_compare:nNnTF} \Arg{fpexpr_1} \meta{relation} \Arg{fpexpr_2} \Arg{true code} \Arg{false code}
+% \cs{fp_compare_p:n} \{ \meta{fpexpr_1} \meta{relation} \meta{fpexpr_2} \}
+% \cs{fp_compare:nTF} \{ \meta{fpexpr_1} \meta{relation} \meta{fpexpr_2} \} \Arg{true code} \Arg{false code}
% \end{syntax}
-% Tests if \meta{floating point} is equal to zero (\emph{i.e.}~equal to
-% the special \cs{c_zero_fp} variable).
+% Compares the \meta{fpexpr_1} and the \meta{fpexpr_2}, and returns
+% \texttt{true} if the \meta{relation} is obeyed. Two floating point
+% numbers $x$ and $y$ may obey four mutually exclusive relations:
+% $x<y$, $x=y$, $x>y$, or $x$ and $y$ are not ordered. The latter
+% case occurs exactly when one of the operands is \texttt{nan}, and
+% this relations is denoted by the symbol |?|. The \texttt{nNn}
+% functions support the \meta{relations} |<|, |=|, |>|, and |?|. The
+% \texttt{n} functions support as a \meta{relation} any combination of
+% those four symbols, plus an optional leading |!| (which negates the
+% \meta{relation}), with the restriction that the \meta{relation} may
+% not start with |?|. Common choices of \meta{relation} include |>=|
+% (greater or equal), |!=| (not equal), |!?| (comparable). Note that
+% a \texttt{nan} is distinct from any value, even another
+% \texttt{nan}, hence $x=x$ is not true for a \texttt{nan}. Thus to
+% test if a value is \texttt{nan}, use
+% \begin{verbatim}
+% \fp_compare:nNnTF { <value> } != { <value> }
+% { } % <value> is nan
+% { } % <value> is not nan
+% \end{verbatim}
% \end{function}
%
-% \begin{function}[TF]{\fp_compare:nNn}
+% \section{Some useful constants, and scratch variables}
+%
+% \begin{variable}[added = 2012-05-08]{\c_zero_fp, \c_minus_zero_fp}
+% Zero, with either sign.
+% \end{variable}
+%
+% \begin{variable}[added = 2012-05-08]{\c_inf_fp, \c_minus_inf_fp}
+% Infinity, with either sign. These can be input directly in a
+% floating point expression as \texttt{inf} and \texttt{-inf}.
+% \end{variable}
+%
+% \begin{variable}[updated = 2012-05-08]{\c_e_fp}
+% The value of the base of the natural logarithm, $\mathrm{e} = \exp(1)$.
+% \end{variable}
+%
+% \begin{variable}[updated = 2012-05-08]{\c_pi_fp}
+% The value of $\pi$. This can be input directly in a floating point
+% expression as \texttt{pi}. The value is rounded in a slightly odd
+% way, to ensure for instance that \texttt{sin(pi)} yields an exact $0$.
+% \end{variable}
+%
+% \begin{variable}[added = 2012-05-08]{\c_one_degree_fp}
+% The value of $1^{\circ}$ in radians. Multiply an angle given in
+% degrees by this value to obtain a result in radians, suitable to be
+% used for trigonometric functions. Within floating point
+% expressions, this can be accessed by \texttt{deg}.
+% \end{variable}
+%
+% \begin{variable}{\l_tmpa_fp, \l_tmpb_fp}
+% Scratch floating points for local assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \begin{variable}{\g_tmpa_fp, \g_tmpb_fp}
+% Scratch floating points for global assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \section{Floating point exceptions}
+% \label{sec:fp-exceptions}
+%^^A todo: redoc
+%
+% \enquote{Exceptions} may occur when performing some floating point
+% operations, such as \texttt{0 / 0}, or \texttt{10 ** 1e9999}. The
+% \textsc{IEEE} standard defines $5$ types of exceptions.
+% \begin{itemize}
+% \item \emph{Overflow} occurs whenever the result of an operation is
+% too large to be represented as a normal floating point number. This
+% results in $\pm \infty$.
+% \item \emph{Underflow} occurs whenever the result of an operation is
+% too close to $0$ to be represented as a normal floating point
+% number. This results in $\pm 0$.
+% \item \emph{Invalid operation} occurs for operations with no defined
+% outcome, for instance $0/0$, or $\sin(\infty)$, and almost any
+% operation involving a \nan{}. This results in a \nan{}.
+% \item \emph{Division by zero} occurs when dividing a non-zero number
+% by $0$, or when evaluating \emph{e.g.}, $\ln(0)$ or $\cot(0)$. This
+% results in $\pm\infty$.
+% \item \emph{Inexact} occurs whenever the result of a computation is
+% not exact, in other words, almost always. This exception is
+% entirely ignored in \LaTeX3.
+% \end{itemize}
+% To each exception is associated a \enquote{flag}, which can be either
+% \emph{on} or \emph{off}. By default, when an exception occurs, the
+% corresponding flag is turned on. The state of the flag can be tested
+% and modified. The behaviour when an exception occurs can be modified
+% (using \cs{fp_trap:nn}) to either produce an error and turn the flag
+% on, or only turn the flag on, or do nothing at all.
+%
+% \begin{function}[EXP, pTF, added = 2012-05-28]{\fp_if_flag_on:n}
% \begin{syntax}
-% \cs{fp_compare:nNnTF}
-% ~~\Arg{floating point1} \meta{relation} \Arg{floating point2}
-% ~~\Arg{true code} \Arg{false code}
+% \cs{fp_if_flag_on_p:n} \Arg{exception}
+% \cs{fp_if_flag_on:nTF} \Arg{exception} \Arg{true code} \Arg{false code}
% \end{syntax}
-% This function compared the two \meta{floating point} values, which
-% may be stored as \texttt{fp} variables, using the \meta{relation}:
-% \begin{center}
-% \begin{tabular}{ll}
-% Equal & |=| \\
-% Greater than & |>| \\
-% Less than & |<| \\
-% \end{tabular}
-% \end{center}
-% The tests treat undefined floating points as
-% zero as the comparison is intended for real numbers only.
+% Tests if the flag for the \meta{exception} is on, which normally
+% means the given \meta{exception} has occurred.
% \end{function}
%
-% \begin{function}[TF]{\fp_compare:n}
+% \begin{function}[added = 2012-05-28]{\fp_flag_off:n}
% \begin{syntax}
-% \cs{fp_compare:nTF}
-% ~~\{ \meta{floating point1} \meta{relation} \meta{floating point2} \}
-% ~~\Arg{true code} \Arg{false code}
+% \cs{fp_flag_off:n} \Arg{exception}
% \end{syntax}
-% This function compared the two \meta{floating point} values, which
-% may be stored as \texttt{fp} variables, using the \meta{relation}:
-% \begin{center}
-% \begin{tabular}{ll}
-% Equal & |=| or |==| \\
-% Greater than & |>| \\
-% Greater than or equal & |>=| \\
-% Less than & |<| \\
-% Less than or equal & |<=| \\
-% Not equal & |!=| \\
-% \end{tabular}
-% \end{center}
-% The tests treat undefined floating points as
-% zero as the comparison is intended for real numbers only.
+% Locally turns off the flag which indicates whether the
+% \meta{exception} has occurred.
% \end{function}
%
-% \section{Unary floating-point operations}
-%
-% The unary operations alter the value stored within an \texttt{fp}
-% variable.
+% \begin{function}[EXP, added = 2012-05-28]{\fp_flag_on:n}
+% \begin{syntax}
+% \cs{fp_flag_on:n} \Arg{exception}
+% \end{syntax}
+% Locally turns on the flag to indicate (or pretend) that the
+% \meta{exception} has occurred. Note that this function is
+% expandable: it is used internally by \pkg{l3fp} to signal when
+% exceptions do occur.
+% \end{function}
%
-% \begin{function}{\fp_abs:N, \fp_abs:c, \fp_gabs:N, \fp_gabs:c}
+% \begin{function}[added = 2012-05-28]{\fp_trap:nn}
% \begin{syntax}
-% \cs{fp_abs:N} \meta{floating point variable}
+% \cs{fp_trap:nn} \Arg{exception} \Arg{trap type}
% \end{syntax}
-% Converts the \meta{floating point variable} to its absolute value.
+% All occurrences of the \meta{exception} (\texttt{invalid_operation},
+% \texttt{division_by_zero}, \texttt{overflow}, or \texttt{underflow})
+% within the current group are treated as \meta{trap type}, which can
+% be
+% \begin{itemize}
+% \item \texttt{none}: the \meta{exception} will be entirely
+% ignored, and leave no trace;
+% \item \texttt{flag}: the \meta{exception} will turn the
+% corresponding flag on when it occurs;
+% \item \texttt{error}: additionally, the \meta{exception} will halt
+% the \TeX{} run and display some information about the current
+% operation in the terminal.
+% \end{itemize}
% \end{function}
%
-% \begin{function}{\fp_neg:N, \fp_neg:c, \fp_gneg:N, \fp_gneg:c}
+% \section{Floating point expressions}
+%
+% \begin{function}[added = 2012-05-08, updated = 2012-05-27]
+% {\fp_show:N, \fp_show:c, \fp_show:n}
% \begin{syntax}
-% \cs{fp_neg:N} \meta{floating point variable}
+% \cs{fp_show:N} \meta{fp~var}
+% \cs{fp_show:n} \Arg{floating point expression}
% \end{syntax}
-% Reverse the sign of the \meta{floating point variable}.
+% Evaluates the \meta{floating point expression} and displays the
+% result in the terminal.
% \end{function}
%
-% \section{Floating-point arithmetic}
+% \subsection{Input of floating point numbers} \label{sec:fp-floats}
%
-% Binary arithmetic operations act on the value stored in an
-% \texttt{fp}, so for example
-% \begin{verbatim}
-% \fp_set:Nn \l_my_fp { 1.234 }
-% \fp_sub:Nn \l_my_fp { 5.678 }
-% \end{verbatim}
-% sets \cs{l_my_fp} to the result of $1.234 - 5.678$
-% (\emph{i.e.}~$-4.444$).
+%^^A todo: write a grammar
+%^^A todo: clarify what has changed compared to the previous l3fp
+%
+% We support four types of floating point numbers:
+% \begin{itemize}
+% \item $\pm 0.d_1d_2\ldots{}d_{16} \cdot 10^{n}$, a normal floating
+% point number, with $d_i\in [0,9]$, $d_1\neq 0$, and $\lvert n\rvert
+% \leq \ExplSyntaxOn \int_use:N \c__fp_max_exponent_int$;
+% \item $\pm 0$, zero, with a given sign;
+% \item $\pm \infty$, infinity, with a given sign;
+% \item \texttt{nan}, is \enquote{not a number}, and can be either quiet
+% or signalling (\emph{not yet}: this distinction is currently
+% unsupported);
+% \item [\emph{not yet}] subnormal numbers $\pm 0.d_1d_2\ldots{}d_{16}
+% \cdot 10^{-\ExplSyntaxOn\int_use:N \c__fp_max_exponent_int}$ with
+% $d_1=0$.
+% \end{itemize}
+% Normal floating point numbers are stored in base $10$, with $16$
+% significant figures.
+%
+% On input, a normal floating point number consists of:
+% \begin{itemize}
+% \item \meta{sign}: a possibly empty string of |+| and |-| characters;
+% \item \meta{mantissa}: a non-empty string of digits together with zero
+% or one dot;
+% \item \meta{exponent} optionally: the character |e|, followed by a
+% possibly empty string of |+|~and~|-| tokens, and a non-empty string
+% of digits.
+% \end{itemize}
+% The sign of the resulting number is |+| if \meta{sign} contains an
+% even number of |-|, and |-| otherwise, hence, an empty \meta{sign}
+% denotes a non-negative input. The stored mantissa is obtained from
+% \meta{mantissa} by omitting the decimal separator and leading zeros,
+% and rounding to $16$ significant digits, filling with trailing zeros
+% if necessary. In particular, the value stored is exact if the input
+% \meta{mantissa} has at most $16$ digits. The stored \meta{exponent}
+% is obtained by combining the input \meta{exponent} ($0$ if absent)
+% with a shift depending on the position of the mantissa and the number
+% of leading zeros.
+%
+% A special case arises if the resulting \meta{exponent} is either
+% too large or too small to be represented. This results either in an
+% overflow (the number is then replaced by $\pm\infty$), or an
+% underflow (resulting in $\pm 0$).
+%
+% The result is thus $\pm 0$ if and only if \meta{mantissa} contains no
+% non-zero digit (\emph{i.e.}, consists only in~|0| characters, and an
+% optional |.| character), or there is an underflow. Note that a single
+% dot is currently a valid floating point number, equal to~$+0$, but
+% that is not guaranteed to remain the case.
+%
+% Special numbers are input as follows:
+% \begin{itemize}
+% \item \texttt{inf} represents $+\infty$, and can be preceded by any
+% \meta{sign}.
+% \item \texttt{nan} represents a (quiet) non-number. It can be preceded
+% by any sign, but that will be ignored.
+% \item Any unrecognisable string will yield a signalling \texttt{nan}.
+% \end{itemize}
+%
+% Note that~|e-1| is not a representation of $10^{-1}$, because it
+% could be mistaken with the difference of \enquote{\texttt{e}} and
+% $1$. This is consistent with several other programming languages.
+% However, in order to avoid confusions, |e-1| is not considered to
+% be this difference either. To input the base of natural logarithms,
+% use \texttt{exp(1)} or \cs{c_e_fp}.
+%
+% \subsection{Precedence of operators}
+% \label{sec:fp-precedence}
+%
+% ^^A List "juxtaposition" somewhere in the list.
%
-% \begin{function}{\fp_add:Nn, \fp_add:cn, \fp_gadd:Nn, \fp_gadd:cn}
+% We list here all the operations supported in floating point
+% expressions, in order of decreasing precedence: operations listed
+% earlier bind more tightly than operations listed below them.
+% \begin{itemize}
+% \item Implicit multiplication by juxtaposition (\texttt{2pi}, \emph{etc}).
+% \item Function calls (\texttt{sin}, \texttt{ln}, \emph{etc}).
+% \item Binary |**| and |^| (right associative).
+% \item Unary |+|, |-|, |!|.
+% \item Binary |*|, |/| and |%|.
+% \item Binary |+| and |-|.
+% \item Comparisons |>=|, |!=|, |<?|, \emph{etc}.
+% \item Logical \texttt{and}, denoted by |&&|.
+% \item Logical \texttt{or}, denoted by \verb*+||+.
+% \item Ternary operator |?:| (right associative).
+% \end{itemize}
+% The precedence of operations can be overridden using parentheses.
+% In particular, those precedences imply that
+% \begin{align*}
+% \mathtt{sin 2pi} & = \sin(2\pi) = 0, \\
+% \mathtt{2\char`\^2max(3,4)} & = 2^{2 \max(3,4)} = 256.
+% \end{align*}
+% Functions are called on the value of their argument, contrarily to
+% \TeX{} macros.
+%
+% \subsection{Operations} \label{sec:fp-operations}
+%
+% We now present the various operations allowed in floating point
+% expressions. When used as a truth value, a floating point expression
+% is \texttt{false} if it is $\pm 0$, and \texttt{false} otherwise.
+%
+% The exceptions listed below are mostly not implemented yet. ^^A todo:
+%
+% \begin{function}{?:}
% \begin{syntax}
-% \cs{fp_add:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ \meta{operand_1} |?| \meta{operand_2} |:| \meta{operand_3} \}
% \end{syntax}
-% Adds the \meta{value} to the \meta{floating point}.
+% The ternary operator |?:| results in \meta{operand_2} if
+% \meta{operand_1} is true, and \meta{operand_3} if it is false (equal to
+% $\pm 0$). All three \meta{operands} are evaluated in all cases. The
+% operator is right associative, hence
+% \begin{verbatim}
+% \fp_eval:n
+% {
+% 1 + 3 > 4 ? 1 :
+% 2 + 4 > 5 ? 2 :
+% 3 + 5 > 6 ? 3 : 4
+% }
+% \end{verbatim}
+% first tests whether $1 + 3 > 4$; since this isn't true, the branch
+% following |:| is taken, and $2 + 4 > 5$ is compared; since this is
+% true, the branch before |:| is taken, and everything else is
+% (evaluated then) ignored. That allows testing for various cases in
+% a concise manner, with the drawback that all computations are made
+% in all cases.
% \end{function}
%
-% \begin{function}{\fp_sub:Nn, \fp_sub:cn, \fp_gsub:Nn, \fp_gsub:cn}
+% \begingroup \catcode`\|=12
+% \begin{function}{TWO BARS} ^^A To fix
% \begin{syntax}
-% \cs{fp_sub:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ \meta{operand_1} \texttt{||} \meta{operand_2} \}
% \end{syntax}
-% Subtracts the \meta{value} from the \meta{floating point}.
+% If \meta{operand_1} is true (non-zero), use that value, otherwise the
+% value of \meta{operand_2}. Both \meta{operands} are evaluated in all
+% cases.
% \end{function}
+% \endgroup
%
-% \begin{function}{\fp_mul:Nn, \fp_mul:cn, \fp_gmul:Nn, \fp_gmul:cn}
+% \begingroup \catcode`\&=12
+% \begin{function}{&&}
% \begin{syntax}
-% \cs{fp_mul:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ \meta{operand_1} \texttt{&&} \meta{operand_2} \}
% \end{syntax}
-% Multiples the \meta{floating point} by the \meta{value}.
+% If \meta{operand_1} is false (equal to $\pm 0$), use that value,
+% otherwise the value of \meta{operand_2}. Both \meta{operands} are
+% evaluated in all cases.
% \end{function}
+% \endgroup
%
-% \begin{function}{\fp_div:Nn, \fp_div:cn, \fp_gdiv:Nn, \fp_gdiv:cn}
+% \begin{function}{\<, =, >, ?}
% \begin{syntax}
-% \cs{fp_div:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ \meta{operand_1} \meta{comparison} \meta{operand_2} \}
% \end{syntax}
-% Divides the \meta{floating point} by the \meta{value}, making the
-% assignment within the current \TeX{} group level. If the \meta{value}
-% is zero, the \meta{floating point} will be set to
-% \cs{c_undefined_fp}.
+% The \meta{comparison} consists of a non-empty string of |<|, |=|,
+% |>|, and |?|, optionally preceeded by |!|. It may not start with
+% |?|. This evaluates to $+1$ if the \meta{comparison} between the
+% \meta{operand_1} and \meta{operand_2} is true, and $+0$ otherwise.
% \end{function}
%
-% \section{Floating-point power operations}
-%
-% \begin{function}{\fp_pow:Nn, \fp_pow:cn, \fp_gpow:Nn, \fp_gpow:cn}
+% \begin{function}{+, -}
% \begin{syntax}
-% \cs{fp_pow:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ \meta{operand_1} |+| \meta{operand_2} \}
+% \cs{fp_eval:n} \{ \meta{operand_1} |-| \meta{operand_2} \}
% \end{syntax}
-% Raises the \meta{floating point} to the given \meta{value}. If the
-% \meta{floating point} is negative, then the \meta{value} should be
-% either a positive real number or a negative integer. If the
-% \meta{floating point} is positive, then the \meta{value} may be any
-% real value. Mathematically invalid operations such as $0^{0}$
-% will give set the \meta{floating point} to to \cs{c_undefined_fp}.
+% Computes the sum or the difference of its two \meta{operands}. The
+% \enquote{invalid operation} exception occurs for $\infty-\infty$.
+% \enquote{Inexact}, \enquote{underflow} and \enquote{overflow} occur
+% when appropriate.
% \end{function}
%
-% \section{Exponential and logarithm functions}
-%
-% \begin{function}{\fp_exp:Nn, \fp_exp:cn, \fp_gexp:Nn, \fp_gexp:cn}
+% \begin{function}{*, /}
% \begin{syntax}
-% \cs{fp_exp:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ \meta{operand_1} |*| \meta{operand_2} \}
+% \cs{fp_eval:n} \{ \meta{operand_1} |/| \meta{operand_2} \}
% \end{syntax}
-% Calculates the exponential of the \meta{value} and assigns this
-% to the \meta{floating point}.
+% Computes the product or the ratio of its two \meta{operands}. The
+% \enquote{invalid operation} exception occurs for $\infty/\infty$,
+% $0/0$, or $0*\infty$. \enquote{Division by zero} occurs when
+% dividing a finite non-zero number by $\pm 0$. The
+% \enquote{inexact}, \enquote{underflow} and \enquote{overflow}
+% exceptions occur when appropriate.
% \end{function}
%
-% \begin{function}{\fp_ln:Nn, \fp_ln:cn, \fp_gln:Nn, \fp_gln:cn}
+% \begin{function}{+, -, !}
% \begin{syntax}
-% \cs{fp_ln:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ |+| \meta{operand} \}
+% \cs{fp_eval:n} \{ |-| \meta{operand} \}
+% \cs{fp_eval:n} \{ |!| \meta{operand} \}
% \end{syntax}
-% Calculates the natural logarithm of the \meta{value} and assigns
-% this to the \meta{floating point}.
+% The unary |+| does nothing, the unary |-| changes the sign of the
+% \meta{operand}, and |!| \meta{operand} evaluates to $1$ if
+% \meta{operand} is false and $0$ otherwise (this is the \texttt{not}
+% boolean function).
% \end{function}
%
-% \section{Trigonometric functions}
-%
-% The trigonometric functions all work in radians. They accept a maximum
-% input value of $100\,000\,000$, as there are issues with range
-% reduction and very large input values.
-%
-% \begin{function}{\fp_sin:Nn, \fp_sin:cn, \fp_gsin:Nn, \fp_gsin:cn}
+% \begingroup\catcode`\^=12
+% \begin{function}{**, ^}
% \begin{syntax}
-% \cs{fp_sin:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ \meta{operand_1} |**| \meta{operand_2} \}
+% \cs{fp_eval:n} \{ \meta{operand_1} |^| \meta{operand_2} \}
% \end{syntax}
-% Assigns the sine of the \meta{value} to the \meta{floating point}.
-% The \meta{value} should be given in radians.
+% Raises \meta{operand_1} to the power \meta{operand_2}. This operation
+% is right associative, hence \texttt{2 ** 2 ** 3} equals
+% $2\sp{2\sp{3}} = 256$. The \enquote{invalid operation} exception
+% occurs if \meta{operand_1} is negative or $-0$, \meta{operand_2} is
+% not an integer, and the result is non-zero. \enquote{Division by
+% zero} occurs \emph{not yet}. The \enquote{inexact},
+% \enquote{underflow} and \enquote{overflow} exceptions occur when
+% appropriate.
% \end{function}
+% \endgroup
%
-% \begin{function}{\fp_cos:Nn, \fp_cos:cn, \fp_gcos:Nn, \fp_gcos:cn}
+% \begin{function}{abs}
% \begin{syntax}
-% \cs{fp_cos:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ |abs(| \meta{fpexpr} |)| \}
% \end{syntax}
-% Assigns the cosine of the \meta{value} to the \meta{floating point}.
-% The \meta{value} should be given in radians.
+% Computes the absolute value of the \meta{fpexpr}. This function
+% never raises an exception when \meta{fpexpr} is a number.
% \end{function}
%
-% \begin{function}{\fp_tan:Nn, \fp_tan:cn, \fp_gtan:Nn, \fp_gtan:cn}
+% \begin{function}{exp}
% \begin{syntax}
-% \cs{fp_tan:Nn} \meta{floating point} \Arg{value}
+% \cs{fp_eval:n} \{ |exp(| \meta{fpexpr} |)| \}
% \end{syntax}
-% Assigns the tangent of the \meta{value} to the \meta{floating point}.
-% The \meta{value} should be given in radians.
+% Computes the exponential of the \meta{fpexpr}. The
+% \enquote{inexact}, \enquote{underflow} and \enquote{overflow}
+% exceptions occur when appropriate.
% \end{function}
%
-% \section{Constant floating point values}
-%
-% \begin{variable}{\c_e_fp}
-% The value of the base of natural numbers, $\mathrm{e}$.
-% \end{variable}
-%
-% \begin{variable}{\c_one_fp}
-% A floating point variable with permanent value $1$: used for
-% speeding up some comparisons.
-% \end{variable}
-%
-% \begin{variable}{\c_pi_fp}
-% The value of $\pi$.
-% \end{variable}
-%
-% \begin{variable}{\c_undefined_fp}
-% A special marker floating point variable representing the result of
-% an operation which does not give a defined result (such as division
-% by $0$).
-% \end{variable}
-%
-% \begin{variable}{\c_zero_fp}
-% A permanently zero floating point variable.
-% \end{variable}
-%
-% \section{Notes on the floating point unit}
-%
-% As calculation of the elemental transcendental functions is
-% computationally expensive compared to storage of results, after
-% calculating a trigonometric function, exponent, \emph{etc.}~the module
-% stored the result for reuse. Thus the performance of the module for
-% repeated operations, most probably trigonometric functions, should be
-% much higher than if the values were re-calculated every time they
-% were needed.
-%
-% Anyone with experience of programming floating point calculations will
-% know that this is a complex area. The aim of the unit is to be
-% accurate enough for the likely applications in a typesetting context.
-% The arithmetic operations are therefore intended to provide ten digit
-% accuracy with the last digit accurate to $\pm 1$. The elemental
-% transcendental functions may not provide such high accuracy in every
-% case, although the design aim has been to provide $10$ digit
-% accuracy for cases likely to be relevant in typesetting situations.
-% A good overview of the challenges in this area can be found in
-% J.-M.~Muller, \emph{Elementary functions: algorithms and
-% implementation}, 2nd edition, Birkh{\"{a}}uer Boston, New York, USA,
-% 2006.
-%
-% The internal representation of numbers is tuned to the needs of the
-% underlying \TeX{} system. This means that the format is somewhat
-% different from that used in, for example, computer floating point
-% units. Programming in \TeX{} makes it most convenient to use a
-% radix $10$ system, using \TeX{} \texttt{count} registers for
-% storage and taking advantage where possible of delimited arguments.
-%
-% \end{documentation}
-%
-% \begin{implementation}
-%
-% \section{\pkg{l3fp} Implementation}
-%
-% \TestFiles{m3fp003.lvt}
-%
-% \begin{macrocode}
-%<*initex|package>
-% \end{macrocode}
-%
-% \begin{macrocode}
-%<*package>
-\ProvidesExplPackage
- {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
-%</package>
-% \end{macrocode}
-%
-% \subsection{Constants}
-%
-% \begin{variable}{\c_forty_four}
-% \begin{variable}{\c_one_million}
-% \begin{variable}{\c_one_hundred_million}
-% \begin{variable}{\c_five_hundred_million}
-% \begin{variable}{\c_one_thousand_million}
-% There is some speed to gain by moving numbers into fixed positions.
-% \begin{macrocode}
-\int_const:Nn \c_forty_four { 44 }
-\int_const:Nn \c_one_million { 1 000 000 }
-\int_const:Nn \c_one_hundred_million { 100 000 000 }
-\int_const:Nn \c_five_hundred_million { 500 000 000 }
-\int_const:Nn \c_one_thousand_million { 1 000 000 000 }
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\c_fp_pi_by_four_decimal_int}
-% \begin{variable}{\c_fp_pi_by_four_extended_int}
-% \begin{variable}{\c_fp_pi_decimal_int}
-% \begin{variable}{\c_fp_pi_extended_int}
-% \begin{variable}{\c_fp_two_pi_decimal_int}
-% \begin{variable}{\c_fp_two_pi_extended_int}
-% Parts of $\pi$ for trigonometric range reduction, implemented
-% as \texttt{int} variables for speed.
-% \begin{macrocode}
-\int_new:N \c_fp_pi_by_four_decimal_int
-\int_set:Nn \c_fp_pi_by_four_decimal_int { 785 398 158 }
-\int_new:N \c_fp_pi_by_four_extended_int
-\int_set:Nn \c_fp_pi_by_four_extended_int { 897 448 310 }
-\int_new:N \c_fp_pi_decimal_int
-\int_set:Nn \c_fp_pi_decimal_int { 141 592 653 }
-\int_new:N \c_fp_pi_extended_int
-\int_set:Nn \c_fp_pi_extended_int { 589 793 238 }
-\int_new:N \c_fp_two_pi_decimal_int
-\int_set:Nn \c_fp_two_pi_decimal_int { 283 185 307 }
-\int_new:N \c_fp_two_pi_extended_int
-\int_set:Nn \c_fp_two_pi_extended_int { 179 586 477 }
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\c_e_fp}
-% The value $\mathrm{e}$ as a \enquote{machine number}.
-% \begin{macrocode}
-\tl_const:Nn \c_e_fp { + 2.718281828 e 0 }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\c_one_fp}
-% The constant value $1$: used for fast comparisons.
-% \begin{macrocode}
-\tl_const:Nn \c_one_fp { + 1.000000000 e 0 }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\c_pi_fp}
-% The value $\pi$ as a \enquote{machine number}.
-% \begin{macrocode}
-\tl_const:Nn \c_pi_fp { + 3.141592654 e 0 }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\c_undefined_fp}
-% A marker for undefined values.
-% \begin{macrocode}
-\tl_const:Nn \c_undefined_fp { X 0.000000000 e 0 }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\c_zero_fp}
-% The constant zero value.
-% \begin{macrocode}
-\tl_const:Nn \c_zero_fp { + 0.000000000 e 0 }
-% \end{macrocode}
-% \end{variable}
-%
-% \subsection{Variables}
-%
-% \begin{variable}{\l_fp_arg_tl}
-% A token list to store the formalised representation of the input
-% for transcendental functions.
-% \begin{macrocode}
-\tl_new:N \l_fp_arg_tl
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_count_int}
-% A counter for things like the number of divisions possible.
-% \begin{macrocode}
-\int_new:N \l_fp_count_int
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_div_offset_int}
-% When carrying out division, an offset is used for the results to
-% get the decimal part correct.
-% \begin{macrocode}
-\int_new:N \l_fp_div_offset_int
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_exp_integer_int}
-% \begin{variable}{\l_fp_exp_decimal_int}
-% \begin{variable}{\l_fp_exp_extended_int}
-% \begin{variable}{\l_fp_exp_exponent_int}
-% Used for the calculation of exponent values.
-% \begin{macrocode}
-\int_new:N \l_fp_exp_integer_int
-\int_new:N \l_fp_exp_decimal_int
-\int_new:N \l_fp_exp_extended_int
-\int_new:N \l_fp_exp_exponent_int
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_input_a_sign_int}
-% \begin{variable}{\l_fp_input_a_integer_int}
-% \begin{variable}{\l_fp_input_a_decimal_int}
-% \begin{variable}{\l_fp_input_a_exponent_int}
-% \begin{variable}{\l_fp_input_b_sign_int}
-% \begin{variable}{\l_fp_input_b_integer_int}
-% \begin{variable}{\l_fp_input_b_decimal_int}
-% \begin{variable}{\l_fp_input_b_exponent_int}
-% Storage for the input: two storage areas as there are at most two
-% inputs.
-% \begin{macrocode}
-\int_new:N \l_fp_input_a_sign_int
-\int_new:N \l_fp_input_a_integer_int
-\int_new:N \l_fp_input_a_decimal_int
-\int_new:N \l_fp_input_a_exponent_int
-\int_new:N \l_fp_input_b_sign_int
-\int_new:N \l_fp_input_b_integer_int
-\int_new:N \l_fp_input_b_decimal_int
-\int_new:N \l_fp_input_b_exponent_int
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_input_a_extended_int}
-% \begin{variable}{\l_fp_input_b_extended_int}
-% For internal use, \enquote{extended} floating point numbers are
-% needed.
-% \begin{macrocode}
-\int_new:N \l_fp_input_a_extended_int
-\int_new:N \l_fp_input_b_extended_int
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_mul_a_i_int}
-% \begin{variable}{\l_fp_mul_a_ii_int}
-% \begin{variable}{\l_fp_mul_a_iii_int}
-% \begin{variable}{\l_fp_mul_a_iv_int}
-% \begin{variable}{\l_fp_mul_a_v_int}
-% \begin{variable}{\l_fp_mul_a_vi_int}
-% \begin{variable}{\l_fp_mul_b_i_int}
-% \begin{variable}{\l_fp_mul_b_ii_int}
-% \begin{variable}{\l_fp_mul_b_iii_int}
-% \begin{variable}{\l_fp_mul_b_iv_int}
-% \begin{variable}{\l_fp_mul_b_v_int}
-% \begin{variable}{\l_fp_mul_b_vi_int}
-% Multiplication requires that the decimal part is split into parts
-% so that there are no overflows.
-% \begin{macrocode}
-\int_new:N \l_fp_mul_a_i_int
-\int_new:N \l_fp_mul_a_ii_int
-\int_new:N \l_fp_mul_a_iii_int
-\int_new:N \l_fp_mul_a_iv_int
-\int_new:N \l_fp_mul_a_v_int
-\int_new:N \l_fp_mul_a_vi_int
-\int_new:N \l_fp_mul_b_i_int
-\int_new:N \l_fp_mul_b_ii_int
-\int_new:N \l_fp_mul_b_iii_int
-\int_new:N \l_fp_mul_b_iv_int
-\int_new:N \l_fp_mul_b_v_int
-\int_new:N \l_fp_mul_b_vi_int
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_mul_output_int}
-% \begin{variable}{\l_fp_mul_output_tl}
-% Space for multiplication results.
-% \begin{macrocode}
-\int_new:N \l_fp_mul_output_int
-\tl_new:N \l_fp_mul_output_tl
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_output_sign_int}
-% \begin{variable}{\l_fp_output_integer_int}
-% \begin{variable}{\l_fp_output_decimal_int}
-% \begin{variable}{\l_fp_output_exponent_int}
-% Output is stored in the same way as input.
-% \begin{macrocode}
-\int_new:N \l_fp_output_sign_int
-\int_new:N \l_fp_output_integer_int
-\int_new:N \l_fp_output_decimal_int
-\int_new:N \l_fp_output_exponent_int
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_output_extended_int}
-% Again, for calculations an extended part.
-% \begin{macrocode}
-\int_new:N \l_fp_output_extended_int
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_round_carry_bool}
-% To indicate that a digit needs to be carried forward.
-% \begin{macrocode}
-\bool_new:N \l_fp_round_carry_bool
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\l_fp_round_decimal_tl}
-% A temporary store when rounding, to build up the decimal part without
-% needing to do any maths.
-% \begin{macrocode}
-\tl_new:N \l_fp_round_decimal_tl
-% \end{macrocode}
-% \end{variable}
+% \begin{function}{ln}
+% \begin{syntax}
+% \cs{fp_eval:n} \{ |ln(| \meta{fpexpr} |)| \}
+% \end{syntax}
+% Computes the natural logarithm of the \meta{fpexpr}. Negative
+% numbers have no (real) logarithm, hence the \enquote{invalid
+% operation} is raised in that case. \enquote{Division by zero}
+% occurs when evaluating the logarithm of $\pm 0$. The
+% \enquote{inexact}, \enquote{underflow} and \enquote{overflow}
+% exceptions occur when appropriate.
+% \end{function}
%
-% \begin{variable}{\l_fp_round_position_int}
-% \begin{variable}{\l_fp_round_target_int}
-% Used to check the position for rounding.
-% \begin{macrocode}
-\int_new:N \l_fp_round_position_int
-\int_new:N \l_fp_round_target_int
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
+% \begin{function}{max, min}
+% \begin{syntax}
+% \cs{fp_eval:n} \{ |max(| \meta{fpexpr_1} |,| \meta{fpexpr_2} |,| \ldots{} |)| \}
+% \cs{fp_eval:n} \{ |min(| \meta{fpexpr_1} |,| \meta{fpexpr_2} |,| \ldots{} |)| \}
+% \end{syntax}
+% Evalutes each \meta{fpexpr} and computes the largest (smallest) of
+% those. If any of the \meta{fpexpr} is a \nan{}, the result is
+% \nan{}.
+% \end{function}
%
-% \begin{variable}{\l_fp_sign_tl}
-% There are places where the sign needs to be set up \enquote{early},
-% so that the registers can be re-used.
-% \begin{macrocode}
-\tl_new:N \l_fp_sign_tl
-% \end{macrocode}
-% \end{variable}
+% \begin{function}{round, round0, round+, round-}
+% \begin{syntax}
+% \cs{fp_eval:n} \{ |round| \meta{option} |(| \meta{fpexpr} |)| \}
+% \cs{fp_eval:n} \{ |round| \meta{option} |(| \meta{fpexpr_1} , \meta{fpexpr_2} |)| \}
+% \end{syntax}
+% Rounds \meta{fpexpr_1} to \meta{fpexpr_2} places (this must be an
+% integer). When \meta{fpexpr_2} is missing, it is assumed to be $0$,
+% \emph{i.e.}, \meta{fpexpr_1} is rounded to an integer. The
+% \meta{option} controls the rounding direction:
+% \begin{itemize}
+% \item by default, the function rounds to the closest allowed number
+% (rounding ties to even);
+% \item with |0|, the function rounds towards $0$, \emph{i.e.}, truncates;
+% \item with |+|, the function rounds towards $+\infty$;
+% \item with |-|, the function rounds towards $-\infty$.
+% \end{itemize}
+% \end{function}
%
-% \begin{variable}{\l_fp_split_sign_int}
-% When splitting the input it is fastest to use a fixed name for the
-% sign part, and to transfer it after the split is complete.
-% \begin{macrocode}
-\int_new:N \l_fp_split_sign_int
-% \end{macrocode}
-% \end{variable}
+% \begin{function}{sin, cos, tan, cot}
+% \begin{syntax}
+% \cs{fp_eval:n} \{ |sin(| \meta{fpexpr} |)| \}
+% \cs{fp_eval:n} \{ |cos(| \meta{fpexpr} |)| \}
+% \cs{fp_eval:n} \{ |tan(| \meta{fpexpr} |)| \}
+% \cs{fp_eval:n} \{ |cot(| \meta{fpexpr} |)| \}
+% \end{syntax}
+% Computes the sine, cosine, tangent or cotangent of the
+% \meta{fpexpr}. The trigonometric functions are undefined for an
+% argument of $\pm\infty$, leading to the \enquote{invalid operation}
+% exception. Additionally, evaluating tangent or cotangent at one of
+% their poles leads to a \enquote{division by zero} exception. Other
+% exceptions occur when appropriate.
+% \end{function}
%
-% \begin{variable}{\l_fp_internal_int}
-% A scratch \texttt{int}: used only where the value is not carried
-% forward.
-% \begin{macrocode}
-\int_new:N \l_fp_internal_int
-% \end{macrocode}
+% \begin{variable}{inf, nan}
+% The special values $+\infty$, $-\infty$, and \nan{} are represented
+% as \texttt{inf}, \texttt{-inf} and \texttt{nan} (see \cs{c_inf_fp},
+% \cs{c_minus_inf_fp} and \cs{c_nan_fp}).
% \end{variable}
%
-% \begin{variable}{\l_fp_internal_tl}
-% A scratch token list variable for expanding material.
-% \begin{macrocode}
-\tl_new:N \l_fp_internal_tl
-% \end{macrocode}
+% \begin{variable}{pi}
+% The value of $\pi$ (see \cs{c_pi_fp}).
% \end{variable}
%
-% \begin{variable}{\l_fp_trig_octant_int}
-% To track which octant the trigonometric input is in.
-% \begin{macrocode}
-\int_new:N \l_fp_trig_octant_int
-% \end{macrocode}
+% \begin{variable}{deg}
+% The value of $1^{\circ}$ in radians (see \cs{c_one_degree_fp}).
% \end{variable}
%
-% \begin{variable}{\l_fp_trig_sign_int}
-% \begin{variable}{\l_fp_trig_decimal_int}
-% \begin{variable}{\l_fp_trig_extended_int}
-% Used for the calculation of trigonometric values.
-% \begin{macrocode}
-\int_new:N \l_fp_trig_sign_int
-\int_new:N \l_fp_trig_decimal_int
-\int_new:N \l_fp_trig_extended_int
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
+% \begin{variable}{em, ex, in, pt, pc, cm, mm, dd, cc, nd, nc, bp, sp}
+% \newcommand{\unit}[1]{\text{\texttt{#1}}}
+% Those units of measurement are equal to their values in \texttt{pt},
+% namely
+% \begin{align*}
+% 1 \unit{in} & = 72.27 \unit{pt} \\
+% 1 \unit{pt} & = 1 \unit{pt} \\
+% 1 \unit{pc} & = 12 \unit{pt} \\
+% 1 \unit{cm} & = \frac{1}{2.54} \unit{in} = 28.45275590551181 \unit{pt} \\
+% 1 \unit{mm} & = \frac{1}{25.4} \unit{in} = 2.845275590551181 \unit{pt} \\
+% 1 \unit{dd} & = 0.376065 \unit{mm} = 1.07000856496063 \unit{pt} \\
+% 1 \unit{cc} & = 12 \unit{dd} = 12.84010277952756 \unit{pt} \\
+% 1 \unit{nd} & = 0.375 \unit{mm} = 1.066978346456693 \unit{pt} \\
+% 1 \unit{nc} & = 12 \unit{nd} = 12.80374015748031 \unit{pt} \\
+% 1 \unit{bp} & = \frac{1}{72} \unit{in} = 1.00375 \unit{pt} \\
+% 1 \unit{sp} & = 2^{-16} \unit{pt} = 1.52587890625e-5 \unit{pt}.
+% \end{align*}
+% The values of the (font-dependent) units \texttt{em} and \texttt{ex}
+% are gathered from \TeX{} when the surrounding floating point
+% expression is evaluated.
% \end{variable}
%
-% \subsection{Parsing numbers}
-%
-% \begin{macro}{\fp_read:N}
-% \begin{macro}[aux]{\fp_read_aux:w}
-% Reading a stored value is made easier as the format is designed to
-% match the delimited function. This is always used to read the first
-% value (register |a|).
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_read:N #1
- { \exp_after:wN \fp_read_aux:w #1 \q_stop }
-\cs_new_protected:Npn \fp_read_aux:w #1#2 . #3 e #4 \q_stop
- {
- \if:w #1 -
- \l_fp_input_a_sign_int \c_minus_one
- \else:
- \l_fp_input_a_sign_int \c_one
- \fi:
- \l_fp_input_a_integer_int #2 \scan_stop:
- \l_fp_input_a_decimal_int #3 \scan_stop:
- \l_fp_input_a_exponent_int #4 \scan_stop:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_split:Nn}
-% \begin{macro}[aux]{\fp_split_sign:}
-% \begin{macro}[aux]{\fp_split_exponent:}
-% \begin{macro}[aux]{\fp_split_aux_i:w}
-% \begin{macro}[aux]{\fp_split_aux_ii:w}
-% \begin{macro}[aux]{\fp_split_aux_iii:w}
-% \begin{macro}[aux]{\fp_split_decimal:w}
-% \begin{macro}[aux]{\fp_split_decimal_aux:w}
-% The aim here is to use as much of \TeX{}'s mechanism as possible to pick
-% up the numerical input without any mistakes. In particular, negative
-% numbers have to be filtered out first in case the integer part is
-% $0$ (in which case \TeX{} would drop the |-| sign). That process
-% has to be done in a loop for cases where the sign is repeated.
-% Finding an exponent is relatively easy, after which the next phase is
-% to find the integer part, which will terminate with a |.|, and trigger
-% the decimal-finding code. The later will allow the decimal to be too
-% long, truncating the result.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_split:Nn #1#2
- {
- \tl_set:Nx \l_fp_internal_tl {#2}
- \tl_set_rescan:Nno \l_fp_internal_tl { \char_set_catcode_ignore:n { 32 } }
- { \l_fp_internal_tl }
- \l_fp_split_sign_int \c_one
- \fp_split_sign:
- \use:c { l_fp_input_ #1 _sign_int } \l_fp_split_sign_int
- \exp_after:wN \fp_split_exponent:w \l_fp_internal_tl e e \q_stop #1
- }
-\cs_new_protected_nopar:Npn \fp_split_sign:
- {
- \if_int_compare:w \pdftex_strcmp:D
- { \exp_after:wN \tl_head:w \l_fp_internal_tl ? \q_stop } { - }
- = \c_zero
- \tl_set:Nx \l_fp_internal_tl
- {
- \exp_after:wN
- \tl_tail:w \l_fp_internal_tl \prg_do_nothing: \q_stop
- }
- \l_fp_split_sign_int -\l_fp_split_sign_int
- \exp_after:wN \fp_split_sign:
- \else:
- \if_int_compare:w \pdftex_strcmp:D
- { \exp_after:wN \tl_head:w \l_fp_internal_tl ? \q_stop } { + }
- = \c_zero
- \tl_set:Nx \l_fp_internal_tl
- {
- \exp_after:wN
- \tl_tail:w \l_fp_internal_tl \prg_do_nothing: \q_stop
- }
- \exp_after:wN \exp_after:wN \exp_after:wN \fp_split_sign:
- \fi:
- \fi:
- }
-\cs_new_protected:Npn \fp_split_exponent:w #1 e #2 e #3 \q_stop #4
- {
- \use:c { l_fp_input_ #4 _exponent_int }
- \int_eval:w 0 #2 \scan_stop:
- \tex_afterassignment:D \fp_split_aux_i:w
- \use:c { l_fp_input_ #4 _integer_int }
- \int_eval:w 0 #1 . . \q_stop #4
- }
-\cs_new_protected:Npn \fp_split_aux_i:w #1 . #2 . #3 \q_stop
- { \fp_split_aux_ii:w #2 000000000 \q_stop }
-\cs_new_protected:Npn \fp_split_aux_ii:w #1#2#3#4#5#6#7#8#9
- { \fp_split_aux_iii:w {#1#2#3#4#5#6#7#8#9} }
-\cs_new_protected:Npn \fp_split_aux_iii:w #1#2 \q_stop
- {
- \l_fp_internal_int 1 #1 \scan_stop:
- \exp_after:wN \fp_split_decimal:w
- \int_use:N \l_fp_internal_int 000000000 \q_stop
- }
-\cs_new_protected:Npn \fp_split_decimal:w #1#2#3#4#5#6#7#8#9
- { \fp_split_decimal_aux:w {#2#3#4#5#6#7#8#9} }
-\cs_new_protected:Npn \fp_split_decimal_aux:w #1#2#3 \q_stop #4
- {
- \use:c { l_fp_input_ #4 _decimal_int } #1#2 \scan_stop:
- \if_int_compare:w
- \int_eval:w
- \use:c { l_fp_input_ #4 _integer_int } +
- \use:c { l_fp_input_ #4 _decimal_int }
- \scan_stop:
- = \c_zero
- \use:c { l_fp_input_ #4 _sign_int } \c_one
- \fi:
- \if_int_compare:w
- \use:c { l_fp_input_ #4 _integer_int } < \c_one_thousand_million
- \else:
- \exp_after:wN \fp_overflow_msg:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_standardise:NNNN}
-% \begin{macro}[aux]{\fp_standardise_aux:NNNN}
-% \begin{macro}[aux]{\fp_standardise_aux:}
-% \begin{macro}[aux]{\fp_standardise_aux:w}
-% The idea here is to shift the input into a known exponent range. This
-% is done using \TeX{} tokens where possible, as this is faster than
-% arithmetic.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_standardise:NNNN #1#2#3#4
- {
- \if_int_compare:w
- \int_eval:w #2 + #3 = \c_zero
- #1 \c_one
- #4 \c_zero
- \exp_after:wN \use_none:nnnn
- \else:
- \exp_after:wN \fp_standardise_aux:NNNN
- \fi:
- #1#2#3#4
- }
-\cs_new_protected:Npn \fp_standardise_aux:NNNN #1#2#3#4
- {
- \cs_set_protected_nopar:Npn \fp_standardise_aux:
- {
- \if_int_compare:w #2 = \c_zero
- \tex_advance:D #3 \c_one_thousand_million
- \exp_after:wN \fp_standardise_aux:w
- \int_use:N #3 \q_stop
- \exp_after:wN \fp_standardise_aux:
- \fi:
- }
- \cs_set_protected:Npn
- \fp_standardise_aux:w ##1##2##3##4##5##6##7##8##9 \q_stop
- {
- #2 ##2 \scan_stop:
- #3 ##3##4##5##6##7##8##9 0 \scan_stop:
- \tex_advance:D #4 \c_minus_one
- }
- \fp_standardise_aux:
- \cs_set_protected_nopar:Npn \fp_standardise_aux:
- {
- \if_int_compare:w #2 > \c_nine
- \tex_advance:D #2 \c_one_thousand_million
- \exp_after:wN \use_i:nn \exp_after:wN
- \fp_standardise_aux:w \int_use:N #2
- \exp_after:wN \fp_standardise_aux:
- \fi:
- }
- \cs_set_protected:Npn
- \fp_standardise_aux:w ##1##2##3##4##5##6##7##8##9
- {
- #2 ##1##2##3##4##5##6##7##8 \scan_stop:
- \tex_advance:D #3 \c_one_thousand_million
- \tex_divide:D #3 \c_ten
- \tl_set:Nx \l_fp_internal_tl
- {
- ##9
- \exp_after:wN \use_none:n \int_use:N #3
- }
- #3 \l_fp_internal_tl \scan_stop:
- \tex_advance:D #4 \c_one
- }
- \fp_standardise_aux:
- \if_int_compare:w #4 < \c_one_hundred
- \if_int_compare:w #4 > -\c_one_hundred
- \else:
- #1 \c_one
- #2 \c_zero
- #3 \c_zero
- #4 \c_zero
- \fi:
- \else:
- \exp_after:wN \fp_overflow_msg:
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_standardise_aux: { }
-\cs_new_protected_nopar:Npn \fp_standardise_aux:w { }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Internal utilities}
-%
-% \begin{macro}{\fp_level_input_exponents:}
-% \begin{macro}[aux]{\fp_level_input_exponents_a:}
-% \begin{macro}[aux]{\fp_level_input_exponents_a:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_level_input_exponents_b:}
-% \begin{macro}[aux]{\fp_level_input_exponents_b:NNNNNNNNN}
-% The routines here are similar to those used to standardise the
-% exponent. However, the aim here is different: the two exponents need
-% to end up the same.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_level_input_exponents:
- {
- \if_int_compare:w \l_fp_input_a_exponent_int > \l_fp_input_b_exponent_int
- \exp_after:wN \fp_level_input_exponents_a:
- \else:
- \exp_after:wN \fp_level_input_exponents_b:
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_level_input_exponents_a:
- {
- \if_int_compare:w \l_fp_input_a_exponent_int > \l_fp_input_b_exponent_int
- \tex_advance:D \l_fp_input_b_integer_int \c_one_thousand_million
- \exp_after:wN \use_i:nn \exp_after:wN
- \fp_level_input_exponents_a:NNNNNNNNN
- \int_use:N \l_fp_input_b_integer_int
- \exp_after:wN \fp_level_input_exponents_a:
- \fi:
- }
-\cs_new_protected:Npn \fp_level_input_exponents_a:NNNNNNNNN
- #1#2#3#4#5#6#7#8#9
- {
- \l_fp_input_b_integer_int #1#2#3#4#5#6#7#8 \scan_stop:
- \tex_advance:D \l_fp_input_b_decimal_int \c_one_thousand_million
- \tex_divide:D \l_fp_input_b_decimal_int \c_ten
- \tl_set:Nx \l_fp_internal_tl
- {
- #9
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_input_b_decimal_int
- }
- \l_fp_input_b_decimal_int \l_fp_internal_tl \scan_stop:
- \tex_advance:D \l_fp_input_b_exponent_int \c_one
- }
-\cs_new_protected_nopar:Npn \fp_level_input_exponents_b:
- {
- \if_int_compare:w \l_fp_input_b_exponent_int > \l_fp_input_a_exponent_int
- \tex_advance:D \l_fp_input_a_integer_int \c_one_thousand_million
- \exp_after:wN \use_i:nn \exp_after:wN
- \fp_level_input_exponents_b:NNNNNNNNN
- \int_use:N \l_fp_input_a_integer_int
- \exp_after:wN \fp_level_input_exponents_b:
- \fi:
- }
-\cs_new_protected:Npn \fp_level_input_exponents_b:NNNNNNNNN
- #1#2#3#4#5#6#7#8#9
- {
- \l_fp_input_a_integer_int #1#2#3#4#5#6#7#8 \scan_stop:
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \tex_divide:D \l_fp_input_a_decimal_int \c_ten
- \tl_set:Nx \l_fp_internal_tl
- {
- #9
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_input_a_decimal_int
- }
- \l_fp_input_a_decimal_int \l_fp_internal_tl \scan_stop:
- \tex_advance:D \l_fp_input_a_exponent_int \c_one
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[aux]{\fp_tmp:w}
-% Used for output of results, cutting down on \cs{exp_after:wN}.
-% This is just a place holder definition.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_tmp:w #1#2 { }
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Operations for \texttt{fp} variables}
-%
-% The format of \texttt{fp} variables is tightly defined, so that
-% they can be read quickly by the internal code. The format is a single
-% sign token, a single number, the decimal point, nine decimal numbers,
-% an |e| and finally the exponent. This final part may vary in length.
-% When stored, floating points will always be stored with a value in
-% the integer position unless the number is zero.
-%
-% \begin{macro}{\fp_new:N, \fp_new:c}
-% \UnitTested
-% Fixed-points always have a value, and of course this has to be
-% initialised globally.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_new:N #1
- {
- \tl_new:N #1
- \tl_gset_eq:NN #1 \c_zero_fp
- }
-\cs_generate_variant:Nn \fp_new:N { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\fp_const:Nn, \fp_const:cn}
-% A simple wrapper.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_const:Nn #1#2
- {
- \fp_new:N #1
- \fp_gset:Nn #1 {#2}
- }
-\cs_generate_variant:Nn \fp_const:Nn { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\fp_zero:N, \fp_zero:c}
-% \UnitTested
-% \begin{macro}{\fp_gzero:N, \fp_gzero:c}
-% \UnitTested
-% Zeroing fixed-points is pretty obvious.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_zero:N #1
- { \tl_set_eq:NN #1 \c_zero_fp }
-\cs_new_protected:Npn \fp_gzero:N #1
- { \tl_gset_eq:NN #1 \c_zero_fp }
-\cs_generate_variant:Nn \fp_zero:N { c }
-\cs_generate_variant:Nn \fp_gzero:N { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}
-% {\fp_zero_new:N, \fp_zero_new:c, \fp_gzero_new:N, \fp_gzero_new:c}
-% Create a floating point if needed, otherwise clear it.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_zero_new:N #1
- { \fp_if_exist:NTF #1 { \fp_zero:N #1 } { \fp_new:N #1 } }
-\cs_new_protected:Npn \fp_gzero_new:N #1
- { \fp_if_exist:NTF #1 { \fp_gzero:N #1 } { \fp_new:N #1 } }
-\cs_generate_variant:Nn \fp_zero_new:N { c }
-\cs_generate_variant:Nn \fp_gzero_new:N { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\fp_set:Nn, \fp_set:cn}
-% \UnitTested
-% \begin{macro}{\fp_gset:Nn, \fp_gset:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_set_aux:NNn}
-% To trap any input errors, a very simple version of the parser is run
-% here. This will pick up any invalid characters at this stage, saving
-% issues later. The splitting approach is the same as the more
-% advanced function later.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_set:Nn { \fp_set_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gset:Nn { \fp_set_aux:NNn \tl_gset:Nn }
-\cs_new_protected:Npn \fp_set_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_split:Nn a {#3}
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- {
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- -
- \else:
- +
- \fi:
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_input_a_decimal_int
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- }
- \fp_tmp:w
- }
-\cs_generate_variant:Nn \fp_set:Nn { c }
-\cs_generate_variant:Nn \fp_gset:Nn { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-%
-%
-% \begin{macro}{\fp_set_from_dim:Nn, \fp_set_from_dim:cn}
-% \UnitTested
-% \begin{macro}{\fp_gset_from_dim:Nn, \fp_gset_from_dim:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_set_from_dim_aux:NNn}
-% \begin{macro}[aux]{\fp_set_from_dim_aux:w}
-% \begin{variable}{\l_fp_internal_dim}
-% \begin{variable}{\l_fp_internal_skip}
-% Here, dimensions are converted to fixed-points \emph{via} a
-% temporary variable. This ensures that they always convert as points.
-% The code is then essentially the same as for \cs{fp_set:Nn}, but with
-% the dimension passed so that it will be striped of the |pt| on the
-% way through. The passage through a skip is used to remove any rubber
-% part.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_set_from_dim:Nn
- { \fp_set_from_dim_aux:NNn \tl_set:Nx }
-\cs_new_protected_nopar:Npn \fp_gset_from_dim:Nn
- { \fp_set_from_dim_aux:NNn \tl_gset:Nx }
-\cs_new_protected:Npn \fp_set_from_dim_aux:NNn #1#2#3
- {
- \group_begin:
- \l_fp_internal_skip \etex_glueexpr:D #3 \scan_stop:
- \l_fp_internal_dim \l_fp_internal_skip
- \fp_split:Nn a
- {
- \exp_after:wN \fp_set_from_dim_aux:w
- \dim_use:N \l_fp_internal_dim
- }
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- {
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- -
- \else:
- +
- \fi:
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_input_a_decimal_int
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- }
- \fp_tmp:w
- }
-\cs_set_protected_nopar:Npx \fp_set_from_dim_aux:w
- {
- \cs_set:Npn \exp_not:N \fp_set_from_dim_aux:w
- ##1 \tl_to_str:n { pt } {##1}
- }
-\fp_set_from_dim_aux:w
-\cs_generate_variant:Nn \fp_set_from_dim:Nn { c }
-\cs_generate_variant:Nn \fp_gset_from_dim:Nn { c }
-\dim_new:N \l_fp_internal_dim
-\skip_new:N \l_fp_internal_skip
-% \end{macrocode}
-% \end{variable}
+% \begin{variable}{true, false}
+% Other names for $1$ and $+0$.
% \end{variable}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\fp_set_eq:NN, \fp_set_eq:cN, \fp_set_eq:Nc, \fp_set_eq:cc}
-% \UnitTested
-% \begin{macro}{\fp_gset_eq:NN, \fp_gset_eq:cN, \fp_gset_eq:Nc, \fp_gset_eq:cc}
-% \UnitTested
-% Pretty simple, really.
-% \begin{macrocode}
-\cs_new_eq:NN \fp_set_eq:NN \tl_set_eq:NN
-\cs_new_eq:NN \fp_set_eq:cN \tl_set_eq:cN
-\cs_new_eq:NN \fp_set_eq:Nc \tl_set_eq:Nc
-\cs_new_eq:NN \fp_set_eq:cc \tl_set_eq:cc
-\cs_new_eq:NN \fp_gset_eq:NN \tl_gset_eq:NN
-\cs_new_eq:NN \fp_gset_eq:cN \tl_gset_eq:cN
-\cs_new_eq:NN \fp_gset_eq:Nc \tl_gset_eq:Nc
-\cs_new_eq:NN \fp_gset_eq:cc \tl_gset_eq:cc
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_show:N, \fp_show:c}
-% \UnitTested
-% Simple showing of the underlying variable.
-% \begin{macrocode}
-\cs_new_eq:NN \fp_show:N \tl_show:N
-\cs_new_eq:NN \fp_show:c \tl_show:c
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\fp_use:N, \fp_use:c}
-% \UnitTested
-% \begin{macro}[aux]{\fp_use_aux:w}
-% \begin{macro}[aux]{\fp_use_none:w}
-% \begin{macro}[aux]{\fp_use_small:w}
-% \begin{macro}[aux]{\fp_use_large:w}
-% \begin{macro}[aux]{\fp_use_large_aux_i:w}
-% \begin{macro}[aux]{\fp_use_large_aux_1:w}
-% \begin{macro}[aux]{\fp_use_large_aux_2:w}
-% \begin{macro}[aux]{\fp_use_large_aux_3:w}
-% \begin{macro}[aux]{\fp_use_large_aux_4:w}
-% \begin{macro}[aux]{\fp_use_large_aux_5:w}
-% \begin{macro}[aux]{\fp_use_large_aux_6:w}
-% \begin{macro}[aux]{\fp_use_large_aux_7:w}
-% \begin{macro}[aux]{\fp_use_large_aux_8:w}
-% \begin{macro}[aux]{\fp_use_large_aux_i:w}
-% \begin{macro}[aux]{\fp_use_large_aux_ii:w}
-% The idea of the \cs{fp_use:N} function to convert the stored
-% value into something suitable for \TeX{} to use as a number in an
-% expandable manner. The first step is to deal with the sign, then
-% work out how big the input is.
-% \begin{macrocode}
-\cs_new:Npn \fp_use:N #1
- { \exp_after:wN \fp_use_aux:w #1 \q_stop }
-\cs_generate_variant:Nn \fp_use:N { c }
-\cs_new:Npn \fp_use_aux:w #1#2 e #3 \q_stop
- {
- \if:w #1 -
- -
- \fi:
- \if_int_compare:w #3 > \c_zero
- \exp_after:wN \fp_use_large:w
- \else:
- \if_int_compare:w #3 < \c_zero
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_use_small:w
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN \fp_use_none:w
- \fi:
- \fi:
- #2 e #3 \q_stop
- }
-% \end{macrocode}
-% When the exponent is zero, the input is simply returned as output.
-% \begin{macrocode}
-\cs_new:Npn \fp_use_none:w #1 e #2 \q_stop {#1}
-% \end{macrocode}
-% For small numbers (less than $1$) the correct number of zeros
-% have to be inserted, but the decimal point is easy.
-% \begin{macrocode}
-\cs_new:Npn \fp_use_small:w #1 . #2 e #3 \q_stop
- {
- 0 .
- \prg_replicate:nn { -#3 - 1 } { 0 }
- #1#2
- }
-% \end{macrocode}
-% Life is more complex for large numbers. The decimal point needs to
-% be shuffled, with potentially some zero-filling for very large values.
-% \begin{macrocode}
-\cs_new:Npn \fp_use_large:w #1 . #2 e #3 \q_stop
- {
- \if_int_compare:w #3 < \c_ten
- \exp_after:wN \fp_use_large_aux_i:w
- \else:
- \exp_after:wN \fp_use_large_aux_ii:w
- \fi:
- #1#2 e #3 \q_stop
- }
-\cs_new:Npn \fp_use_large_aux_i:w #1#2 e #3 \q_stop
- {
- #1
- \use:c { fp_use_large_aux_ #3 :w } #2 \q_stop
- }
-\cs_new:cpn { fp_use_large_aux_1:w } #1#2 \q_stop { #1 . #2 }
-\cs_new:cpn { fp_use_large_aux_2:w } #1#2#3 \q_stop
- { #1#2 . #3 }
-\cs_new:cpn { fp_use_large_aux_3:w } #1#2#3#4 \q_stop
- { #1#2#3 . #4 }
-\cs_new:cpn { fp_use_large_aux_4:w } #1#2#3#4#5 \q_stop
- { #1#2#3#4 . #5 }
-\cs_new:cpn { fp_use_large_aux_5:w } #1#2#3#4#5#6 \q_stop
- { #1#2#3#4#5 . #6 }
-\cs_new:cpn { fp_use_large_aux_6:w } #1#2#3#4#5#6#7 \q_stop
- { #1#2#3#4#5#6 . #7 }
-\cs_new:cpn { fp_use_large_aux_7:w } #1#2#3#4#5#6#7#8 \q_stop
- { #1#2#3#4#6#7 . #8 }
-\cs_new:cpn { fp_use_large_aux_8:w } #1#2#3#4#5#6#7#8#9 \q_stop
- { #1#2#3#4#5#6#7#8 . #9 }
-\cs_new:cpn { fp_use_large_aux_9:w } #1 \q_stop { #1 . }
-\cs_new:Npn \fp_use_large_aux_ii:w #1 e #2 \q_stop
- {
- #1
- \prg_replicate:nn { #2 - 9 } { 0 }
- .
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[pTF]{\fp_if_exist:N, \fp_if_exist:c}
-% Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
-% \begin{macrocode}
-\cs_new_eq:NN \fp_if_exist:NTF \cs_if_exist:NTF
-\cs_new_eq:NN \fp_if_exist:NT \cs_if_exist:NT
-\cs_new_eq:NN \fp_if_exist:NF \cs_if_exist:NF
-\cs_new_eq:NN \fp_if_exist_p:N \cs_if_exist_p:N
-\cs_new_eq:NN \fp_if_exist:cTF \cs_if_exist:cTF
-\cs_new_eq:NN \fp_if_exist:cT \cs_if_exist:cT
-\cs_new_eq:NN \fp_if_exist:cF \cs_if_exist:cF
-\cs_new_eq:NN \fp_if_exist_p:c \cs_if_exist_p:c
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Transferring to other types}
-%
-% The \cs{fp_use:N} function converts a floating point variable to
-% a form that can be used by \TeX{}. Here, the functions are slightly
-% different, as some information may be discarded.
-%
-% \begin{macro}{\fp_to_dim:N, \fp_to_dim:c}
-% A very simple wrapper.
-% \begin{macrocode}
-\cs_new:Npn \fp_to_dim:N #1 { \fp_use:N #1 pt }
-\cs_generate_variant:Nn \fp_to_dim:N { c }
-% \end{macrocode}
-% \end{macro}
-%
-%
-% \begin{macro}{\fp_to_int:N, \fp_to_int:c}
-% \UnitTested
-% \begin{macro}[aux]{\fp_to_int_aux:w}
-% \begin{macro}[aux]{\fp_to_int_none:w}
-% \begin{macro}[aux]{\fp_to_int_small:w}
-% \begin{macro}[aux]{\fp_to_int_large:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_i:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_1:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_2:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_3:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_4:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_5:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_6:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_7:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_8:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux_i:w}
-% \begin{macro}[aux]{\fp_to_int_large_aux:nnn}
-% \begin{macro}[aux]{\fp_to_int_large_aux_ii:w}
-% Converting to integers in an expandable manner is very similar to
-% simply using floating point variables, particularly in the lead-off.
-% \begin{macrocode}
-\cs_new:Npn \fp_to_int:N #1
- { \exp_after:wN \fp_to_int_aux:w #1 \q_stop }
-\cs_generate_variant:Nn \fp_to_int:N { c }
-\cs_new:Npn \fp_to_int_aux:w #1#2 e #3 \q_stop
- {
- \if:w #1 -
- -
- \fi:
- \if_int_compare:w #3 < \c_zero
- \exp_after:wN \fp_to_int_small:w
- \else:
- \exp_after:wN \fp_to_int_large:w
- \fi:
- #2 e #3 \q_stop
- }
-% \end{macrocode}
-% For small numbers, if the decimal part is greater than a half then
-% there is rounding up to do.
-% \begin{macrocode}
-\cs_new:Npn \fp_to_int_small:w #1 . #2 e #3 \q_stop
- {
- \if_int_compare:w #3 > \c_one
- \else:
- \if_int_compare:w #1 < \c_five
- 0
- \else:
- 1
- \fi:
- \fi:
- }
-% \end{macrocode}
-% For large numbers, the idea is to split off the part for rounding,
-% do the rounding and fill if needed.
-% \begin{macrocode}
-\cs_new:Npn \fp_to_int_large:w #1 . #2 e #3 \q_stop
- {
- \if_int_compare:w #3 < \c_ten
- \exp_after:wN \fp_to_int_large_aux_i:w
- \else:
- \exp_after:wN \fp_to_int_large_aux_ii:w
- \fi:
- #1#2 e #3 \q_stop
- }
-\cs_new:Npn \fp_to_int_large_aux_i:w #1#2 e #3 \q_stop
- { \use:c { fp_to_int_large_aux_ #3 :w } #2 \q_stop {#1} }
-\cs_new:cpn { fp_to_int_large_aux_1:w } #1#2 \q_stop
- { \fp_to_int_large_aux:nnn { #2 0 } {#1} }
-\cs_new:cpn { fp_to_int_large_aux_2:w } #1#2#3 \q_stop
- { \fp_to_int_large_aux:nnn { #3 00 } {#1#2} }
-\cs_new:cpn { fp_to_int_large_aux_3:w } #1#2#3#4 \q_stop
- { \fp_to_int_large_aux:nnn { #4 000 } {#1#2#3} }
-\cs_new:cpn { fp_to_int_large_aux_4:w } #1#2#3#4#5 \q_stop
- { \fp_to_int_large_aux:nnn { #5 0000 } {#1#2#3#4} }
-\cs_new:cpn { fp_to_int_large_aux_5:w } #1#2#3#4#5#6 \q_stop
- { \fp_to_int_large_aux:nnn { #6 00000 } {#1#2#3#4#5} }
-\cs_new:cpn { fp_to_int_large_aux_6:w } #1#2#3#4#5#6#7 \q_stop
- { \fp_to_int_large_aux:nnn { #7 000000 } {#1#2#3#4#5#6} }
-\cs_new:cpn { fp_to_int_large_aux_7:w } #1#2#3#4#5#6#7#8 \q_stop
- { \fp_to_int_large_aux:nnn { #8 0000000 } {#1#2#3#4#5#6#7} }
-\cs_new:cpn { fp_to_int_large_aux_8:w } #1#2#3#4#5#6#7#8#9 \q_stop
- { \fp_to_int_large_aux:nnn { #9 00000000 } {#1#2#3#4#5#6#7#8} }
-\cs_new:cpn { fp_to_int_large_aux_9:w } #1 \q_stop {#1}
-\cs_new:Npn \fp_to_int_large_aux:nnn #1#2#3
- {
- \if_int_compare:w #1 < \c_five_hundred_million
- #3#2
- \else:
- \int_value:w \int_eval:w #3#2 + 1 \int_eval_end:
- \fi:
- }
-\cs_new:Npn \fp_to_int_large_aux_ii:w #1 e #2 \q_stop
- {
- #1
- \prg_replicate:nn { #2 - 9 } { 0 }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_to_tl:N, \fp_to_tl:c}
-% \UnitTested
-% \begin{macro}[aux]{\fp_to_tl_aux:w}
-% \begin{macro}[aux]{\fp_to_tl_large:w}
-% \begin{macro}[aux]{\fp_to_tl_large_aux_i:w}
-% \begin{macro}[aux]{\fp_to_tl_large_aux_ii:w}
-% \begin{macro}[aux]{\fp_to_tl_large_0:w}
-% \begin{macro}[aux]{\fp_to_tl_large_1:w}
-% \begin{macro}[aux]{\fp_to_tl_large_2:w}
-% \begin{macro}[aux]{\fp_to_tl_large_3:w}
-% \begin{macro}[aux]{\fp_to_tl_large_4:w}
-% \begin{macro}[aux]{\fp_to_tl_large_5:w}
-% \begin{macro}[aux]{\fp_to_tl_large_6:w}
-% \begin{macro}[aux]{\fp_to_tl_large_7:w}
-% \begin{macro}[aux]{\fp_to_tl_large_8:w}
-% \begin{macro}[aux]{\fp_to_tl_large_8_aux:w}
-% \begin{macro}[aux]{\fp_to_tl_large_9:w}
-% \begin{macro}[aux]{\fp_to_tl_small:w}
-% \begin{macro}[aux]{\fp_to_tl_small_one:w}
-% \begin{macro}[aux]{\fp_to_tl_small_two:w}
-% \begin{macro}[aux]{\fp_to_tl_small_aux:w}
-% \begin{macro}[aux]{\fp_to_tl_large_zeros:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_to_tl_small_zeros:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_use_iix_ix:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_use_ix:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_use_i_to_vii:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_use_i_to_iix:NNNNNNNNN}
-% Converting to integers in an expandable manner is very similar to
-% simply using floating point variables, particularly in the lead-off.
-% \begin{macrocode}
-\cs_new:Npn \fp_to_tl:N #1
- { \exp_after:wN \fp_to_tl_aux:w #1 \q_stop }
-\cs_generate_variant:Nn \fp_to_tl:N { c }
-\cs_new:Npn \fp_to_tl_aux:w #1#2 e #3 \q_stop
- {
- \if:w #1 -
- -
- \fi:
- \if_int_compare:w #3 < \c_zero
- \exp_after:wN \fp_to_tl_small:w
- \else:
- \exp_after:wN \fp_to_tl_large:w
- \fi:
- #2 e #3 \q_stop
- }
-% \end{macrocode}
-% For \enquote{large} numbers (exponent $\ge 0$) there are two
-% cases. For very large exponents ($ \ge 10 $) life is easy: apart
-% from dropping extra zeros there is no work to do. On the other hand,
-% for intermediate exponent values the decimal needs to be moved, then
-% zeros can be dropped.
-% \begin{macrocode}
-\cs_new:Npn \fp_to_tl_large:w #1 e #2 \q_stop
- {
- \if_int_compare:w #2 < \c_ten
- \exp_after:wN \fp_to_tl_large_aux_i:w
- \else:
- \exp_after:wN \fp_to_tl_large_aux_ii:w
- \fi:
- #1 e #2 \q_stop
- }
-\cs_new:Npn \fp_to_tl_large_aux_i:w #1 e #2 \q_stop
- { \use:c { fp_to_tl_large_ #2 :w } #1 \q_stop }
-\cs_new:Npn \fp_to_tl_large_aux_ii:w #1 . #2 e #3 \q_stop
- {
- #1
- \fp_to_tl_large_zeros:NNNNNNNNN #2
- e #3
- }
-\cs_new:cpn { fp_to_tl_large_0:w } #1 . #2 \q_stop
- {
- #1
- \fp_to_tl_large_zeros:NNNNNNNNN #2
- }
-\cs_new:cpn { fp_to_tl_large_1:w } #1 . #2#3 \q_stop
- {
- #1#2
- \fp_to_tl_large_zeros:NNNNNNNNN #3 0
- }
-\cs_new:cpn { fp_to_tl_large_2:w } #1 . #2#3#4 \q_stop
- {
- #1#2#3
- \fp_to_tl_large_zeros:NNNNNNNNN #4 00
- }
-\cs_new:cpn { fp_to_tl_large_3:w } #1 . #2#3#4#5 \q_stop
- {
- #1#2#3#4
- \fp_to_tl_large_zeros:NNNNNNNNN #5 000
- }
-\cs_new:cpn { fp_to_tl_large_4:w } #1 . #2#3#4#5#6 \q_stop
- {
- #1#2#3#4#5
- \fp_to_tl_large_zeros:NNNNNNNNN #6 0000
- }
-\cs_new:cpn { fp_to_tl_large_5:w } #1 . #2#3#4#5#6#7 \q_stop
- {
- #1#2#3#4#5#6
- \fp_to_tl_large_zeros:NNNNNNNNN #7 00000
- }
-\cs_new:cpn { fp_to_tl_large_6:w } #1 . #2#3#4#5#6#7#8 \q_stop
- {
- #1#2#3#4#5#6#7
- \fp_to_tl_large_zeros:NNNNNNNNN #8 000000
- }
-\cs_new:cpn { fp_to_tl_large_7:w } #1 . #2#3#4#5#6#7#8#9 \q_stop
- {
- #1#2#3#4#5#6#7#8
- \fp_to_tl_large_zeros:NNNNNNNNN #9 0000000
- }
-\cs_new:cpn { fp_to_tl_large_8:w } #1 .
- {
- #1
- \use:c { fp_to_tl_large_8_aux:w }
- }
-\cs_new:cpn { fp_to_tl_large_8_aux:w } #1#2#3#4#5#6#7#8#9 \q_stop
- {
- #1#2#3#4#5#6#7#8
- \fp_to_tl_large_zeros:NNNNNNNNN #9 00000000
- }
-\cs_new:cpn { fp_to_tl_large_9:w } #1 . #2 \q_stop {#1#2}
-% \end{macrocode}
-% Dealing with small numbers is a bit more complex as there has to be
-% rounding. This makes life rather awkward, as there need to be a series
-% of tests and calculations, as things cannot be stored in an
-% expandable system.
-% \begin{macrocode}
-\cs_new:Npn \fp_to_tl_small:w #1 e #2 \q_stop
- {
- \if_int_compare:w #2 = \c_minus_one
- \exp_after:wN \fp_to_tl_small_one:w
- \else:
- \if_int_compare:w #2 = -\c_two
- \exp_after:wN \exp_after:wN \exp_after:wN \fp_to_tl_small_two:w
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN \fp_to_tl_small_aux:w
- \fi:
- \fi:
- #1 e #2 \q_stop
- }
-\cs_new:Npn \fp_to_tl_small_one:w #1 . #2 e #3 \q_stop
- {
- \if_int_compare:w \fp_use_ix:NNNNNNNNN #2 > \c_four
- \if_int_compare:w
- \int_eval:w #1 \fp_use_i_to_iix:NNNNNNNNN #2 + 1
- < \c_one_thousand_million
- 0.
- \exp_after:wN \fp_to_tl_small_zeros:NNNNNNNNN
- \int_value:w \int_eval:w
- #1 \fp_use_i_to_iix:NNNNNNNNN #2 + 1
- \int_eval_end:
- \else:
- 1
- \fi:
- \else:
- 0. #1
- \fp_to_tl_small_zeros:NNNNNNNNN #2
- \fi:
- }
-\cs_new:Npn \fp_to_tl_small_two:w #1 . #2 e #3 \q_stop
- {
- \if_int_compare:w \fp_use_iix_ix:NNNNNNNNN #2 > \c_forty_four
- \if_int_compare:w
- \int_eval:w #1 \fp_use_i_to_vii:NNNNNNNNN #2 0 + \c_ten
- < \c_one_thousand_million
- 0.0
- \exp_after:wN \fp_to_tl_small_zeros:NNNNNNNNN
- \int_value:w \int_eval:w
- #1 \fp_use_i_to_vii:NNNNNNNNN #2 0 + \c_ten
- \int_eval_end:
- \else:
- 0.1
- \fi:
- \else:
- 0.0
- #1
- \fp_to_tl_small_zeros:NNNNNNNNN #2
- \fi:
- }
-\cs_new:Npn \fp_to_tl_small_aux:w #1 . #2 e #3 \q_stop
- {
- #1
- \fp_to_tl_large_zeros:NNNNNNNNN #2
- e #3
- }
-% \end{macrocode}
-% Rather than a complex recursion, the tests for finding trailing zeros
-% are written out long-hand. The difference between the two is only the
-% need for a decimal marker.
-% \begin{macrocode}
-\cs_new:Npn \fp_to_tl_large_zeros:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {
- \if_int_compare:w #9 = \c_zero
- \if_int_compare:w #8 = \c_zero
- \if_int_compare:w #7 = \c_zero
- \if_int_compare:w #6 = \c_zero
- \if_int_compare:w #5 = \c_zero
- \if_int_compare:w #4 = \c_zero
- \if_int_compare:w #3 = \c_zero
- \if_int_compare:w #2 = \c_zero
- \if_int_compare:w #1 = \c_zero
- \else:
- . #1
- \fi:
- \else:
- . #1#2
- \fi:
- \else:
- . #1#2#3
- \fi:
- \else:
- . #1#2#3#4
- \fi:
- \else:
- . #1#2#3#4#5
- \fi:
- \else:
- . #1#2#3#4#5#6
- \fi:
- \else:
- . #1#2#3#4#5#6#7
- \fi:
- \else:
- . #1#2#3#4#5#6#7#8
- \fi:
- \else:
- . #1#2#3#4#5#6#7#8#9
- \fi:
- }
-\cs_new:Npn \fp_to_tl_small_zeros:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {
- \if_int_compare:w #9 = \c_zero
- \if_int_compare:w #8 = \c_zero
- \if_int_compare:w #7 = \c_zero
- \if_int_compare:w #6 = \c_zero
- \if_int_compare:w #5 = \c_zero
- \if_int_compare:w #4 = \c_zero
- \if_int_compare:w #3 = \c_zero
- \if_int_compare:w #2 = \c_zero
- \if_int_compare:w #1 = \c_zero
- \else:
- #1
- \fi:
- \else:
- #1#2
- \fi:
- \else:
- #1#2#3
- \fi:
- \else:
- #1#2#3#4
- \fi:
- \else:
- #1#2#3#4#5
- \fi:
- \else:
- #1#2#3#4#5#6
- \fi:
- \else:
- #1#2#3#4#5#6#7
- \fi:
- \else:
- #1#2#3#4#5#6#7#8
- \fi:
- \else:
- #1#2#3#4#5#6#7#8#9
- \fi:
- }
-% \end{macrocode}
-% Some quick \enquote{return a few} functions.
-% \begin{macrocode}
-\cs_new:Npn \fp_use_iix_ix:NNNNNNNNN #1#2#3#4#5#6#7#8#9 {#8#9}
-\cs_new:Npn \fp_use_ix:NNNNNNNNN #1#2#3#4#5#6#7#8#9 {#9}
-\cs_new:Npn \fp_use_i_to_vii:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {#1#2#3#4#5#6#7}
-\cs_new:Npn \fp_use_i_to_iix:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {#1#2#3#4#5#6#7#8}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Rounding numbers}
-%
-% The results may well need to be rounded. A couple of related functions
-% to do this for a stored value.
-%
-% \begin{macro}{\fp_round_figures:Nn, \fp_round_figures:cn}
-% \UnitTested
-% \begin{macro}{\fp_ground_figures:Nn, \fp_ground_figures:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_round_figures_aux:NNn}
-% Rounding to figures needs only an adjustment to the target by one
-% (as the target is in decimal places).
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_round_figures:Nn
- { \fp_round_figures_aux:NNn \tl_set:Nn }
-\cs_generate_variant:Nn \fp_round_figures:Nn { c }
-\cs_new_protected_nopar:Npn \fp_ground_figures:Nn
- { \fp_round_figures_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_ground_figures:Nn { c }
-\cs_new_protected:Npn \fp_round_figures_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_read:N #2
- \int_set:Nn \l_fp_round_target_int { #3 - 1 }
- \if_int_compare:w \l_fp_round_target_int < \c_ten
- \exp_after:wN \fp_round:
- \fi:
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- {
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- -
- \else:
- +
- \fi:
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_input_a_decimal_int
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- }
- \fp_tmp:w
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_round_places:Nn, \fp_round_places:cn}
-% \UnitTested
-% \begin{macro}{\fp_ground_places:Nn, \fp_ground_places:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_round_places_aux:NNn}
-% Rounding to places needs an adjustment for the exponent value, which
-% will mean that everything should be correct.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_round_places:Nn
- { \fp_round_places_aux:NNn \tl_set:Nn }
-\cs_generate_variant:Nn \fp_round_places:Nn { c }
-\cs_new_protected_nopar:Npn \fp_ground_places:Nn
- { \fp_round_places_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_ground_places:Nn { c }
-\cs_new_protected:Npn \fp_round_places_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_read:N #2
- \int_set:Nn \l_fp_round_target_int
- { #3 + \l_fp_input_a_exponent_int }
- \if_int_compare:w \l_fp_round_target_int < \c_ten
- \exp_after:wN \fp_round:
- \fi:
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- {
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- -
- \else:
- +
- \fi:
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_input_a_decimal_int
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- }
- \fp_tmp:w
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_round:}
-% \begin{macro}[aux]{\fp_round_aux:NNNNNNNNN}
-% \begin{macro}{\fp_round_loop:N}
-% The rounding approach is the same for decimal places and significant
-% figures. There are always nine decimal digits to round, so the code
-% can be written to account for this. The basic logic is simply to
-% find the rounding, track any carry digit and move along. At the end
-% of the loop there is a possible shuffle if the integer part has
-% become $10$.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_round:
- {
- \bool_set_false:N \l_fp_round_carry_bool
- \l_fp_round_position_int \c_eight
- \tl_clear:N \l_fp_round_decimal_tl
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \exp_after:wN \use_i:nn \exp_after:wN
- \fp_round_aux:NNNNNNNNN \int_use:N \l_fp_input_a_decimal_int
- }
-\cs_new_protected:Npn \fp_round_aux:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {
- \fp_round_loop:N #9#8#7#6#5#4#3#2#1
- \bool_if:NT \l_fp_round_carry_bool
- { \tex_advance:D \l_fp_input_a_integer_int \c_one }
- \l_fp_input_a_decimal_int \l_fp_round_decimal_tl \scan_stop:
- \if_int_compare:w \l_fp_input_a_integer_int < \c_ten
- \else:
- \l_fp_input_a_integer_int \c_one
- \tex_divide:D \l_fp_input_a_decimal_int \c_ten
- \tex_advance:D \l_fp_input_a_exponent_int \c_one
- \fi:
- }
-\cs_new_protected:Npn \fp_round_loop:N #1
- {
- \if_int_compare:w \l_fp_round_position_int < \l_fp_round_target_int
- \bool_if:NTF \l_fp_round_carry_bool
- { \l_fp_internal_int \int_eval:w #1 + \c_one \scan_stop: }
- { \l_fp_internal_int \int_eval:w #1 \scan_stop: }
- \if_int_compare:w \l_fp_internal_int = \c_ten
- \l_fp_internal_int \c_zero
- \else:
- \bool_set_false:N \l_fp_round_carry_bool
- \fi:
- \tl_set:Nx \l_fp_round_decimal_tl
- { \int_use:N \l_fp_internal_int \l_fp_round_decimal_tl }
- \else:
- \tl_set:Nx \l_fp_round_decimal_tl { 0 \l_fp_round_decimal_tl }
- \if_int_compare:w \l_fp_round_position_int = \l_fp_round_target_int
- \if_int_compare:w #1 > \c_four
- \bool_set_true:N \l_fp_round_carry_bool
- \fi:
- \fi:
- \fi:
- \tex_advance:D \l_fp_round_position_int \c_minus_one
- \if_int_compare:w \l_fp_round_position_int > \c_minus_one
- \exp_after:wN \fp_round_loop:N
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Unary functions}
-%
-% \begin{macro}{\fp_abs:N, \fp_abs:c}
-% \UnitTested
-% \begin{macro}{\fp_gabs:N, \fp_gabs:c}
-% \UnitTested
-% \begin{macro}[aux]{\fp_abs_aux:NN}
-% Setting the absolute value is easy: read the value, ignore the sign,
-% return the result.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_abs:N { \fp_abs_aux:NN \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gabs:N { \fp_abs_aux:NN \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_abs:N { c }
-\cs_generate_variant:Nn \fp_gabs:N { c }
-\cs_new_protected:Npn \fp_abs_aux:NN #1#2
- {
- \group_begin:
- \fp_read:N #2
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- {
- +
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_input_a_decimal_int
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- }
- \fp_tmp:w
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_neg:N, \fp_neg:c}
-% \UnitTested
-% \begin{macro}{\fp_gneg:N, \fp_gneg:c}
-% \UnitTested
-% \begin{macro}[aux]{\fp_neg:NN}
-% Just a bit more complex: read the input, reverse the sign and
-% output the result.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_neg:N { \fp_neg_aux:NN \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gneg:N { \fp_neg_aux:NN \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_neg:N { c }
-\cs_generate_variant:Nn \fp_gneg:N { c }
-\cs_new_protected:Npn \fp_neg_aux:NN #1#2
- {
- \group_begin:
- \fp_read:N #2
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \tl_set:Nx \l_fp_internal_tl
- {
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- +
- \else:
- -
- \fi:
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_input_a_decimal_int
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- \exp_after:wN \group_end: \exp_after:wN
- #1 \exp_after:wN #2 \exp_after:wN { \l_fp_internal_tl }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Basic arithmetic}
-%
-% \begin{macro}{\fp_add:Nn, \fp_add:cn}
-% \UnitTested
-% \begin{macro}{\fp_gadd:Nn,\fp_gadd:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_add_aux:NNn}
-% \begin{macro}[aux]{\fp_add_core:}
-% \begin{macro}[aux]{\fp_add_sum:}
-% \begin{macro}[aux]{\fp_add_difference:}
-% The various addition functions are simply different ways to call the
-% single master function below. This pattern is repeated for the
-% other arithmetic functions.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_add:Nn { \fp_add_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gadd:Nn { \fp_add_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_add:Nn { c }
-\cs_generate_variant:Nn \fp_gadd:Nn { c }
-% \end{macrocode}
-% Addition takes place using one of two paths. If the signs of the
-% two parts are the same, they are simply combined. On the other
-% hand, if the signs are different the calculation finds this
-% difference.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_add_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_read:N #2
- \fp_split:Nn b {#3}
- \fp_standardise:NNNN
- \l_fp_input_b_sign_int
- \l_fp_input_b_integer_int
- \l_fp_input_b_decimal_int
- \l_fp_input_b_exponent_int
- \fp_add_core:
- \fp_tmp:w #1#2
- }
-\cs_new_protected_nopar:Npn \fp_add_core:
- {
- \fp_level_input_exponents:
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_sign_int * \l_fp_input_b_sign_int
- > \c_zero
- \exp_after:wN \fp_add_sum:
- \else:
- \exp_after:wN \fp_add_difference:
- \fi:
- \l_fp_output_exponent_int \l_fp_input_a_exponent_int
- \fp_standardise:NNNN
- \l_fp_output_sign_int
- \l_fp_output_integer_int
- \l_fp_output_decimal_int
- \l_fp_output_exponent_int
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 ##2
- {
- \if_int_compare:w \l_fp_output_sign_int < \c_zero
- -
- \else:
- +
- \fi:
- \int_use:N \l_fp_output_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_output_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_output_exponent_int
- }
- }
- }
-% \end{macrocode}
-% Finding the sum of two numbers is trivially easy.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_add_sum:
- {
- \l_fp_output_sign_int \l_fp_input_a_sign_int
- \l_fp_output_integer_int
- \int_eval:w
- \l_fp_input_a_integer_int + \l_fp_input_b_integer_int
- \scan_stop:
- \l_fp_output_decimal_int
- \int_eval:w
- \l_fp_input_a_decimal_int + \l_fp_input_b_decimal_int
- \scan_stop:
- \if_int_compare:w \l_fp_output_decimal_int < \c_one_thousand_million
- \else:
- \tex_advance:D \l_fp_output_integer_int \c_one
- \tex_advance:D \l_fp_output_decimal_int -\c_one_thousand_million
- \fi:
- }
-% \end{macrocode}
-% When the signs of the two parts of the input are different, the
-% absolute difference is worked out first. There is then a calculation
-% to see which way around everything has worked out, so that the final
-% sign is correct. The difference might also give a zero result with
-% a negative sign, which is reversed as zero is regarded as positive.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_add_difference:
- {
- \l_fp_output_integer_int
- \int_eval:w
- \l_fp_input_a_integer_int - \l_fp_input_b_integer_int
- \scan_stop:
- \l_fp_output_decimal_int
- \int_eval:w
- \l_fp_input_a_decimal_int - \l_fp_input_b_decimal_int
- \scan_stop:
- \if_int_compare:w \l_fp_output_decimal_int < \c_zero
- \tex_advance:D \l_fp_output_integer_int \c_minus_one
- \tex_advance:D \l_fp_output_decimal_int \c_one_thousand_million
- \fi:
- \if_int_compare:w \l_fp_output_integer_int < \c_zero
- \l_fp_output_sign_int \l_fp_input_b_sign_int
- \if_int_compare:w \l_fp_output_decimal_int = \c_zero
- \l_fp_output_integer_int -\l_fp_output_integer_int
- \else:
- \l_fp_output_decimal_int
- \int_eval:w
- \c_one_thousand_million - \l_fp_output_decimal_int
- \scan_stop:
- \l_fp_output_integer_int
- \int_eval:w
- - \l_fp_output_integer_int - \c_one
- \scan_stop:
- \fi:
- \else:
- \l_fp_output_sign_int \l_fp_input_a_sign_int
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+% \begin{function}[EXP, added = 2012-05-08]{\dim_to_fp:n}
+% \begin{syntax}
+% \cs{dim_to_fp:n} \Arg{dimexpr}
+% \end{syntax}
+% Expands to an internal floating point number equal to the value of
+% the \meta{dimexpr} in \texttt{pt}.
+% \end{function}
%
-% \begin{macro}{\fp_sub:Nn, \fp_sub:cn}
-% \UnitTested
-% \begin{macro}{\fp_gsub:Nn,\fp_gsub:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_sub_aux:NNn}
-% Subtraction is essentially the same as addition, but with the sign
-% of the second component reversed. Thus the core of the two function
-% groups is the same, with just a little set up here.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_sub:Nn { \fp_sub_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gsub:Nn { \fp_sub_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_sub:Nn { c }
-\cs_generate_variant:Nn \fp_gsub:Nn { c }
-\cs_new_protected:Npn \fp_sub_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_read:N #2
- \fp_split:Nn b {#3}
- \fp_standardise:NNNN
- \l_fp_input_b_sign_int
- \l_fp_input_b_integer_int
- \l_fp_input_b_decimal_int
- \l_fp_input_b_exponent_int
- \tex_multiply:D \l_fp_input_b_sign_int \c_minus_one
- \fp_add_core:
- \fp_tmp:w #1#2
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+% \begin{function}[EXP, added = 2012-05-14, updated = 2012-07-08]{\fp_abs:n}
+% \begin{syntax}
+% \cs{fp_abs:n} \Arg{floating point expression}
+% \end{syntax}
+% Evaluates the \meta{floating point expression} as described for
+% \cs{fp_eval:n} and leaves the absolute value of the result in
+% the input stream.
+% \end{function}
%
-% \begin{macro}{\fp_mul:Nn, \fp_mul:cn}
-% \UnitTested
-% \begin{macro}{\fp_gmul:Nn,\fp_gmul:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_mul_aux:NNn}
-% \begin{macro}[aux]{\fp_mul_internal:}
-% \begin{macro}[aux]{\fp_mul_split:NNNN}
-% \begin{macro}[aux]{\fp_mul_split:w}
-% \begin{macro}[aux]{\fp_mul_end_level:}
-% \begin{macro}[aux]{\fp_mul_end_level:NNNNNNNNN}
-% The pattern is much the same for multiplication.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_mul:Nn { \fp_mul_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gmul:Nn { \fp_mul_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_mul:Nn { c }
-\cs_generate_variant:Nn \fp_gmul:Nn { c }
-% \end{macrocode}
-% The approach to multiplication is as follows. First, the two numbers
-% are split into blocks of three digits. These are then multiplied
-% together to find products for each group of three output digits. This
-% is al written out in full for speed reasons. Between each block of
-% three digits in the output, there is a carry step. The very lowest
-% digits are not calculated, while
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_mul_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_read:N #2
- \fp_split:Nn b {#3}
- \fp_standardise:NNNN
- \l_fp_input_b_sign_int
- \l_fp_input_b_integer_int
- \l_fp_input_b_decimal_int
- \l_fp_input_b_exponent_int
- \fp_mul_internal:
- \l_fp_output_exponent_int
- \int_eval:w
- \l_fp_input_a_exponent_int + \l_fp_input_b_exponent_int
- \scan_stop:
- \fp_standardise:NNNN
- \l_fp_output_sign_int
- \l_fp_output_integer_int
- \l_fp_output_decimal_int
- \l_fp_output_exponent_int
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- {
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_sign_int * \l_fp_input_b_sign_int
- < \c_zero
- \if_int_compare:w
- \int_eval:w
- \l_fp_output_integer_int + \l_fp_output_decimal_int
- = \c_zero
- +
- \else:
- -
- \fi:
- \else:
- +
- \fi:
- \int_use:N \l_fp_output_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_output_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_output_exponent_int
- }
- }
- \fp_tmp:w
- }
-% \end{macrocode}
-% Done separately so that the internal use is a bit easier.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_mul_internal:
- {
- \fp_mul_split:NNNN \l_fp_input_a_decimal_int
- \l_fp_mul_a_i_int \l_fp_mul_a_ii_int \l_fp_mul_a_iii_int
- \fp_mul_split:NNNN \l_fp_input_b_decimal_int
- \l_fp_mul_b_i_int \l_fp_mul_b_ii_int \l_fp_mul_b_iii_int
- \l_fp_mul_output_int \c_zero
- \tl_clear:N \l_fp_mul_output_tl
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_i_int
- \tex_divide:D \l_fp_mul_output_int \c_one_thousand
- \fp_mul_product:NN \l_fp_input_a_integer_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_i_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_input_b_integer_int
- \fp_mul_end_level:
- \fp_mul_product:NN \l_fp_input_a_integer_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_i_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_input_b_integer_int
- \fp_mul_end_level:
- \fp_mul_product:NN \l_fp_input_a_integer_int \l_fp_mul_b_i_int
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_input_b_integer_int
- \fp_mul_end_level:
- \l_fp_output_decimal_int 0 \l_fp_mul_output_tl \scan_stop:
- \tl_clear:N \l_fp_mul_output_tl
- \fp_mul_product:NN \l_fp_input_a_integer_int \l_fp_input_b_integer_int
- \fp_mul_end_level:
- \l_fp_output_integer_int 0 \l_fp_mul_output_tl \scan_stop:
- }
-% \end{macrocode}
-% The split works by making a $10$ digit number, from which
-% the first digit can then be dropped using a delimited argument. The
-% groups of three digits are then assigned to the various parts of
-% the input: notice that |##9| contains the last two digits of the
-% smallest part of the input.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_mul_split:NNNN #1#2#3#4
- {
- \tex_advance:D #1 \c_one_thousand_million
- \cs_set_protected:Npn \fp_mul_split_aux:w
- ##1##2##3##4##5##6##7##8##9 \q_stop {
- #2 ##2##3##4 \scan_stop:
- #3 ##5##6##7 \scan_stop:
- #4 ##8##9 \scan_stop:
- }
- \exp_after:wN \fp_mul_split_aux:w \int_use:N #1 \q_stop
- \tex_advance:D #1 -\c_one_thousand_million
- }
-\cs_new_protected:Npn \fp_mul_product:NN #1#2
- {
- \l_fp_mul_output_int
- \int_eval:w \l_fp_mul_output_int + #1 * #2 \scan_stop:
- }
-% \end{macrocode}
-% At the end of each output group of three, there is a transfer of
-% information so that there is no danger of an overflow. This is done by
-% expansion to keep the number of calculations down.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_mul_end_level:
- {
- \tex_advance:D \l_fp_mul_output_int \c_one_thousand_million
- \exp_after:wN \use_i:nn \exp_after:wN
- \fp_mul_end_level:NNNNNNNNN \int_use:N \l_fp_mul_output_int
- }
-\cs_new_protected:Npn \fp_mul_end_level:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {
- \tl_set:Nx \l_fp_mul_output_tl { #7#8#9 \l_fp_mul_output_tl }
- \l_fp_mul_output_int #1#2#3#4#5#6 \scan_stop:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+% ^^A todo
+% ^^A \section{Rounding}
+% ^^A
+% ^^A This explains how to go from a floating point number to a
+% ^^A rounded value for various applications. Perhaps worth coding
+% ^^A functionalities up to what siunitx can do on this matter.
%
-% \begin{macro}{\fp_div:Nn, \fp_div:cn}
-% \UnitTested
-% \begin{macro}{\fp_gdiv:Nn,\fp_gdiv:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_div_aux:NNn}
-% \begin{macro}{\fp_div_internal:}
-% \begin{macro}[aux]{\fp_div_loop:}
-% \begin{macro}[aux]{\fp_div_divide:}
-% \begin{macro}[aux]{\fp_div_divide_aux:}
-% \begin{macro}[aux]{\fp_div_store:}
-% \begin{macro}[aux]{\fp_div_store_integer:}
-% \begin{macro}[aux]{\fp_div_store_decimal:}
-% The pattern is much the same for multiplication.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_div:Nn { \fp_div_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gdiv:Nn { \fp_div_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_div:Nn { c }
-\cs_generate_variant:Nn \fp_gdiv:Nn { c }
-% \end{macrocode}
-% Division proper starts with a couple of tests. If the denominator is
-% zero then a error is issued. On the other hand, if the numerator is
-% zero then the result must be $0.0$ and can be given with no
-% further work.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_div_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_read:N #2
- \fp_split:Nn b {#3}
- \fp_standardise:NNNN
- \l_fp_input_b_sign_int
- \l_fp_input_b_integer_int
- \l_fp_input_b_decimal_int
- \l_fp_input_b_exponent_int
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_b_integer_int + \l_fp_input_b_decimal_int
- = \c_zero
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- #1 \exp_not:N #2 { \c_undefined_fp }
- }
- \else:
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_integer_int + \l_fp_input_a_decimal_int
- = \c_zero
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- #1 \exp_not:N #2 { \c_zero_fp }
- }
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN \fp_div_internal:
- \fi:
- \fi:
- \fp_tmp:w #1#2
- }
-% \end{macrocode}
-% The main division algorithm works by finding how many times |b| can
-% be removed from |a|, storing the result and doing the subtraction.
-% Input |a| is then multiplied by $10$, and the process is repeated.
-% The looping ends either when there is nothing left of |a|
-% (\emph{i.e.}~an exact result) or when the code reaches the ninth
-% decimal place. Most of the process takes place in the loop function
-% below.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_div_internal: {
- \l_fp_output_integer_int \c_zero
- \l_fp_output_decimal_int \c_zero
- \cs_set_eq:NN \fp_div_store: \fp_div_store_integer:
- \l_fp_div_offset_int \c_one_hundred_million
- \fp_div_loop:
- \l_fp_output_exponent_int
- \int_eval:w
- \l_fp_input_a_exponent_int - \l_fp_input_b_exponent_int
- \scan_stop:
- \fp_standardise:NNNN
- \l_fp_output_sign_int
- \l_fp_output_integer_int
- \l_fp_output_decimal_int
- \l_fp_output_exponent_int
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 ##2
- {
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_sign_int * \l_fp_input_b_sign_int
- < \c_zero
- \if_int_compare:w
- \int_eval:w
- \l_fp_output_integer_int + \l_fp_output_decimal_int
- = \c_zero
- +
- \else:
- -
- \fi:
- \else:
- +
- \fi:
- \int_use:N \l_fp_output_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_output_decimal_int + \c_one_thousand_million
- \int_eval_end:
- e
- \int_use:N \l_fp_output_exponent_int
- }
- }
-}
-% \end{macrocode}
-% The main loop implements the approach described above. The storing
-% function is done as a function so that the integer and decimal parts
-% can be done separately but rapidly.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_div_loop:
- {
- \l_fp_count_int \c_zero
- \fp_div_divide:
- \fp_div_store:
- \tex_multiply:D \l_fp_input_a_integer_int \c_ten
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \exp_after:wN \fp_div_loop_step:w
- \int_use:N \l_fp_input_a_decimal_int \q_stop
- \if_int_compare:w
- \int_eval:w \l_fp_input_a_integer_int + \l_fp_input_a_decimal_int
- > \c_zero
- \if_int_compare:w \l_fp_div_offset_int > \c_zero
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_div_loop:
- \fi:
- \fi:
- }
-% \end{macrocode}
-% Checking to see if the numerator can be divides needs quite an
-% involved check. Either the integer part has to be bigger for the
-% numerator or, if it is not smaller then the decimal part of the
-% numerator must not be smaller than that of the denominator. Once
-% the test is right the rest is much as elsewhere.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_div_divide:
- {
- \if_int_compare:w \l_fp_input_a_integer_int > \l_fp_input_b_integer_int
- \exp_after:wN \fp_div_divide_aux:
- \else:
- \if_int_compare:w \l_fp_input_a_integer_int < \l_fp_input_b_integer_int
- \else:
- \if_int_compare:w
- \l_fp_input_a_decimal_int < \l_fp_input_b_decimal_int
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_div_divide_aux:
- \fi:
- \fi:
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_div_divide_aux:
- {
- \tex_advance:D \l_fp_count_int \c_one
- \tex_advance:D \l_fp_input_a_integer_int -\l_fp_input_b_integer_int
- \tex_advance:D \l_fp_input_a_decimal_int -\l_fp_input_b_decimal_int
- \if_int_compare:w \l_fp_input_a_decimal_int < \c_zero
- \tex_advance:D \l_fp_input_a_integer_int \c_minus_one
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \fi:
- \fp_div_divide:
- }
-% \end{macrocode}
-% Storing the number of each division is done differently for the
-% integer and decimal. The integer is easy and a one-off, while the
-% decimal also needs to account for the position of the digit to store.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_div_store: { }
-\cs_new_protected_nopar:Npn \fp_div_store_integer:
- {
- \l_fp_output_integer_int \l_fp_count_int
- \cs_set_eq:NN \fp_div_store: \fp_div_store_decimal:
- }
-\cs_new_protected_nopar:Npn \fp_div_store_decimal:
- {
- \l_fp_output_decimal_int
- \int_eval:w
- \l_fp_output_decimal_int +
- \l_fp_count_int * \l_fp_div_offset_int
- \int_eval_end:
- \tex_divide:D \l_fp_div_offset_int \c_ten
- }
-\cs_new_protected:Npn \fp_div_loop_step:w #1#2#3#4#5#6#7#8#9 \q_stop
- {
- \l_fp_input_a_integer_int
- \int_eval:w #2 + \l_fp_input_a_integer_int \int_eval_end:
- \l_fp_input_a_decimal_int #3#4#5#6#7#8#9 0 \scan_stop:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+% ^^A todo
+% ^^A \section{Floating points}
+% ^^A
+% ^^A Here, there may be a discussion of what floating point numbers
+% ^^A are, and a list of relevant resources (\emph{e.g.}, some of
+% ^^A Kahan's articles), and previous \TeX{} packages.
%
-% \subsection{Arithmetic for internal use}
+% \section{Disclaimer and roadmap}
%
-% For the more complex functions, it is only possible to deliver
-% reliable $10$ digit accuracy if the internal calculations are
-% carried out to a higher degree of precision. This is done using a
-% second set of functions so that the `user' versions are not
-% slowed down. These versions are also focussed on the needs of internal
-% calculations. No error checking, sign checking or exponent levelling
-% is done. For addition and subtraction, the arguments are:
+% The package may break down if:
% \begin{itemize}
-% \item Integer part of input |a|.
-% \item Decimal part of input |a|.
-% \item Additional decimal part of input |a|.
-% \item Integer part of input |b|.
-% \item Decimal part of input |b|.
-% \item Additional decimal part of input |b|.
-% \item Integer part of output.
-% \item Decimal part of output.
-% \item Additional decimal part of output.
+% \item the escape character is either a digit, or an underscore,
+% \item the \tn{uccodes} are changed: the test for whether a character
+% is a letter actually tests if the upper-case code of the character
+% is between A and Z.
% \end{itemize}
-% The situation for multiplication and division is a little different as
-% they only deal with the decimal part.
-%
-% \begin{macro}{\fp_add:NNNNNNNNN}
-% The internal sum is always exactly that: it is always a sum and there
-% is no sign check.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_add:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {
- #7 \int_eval:w #1 + #4 \int_eval_end:
- #8 \int_eval:w #2 + #5 \int_eval_end:
- #9 \int_eval:w #3 + #6 \int_eval_end:
- \if_int_compare:w #9 < \c_one_thousand_million
- \else:
- \tex_advance:D #8 \c_one
- \tex_advance:D #9 -\c_one_thousand_million
- \fi:
- \if_int_compare:w #8 < \c_one_thousand_million
- \else:
- \tex_advance:D #7 \c_one
- \tex_advance:D #8 -\c_one_thousand_million
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\fp_sub:NNNNNNNNN}
-% Internal subtraction is needed only when the first number is bigger
-% than the second, so there is no need to worry about the sign. This is
-% a good job as there are no arguments left. The flipping flag is
-% used in the rare case where a sign change is possible.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_sub:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {
- #7 \int_eval:w #1 - #4 \int_eval_end:
- #8 \int_eval:w #2 - #5 \int_eval_end:
- #9 \int_eval:w #3 - #6 \int_eval_end:
- \if_int_compare:w #9 < \c_zero
- \tex_advance:D #8 \c_minus_one
- \tex_advance:D #9 \c_one_thousand_million
- \fi:
- \if_int_compare:w #8 < \c_zero
- \tex_advance:D #7 \c_minus_one
- \tex_advance:D #8 \c_one_thousand_million
- \fi:
- \if_int_compare:w #7 < \c_zero
- \if_int_compare:w \int_eval:w #8 + #9 = \c_zero
- #7 -#7
- \else:
- \tex_advance:D #7 \c_one
- #8 \int_eval:w \c_one_thousand_million - #8 \int_eval_end:
- #9 \int_eval:w \c_one_thousand_million - #9 \int_eval_end:
- \fi:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\fp_mul:NNNNNN}
-% Decimal-part only multiplication but with higher accuracy than the
-% user version.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_mul:NNNNNN #1#2#3#4#5#6
- {
- \fp_mul_split:NNNN #1
- \l_fp_mul_a_i_int \l_fp_mul_a_ii_int \l_fp_mul_a_iii_int
- \fp_mul_split:NNNN #2
- \l_fp_mul_a_iv_int \l_fp_mul_a_v_int \l_fp_mul_a_vi_int
- \fp_mul_split:NNNN #3
- \l_fp_mul_b_i_int \l_fp_mul_b_ii_int \l_fp_mul_b_iii_int
- \fp_mul_split:NNNN #4
- \l_fp_mul_b_iv_int \l_fp_mul_b_v_int \l_fp_mul_b_vi_int
- \l_fp_mul_output_int \c_zero
- \tl_clear:N \l_fp_mul_output_tl
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_vi_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_v_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_iv_int
- \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_v_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_vi_int \l_fp_mul_b_i_int
- \tex_divide:D \l_fp_mul_output_int \c_one_thousand
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_v_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_iv_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_v_int \l_fp_mul_b_i_int
- \fp_mul_end_level:
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_iv_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_i_int
- \fp_mul_end_level:
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_i_int
- \fp_mul_end_level:
- #6 0 \l_fp_mul_output_tl \scan_stop:
- \tl_clear:N \l_fp_mul_output_tl
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_i_int
- \fp_mul_end_level:
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_i_int
- \fp_mul_end_level:
- \fp_mul_end_level:
- #5 0 \l_fp_mul_output_tl \scan_stop:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\fp_mul:NNNNNNNNN}
-% For internal multiplication where the integer does need to be
-% retained. This means of course that this code is quite slow, and so
-% is only used when necessary.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_mul:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {
- \fp_mul_split:NNNN #2
- \l_fp_mul_a_i_int \l_fp_mul_a_ii_int \l_fp_mul_a_iii_int
- \fp_mul_split:NNNN #3
- \l_fp_mul_a_iv_int \l_fp_mul_a_v_int \l_fp_mul_a_vi_int
- \fp_mul_split:NNNN #5
- \l_fp_mul_b_i_int \l_fp_mul_b_ii_int \l_fp_mul_b_iii_int
- \fp_mul_split:NNNN #6
- \l_fp_mul_b_iv_int \l_fp_mul_b_v_int \l_fp_mul_b_vi_int
- \l_fp_mul_output_int \c_zero
- \tl_clear:N \l_fp_mul_output_tl
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_vi_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_v_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_iv_int
- \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_v_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_vi_int \l_fp_mul_b_i_int
- \tex_divide:D \l_fp_mul_output_int \c_one_thousand
- \fp_mul_product:NN #1 \l_fp_mul_b_vi_int
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_v_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_iv_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_v_int \l_fp_mul_b_i_int
- \fp_mul_product:NN \l_fp_mul_a_vi_int #4
- \fp_mul_end_level:
- \fp_mul_product:NN #1 \l_fp_mul_b_v_int
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_iv_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_iv_int \l_fp_mul_b_i_int
- \fp_mul_product:NN \l_fp_mul_a_v_int #4
- \fp_mul_end_level:
- \fp_mul_product:NN #1 \l_fp_mul_b_iv_int
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int \l_fp_mul_b_i_int
- \fp_mul_product:NN \l_fp_mul_a_iv_int #4
- \fp_mul_end_level:
- #9 0 \l_fp_mul_output_tl \scan_stop:
- \tl_clear:N \l_fp_mul_output_tl
- \fp_mul_product:NN #1 \l_fp_mul_b_iii_int
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int \l_fp_mul_b_i_int
- \fp_mul_product:NN \l_fp_mul_a_iii_int #4
- \fp_mul_end_level:
- \fp_mul_product:NN #1 \l_fp_mul_b_ii_int
- \fp_mul_product:NN \l_fp_mul_a_i_int \l_fp_mul_b_i_int
- \fp_mul_product:NN \l_fp_mul_a_ii_int #4
- \fp_mul_end_level:
- \fp_mul_product:NN #1 \l_fp_mul_b_i_int
- \fp_mul_product:NN \l_fp_mul_a_i_int #4
- \fp_mul_end_level:
- #8 0 \l_fp_mul_output_tl \scan_stop:
- \tl_clear:N \l_fp_mul_output_tl
- \fp_mul_product:NN #1 #4
- \fp_mul_end_level:
- #7 0 \l_fp_mul_output_tl \scan_stop:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\fp_div_integer:NNNNN}
-% Here, division is always by an integer, and so it is possible to
-% use \TeX{}'s native calculations rather than doing it in macros.
-% The idea here is to divide the decimal part, find any remainder,
-% then do the real division of the two parts before adding in what
-% is needed for the remainder.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_div_integer:NNNNN #1#2#3#4#5
- {
- \l_fp_internal_int #1
- \tex_divide:D \l_fp_internal_int #3
- \l_fp_internal_int \int_eval:w #1 - \l_fp_internal_int * #3 \int_eval_end:
- #4 #1
- \tex_divide:D #4 #3
- #5 #2
- \tex_divide:D #5 #3
- \tex_multiply:D \l_fp_internal_int \c_one_thousand
- \tex_divide:D \l_fp_internal_int #3
- #5 \int_eval:w #5 + \l_fp_internal_int * \c_one_million \int_eval_end:
- \if_int_compare:w #5 > \c_one_thousand_million
- \tex_advance:D #4 \c_one
- \tex_advance:D #5 -\c_one_thousand_million
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\fp_extended_normalise:}
-% \begin{macro}[aux]{\fp_extended_normalise_aux_i:}
-% \begin{macro}[aux]{\fp_extended_normalise_aux_i:w}
-% \begin{macro}[aux]{\fp_extended_normalise_aux_ii:w}
-% \begin{macro}[aux]{\fp_extended_normalise_aux_ii:}
-% \begin{macro}[aux]{\fp_extended_normalise_aux:NNNNNNNNN}
-% The \enquote{extended} integers for internal use are mainly used in
-% fixed-point mode. This comes up in a few places, so a generalised
-% utility is made available to carry out the change. This function
-% simply calls the two loops to shift the input to the point of
-% having a zero exponent.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_extended_normalise:
- {
- \fp_extended_normalise_aux_i:
- \fp_extended_normalise_aux_ii:
- }
-\cs_new_protected_nopar:Npn \fp_extended_normalise_aux_i:
- {
- \if_int_compare:w \l_fp_input_a_exponent_int > \c_zero
- \tex_multiply:D \l_fp_input_a_integer_int \c_ten
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \exp_after:wN \fp_extended_normalise_aux_i:w
- \int_use:N \l_fp_input_a_decimal_int \q_stop
- \exp_after:wN \fp_extended_normalise_aux_i:
- \fi:
- }
-\cs_new_protected:Npn \fp_extended_normalise_aux_i:w
- #1#2#3#4#5#6#7#8#9 \q_stop
- {
- \l_fp_input_a_integer_int
- \int_eval:w \l_fp_input_a_integer_int + #2 \scan_stop:
- \l_fp_input_a_decimal_int #3#4#5#6#7#8#9 0 \scan_stop:
- \tex_advance:D \l_fp_input_a_extended_int \c_one_thousand_million
- \exp_after:wN \fp_extended_normalise_aux_ii:w
- \int_use:N \l_fp_input_a_extended_int \q_stop
- }
-\cs_new_protected:Npn \fp_extended_normalise_aux_ii:w
- #1#2#3#4#5#6#7#8#9 \q_stop
- {
- \l_fp_input_a_decimal_int
- \int_eval:w \l_fp_input_a_decimal_int + #2 \scan_stop:
- \l_fp_input_a_extended_int #3#4#5#6#7#8#9 0 \scan_stop:
- \tex_advance:D \l_fp_input_a_exponent_int \c_minus_one
- }
-\cs_new_protected_nopar:Npn \fp_extended_normalise_aux_ii:
- {
- \if_int_compare:w \l_fp_input_a_exponent_int < \c_zero
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \exp_after:wN \use_i:nn \exp_after:wN
- \fp_extended_normalise_ii_aux:NNNNNNNNN
- \int_use:N \l_fp_input_a_decimal_int
- \exp_after:wN \fp_extended_normalise_aux_ii:
- \fi:
- }
-\cs_new_protected:Npn \fp_extended_normalise_ii_aux:NNNNNNNNN
- #1#2#3#4#5#6#7#8#9
- {
- \if_int_compare:w \l_fp_input_a_integer_int = \c_zero
- \l_fp_input_a_decimal_int #1#2#3#4#5#6#7#8 \scan_stop:
- \else:
- \tl_set:Nx \l_fp_internal_tl
- {
- \int_use:N \l_fp_input_a_integer_int
- #1#2#3#4#5#6#7#8
- }
- \l_fp_input_a_integer_int \c_zero
- \l_fp_input_a_decimal_int \l_fp_internal_tl \scan_stop:
- \fi:
- \tex_divide:D \l_fp_input_a_extended_int \c_ten
- \tl_set:Nx \l_fp_internal_tl
- {
- #9
- \int_use:N \l_fp_input_a_extended_int
- }
- \l_fp_input_a_extended_int \l_fp_internal_tl \scan_stop:
- \tex_advance:D \l_fp_input_a_exponent_int \c_one
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_extended_normalise_output:}
-% \begin{macro}[aux]{\fp_extended_normalise_output_aux_i:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_extended_normalise_output_aux_ii:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_extended_normalise_output_aux:N}
-% At some stages in working out extended output, it is possible for the
-% value to need shifting to keep the integer part in range. This only
-% ever happens such that the integer needs to be made smaller.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_extended_normalise_output:
- {
- \if_int_compare:w \l_fp_output_integer_int > \c_nine
- \tex_advance:D \l_fp_output_integer_int \c_one_thousand_million
- \exp_after:wN \use_i:nn \exp_after:wN
- \fp_extended_normalise_output_aux_i:NNNNNNNNN
- \int_use:N \l_fp_output_integer_int
- \exp_after:wN \fp_extended_normalise_output:
- \fi:
- }
-\cs_new_protected:Npn \fp_extended_normalise_output_aux_i:NNNNNNNNN
- #1#2#3#4#5#6#7#8#9
- {
- \l_fp_output_integer_int #1#2#3#4#5#6#7#8 \scan_stop:
- \tex_advance:D \l_fp_output_decimal_int \c_one_thousand_million
- \tl_set:Nx \l_fp_internal_tl
- {
- #9
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_output_decimal_int
- }
- \exp_after:wN \fp_extended_normalise_output_aux_ii:NNNNNNNNN
- \l_fp_internal_tl
- }
-\cs_new_protected:Npn \fp_extended_normalise_output_aux_ii:NNNNNNNNN
- #1#2#3#4#5#6#7#8#9
- {
- \l_fp_output_decimal_int #1#2#3#4#5#6#7#8#9 \scan_stop:
- \fp_extended_normalise_output_aux:N
- }
-\cs_new_protected:Npn \fp_extended_normalise_output_aux:N #1
- {
- \tex_advance:D \l_fp_output_extended_int \c_one_thousand_million
- \tex_divide:D \l_fp_output_extended_int \c_ten
- \tl_set:Nx \l_fp_internal_tl
- {
- #1
- \exp_after:wN \use_none:n
- \int_use:N \l_fp_output_extended_int
- }
- \l_fp_output_extended_int \l_fp_internal_tl \scan_stop:
- \tex_advance:D \l_fp_output_exponent_int \c_one
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Trigonometric functions}
-%
-% \begin{macro}{\fp_trig_normalise:}
-% \begin{macro}[aux]{\fp_trig_normalise_aux:}
-% \begin{macro}[aux]{\fp_trig_sub:NNN}
-% For normalisation, the code essentially switches to fixed-point
-% arithmetic. There is a shift of the exponent, then repeated
-% subtractions. The end result is a number in the range
-% $ -\pi < x \le \pi $.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_trig_normalise:
- {
- \if_int_compare:w \l_fp_input_a_exponent_int < \c_ten
- \l_fp_input_a_extended_int \c_zero
- \fp_extended_normalise:
- \fp_trig_normalise_aux:
- \if_int_compare:w \l_fp_input_a_integer_int < \c_zero
- \l_fp_input_a_sign_int -\l_fp_input_a_sign_int
- \l_fp_input_a_integer_int -\l_fp_input_a_integer_int
- \fi:
- \exp_after:wN \fp_trig_octant:
- \else:
- \l_fp_input_a_sign_int \c_one
- \l_fp_output_integer_int \c_zero
- \l_fp_output_decimal_int \c_zero
- \l_fp_output_exponent_int \c_zero
- \exp_after:wN \fp_trig_overflow_msg:
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_trig_normalise_aux:
- {
- \if_int_compare:w \l_fp_input_a_integer_int > \c_three
- \fp_trig_sub:NNN
- \c_six \c_fp_two_pi_decimal_int \c_fp_two_pi_extended_int
- \exp_after:wN \fp_trig_normalise_aux:
- \else:
- \if_int_compare:w \l_fp_input_a_integer_int > \c_two
- \if_int_compare:w \l_fp_input_a_decimal_int > \c_fp_pi_decimal_int
- \fp_trig_sub:NNN
- \c_six \c_fp_two_pi_decimal_int \c_fp_two_pi_extended_int
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_trig_normalise_aux:
- \fi:
- \fi:
- \fi:
- }
-% \end{macrocode}
-% Here, there may be a sign change but there will never be any
-% variation in the input. So a dedicated function can be used.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_trig_sub:NNN #1#2#3
- {
- \l_fp_input_a_integer_int
- \int_eval:w \l_fp_input_a_integer_int - #1 \int_eval_end:
- \l_fp_input_a_decimal_int
- \int_eval:w \l_fp_input_a_decimal_int - #2 \int_eval_end:
- \l_fp_input_a_extended_int
- \int_eval:w \l_fp_input_a_extended_int - #3 \int_eval_end:
- \if_int_compare:w \l_fp_input_a_extended_int < \c_zero
- \tex_advance:D \l_fp_input_a_decimal_int \c_minus_one
- \tex_advance:D \l_fp_input_a_extended_int \c_one_thousand_million
- \fi:
- \if_int_compare:w \l_fp_input_a_decimal_int < \c_zero
- \tex_advance:D \l_fp_input_a_integer_int \c_minus_one
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \fi:
- \if_int_compare:w \l_fp_input_a_integer_int < \c_zero
- \l_fp_input_a_sign_int -\l_fp_input_a_sign_int
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_decimal_int + \l_fp_input_a_extended_int
- = \c_zero
- \l_fp_input_a_integer_int -\l_fp_input_a_integer_int
- \else:
- \l_fp_input_a_integer_int
- \int_eval:w
- - \l_fp_input_a_integer_int - \c_one
- \int_eval_end:
- \l_fp_input_a_decimal_int
- \int_eval:w
- \c_one_thousand_million - \l_fp_input_a_decimal_int
- \int_eval_end:
- \l_fp_input_a_extended_int
- \int_eval:w
- \c_one_thousand_million - \l_fp_input_a_extended_int
- \int_eval_end:
- \fi:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_trig_octant:}
-% \begin{macro}[aux]
-% {\fp_trig_octant_aux_i:, \fp_trig_octant_aux_ii:}
-% Here, the input is further reduced into the range
-% $ 0 < x \le \pi / 4 $. This is pretty simple: check if
-% $ \pi / 4 $ can be taken off and if it can do it and loop. The
-% check at the end is to \enquote{mop up} values which are so close to
-% $ \pi / 4 $ that they should be treated as such. The test for
-% an even octant is needed as the `remainder' needed is from
-% the nearest $ \pi / 2 $. The check for octant $4$ is needed as an exact
-% $\pi$ input will otherwise end up in the wrong place!
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_trig_octant:
- {
- \l_fp_trig_octant_int \c_one
- \fp_trig_octant_aux_i:
- \if_int_compare:w \l_fp_input_a_decimal_int < \c_ten
- \l_fp_input_a_decimal_int \c_zero
- \l_fp_input_a_extended_int \c_zero
- \fi:
- \if_int_odd:w \l_fp_trig_octant_int
- \else:
- \fp_sub:NNNNNNNNN
- \c_zero \c_fp_pi_by_four_decimal_int \c_fp_pi_by_four_extended_int
- \l_fp_input_a_integer_int \l_fp_input_a_decimal_int
- \l_fp_input_a_extended_int
- \l_fp_input_a_integer_int \l_fp_input_a_decimal_int
- \l_fp_input_a_extended_int
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_trig_octant_aux_i:
- {
- \if_int_compare:w \l_fp_trig_octant_int > \c_four
- \l_fp_trig_octant_int \c_four
- \l_fp_input_a_decimal_int \c_fp_pi_by_four_decimal_int
- \l_fp_input_a_extended_int \c_fp_pi_by_four_extended_int
- \else:
- \exp_after:wN \fp_trig_octant_aux_ii:
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_trig_octant_aux_ii:
- {
- \if_int_compare:w \l_fp_input_a_integer_int > \c_zero
- \fp_sub:NNNNNNNNN
- \l_fp_input_a_integer_int \l_fp_input_a_decimal_int
- \l_fp_input_a_extended_int
- \c_zero \c_fp_pi_by_four_decimal_int \c_fp_pi_by_four_extended_int
- \l_fp_input_a_integer_int \l_fp_input_a_decimal_int
- \l_fp_input_a_extended_int
- \tex_advance:D \l_fp_trig_octant_int \c_one
- \exp_after:wN \fp_trig_octant_aux_i:
- \else:
- \if_int_compare:w
- \l_fp_input_a_decimal_int > \c_fp_pi_by_four_decimal_int
- \fp_sub:NNNNNNNNN
- \l_fp_input_a_integer_int \l_fp_input_a_decimal_int
- \l_fp_input_a_extended_int
- \c_zero \c_fp_pi_by_four_decimal_int
- \c_fp_pi_by_four_extended_int
- \l_fp_input_a_integer_int \l_fp_input_a_decimal_int
- \l_fp_input_a_extended_int
- \tex_advance:D \l_fp_trig_octant_int \c_one
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_trig_octant_aux_i:
- \fi:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_sin:Nn, \fp_sin:cn}
-% \UnitTested
-% \begin{macro}{\fp_gsin:Nn,\fp_gsin:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_sin_aux:NNn}
-% \begin{macro}[aux]{\fp_sin_aux_i:}
-% \begin{macro}[aux]{\fp_sin_aux_ii:}
-% Calculating the sine starts off in the usual way. There is a check
-% to see if the value has already been worked out before proceeding
-% further.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_sin:Nn { \fp_sin_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gsin:Nn { \fp_sin_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_sin:Nn { c }
-\cs_generate_variant:Nn \fp_gsin:Nn { c }
-% \end{macrocode}
-% The internal routine for sines does a check to see if the value is
-% already known. This saves a lot of repetition when doing rotations.
-% For very small values it is best to simply return the input as the
-% sine: the cut-off is $ 1 \times 10^{-5} $.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_sin_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_split:Nn a {#3}
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \tl_set:Nx \l_fp_arg_tl
- {
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- -
- \else:
- +
- \fi:
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_input_a_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- \if_int_compare:w \l_fp_input_a_exponent_int < -\c_five
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2 { \l_fp_arg_tl }
- }
- \else:
- \if_cs_exist:w
- c_fp_sin ( \l_fp_arg_tl ) _fp
- \cs_end:
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_sin_aux_i:
- \fi:
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- { \use:c { c_fp_sin ( \l_fp_arg_tl ) _fp } }
- }
- \fi:
- \fp_tmp:w
- }
-% \end{macrocode}
-% The internals for sine first normalise the input into an octant, then
-% choose the correct set up for the Taylor series. The sign for the sine
-% function is easy, so there is no worry about it. So the only thing to
-% do is to get the output standardised.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_sin_aux_i:
- {
- \fp_trig_normalise:
- \fp_sin_aux_ii:
- \if_int_compare:w \l_fp_output_integer_int = \c_one
- \l_fp_output_exponent_int \c_zero
- \else:
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_decimal_int \l_fp_output_extended_int
- \l_fp_output_exponent_int -\c_nine
- \fi:
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_output_integer_int
- \l_fp_output_decimal_int
- \l_fp_output_exponent_int
- \tl_new:c { c_fp_sin ( \l_fp_arg_tl ) _fp }
- \tl_gset:cx { c_fp_sin ( \l_fp_arg_tl ) _fp }
- {
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- +
- \else:
- -
- \fi:
- \int_use:N \l_fp_output_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_output_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_output_exponent_int
- }
- }
-\cs_new_protected_nopar:Npn \fp_sin_aux_ii:
- {
- \if_case:w \l_fp_trig_octant_int
- \or:
- \exp_after:wN \fp_trig_calc_sin:
- \or:
- \exp_after:wN \fp_trig_calc_cos:
- \or:
- \exp_after:wN \fp_trig_calc_cos:
- \or:
- \exp_after:wN \fp_trig_calc_sin:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_cos:Nn, \fp_cos:cn}
-% \UnitTested
-% \begin{macro}{\fp_gcos:Nn,\fp_gcos:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_cos_aux:NNn}
-% \begin{macro}[aux]{\fp_cos_aux_i:}
-% \begin{macro}[aux]{\fp_cos_aux_ii:}
-% Cosine is almost identical, but there is no short cut code here.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_cos:Nn { \fp_cos_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gcos:Nn { \fp_cos_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_cos:Nn { c }
-\cs_generate_variant:Nn \fp_gcos:Nn { c }
-\cs_new_protected:Npn \fp_cos_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_split:Nn a {#3}
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \tl_set:Nx \l_fp_arg_tl
- {
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- -
- \else:
- +
- \fi:
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_input_a_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- \if_cs_exist:w c_fp_cos ( \l_fp_arg_tl ) _fp \cs_end:
- \else:
- \exp_after:wN \fp_cos_aux_i:
- \fi:
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- { \use:c { c_fp_cos ( \l_fp_arg_tl ) _fp } }
- }
- \fp_tmp:w
- }
-% \end{macrocode}
-% Almost the same as for sine: just a bit of correction for the sign
-% of the output.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_cos_aux_i:
- {
- \fp_trig_normalise:
- \fp_cos_aux_ii:
- \if_int_compare:w \l_fp_output_integer_int = \c_one
- \l_fp_output_exponent_int \c_zero
- \else:
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_decimal_int \l_fp_output_extended_int
- \l_fp_output_exponent_int -\c_nine
- \fi:
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_output_integer_int
- \l_fp_output_decimal_int
- \l_fp_output_exponent_int
- \tl_new:c { c_fp_cos ( \l_fp_arg_tl ) _fp }
- \tl_gset:cx { c_fp_cos ( \l_fp_arg_tl ) _fp }
- {
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- +
- \else:
- -
- \fi:
- \int_use:N \l_fp_output_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_output_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_output_exponent_int
- }
- }
-\cs_new_protected_nopar:Npn \fp_cos_aux_ii:
- {
- \if_case:w \l_fp_trig_octant_int
- \or:
- \exp_after:wN \fp_trig_calc_cos:
- \or:
- \exp_after:wN \fp_trig_calc_sin:
- \or:
- \exp_after:wN \fp_trig_calc_sin:
- \or:
- \exp_after:wN \fp_trig_calc_cos:
- \fi:
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \if_int_compare:w \l_fp_trig_octant_int > \c_two
- \l_fp_input_a_sign_int \c_minus_one
- \fi:
- \else:
- \if_int_compare:w \l_fp_trig_octant_int > \c_two
- \else:
- \l_fp_input_a_sign_int \c_one
- \fi:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_trig_calc_cos:}
-% \begin{macro}{\fp_trig_calc_sin:}
-% \begin{macro}[aux]{\fp_trig_calc_Taylor:}
-% These functions actually do the calculation for sine and cosine.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_trig_calc_cos:
- {
- \if_int_compare:w \l_fp_input_a_decimal_int = \c_zero
- \l_fp_output_integer_int \c_one
- \l_fp_output_decimal_int \c_zero
- \else:
- \l_fp_trig_sign_int \c_minus_one
- \fp_mul:NNNNNN
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \fp_div_integer:NNNNN
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \c_two
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \l_fp_count_int \c_three
- \if_int_compare:w \l_fp_trig_extended_int = \c_zero
- \if_int_compare:w \l_fp_trig_decimal_int = \c_zero
- \l_fp_output_integer_int \c_one
- \l_fp_output_decimal_int \c_zero
- \l_fp_output_extended_int \c_zero
- \else:
- \l_fp_output_integer_int \c_zero
- \l_fp_output_decimal_int \c_one_thousand_million
- \l_fp_output_extended_int \c_zero
- \fi:
- \else:
- \l_fp_output_integer_int \c_zero
- \l_fp_output_decimal_int 999999999 \scan_stop:
- \l_fp_output_extended_int \c_one_thousand_million
- \fi:
- \tex_advance:D \l_fp_output_extended_int -\l_fp_trig_extended_int
- \tex_advance:D \l_fp_output_decimal_int -\l_fp_trig_decimal_int
- \exp_after:wN \fp_trig_calc_Taylor:
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_trig_calc_sin:
- {
- \l_fp_output_integer_int \c_zero
- \if_int_compare:w \l_fp_input_a_decimal_int = \c_zero
- \l_fp_output_decimal_int \c_zero
- \else:
- \l_fp_output_decimal_int \l_fp_input_a_decimal_int
- \l_fp_output_extended_int \l_fp_input_a_extended_int
- \l_fp_trig_sign_int \c_one
- \l_fp_trig_decimal_int \l_fp_input_a_decimal_int
- \l_fp_trig_extended_int \l_fp_input_a_extended_int
- \l_fp_count_int \c_two
- \exp_after:wN \fp_trig_calc_Taylor:
- \fi:
- }
-% \end{macrocode}
-% This implements a Taylor series calculation for the trigonometric
-% functions. Lots of shuffling about as \TeX\ is not exactly a natural
-% choice for this sort of thing.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_trig_calc_Taylor:
- {
- \l_fp_trig_sign_int -\l_fp_trig_sign_int
- \fp_mul:NNNNNN
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \fp_mul:NNNNNN
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \fp_div_integer:NNNNN
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \l_fp_count_int
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \tex_advance:D \l_fp_count_int \c_one
- \fp_div_integer:NNNNN
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \l_fp_count_int
- \l_fp_trig_decimal_int \l_fp_trig_extended_int
- \tex_advance:D \l_fp_count_int \c_one
- \if_int_compare:w \l_fp_trig_decimal_int > \c_zero
- \if_int_compare:w \l_fp_trig_sign_int > \c_zero
- \tex_advance:D \l_fp_output_decimal_int \l_fp_trig_decimal_int
- \tex_advance:D \l_fp_output_extended_int
- \l_fp_trig_extended_int
- \if_int_compare:w \l_fp_output_extended_int < \c_one_thousand_million
- \else:
- \tex_advance:D \l_fp_output_decimal_int \c_one
- \tex_advance:D \l_fp_output_extended_int
- -\c_one_thousand_million
- \fi:
- \if_int_compare:w \l_fp_output_decimal_int < \c_one_thousand_million
- \else:
- \tex_advance:D \l_fp_output_integer_int \c_one
- \tex_advance:D \l_fp_output_decimal_int
- -\c_one_thousand_million
- \fi:
- \else:
- \tex_advance:D \l_fp_output_decimal_int -\l_fp_trig_decimal_int
- \tex_advance:D \l_fp_output_extended_int
- -\l_fp_input_a_extended_int
- \if_int_compare:w \l_fp_output_extended_int < \c_zero
- \tex_advance:D \l_fp_output_decimal_int \c_minus_one
- \tex_advance:D \l_fp_output_extended_int \c_one_thousand_million
- \fi:
- \if_int_compare:w \l_fp_output_decimal_int < \c_zero
- \tex_advance:D \l_fp_output_integer_int \c_minus_one
- \tex_advance:D \l_fp_output_decimal_int \c_one_thousand_million
- \fi:
- \fi:
- \exp_after:wN \fp_trig_calc_Taylor:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_tan:Nn, \fp_tan:cn}
-% \UnitTested
-% \begin{macro}{\fp_gtan:Nn,\fp_gtan:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_tan_aux:NNn}
-% \begin{macro}[aux]{\fp_tan_aux_i:}
-% \begin{macro}[aux]{\fp_tan_aux_ii:}
-% \begin{macro}[aux]{\fp_tan_aux_iii:}
-% \begin{macro}[aux]{\fp_tan_aux_iv:}
-% As might be expected, tangents are calculated from the sine and cosine
-% by division. So there is a bit of set up, the two subsidiary pieces
-% of work are done and then a division takes place. For small numbers,
-% the same approach is used as for sines, with the input value simply
-% returned as is.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_tan:Nn { \fp_tan_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gtan:Nn { \fp_tan_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_tan:Nn { c }
-\cs_generate_variant:Nn \fp_gtan:Nn { c }
-\cs_new_protected:Npn \fp_tan_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_split:Nn a {#3}
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \tl_set:Nx \l_fp_arg_tl
- {
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- -
- \else:
- +
- \fi:
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_input_a_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- \if_int_compare:w \l_fp_input_a_exponent_int < -\c_five
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2 { \l_fp_arg_tl }
- }
- \else:
- \if_cs_exist:w
- c_fp_tan ( \l_fp_arg_tl ) _fp
- \cs_end:
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_tan_aux_i:
- \fi:
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- { \use:c { c_fp_tan ( \l_fp_arg_tl ) _fp } }
- }
- \fi:
- \fp_tmp:w
- }
-% \end{macrocode}
-% The business of the calculation does not check for stored sines or
-% cosines as there would then be an overhead to reading them back in.
-% There is also no need to worry about \enquote{small} sine values as
-% these will have been dealt with earlier. There is a two-step lead off
-% so that undefined division is not even attempted.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_tan_aux_i:
- {
- \if_int_compare:w \l_fp_input_a_exponent_int < \c_ten
- \exp_after:wN \fp_tan_aux_ii:
- \else:
- \cs_new_eq:cN { c_fp_tan ( \l_fp_arg_tl ) _fp }
- \c_zero_fp
- \exp_after:wN \fp_trig_overflow_msg:
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_tan_aux_ii:
- {
- \fp_trig_normalise:
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \if_int_compare:w \l_fp_trig_octant_int > \c_two
- \l_fp_output_sign_int \c_minus_one
- \else:
- \l_fp_output_sign_int \c_one
- \fi:
- \else:
- \if_int_compare:w \l_fp_trig_octant_int > \c_two
- \l_fp_output_sign_int \c_one
- \else:
- \l_fp_output_sign_int \c_minus_one
- \fi:
- \fi:
- \fp_cos_aux_ii:
- \if_int_compare:w \l_fp_input_a_decimal_int = \c_zero
- \if_int_compare:w \l_fp_input_a_integer_int = \c_zero
- \cs_new_eq:cN { c_fp_tan ( \l_fp_arg_tl ) _fp }
- \c_undefined_fp
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_tan_aux_iii:
- \fi:
- \else:
- \exp_after:wN \fp_tan_aux_iii:
- \fi:
- }
-% \end{macrocode}
-% The division is done here using the same code as the standard division
-% unit, shifting the digits in the calculated sine and cosine to
-% maintain accuracy.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_tan_aux_iii:
- {
- \l_fp_input_b_integer_int \l_fp_output_decimal_int
- \l_fp_input_b_decimal_int \l_fp_output_extended_int
- \l_fp_input_b_exponent_int -\c_nine
- \fp_standardise:NNNN
- \l_fp_input_b_sign_int
- \l_fp_input_b_integer_int
- \l_fp_input_b_decimal_int
- \l_fp_input_b_exponent_int
- \fp_sin_aux_ii:
- \l_fp_input_a_integer_int \l_fp_output_decimal_int
- \l_fp_input_a_decimal_int \l_fp_output_extended_int
- \l_fp_input_a_exponent_int -\c_nine
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \if_int_compare:w \l_fp_input_a_decimal_int = \c_zero
- \if_int_compare:w \l_fp_input_a_integer_int = \c_zero
- \cs_new_eq:cN { c_fp_tan ( \l_fp_arg_tl ) _fp }
- \c_zero_fp
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN \fp_tan_aux_iv:
- \fi:
- \else:
- \exp_after:wN \fp_tan_aux_iv:
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_tan_aux_iv:
- {
- \l_fp_output_integer_int \c_zero
- \l_fp_output_decimal_int \c_zero
- \cs_set_eq:NN \fp_div_store: \fp_div_store_integer:
- \l_fp_div_offset_int \c_one_hundred_million
- \fp_div_loop:
- \l_fp_output_exponent_int
- \int_eval:w
- \l_fp_input_a_exponent_int - \l_fp_input_b_exponent_int
- \int_eval_end:
- \fp_standardise:NNNN
- \l_fp_output_sign_int
- \l_fp_output_integer_int
- \l_fp_output_decimal_int
- \l_fp_output_exponent_int
- \tl_new:c { c_fp_tan ( \l_fp_arg_tl ) _fp }
- \tl_gset:cx { c_fp_tan ( \l_fp_arg_tl ) _fp }
- {
- \if_int_compare:w \l_fp_output_sign_int > \c_zero
- +
- \else:
- -
- \fi:
- \int_use:N \l_fp_output_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_output_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_output_exponent_int
- }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Exponent and logarithm functions}
-%
-% \begin{variable}{\c_fp_exp_1_tl}
-% \begin{variable}{\c_fp_exp_2_tl}
-% \begin{variable}{\c_fp_exp_3_tl}
-% \begin{variable}{\c_fp_exp_4_tl}
-% \begin{variable}{\c_fp_exp_5_tl}
-% \begin{variable}{\c_fp_exp_6_tl}
-% \begin{variable}{\c_fp_exp_7_tl}
-% \begin{variable}{\c_fp_exp_8_tl}
-% \begin{variable}{\c_fp_exp_9_tl}
-% \begin{variable}{\c_fp_exp_10_tl}
-% \begin{variable}{\c_fp_exp_20_tl}
-% \begin{variable}{\c_fp_exp_30_tl}
-% \begin{variable}{\c_fp_exp_40_tl}
-% \begin{variable}{\c_fp_exp_50_tl}
-% \begin{variable}{\c_fp_exp_60_tl}
-% \begin{variable}{\c_fp_exp_70_tl}
-% \begin{variable}{\c_fp_exp_80_tl}
-% \begin{variable}{\c_fp_exp_90_tl}
-% \begin{variable}{\c_fp_exp_100_tl}
-% \begin{variable}{\c_fp_exp_200_tl}
-% Calculation of exponentials requires a number of precomputed values:
-% first the positive integers.
-% \begin{macrocode}
-\tl_const:cn { c_fp_exp_1_tl } { { 2 } { 718281828 } { 459045235 } { 0 } }
-\tl_const:cn { c_fp_exp_2_tl } { { 7 } { 389056098 } { 930650227 } { 0 } }
-\tl_const:cn { c_fp_exp_3_tl } { { 2 } { 008553692 } { 318766774 } { 1 } }
-\tl_const:cn { c_fp_exp_4_tl } { { 5 } { 459815003 } { 314423908 } { 1 } }
-\tl_const:cn { c_fp_exp_5_tl } { { 1 } { 484131591 } { 025766034 } { 2 } }
-\tl_const:cn { c_fp_exp_6_tl } { { 4 } { 034287934 } { 927351226 } { 2 } }
-\tl_const:cn { c_fp_exp_7_tl } { { 1 } { 096633158 } { 428458599 } { 3 } }
-\tl_const:cn { c_fp_exp_8_tl } { { 2 } { 980957987 } { 041728275 } { 3 } }
-\tl_const:cn { c_fp_exp_9_tl } { { 8 } { 103083927 } { 575384008 } { 3 } }
-\tl_const:cn { c_fp_exp_10_tl } { { 2 } { 202646579 } { 480671652 } { 4 } }
-\tl_const:cn { c_fp_exp_20_tl } { { 4 } { 851651954 } { 097902280 } { 8 } }
-\tl_const:cn { c_fp_exp_30_tl } { { 1 } { 068647458 } { 152446215 } { 13 } }
-\tl_const:cn { c_fp_exp_40_tl } { { 2 } { 353852668 } { 370199854 } { 17 } }
-\tl_const:cn { c_fp_exp_50_tl } { { 5 } { 184705528 } { 587072464 } { 21 } }
-\tl_const:cn { c_fp_exp_60_tl } { { 1 } { 142007389 } { 815684284 } { 26 } }
-\tl_const:cn { c_fp_exp_70_tl } { { 2 } { 515438670 } { 919167006 } { 30 } }
-\tl_const:cn { c_fp_exp_80_tl } { { 5 } { 540622384 } { 393510053 } { 34 } }
-\tl_const:cn { c_fp_exp_90_tl } { { 1 } { 220403294 } { 317840802 } { 39 } }
-\tl_const:cn { c_fp_exp_100_tl } { { 2 } { 688117141 } { 816135448 } { 43 } }
-\tl_const:cn { c_fp_exp_200_tl } { { 7 } { 225973768 } { 125749258 } { 86 } }
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{variable}{\c_fp_exp_-1_tl}
-% \begin{variable}{\c_fp_exp_-2_tl}
-% \begin{variable}{\c_fp_exp_-3_tl}
-% \begin{variable}{\c_fp_exp_-4_tl}
-% \begin{variable}{\c_fp_exp_-5_tl}
-% \begin{variable}{\c_fp_exp_-6_tl}
-% \begin{variable}{\c_fp_exp_-7_tl}
-% \begin{variable}{\c_fp_exp_-8_tl}
-% \begin{variable}{\c_fp_exp_-9_tl}
-% \begin{variable}{\c_fp_exp_-10_tl}
-% \begin{variable}{\c_fp_exp_-20_tl}
-% \begin{variable}{\c_fp_exp_-30_tl}
-% \begin{variable}{\c_fp_exp_-40_tl}
-% \begin{variable}{\c_fp_exp_-50_tl}
-% \begin{variable}{\c_fp_exp_-60_tl}
-% \begin{variable}{\c_fp_exp_-70_tl}
-% \begin{variable}{\c_fp_exp_-80_tl}
-% \begin{variable}{\c_fp_exp_-90_tl}
-% \begin{variable}{\c_fp_exp_-100_tl}
-% \begin{variable}{\c_fp_exp_-200_tl}
-% Now the negative integers.
-% \begin{macrocode}
-\tl_const:cn { c_fp_exp_-1_tl } { { 3 } { 678794411 } { 71442322 } { -1 } }
-\tl_const:cn { c_fp_exp_-2_tl } { { 1 } { 353352832 } { 366132692 } { -1 } }
-\tl_const:cn { c_fp_exp_-3_tl } { { 4 } { 978706836 } { 786394298 } { -2 } }
-\tl_const:cn { c_fp_exp_-4_tl } { { 1 } { 831563888 } { 873418029 } { -2 } }
-\tl_const:cn { c_fp_exp_-5_tl } { { 6 } { 737946999 } { 085467097 } { -3 } }
-\tl_const:cn { c_fp_exp_-6_tl } { { 2 } { 478752176 } { 666358423 } { -3 } }
-\tl_const:cn { c_fp_exp_-7_tl } { { 9 } { 118819655 } { 545162080 } { -4 } }
-\tl_const:cn { c_fp_exp_-8_tl } { { 3 } { 354626279 } { 025118388 } { -4 } }
-\tl_const:cn { c_fp_exp_-9_tl } { { 1 } { 234098040 } { 866795495 } { -4 } }
-\tl_const:cn { c_fp_exp_-10_tl } { { 4 } { 539992976 } { 248451536 } { -5 } }
-\tl_const:cn { c_fp_exp_-20_tl } { { 2 } { 061153622 } { 438557828 } { -9 } }
-\tl_const:cn { c_fp_exp_-30_tl } { { 9 } { 357622968 } { 840174605 } { -14 } }
-\tl_const:cn { c_fp_exp_-40_tl } { { 4 } { 248354255 } { 291588995 } { -18 } }
-\tl_const:cn { c_fp_exp_-50_tl } { { 1 } { 928749847 } { 963917783 } { -22 } }
-\tl_const:cn { c_fp_exp_-60_tl } { { 8 } { 756510762 } { 696520338 } { -27 } }
-\tl_const:cn { c_fp_exp_-70_tl } { { 3 } { 975449735 } { 908646808 } { -31 } }
-\tl_const:cn { c_fp_exp_-80_tl } { { 1 } { 804851387 } { 845415172 } { -35 } }
-\tl_const:cn { c_fp_exp_-90_tl } { { 8 } { 194012623 } { 990515430 } { -40 } }
-\tl_const:cn { c_fp_exp_-100_tl } { { 3 } { 720075976 } { 020835963 } { -44 } }
-\tl_const:cn { c_fp_exp_-200_tl } { { 1 } { 383896526 } { 736737530 } { -87 } }
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{macro}{\fp_exp:Nn, \fp_exp:cn}
-% \UnitTested
-% \begin{macro}{\fp_gexp:Nn,\fp_gexp:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_exp_aux:NNn}
-% \begin{macro}[aux]{\fp_exp_internal:}
-% \begin{macro}[aux]{\fp_exp_aux:}
-% \begin{macro}[aux]{\fp_exp_integer:}
-% \begin{macro}[aux]{\fp_exp_integer_tens:}
-% \begin{macro}[aux]{\fp_exp_integer_units:}
-% \begin{macro}[aux]{\fp_exp_integer_const:n}
-% \begin{macro}[aux]{\fp_exp_integer_const:nnnn}
-% \begin{macro}[aux]{\fp_exp_decimal:}
-% \begin{macro}[aux]{\fp_exp_Taylor:}
-% \begin{macro}[aux]{\fp_exp_const:Nx}
-% \begin{macro}[aux]{\fp_exp_const:cx}
-% The calculation of an exponent starts off starts in much the same
-% way as the trigonometric functions: normalise the input, look for
-% a pre-defined value and if one is not found hand off to the real
-% workhorse function. The test for a definition of the result is used
-% so that overflows do not result in any outcome being defined.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_exp:Nn { \fp_exp_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gexp:Nn { \fp_exp_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_exp:Nn { c }
-\cs_generate_variant:Nn \fp_gexp:Nn { c }
-\cs_new_protected:Npn \fp_exp_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_split:Nn a {#3}
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \l_fp_input_a_extended_int \c_zero
- \tl_set:Nx \l_fp_arg_tl
- {
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- -
- \else:
- +
- \fi:
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_input_a_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- \if_cs_exist:w c_fp_exp ( \l_fp_arg_tl ) _fp \cs_end:
- \else:
- \exp_after:wN \fp_exp_internal:
- \fi:
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- #1 \exp_not:N #2
- {
- \if_cs_exist:w c_fp_exp ( \l_fp_arg_tl ) _fp
- \cs_end:
- \use:c { c_fp_exp ( \l_fp_arg_tl ) _fp }
- \else:
- \c_zero_fp
- \fi:
- }
- }
- \fp_tmp:w
- }
-% \end{macrocode}
-% The first real step is to convert the input into a fixed-point
-% representation for further calculation: anything which is dropped
-% here as too small would not influence the output in any case. There
-% are a couple of overflow tests: the maximum
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_exp_internal:
- {
- \if_int_compare:w \l_fp_input_a_exponent_int < \c_three
- \fp_extended_normalise:
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \if_int_compare:w \l_fp_input_a_integer_int < 230 \scan_stop:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_exp_aux:
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_exp_overflow_msg:
- \fi:
- \else:
- \if_int_compare:w \l_fp_input_a_integer_int < 230 \scan_stop:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_exp_aux:
- \else:
- \fp_exp_const:cx { c_fp_exp ( \l_fp_arg_tl ) _fp }
- { \c_zero_fp }
- \fi:
- \fi:
- \else:
- \exp_after:wN \fp_exp_overflow_msg:
- \fi:
- }
-% \end{macrocode}
-% The main algorithm makes use of the fact that
-% \[
-% \mathrm{e}^{nmp.q} =
-% \mathrm{e}^{n}
-% \mathrm{e}^{m}
-% \mathrm{e}^{p}
-% \mathrm{e}^{0.q}
-% \]
-% and that there is a Taylor series that can be used to calculate
-% $ \mathrm{e}^{0.q} $. Thus the approach needed is in three parts.
-% First, the exponent of the integer part of the input is found
-% using the pre-calculated constants. Second, the Taylor series is
-% used to find the exponent for the decimal part of the input. Finally,
-% the two parts are multiplied together to give the result. As the
-% normalisation code will already have dealt with any overflowing
-% values, there are no further checks needed.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_exp_aux:
- {
- \if_int_compare:w \l_fp_input_a_integer_int > \c_zero
- \exp_after:wN \fp_exp_integer:
- \else:
- \l_fp_output_integer_int \c_one
- \l_fp_output_decimal_int \c_zero
- \l_fp_output_extended_int \c_zero
- \l_fp_output_exponent_int \c_zero
- \exp_after:wN \fp_exp_decimal:
- \fi:
- }
-% \end{macrocode}
-% The integer part calculation starts with the hundreds. This is
-% set up such that very large negative numbers can short-cut the entire
-% procedure and simply return zero. In other cases, the code either
-% recovers the exponent of the hundreds value or sets the appropriate
-% storage to one (so that multiplication works correctly).
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_exp_integer:
- {
- \if_int_compare:w \l_fp_input_a_integer_int < \c_one_hundred
- \l_fp_exp_integer_int \c_one
- \l_fp_exp_decimal_int \c_zero
- \l_fp_exp_extended_int \c_zero
- \l_fp_exp_exponent_int \c_zero
- \exp_after:wN \fp_exp_integer_tens:
- \else:
- \tl_set:Nx \l_fp_internal_tl
- {
- \exp_after:wN \use_i:nnn
- \int_use:N \l_fp_input_a_integer_int
- }
- \l_fp_input_a_integer_int
- \int_eval:w
- \l_fp_input_a_integer_int - \l_fp_internal_tl 00
- \int_eval_end:
- \if_int_compare:w \l_fp_input_a_sign_int < \c_zero
- \if_int_compare:w \l_fp_output_integer_int > 200 \scan_stop:
- \fp_exp_const:cx { c_fp_exp ( \l_fp_arg_tl ) _fp }
- { \c_zero_fp }
- \else:
- \fp_exp_integer_const:n { - \l_fp_internal_tl 00 }
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_exp_integer_tens:
- \fi:
- \else:
- \fp_exp_integer_const:n { \l_fp_internal_tl 00 }
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_exp_integer_tens:
- \fi:
- \fi:
- }
-% \end{macrocode}
-% The tens and units parts are handled in a similar way, with a
-% multiplication step to build up the final value. That also includes a
-% correction step to avoid an overflow of the integer part.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_exp_integer_tens:
- {
- \l_fp_output_integer_int \l_fp_exp_integer_int
- \l_fp_output_decimal_int \l_fp_exp_decimal_int
- \l_fp_output_extended_int \l_fp_exp_extended_int
- \l_fp_output_exponent_int \l_fp_exp_exponent_int
- \if_int_compare:w \l_fp_input_a_integer_int > \c_nine
- \tl_set:Nx \l_fp_internal_tl
- {
- \exp_after:wN \use_i:nn
- \int_use:N \l_fp_input_a_integer_int
- }
- \l_fp_input_a_integer_int
- \int_eval:w
- \l_fp_input_a_integer_int - \l_fp_internal_tl 0
- \int_eval_end:
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \fp_exp_integer_const:n { \l_fp_internal_tl 0 }
- \else:
- \fp_exp_integer_const:n { - \l_fp_internal_tl 0 }
- \fi:
- \fp_mul:NNNNNNNNN
- \l_fp_exp_integer_int \l_fp_exp_decimal_int \l_fp_exp_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \tex_advance:D \l_fp_output_exponent_int \l_fp_exp_exponent_int
- \fp_extended_normalise_output:
- \fi:
- \fp_exp_integer_units:
- }
-\cs_new_protected_nopar:Npn \fp_exp_integer_units:
- {
- \if_int_compare:w \l_fp_input_a_integer_int > \c_zero
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \fp_exp_integer_const:n { \int_use:N \l_fp_input_a_integer_int }
- \else:
- \fp_exp_integer_const:n
- { - \int_use:N \l_fp_input_a_integer_int }
- \fi:
- \fp_mul:NNNNNNNNN
- \l_fp_exp_integer_int \l_fp_exp_decimal_int \l_fp_exp_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \tex_advance:D \l_fp_output_exponent_int \l_fp_exp_exponent_int
- \fp_extended_normalise_output:
- \fi:
- \fp_exp_decimal:
- }
-% \end{macrocode}
-% Recovery of the stored constant values into the separate registers
-% is done with a simple expansion then assignment.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_exp_integer_const:n #1
- {
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_exp_integer_const:nnnn
- \cs:w c_fp_exp_ #1 _tl \cs_end:
- }
-\cs_new_protected:Npn \fp_exp_integer_const:nnnn #1#2#3#4
- {
- \l_fp_exp_integer_int #1 \scan_stop:
- \l_fp_exp_decimal_int #2 \scan_stop:
- \l_fp_exp_extended_int #3 \scan_stop:
- \l_fp_exp_exponent_int #4 \scan_stop:
- }
-% \end{macrocode}
-% Finding the exponential for the decimal part of the number requires
-% a Taylor series calculation. The set up is done here with the loop
-% itself a separate function. Once the decimal part is available this
-% is multiplied by the integer part already worked out to give
-% the final result.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_exp_decimal:
- {
- \if_int_compare:w \l_fp_input_a_decimal_int > \c_zero
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \l_fp_exp_integer_int \c_one
- \l_fp_exp_decimal_int \l_fp_input_a_decimal_int
- \l_fp_exp_extended_int \l_fp_input_a_extended_int
- \else:
- \l_fp_exp_integer_int \c_zero
- \if_int_compare:w \l_fp_exp_extended_int = \c_zero
- \l_fp_exp_decimal_int
- \int_eval:w
- \c_one_thousand_million - \l_fp_input_a_decimal_int
- \int_eval_end:
- \l_fp_exp_extended_int \c_zero
- \else:
- \l_fp_exp_decimal_int
- \int_eval:w
- 999999999 - \l_fp_input_a_decimal_int
- \scan_stop:
- \l_fp_exp_extended_int
- \int_eval:w
- \c_one_thousand_million - \l_fp_input_a_extended_int
- \int_eval_end:
- \fi:
- \fi:
- \l_fp_input_b_sign_int \l_fp_input_a_sign_int
- \l_fp_input_b_decimal_int \l_fp_input_a_decimal_int
- \l_fp_input_b_extended_int \l_fp_input_a_extended_int
- \l_fp_count_int \c_one
- \fp_exp_Taylor:
- \fp_mul:NNNNNNNNN
- \l_fp_exp_integer_int \l_fp_exp_decimal_int \l_fp_exp_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \fi:
- \if_int_compare:w \l_fp_output_extended_int < \c_five_hundred_million
- \else:
- \tex_advance:D \l_fp_output_decimal_int \c_one
- \if_int_compare:w \l_fp_output_decimal_int < \c_one_thousand_million
- \else:
- \l_fp_output_decimal_int \c_zero
- \tex_advance:D \l_fp_output_integer_int \c_one
- \fi:
- \fi:
- \fp_standardise:NNNN
- \l_fp_output_sign_int
- \l_fp_output_integer_int
- \l_fp_output_decimal_int
- \l_fp_output_exponent_int
- \fp_exp_const:cx { c_fp_exp ( \l_fp_arg_tl ) _fp }
- {
- +
- \int_use:N \l_fp_output_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_output_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_output_exponent_int
- }
- }
-% \end{macrocode}
-% The Taylor series for $ \exp(x) $ is
-% \[
-% 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \frac{x^4}{4!} + \cdots
-% \]
-% which converges for $ -1 < x < 1 $. The code above sets up
-% the $ x $ part, leaving the loop to multiply the running
-% value by $ x / n $ and add it onto the sum. The way that this is
-% done is that the running total is stored in the \texttt{exp} set of
-% registers, while the current item is stored as \texttt{input_b}.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_exp_Taylor:
- {
- \tex_advance:D \l_fp_count_int \c_one
- \tex_multiply:D \l_fp_input_b_sign_int \l_fp_input_a_sign_int
- \fp_mul:NNNNNN
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \l_fp_input_b_decimal_int \l_fp_input_b_extended_int
- \l_fp_input_b_decimal_int \l_fp_input_b_extended_int
- \fp_div_integer:NNNNN
- \l_fp_input_b_decimal_int \l_fp_input_b_extended_int
- \l_fp_count_int
- \l_fp_input_b_decimal_int \l_fp_input_b_extended_int
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_b_decimal_int + \l_fp_input_b_extended_int
- > \c_zero
- \if_int_compare:w \l_fp_input_b_sign_int > \c_zero
- \tex_advance:D \l_fp_exp_decimal_int \l_fp_input_b_decimal_int
- \tex_advance:D \l_fp_exp_extended_int
- \l_fp_input_b_extended_int
- \if_int_compare:w \l_fp_exp_extended_int < \c_one_thousand_million
- \else:
- \tex_advance:D \l_fp_exp_decimal_int \c_one
- \tex_advance:D \l_fp_exp_extended_int
- -\c_one_thousand_million
- \fi:
- \if_int_compare:w \l_fp_exp_decimal_int < \c_one_thousand_million
- \else:
- \tex_advance:D \l_fp_exp_integer_int \c_one
- \tex_advance:D \l_fp_exp_decimal_int
- -\c_one_thousand_million
- \fi:
- \else:
- \tex_advance:D \l_fp_exp_decimal_int -\l_fp_input_b_decimal_int
- \tex_advance:D \l_fp_exp_extended_int
- -\l_fp_input_a_extended_int
- \if_int_compare:w \l_fp_exp_extended_int < \c_zero
- \tex_advance:D \l_fp_exp_decimal_int \c_minus_one
- \tex_advance:D \l_fp_exp_extended_int \c_one_thousand_million
- \fi:
- \if_int_compare:w \l_fp_exp_decimal_int < \c_zero
- \tex_advance:D \l_fp_exp_integer_int \c_minus_one
- \tex_advance:D \l_fp_exp_decimal_int \c_one_thousand_million
- \fi:
- \fi:
- \exp_after:wN \fp_exp_Taylor:
- \fi:
- }
-% \end{macrocode}
-% This is set up as a function so that the power code can redirect
-% the effect.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_exp_const:Nx #1#2
- {
- \tl_new:N #1
- \tl_gset:Nx #1 {#2}
- }
-\cs_generate_variant:Nn \fp_exp_const:Nx { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{variable}{\c_fp_ln_10_1_tl}
-% \begin{variable}{\c_fp_ln_10_2_tl}
-% \begin{variable}{\c_fp_ln_10_3_tl}
-% \begin{variable}{\c_fp_ln_10_4_tl}
-% \begin{variable}{\c_fp_ln_10_5_tl}
-% \begin{variable}{\c_fp_ln_10_6_tl}
-% \begin{variable}{\c_fp_ln_10_7_tl}
-% \begin{variable}{\c_fp_ln_10_8_tl}
-% \begin{variable}{\c_fp_ln_10_9_tl}
-% Constants for working out logarithms: first those for the powers of
-% ten.
-% \begin{macrocode}
-\tl_const:cn { c_fp_ln_10_1_tl } { { 2 } { 302585092 } { 994045684 } { 0 } }
-\tl_const:cn { c_fp_ln_10_2_tl } { { 4 } { 605170185 } { 988091368 } { 0 } }
-\tl_const:cn { c_fp_ln_10_3_tl } { { 6 } { 907755278 } { 982137052 } { 0 } }
-\tl_const:cn { c_fp_ln_10_4_tl } { { 9 } { 210340371 } { 976182736 } { 0 } }
-\tl_const:cn { c_fp_ln_10_5_tl } { { 1 } { 151292546 } { 497022842 } { 1 } }
-\tl_const:cn { c_fp_ln_10_6_tl } { { 1 } { 381551055 } { 796427410 } { 1 } }
-\tl_const:cn { c_fp_ln_10_7_tl } { { 1 } { 611809565 } { 095831979 } { 1 } }
-\tl_const:cn { c_fp_ln_10_8_tl } { { 1 } { 842068074 } { 395226547 } { 1 } }
-\tl_const:cn { c_fp_ln_10_9_tl } { { 2 } { 072326583 } { 694641116 } { 1 } }
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%^^A 0.69...309 4.
-% \begin{variable}{\c_fp_ln_2_1_tl }
-% \begin{variable}{\c_fp_ln_2_2_tl }
-% \begin{variable}{\c_fp_ln_2_3_tl }
-% The smaller set for powers of two.
-% \begin{macrocode}
-\tl_const:cn { c_fp_ln_2_1_tl } { { 0 } { 693147180 } { 559945309 } { 0 } }
-\tl_const:cn { c_fp_ln_2_2_tl } { { 1 } { 386294361 } { 119890618 } { 0 } }
-\tl_const:cn { c_fp_ln_2_3_tl } { { 2 } { 079441541 } { 679835928 } { 0 } }
-% \end{macrocode}
-% \end{variable}
-% \end{variable}
-% \end{variable}
-%
-% \begin{macro}{\fp_ln:Nn, \fp_ln:cn}
-% \UnitTested
-% \begin{macro}{\fp_gln:Nn,\fp_gln:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_ln_aux:NNn}
-% \begin{macro}[aux]{\fp_ln_aux:}
-% \begin{macro}[aux]{\fp_ln_exponent:}
-% \begin{macro}[aux]{\fp_ln_internal:}
-% \begin{macro}[aux]{\fp_ln_exponent_tens:}
-% \begin{macro}[aux]{\fp_ln_exponent_units:}
-% \begin{macro}[aux]{\fp_ln_normalise:}
-% \begin{macro}[aux]{\fp_ln_nornalise_aux:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_ln_mantissa:}
-% \begin{macro}[aux]{\fp_ln_mantissa_aux:}
-% \begin{macro}[aux]{\fp_ln_mantissa_divide_two:}
-% \begin{macro}[aux]{\fp_ln_integer_const:nn}
-% \begin{macro}[aux]{\fp_ln_Taylor:}
-% \begin{macro}[aux]{\fp_ln_fixed:}
-% \begin{macro}[aux]{\fp_ln_fixed_aux:NNNNNNNNN}
-% \begin{macro}[aux]{\fp_ln_Taylor_aux:}
-% The approach for logarithms is again based on a mix of tables and
-% Taylor series. Here, the initial validation is a bit easier and so it
-% is set up earlier, meaning less need to escape later on.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln:Nn { \fp_ln_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gln:Nn { \fp_ln_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_ln:Nn { c }
-\cs_generate_variant:Nn \fp_gln:Nn { c }
-\cs_new_protected:Npn \fp_ln_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_split:Nn a {#3}
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_integer_int + \l_fp_input_a_decimal_int
- > \c_zero
- \exp_after:wN \exp_after:wN \exp_after:wN \fp_ln_aux:
- \else:
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 \exp_not:N ##2 { \c_zero_fp }
- }
- \exp_after:wN \exp_after:wN \exp_after:wN \fp_ln_error_msg:
- \fi:
- \else:
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 \exp_not:N ##2 { \c_zero_fp }
- }
- \exp_after:wN \fp_ln_error_msg:
- \fi:
- \fp_tmp:w #1 #2
- }
-% \end{macrocode}
-% As the input at this stage meets the validity criteria above, the
-% argument can now be saved for further processing. There is no need
-% to look at the sign of the input as it must be positive. The function
-% here simply sets up to either do the full calculation or recover
-% the stored value, as appropriate.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln_aux:
- {
- \tl_set:Nx \l_fp_arg_tl
- {
- +
- \int_use:N \l_fp_input_a_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_input_a_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_input_a_exponent_int
- }
- \if_cs_exist:w c_fp_ln ( \l_fp_arg_tl ) _fp \cs_end:
- \else:
- \exp_after:wN \fp_ln_exponent:
- \fi:
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 \exp_not:N ##2
- { \use:c { c_fp_ln ( \l_fp_arg_tl ) _fp } }
- }
- }
-% \end{macrocode}
-% The main algorithm here uses the fact the logarithm can be divided
-% up, first taking out the powers of ten, then powers of two and finally
-% using a Taylor series for the remainder.
-% \[
-% \ln ( 10^{n} \times 2^{m} \times x )
-% = \ln ( 10^{n} ) + \ln ( 2^{m} ) + \ln ( x )
-% \]
-% The second point to remember is that
-% \[
-% \ln ( x^{-1} ) = - \ln ( x )
-% \]
-% which means that for the powers of $ 10 $ and $ 2 $ constants
-% are only needed for positive powers.
-%
-% The first step is to set up the sign for the output functions and
-% work out the powers of ten in the exponent. First the larger powers
-% are sorted out. The values for the constants are the same as those
-% for the smaller ones, just with a shift in the exponent.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln_exponent:
- {
- \fp_ln_internal:
- \if_int_compare:w \l_fp_output_extended_int < \c_five_hundred_million
- \else:
- \tex_advance:D \l_fp_output_decimal_int \c_one
- \if_int_compare:w \l_fp_output_decimal_int < \c_one_thousand_million
- \else:
- \l_fp_output_decimal_int \c_zero
- \tex_advance:D \l_fp_output_integer_int \c_one
- \fi:
- \fi:
- \fp_standardise:NNNN
- \l_fp_output_sign_int
- \l_fp_output_integer_int
- \l_fp_output_decimal_int
- \l_fp_output_exponent_int
- \tl_const:cx { c_fp_ln ( \l_fp_arg_tl ) _fp }
- {
- \if_int_compare:w \l_fp_output_sign_int > \c_zero
- +
- \else:
- -
- \fi:
- \int_use:N \l_fp_output_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_output_decimal_int + \c_one_thousand_million
- \scan_stop:
- e
- \int_use:N \l_fp_output_exponent_int
- }
- }
-\cs_new_protected_nopar:Npn \fp_ln_internal:
- {
- \if_int_compare:w \l_fp_input_a_exponent_int < \c_zero
- \l_fp_input_a_exponent_int -\l_fp_input_a_exponent_int
- \l_fp_output_sign_int \c_minus_one
- \else:
- \l_fp_output_sign_int \c_one
- \fi:
- \if_int_compare:w \l_fp_input_a_exponent_int > \c_nine
- \exp_after:wN \fp_ln_exponent_tens:NN
- \int_use:N \l_fp_input_a_exponent_int
- \else:
- \l_fp_output_integer_int \c_zero
- \l_fp_output_decimal_int \c_zero
- \l_fp_output_extended_int \c_zero
- \l_fp_output_exponent_int \c_zero
- \fi:
- \fp_ln_exponent_units:
- }
-\cs_new_protected:Npn \fp_ln_exponent_tens:NN #1 #2
- {
- \l_fp_input_a_exponent_int #2 \scan_stop:
- \fp_ln_const:nn { 10 } { #1 }
- \tex_advance:D \l_fp_exp_exponent_int \c_one
- \l_fp_output_integer_int \l_fp_exp_integer_int
- \l_fp_output_decimal_int \l_fp_exp_decimal_int
- \l_fp_output_extended_int \l_fp_exp_extended_int
- \l_fp_output_exponent_int \l_fp_exp_exponent_int
- }
-% \end{macrocode}
-% Next the smaller powers of ten, which will need to be combined
-% with the above: always an additive process.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln_exponent_units:
- {
- \if_int_compare:w \l_fp_input_a_exponent_int > \c_zero
- \fp_ln_const:nn { 10 } { \int_use:N \l_fp_input_a_exponent_int }
- \fp_ln_normalise:
- \fp_add:NNNNNNNNN
- \l_fp_exp_integer_int \l_fp_exp_decimal_int \l_fp_exp_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \fi:
- \fp_ln_mantissa:
- }
-% \end{macrocode}
-% The smaller table-based parts may need to be exponent shifted so that
-% they stay in line with the larger parts. This is similar to the
-% approach in other places, but here there is a need to watch the
-% extended part of the number. The only case where the new exponent is
-% larger than the old is if there was no previous part. Then simply set
-% the exponent.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln_normalise:
- {
- \if_int_compare:w \l_fp_exp_exponent_int < \l_fp_output_exponent_int
- \tex_advance:D \l_fp_exp_decimal_int \c_one_thousand_million
- \exp_after:wN \use_i:nn \exp_after:wN
- \fp_ln_normalise_aux:NNNNNNNNN
- \int_use:N \l_fp_exp_decimal_int
- \exp_after:wN \fp_ln_normalise:
- \else:
- \l_fp_output_exponent_int \l_fp_exp_exponent_int
- \fi:
- }
-\cs_new_protected:Npn \fp_ln_normalise_aux:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {
- \if_int_compare:w \l_fp_exp_integer_int = \c_zero
- \l_fp_exp_decimal_int #1#2#3#4#5#6#7#8 \scan_stop:
- \else:
- \tl_set:Nx \l_fp_internal_tl
- {
- \int_use:N \l_fp_exp_integer_int
- #1#2#3#4#5#6#7#8
- }
- \l_fp_exp_integer_int \c_zero
- \l_fp_exp_decimal_int \l_fp_internal_tl \scan_stop:
- \fi:
- \tex_divide:D \l_fp_exp_extended_int \c_ten
- \tl_set:Nx \l_fp_internal_tl
- {
- #9
- \int_use:N \l_fp_exp_extended_int
- }
- \l_fp_exp_extended_int \l_fp_internal_tl \scan_stop:
- \tex_advance:D \l_fp_exp_exponent_int \c_one
- }
-% \end{macrocode}
-% The next phase is to decompose the mantissa by division by two to
-% leave a value which is in the range $ 1 \le x < 2 $. The sum of the
-% two powers needs to take account of the sign of the output: if it
-% is negative then the result gets \emph{smaller} as the mantissa gets
-% \emph{bigger}.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln_mantissa:
- {
- \l_fp_count_int \c_zero
- \l_fp_input_a_extended_int \c_zero
- \fp_ln_mantissa_aux:
- \if_int_compare:w \l_fp_count_int > \c_zero
- \fp_ln_const:nn { 2 } { \int_use:N \l_fp_count_int }
- \fp_ln_normalise:
- \if_int_compare:w \l_fp_output_sign_int > \c_zero
- \exp_after:wN \fp_add:NNNNNNNNN
- \else:
- \exp_after:wN \fp_sub:NNNNNNNNN
- \fi:
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \l_fp_exp_integer_int \l_fp_exp_decimal_int \l_fp_exp_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \fi:
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_integer_int + \l_fp_input_a_decimal_int > \c_one
- \exp_after:wN \fp_ln_Taylor:
- \fi:
- }
-\cs_new_protected_nopar:Npn \fp_ln_mantissa_aux:
- {
- \if_int_compare:w \l_fp_input_a_integer_int > \c_one
- \tex_advance:D \l_fp_count_int \c_one
- \fp_ln_mantissa_divide_two:
- \exp_after:wN \fp_ln_mantissa_aux:
- \fi:
- }
-% \end{macrocode}
-% A fast one-shot division by two.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln_mantissa_divide_two:
- {
- \if_int_odd:w \l_fp_input_a_decimal_int
- \tex_advance:D \l_fp_input_a_extended_int \c_one_thousand_million
- \fi:
- \if_int_odd:w \l_fp_input_a_integer_int
- \tex_advance:D \l_fp_input_a_decimal_int \c_one_thousand_million
- \fi:
- \tex_divide:D \l_fp_input_a_integer_int \c_two
- \tex_divide:D \l_fp_input_a_decimal_int \c_two
- \tex_divide:D \l_fp_input_a_extended_int \c_two
- }
-% \end{macrocode}
-% Recovering constants makes use of the same auxiliary code as for
-% exponents.
-% \begin{macrocode}
-\cs_new_protected:Npn \fp_ln_const:nn #1#2
- {
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_exp_integer_const:nnnn
- \cs:w c_fp_ln_ #1 _ #2 _tl \cs_end:
- }
-% \end{macrocode}
-% The Taylor series for the logarithm function is best implemented using
-% the identity
-% \[
-% \ln(x) = \ln\left( \frac{y + 1}{y - 1} \right)
-% \]
-% with
-% \[
-% y = \frac{x - 1}{x + 1}
-% \]
-% This leads to the series
-% \[
-% \ln(x)
-% = 2y
-% \left(
-% 1 + y^{2}
-% \left(
-% \frac{1}{3} + y^{2}
-% \left(
-% \frac{1}{5} + y^{2}
-% \left(
-% \frac{1}{7} + y^{2}
-% \left(
-% \frac{1}{9} + \cdots
-% \right)
-% \right)
-% \right)
-% \right)
-% \right)
-% \]
-% This expansion has the advantage that a lot of the work can be
-% loaded up early by finding $ y^{2} $ before the loop itself starts.
-% (In practice, the implementation does the multiplication by two at the
-% end of the loop, and expands out the brackets as this is an overall
-% more efficient approach.)
-%
-% At the implementation level, the code starts by calculating $ y $
-% and storing that in input \texttt{a} (which is no longer needed
-% for other purposes). That is done using the full division system
-% avoiding the parsing step. The value is then switched to a fixed-point
-% representation. There is then some shuffling to get all of the working
-% space set up. At this stage, a lot of registers are in use and so
-% the Taylor series is calculated within a group so that the
-% \texttt{output} variables can be used to hold the result. The value
-% of $ y^{2} $ is held in input \texttt{b} (there are a few
-% assignments saved by choosing this over \texttt{a}), while input
-% \texttt{a} is used for the \enquote{loop value}.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln_Taylor:
- {
- \group_begin:
- \l_fp_input_a_integer_int \c_zero
- \l_fp_input_a_exponent_int \c_zero
- \l_fp_input_b_integer_int \c_two
- \l_fp_input_b_decimal_int \l_fp_input_a_decimal_int
- \l_fp_input_b_exponent_int \c_zero
- \fp_div_internal:
- \fp_ln_fixed:
- \l_fp_input_a_integer_int \l_fp_output_integer_int
- \l_fp_input_a_decimal_int \l_fp_output_decimal_int
- \l_fp_input_a_extended_int \c_zero
- \l_fp_input_a_exponent_int \l_fp_output_exponent_int
- \l_fp_output_decimal_int \c_zero %^^A Bug?
- \l_fp_output_decimal_int \l_fp_input_a_decimal_int
- \l_fp_output_extended_int \l_fp_input_a_extended_int
- \fp_mul:NNNNNN
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \l_fp_input_b_decimal_int \l_fp_input_b_extended_int
- \l_fp_count_int \c_one
- \fp_ln_Taylor_aux:
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- \l_fp_exp_integer_int \c_zero
- \exp_not:N \l_fp_exp_decimal_int
- \int_use:N \l_fp_output_decimal_int \scan_stop:
- \exp_not:N \l_fp_exp_extended_int
- \int_use:N \l_fp_output_extended_int \scan_stop:
- \exp_not:N \l_fp_exp_exponent_int
- \int_use:N \l_fp_output_exponent_int \scan_stop:
- }
- \fp_tmp:w
-% \end{macrocode}
-% After the loop part of the Taylor series, the factor of $ 2 $ needs
-% to be included. The total for the result can then be constructed.
-% \begin{macrocode}
- \tex_advance:D \l_fp_exp_decimal_int \l_fp_exp_decimal_int
- \if_int_compare:w \l_fp_exp_extended_int < \c_five_hundred_million
- \else:
- \tex_advance:D \l_fp_exp_extended_int -\c_five_hundred_million
- \tex_advance:D \l_fp_exp_decimal_int \c_one
- \fi:
- \tex_advance:D \l_fp_exp_extended_int \l_fp_exp_extended_int
- \fp_ln_normalise:
- \if_int_compare:w \l_fp_output_sign_int > \c_zero
- \exp_after:wN \fp_add:NNNNNNNNN
- \else:
- \exp_after:wN \fp_sub:NNNNNNNNN
- \fi:
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \c_zero \l_fp_exp_decimal_int \l_fp_exp_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- }
-% \end{macrocode}
-% The usual shifts to move to fixed-point working. This is done using
-% the \texttt{output} registers as this saves a reassignment here.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln_fixed:
- {
- \if_int_compare:w \l_fp_output_exponent_int < \c_zero
- \tex_advance:D \l_fp_output_decimal_int \c_one_thousand_million
- \exp_after:wN \use_i:nn \exp_after:wN
- \fp_ln_fixed_aux:NNNNNNNNN
- \int_use:N \l_fp_output_decimal_int
- \exp_after:wN \fp_ln_fixed:
- \fi:
- }
-\cs_new_protected:Npn \fp_ln_fixed_aux:NNNNNNNNN #1#2#3#4#5#6#7#8#9
- {
- \if_int_compare:w \l_fp_output_integer_int = \c_zero
- \l_fp_output_decimal_int #1#2#3#4#5#6#7#8 \scan_stop:
- \else:
- \tl_set:Nx \l_fp_internal_tl
- {
- \int_use:N \l_fp_output_integer_int
- #1#2#3#4#5#6#7#8
- }
- \l_fp_output_integer_int \c_zero
- \l_fp_output_decimal_int \l_fp_internal_tl \scan_stop:
- \fi:
- \tex_advance:D \l_fp_output_exponent_int \c_one
- }
-% \end{macrocode}
-% The main loop for the Taylor series: unlike some of the other similar
-% functions, the result here is not the final value and is therefore
-% subject to further manipulation outside of the loop.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_ln_Taylor_aux:
- {
- \tex_advance:D \l_fp_count_int \c_two
- \fp_mul:NNNNNN
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \l_fp_input_b_decimal_int \l_fp_input_b_extended_int
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_decimal_int + \l_fp_input_a_extended_int
- > \c_zero
- \fp_div_integer:NNNNN
- \l_fp_input_a_decimal_int \l_fp_input_a_extended_int
- \l_fp_count_int
- \l_fp_exp_decimal_int \l_fp_exp_extended_int
- \tex_advance:D \l_fp_output_decimal_int \l_fp_exp_decimal_int
- \tex_advance:D \l_fp_output_extended_int \l_fp_exp_extended_int
- \if_int_compare:w \l_fp_output_extended_int < \c_one_thousand_million
- \else:
- \tex_advance:D \l_fp_output_decimal_int \c_one
- \tex_advance:D \l_fp_output_extended_int
- -\c_one_thousand_million
- \fi:
- \if_int_compare:w \l_fp_output_decimal_int < \c_one_thousand_million
- \else:
- \tex_advance:D \l_fp_output_integer_int \c_one
- \tex_advance:D \l_fp_output_decimal_int
- -\c_one_thousand_million
- \fi:
- \exp_after:wN \fp_ln_Taylor_aux:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\fp_pow:Nn, \fp_pow:cn}
-% \UnitTested
-% \begin{macro}{\fp_gpow:Nn,\fp_gpow:cn}
-% \UnitTested
-% \begin{macro}[aux]{\fp_pow_aux:NNn}
-% \begin{macro}[aux]{\fp_pow_aux_i:}
-% \begin{macro}[aux]{\fp_pow_positive:}
-% \begin{macro}[aux]{\fp_pow_negative:}
-% \begin{macro}[aux]{\fp_pow_aux_ii:}
-% \begin{macro}[aux]{\fp_pow_aux_iii:}
-% \begin{macro}[aux]{\fp_pow_aux_iv:}
-% The approach used for working out powers is to first filter out the
-% various special cases and then do most of the work using the
-% logarithm and exponent functions. The two storage areas are used
-% in the reverse of the `natural' logic as this avoids some
-% re-assignment in the sanity checking code.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_pow:Nn { \fp_pow_aux:NNn \tl_set:Nn }
-\cs_new_protected_nopar:Npn \fp_gpow:Nn { \fp_pow_aux:NNn \tl_gset:Nn }
-\cs_generate_variant:Nn \fp_pow:Nn { c }
-\cs_generate_variant:Nn \fp_gpow:Nn { c }
-\cs_new_protected:Npn \fp_pow_aux:NNn #1#2#3
- {
- \group_begin:
- \fp_read:N #2
- \l_fp_input_b_sign_int \l_fp_input_a_sign_int
- \l_fp_input_b_integer_int \l_fp_input_a_integer_int
- \l_fp_input_b_decimal_int \l_fp_input_a_decimal_int
- \l_fp_input_b_exponent_int \l_fp_input_a_exponent_int
- \fp_split:Nn a {#3}
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_b_integer_int + \l_fp_input_b_decimal_int
- = \c_zero
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_integer_int + \l_fp_input_a_decimal_int
- = \c_zero
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 ##2 { \c_undefined_fp }
- }
- \else:
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 ##2 { \c_zero_fp }
- }
- \fi:
- \else:
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_integer_int + \l_fp_input_a_decimal_int
- = \c_zero
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 ##2 { \c_one_fp }
- }
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_pow_aux_i:
- \fi:
- \fi:
- \fp_tmp:w #1 #2
-}
-% \end{macrocode}
-% Simply using the logarithm function directly will fail when negative
-% numbers are raised to integer powers, which is a mathematically valid
-% operation. So there are some more tests to make, after forcing the
-% power into an integer and decimal parts, if necessary.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_pow_aux_i:
- {
- \if_int_compare:w \l_fp_input_b_sign_int > \c_zero
- \tl_set:Nn \l_fp_sign_tl { + }
- \exp_after:wN \fp_pow_aux_ii:
- \else:
- \l_fp_input_a_extended_int \c_zero
- \if_int_compare:w \l_fp_input_a_exponent_int < \c_ten
- \group_begin:
- \fp_extended_normalise:
- \if_int_compare:w
- \int_eval:w
- \l_fp_input_a_decimal_int + \l_fp_input_a_extended_int
- = \c_zero
- \group_end:
- \tl_set:Nn \l_fp_sign_tl { - }
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_pow_aux_ii:
- \else:
- \group_end:
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 ##2 { \c_undefined_fp }
- }
- \fi:
- \else:
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 ##2 { \c_undefined_fp }
- }
- \fi:
- \fi:
- }
-% \end{macrocode}
-% The approach used here for powers works well in most cases but gives
-% poorer results for negative integer powers, which often have exact
-% values. So there is some filtering to do. For negative powers where
-% the power is small, an alternative approach is used in which the
-% positive value is worked out and the reciprocal is then taken. The
-% filtering is unfortunately rather long.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_pow_aux_ii:
- {
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \exp_after:wN \fp_pow_aux_iv:
- \else:
- \if_int_compare:w \l_fp_input_a_exponent_int < \c_ten
- \group_begin:
- \l_fp_input_a_extended_int \c_zero
- \fp_extended_normalise:
- \if_int_compare:w \l_fp_input_a_decimal_int = \c_zero
- \if_int_compare:w \l_fp_input_a_integer_int > \c_ten
- \group_end:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_pow_aux_iv:
- \else:
- \group_end:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_pow_aux_iii:
- \fi:
- \else:
- \group_end:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \exp_after:wN \exp_after:wN
- \exp_after:wN \fp_pow_aux_iv:
- \fi:
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN
- \fp_pow_aux_iv:
- \fi:
- \fi:
- \cs_set_protected:Npx \fp_tmp:w ##1##2
- {
- \group_end:
- ##1 ##2
- {
- \l_fp_sign_tl
- \int_use:N \l_fp_output_integer_int
- .
- \exp_after:wN \use_none:n
- \int_value:w \int_eval:w
- \l_fp_output_decimal_int + \c_one_thousand_million
- e
- \int_use:N \l_fp_output_exponent_int
- }
- }
- }
-% \end{macrocode}
-% For the small negative integer powers, the calculation is done for
-% the positive power and the reciprocal is then taken.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_pow_aux_iii:
- {
- \l_fp_input_a_sign_int \c_one
- \fp_pow_aux_iv:
- \l_fp_input_a_integer_int \c_one
- \l_fp_input_a_decimal_int \c_zero
- \l_fp_input_a_exponent_int \c_zero
- \l_fp_input_b_integer_int \l_fp_output_integer_int
- \l_fp_input_b_decimal_int \l_fp_output_decimal_int
- \l_fp_input_b_exponent_int \l_fp_output_exponent_int
- \fp_div_internal:
- }
-% \end{macrocode}
-% The business end of the code starts by finding the logarithm of the
-% given base. There is a bit of a shuffle so that this does not have
-% to be re-parsed and so that the output ends up in the correct place.
-% There is also a need to enable using the short-cut for a
-% pre-calculated result. The internal part of the multiplication
-% function can then be used to do the second part of the calculation
-% directly. There is some more set up before doing the exponential:
-% the idea here is to deactivate some internals so that everything works
-% smoothly.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \fp_pow_aux_iv:
- {
- \group_begin:
- \l_fp_input_a_integer_int \l_fp_input_b_integer_int
- \l_fp_input_a_decimal_int \l_fp_input_b_decimal_int
- \l_fp_input_a_exponent_int \l_fp_input_b_exponent_int
- \fp_ln_internal:
- \cs_set_protected_nopar:Npx \fp_tmp:w
- {
- \group_end:
- \exp_not:N \l_fp_input_b_sign_int
- \int_use:N \l_fp_output_sign_int \scan_stop:
- \exp_not:N \l_fp_input_b_integer_int
- \int_use:N \l_fp_output_integer_int \scan_stop:
- \exp_not:N \l_fp_input_b_decimal_int
- \int_use:N \l_fp_output_decimal_int \scan_stop:
- \exp_not:N \l_fp_input_b_extended_int
- \int_use:N \l_fp_output_extended_int \scan_stop:
- \exp_not:N \l_fp_input_b_exponent_int
- \int_use:N \l_fp_output_exponent_int \scan_stop:
- }
- \fp_tmp:w
- \l_fp_input_a_extended_int \c_zero
- \fp_mul:NNNNNNNNN
- \l_fp_input_a_integer_int \l_fp_input_a_decimal_int
- \l_fp_input_a_extended_int
- \l_fp_input_b_integer_int \l_fp_input_b_decimal_int
- \l_fp_input_b_extended_int
- \l_fp_output_integer_int \l_fp_output_decimal_int
- \l_fp_output_extended_int
- \l_fp_output_exponent_int
- \int_eval:w
- \l_fp_input_a_exponent_int + \l_fp_input_b_exponent_int
- \scan_stop:
- \fp_extended_normalise_output:
- \tex_multiply:D \l_fp_input_a_sign_int \l_fp_input_b_sign_int
- \l_fp_input_a_integer_int \l_fp_output_integer_int
- \l_fp_input_a_decimal_int \l_fp_output_decimal_int
- \l_fp_input_a_extended_int \l_fp_output_extended_int
- \l_fp_input_a_exponent_int \l_fp_output_exponent_int
- \l_fp_output_integer_int \c_zero
- \l_fp_output_decimal_int \c_zero
- \l_fp_output_extended_int \c_zero
- \l_fp_output_exponent_int \c_zero
- \cs_set_eq:NN \fp_exp_const:Nx \use_none:nn
- \fp_exp_internal:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
-% \subsection{Tests for special values}
-%
-% \begin{macro}[pTF]{\fp_if_undefined:N}
-% \UnitTested
-% Testing for an undefined value is easy.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \fp_if_undefined:N #1 { p , T , F , TF }
- {
- \if_meaning:w #1 \c_undefined_fp
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[pTF]{\fp_if_zero:N}
-% \UnitTested
-% Testing for a zero fixed-point is also easy.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \fp_if_zero:N #1 { p , T , F , TF }
- {
- \if_meaning:w #1 \c_zero_fp
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \subsection{Floating-point conditionals}
-%
-% \begin{macro}[TF]{\fp_compare:nNn}
-% \begin{macro}[TF]{\fp_compare:NNN}
-% \UnitTested
-% \begin{macro}[aux]{\fp_compare_aux:N}
-% \begin{macro}[aux]{\fp_compare_=:}
-% \begin{macro}[aux]{\fp_compare_<:}
-% \begin{macro}[aux]{\fp_compare_<_aux:}
-% \begin{macro}[aux]{\fp_compare_absolute_a>b:}
-% \begin{macro}[aux]{\fp_compare_absolute_a<b:}
-% \begin{macro}[aux]{\fp_compare_>:}
-% The idea for the comparisons is to provide two versions: slower and
-% faster. The lead off for both is the same: get the two numbers
-% read and then look for a function to handle the comparison.
-% \begin{macrocode}
-\prg_new_protected_conditional:Npnn \fp_compare:nNn #1#2#3 { T , F , TF }
- {
- \group_begin:
- \fp_split:Nn a {#1}
- \fp_standardise:NNNN
- \l_fp_input_a_sign_int
- \l_fp_input_a_integer_int
- \l_fp_input_a_decimal_int
- \l_fp_input_a_exponent_int
- \fp_split:Nn b {#3}
- \fp_standardise:NNNN
- \l_fp_input_b_sign_int
- \l_fp_input_b_integer_int
- \l_fp_input_b_decimal_int
- \l_fp_input_b_exponent_int
- \fp_compare_aux:N #2
- }
-\prg_new_protected_conditional:Npnn \fp_compare:NNN #1#2#3 { T , F , TF }
- {
- \group_begin:
- \fp_read:N #3
- \l_fp_input_b_sign_int \l_fp_input_a_sign_int
- \l_fp_input_b_integer_int \l_fp_input_a_integer_int
- \l_fp_input_b_decimal_int \l_fp_input_a_decimal_int
- \l_fp_input_b_exponent_int \l_fp_input_a_exponent_int
- \fp_read:N #1
- \fp_compare_aux:N #2
- }
-\cs_new_protected:Npn \fp_compare_aux:N #1
- {
- \cs_if_exist:cTF { fp_compare_#1: }
- { \use:c { fp_compare_#1: } }
- {
- \group_end:
- \prg_return_false:
- }
- }
-% \end{macrocode}
-% For equality, the test is pretty easy as things are either equal or
-% they are not.
-% \begin{macrocode}
-\cs_new_protected_nopar:cpn { fp_compare_=: }
- {
- \if_int_compare:w \l_fp_input_a_sign_int = \l_fp_input_b_sign_int
- \if_int_compare:w \l_fp_input_a_integer_int = \l_fp_input_b_integer_int
- \if_int_compare:w \l_fp_input_a_decimal_int = \l_fp_input_b_decimal_int
- \if_int_compare:w
- \l_fp_input_a_exponent_int = \l_fp_input_b_exponent_int
- \group_end:
- \prg_return_true:
- \else:
- \group_end:
- \prg_return_false:
- \fi:
- \else:
- \group_end:
- \prg_return_false:
- \fi:
- \else:
- \group_end:
- \prg_return_false:
- \fi:
- \else:
- \group_end:
- \prg_return_false:
- \fi:
- }
-% \end{macrocode}
-% Comparing two values is quite complex. First, there is a filter step
-% to check if one or other of the given values is zero. If it is then
-% the result is relatively easy to determine.
-% \begin{macrocode}
-\cs_new_protected_nopar:cpn { fp_compare_>: }
- {
- \if_int_compare:w \int_eval:w
- \l_fp_input_a_integer_int + \l_fp_input_a_decimal_int
- = \c_zero
- \if_int_compare:w \int_eval:w
- \l_fp_input_b_integer_int + \l_fp_input_b_decimal_int
- = \c_zero
- \group_end:
- \prg_return_false:
- \else:
- \if_int_compare:w \l_fp_input_b_sign_int > \c_zero
- \group_end:
- \prg_return_false:
- \else:
- \group_end:
- \prg_return_true:
- \fi:
- \fi:
- \else:
- \if_int_compare:w \int_eval:w
- \l_fp_input_b_integer_int + \l_fp_input_b_decimal_int
- = \c_zero
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \group_end:
- \prg_return_true:
- \else:
- \group_end:
- \prg_return_false:
- \fi:
- \else:
- \use:c { fp_compare_>_aux: }
- \fi:
- \fi:
- }
-% \end{macrocode}
-% Next, check the sign of the input: this again may give an obvious
-% result. If both signs are the same, then hand off to comparing the
-% absolute values.
-% \begin{macrocode}
-\cs_new_protected_nopar:cpn { fp_compare_>_aux: }
- {
- \if_int_compare:w \l_fp_input_a_sign_int > \l_fp_input_b_sign_int
- \group_end:
- \prg_return_true:
- \else:
- \if_int_compare:w \l_fp_input_a_sign_int < \l_fp_input_b_sign_int
- \group_end:
- \prg_return_false:
- \else:
- \if_int_compare:w \l_fp_input_a_sign_int > \c_zero
- \use:c { fp_compare_absolute_a>b: }
- \else:
- \use:c { fp_compare_absolute_a<b: }
- \fi:
- \fi:
- \fi:
- }
-% \end{macrocode}
-% Rather long runs of checks, as there is the need to go through each
-% layer of the input and do the comparison. There is also the need to
-% avoid messing up with equal inputs at each stage.
-% \begin{macrocode}
-\cs_new_protected_nopar:cpn { fp_compare_absolute_a>b: }
- {
- \if_int_compare:w \l_fp_input_a_exponent_int > \l_fp_input_b_exponent_int
- \group_end:
- \prg_return_true:
- \else:
- \if_int_compare:w \l_fp_input_a_exponent_int < \l_fp_input_b_exponent_int
- \group_end:
- \prg_return_false:
- \else:
- \if_int_compare:w \l_fp_input_a_integer_int > \l_fp_input_b_integer_int
- \group_end:
- \prg_return_true:
- \else:
- \if_int_compare:w
- \l_fp_input_a_integer_int < \l_fp_input_b_integer_int
- \group_end:
- \prg_return_false:
- \else:
- \if_int_compare:w
- \l_fp_input_a_decimal_int > \l_fp_input_b_decimal_int
- \group_end:
- \prg_return_true:
- \else:
- \group_end:
- \prg_return_false:
- \fi:
- \fi:
- \fi:
- \fi:
- \fi:
- }
-\cs_new_protected_nopar:cpn { fp_compare_absolute_a<b: }
- {
- \if_int_compare:w \l_fp_input_b_exponent_int > \l_fp_input_a_exponent_int
- \group_end:
- \prg_return_true:
- \else:
- \if_int_compare:w \l_fp_input_b_exponent_int < \l_fp_input_a_exponent_int
- \group_end:
- \prg_return_false:
- \else:
- \if_int_compare:w \l_fp_input_b_integer_int > \l_fp_input_a_integer_int
- \group_end:
- \prg_return_true:
- \else:
- \if_int_compare:w
- \l_fp_input_b_integer_int < \l_fp_input_a_integer_int
- \group_end:
- \prg_return_false:
- \else:
- \if_int_compare:w
- \l_fp_input_b_decimal_int > \l_fp_input_a_decimal_int
- \group_end:
- \prg_return_true:
- \else:
- \group_end:
- \prg_return_false:
- \fi:
- \fi:
- \fi:
- \fi:
- \fi:
- }
-% \end{macrocode}
-% This is just a case of reversing the two input values and then
-% running the tests already defined.
-% \begin{macrocode}
-\cs_new_protected_nopar:cpn { fp_compare_<: }
- {
- \tl_set:Nx \l_fp_internal_tl
- {
- \int_set:Nn \exp_not:N \l_fp_input_a_sign_int
- { \int_use:N \l_fp_input_b_sign_int }
- \int_set:Nn \exp_not:N \l_fp_input_a_integer_int
- { \int_use:N \l_fp_input_b_integer_int }
- \int_set:Nn \exp_not:N \l_fp_input_a_decimal_int
- { \int_use:N \l_fp_input_b_decimal_int }
- \int_set:Nn \exp_not:N \l_fp_input_a_exponent_int
- { \int_use:N \l_fp_input_b_exponent_int }
- \int_set:Nn \exp_not:N \l_fp_input_b_sign_int
- { \int_use:N \l_fp_input_a_sign_int }
- \int_set:Nn \exp_not:N \l_fp_input_b_integer_int
- { \int_use:N \l_fp_input_a_integer_int }
- \int_set:Nn \exp_not:N \l_fp_input_b_decimal_int
- { \int_use:N \l_fp_input_a_decimal_int }
- \int_set:Nn \exp_not:N \l_fp_input_b_exponent_int
- { \int_use:N \l_fp_input_a_exponent_int }
- }
- \l_fp_internal_tl
- \use:c { fp_compare_>: }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+% The following need to be done. I'll try to time-order the items.
+% \begin{itemize}
+% \item Decide what exponent range to consider.
+% \item Change the internal representation of fp, by replacing braced
+% groups of $4$ digits by delimited arguments.
+% \item Modulo and remainder, and rounding functions |quantize|,
+% |quantize0|, |quantize+|, |quantize-|, |quantize=|, |round=|.
+% Should the modulo also be provided as (catcode 12) |%|?
+% \item \cs{fp_format:nn} \Arg{fpexpr} \Arg{format}, but what should
+% \meta{format} be? More general pretty printing?
+% \item Add |and|, |or|, |xor|? Perhaps under the names \texttt{all},
+% \texttt{any}, and \texttt{xor}?
+% \item Add \texttt{csc} and \texttt{sec}.
+% \item Add $\log(x,b)$ for logarithm of $x$ in base $b$.
+% \item \texttt{hypot} (Euclidean length) and $\atan(x,y) = \atan(x/y)$,
+% also called \texttt{atan2} in other math packages.
+% Cartesian-to-polar transform. Other inverse trigonometric functions
+% \texttt{acos}, \texttt{asin}, \texttt{atan} (one and two arguments).
+% Also \texttt{asec}, \texttt{acsc}?
+% \item Hyperbolic functions \texttt{cosh}, \texttt{sinh}, \texttt{tanh}.
+% \item Inverse hyperbolics.
+% \item Base conversion, input such as \texttt{0xAB.CDEF}.
+% \item Random numbers (pgfmath provides |rnd|, |rand|, |random|), with
+% seed reset at every \cs{fp_set:Nn}.
+% \item Factorial (not with |!|), gamma function.
+% \item Improve coefficients of \texttt{sin}, \texttt{cos} and
+% \texttt{tan}.
+% \item Treat upper and lower case letters identically in
+% identifiers, and ignore underscores.
+% \item Parse $-3<-2<-1$ as it should, not $(-3<-2)<-1$.
+% \item Add an |array(1,2,3)| and |i=complex(0,1)|.
+% \item Provide an experimental |map| function? Perhaps easier to
+% implement if it is a single character, |@sin(1,2)|?
+% \item Provide \cs{fp_if_nan:nTF}?
+% \end{itemize}
+% \pkg{Pgfmath} also provides box-measurements (depth, height, width), but
+% boxes are not possible expandably.
%
-% \begin{macro}[TF]{\fp_compare:n}
-% \begin{macro}[aux]
-% {
-% \fp_compare_aux_i:w, \fp_compare_aux_ii:w, \fp_compare_aux_iii:w,
-% \fp_compare_aux_iv:w, \fp_compare_aux_v:w, \fp_compare_aux_vi:w,
-% \fp_compare_aux_vii:w
-% }
-% As \TeX{} cannot help out here, a daisy-chain of delimited functions
-% are used. This is very much a first-generation approach: revision will
-% be needed if these functions are really useful.
-% \begin{macrocode}
-\prg_new_protected_conditional:Npnn \fp_compare:n #1 { T , F , TF }
- {
- \group_begin:
- \tl_set:Nx \l_fp_internal_tl
- {
- \group_end:
- \fp_compare_aux_i:w #1 \exp_not:n { == \q_nil == \q_stop }
- }
- \l_fp_internal_tl
- }
-\cs_new_protected:Npn \fp_compare_aux_i:w #1 == #2 == #3 \q_stop
- {
- \quark_if_nil:nTF {#2}
- { \fp_compare_aux_ii:w #1 != \q_nil != \q_stop }
- { \fp_compare:nNnTF {#1} = {#2} \prg_return_true: \prg_return_false: }
- }
-\cs_new_protected:Npn \fp_compare_aux_ii:w #1 != #2 != #3 \q_stop
- {
- \quark_if_nil:nTF {#2}
- { \fp_compare_aux_iii:w #1 <= \q_nil <= \q_stop }
- { \fp_compare:nNnTF {#1} = {#2} \prg_return_false: \prg_return_true: }
- }
-\cs_new_protected:Npn \fp_compare_aux_iii:w #1 <= #2 <= #3 \q_stop
- {
- \quark_if_nil:nTF {#2}
- { \fp_compare_aux_iv:w #1 >= \q_nil >= \q_stop }
- { \fp_compare:nNnTF {#1} > {#2} \prg_return_false: \prg_return_true: }
- }
-\cs_new_protected:Npn \fp_compare_aux_iv:w #1 >= #2 >= #3 \q_stop
- {
- \quark_if_nil:nTF {#2}
- { \fp_compare_aux_v:w #1 = \q_nil \q_stop }
- { \fp_compare:nNnTF {#1} < {#2} \prg_return_false: \prg_return_true: }
- }
-\cs_new_protected:Npn \fp_compare_aux_v:w #1 = #2 = #3 \q_stop
- {
- \quark_if_nil:nTF {#2}
- { \fp_compare_aux_vi:w #1 < \q_nil < \q_stop }
- { \fp_compare:nNnTF {#1} = {#2} \prg_return_true: \prg_return_false: }
- }
-\cs_new_protected:Npn \fp_compare_aux_vi:w #1 < #2 < #3 \q_stop
- {
- \quark_if_nil:nTF {#2}
- { \fp_compare_aux_vii:w #1 > \q_nil > \q_stop }
- { \fp_compare:nNnTF {#1} < {#2} \prg_return_true: \prg_return_false: }
- }
-\cs_new_protected:Npn \fp_compare_aux_vii:w #1 > #2 > #3 \q_stop
- {
- \quark_if_nil:nTF {#2}
- { \prg_return_false: }
- { \fp_compare:nNnTF {#1} > {#2} \prg_return_true: \prg_return_false: }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
+% Bugs. (Exclamation points mark important bugs.)
+% \begin{itemize}
+% \item[!] \cs{fp_eval:n} |{nan}| mustn't produce an error.
+% \item $1-10^{-16}$ should not give $1$.
+% \item When rounding towards $-\infty$, |\dim_to_fp:n {0pt}| should
+% return $-0$, not $+0$.
+% \item \texttt{0e9999999999} gives a \TeX{} \enquote{number too
+% large} error.
+% \item \texttt{tan} and \texttt{cot} give very slightly wrong results
+% for arguments near $10^{-8}$.
+% \item[!] Multiplying $0$ with $\infty$ doesn't trigger an invalid
+% operation error.
+% \item Conversion to integers with \cs{fp_to_int:n} does not check
+% for overflow.
+% \item Subnormals are not implemented.
+% \end{itemize}
%
-% \subsection{Messages}
+% \end{documentation}
%
-% \begin{macro}{\fp_overflow_msg:}
-% A generic overflow message, used whenever there is a possible
-% overflow.
-% \begin{macrocode}
-\msg_kernel_new:nnnn { fpu } { overflow }
- { Number~too~big. }
- {
- The~input~given~is~too~big~for~the~LaTeX~floating~point~unit. \\
- Further~errors~may~well~occur!
- }
-\cs_new_protected_nopar:Npn \fp_overflow_msg:
- { \msg_kernel_error:nn { fpu } { overflow } }
-% \end{macrocode}
-% \end{macro}
+% \begin{implementation}
%
-% \begin{macro}{\fp_exp_overflow_msg:}
-% A slightly more helpful message for exponent overflows.
-% \begin{macrocode}
-\msg_kernel_new:nnnn { fpu } { exponent-overflow }
- { Number~too~big~for~exponent~unit. }
- {
- The~exponent~of~the~input~given~is~too~big~for~the~floating~point~
- unit:~the~maximum~input~value~for~an~exponent~is~230.
- }
-\cs_new_protected_nopar:Npn \fp_exp_overflow_msg:
- { \msg_kernel_error:nn { fpu } { exponent-overflow } }
-% \end{macrocode}
-% \end{macro}
+% \section{\pkg{l3fp} implementation}
%
-% \begin{macro}{\fp_ln_error_msg:}
-% Logarithms are only valid for positive number
% \begin{macrocode}
-\msg_kernel_new:nnnn { fpu } { logarithm-input-error }
- { Invalid~input~to~ln~function. }
- { Logarithms~can~only~be~calculated~for~positive~numbers. }
-\cs_new_protected_nopar:Npn \fp_ln_error_msg: {
- \msg_kernel_error:nn { fpu } { logarithm-input-error }
-}
+%<*package>
% \end{macrocode}
-% \end{macro}
%
-% \begin{macro}{\fp_trig_overflow_msg:}
-% A slightly more helpful message for trigonometric overflows.
% \begin{macrocode}
-\msg_kernel_new:nnnn { fpu } { trigonometric-overflow }
- { Number~too~big~for~trigonometry~unit. }
- {
- The~trigonometry~code~can~only~work~with~numbers~smaller~
- than~1000000000.
- }
-\cs_new_protected_nopar:Npn \fp_trig_overflow_msg:
- { \msg_kernel_error:nn { fpu } { trigonometric-overflow } }
+\ProvidesExplPackage
+ {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+\__expl_package_check:
% \end{macrocode}
-% \end{macro}
%
% \begin{macrocode}
-%</initex|package>
+%</package>
% \end{macrocode}
%
% \end{implementation}
%
-%\PrintIndex
+% \PrintIndex
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
index fdae7fa1046..a12b22a45fb 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3int.dtx
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3int.dtx 3490 2012-03-04 01:00:53Z bruno $
- {L3 Experimental integers}
+\GetIdInfo$Id: l3int.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Integers}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -73,7 +73,7 @@
% \texttt{+}, \texttt{-}, \texttt{/} and \texttt{*} and
% parentheses can be used within such expressions to carry
% arithmetic operations. This module carries out these functions
-% on \emph{integer expressions} (\enquote{\texttt{int expr}}).
+% on \emph{integer expressions} (\enquote{\texttt{intexpr}}).
%
% \section{Integer expressions}
%
@@ -99,7 +99,7 @@
% both evaluate to \( -6 \). The \Arg{integer expression} may
% contain the operators \texttt{+}, \texttt{-}, \texttt{*} and
% \texttt{/}, along with parenthesis \texttt{(} and \texttt{)}.
-% After two expansions, \cs{int_eval:n} yields a
+% After two expansions, \cs{int_eval:n} yields an
% \meta{integer denotation} which is left in the input stream. This is
% \emph{not} an \meta{internal integer}, and therefore requires
% suitable termination if used in a \TeX{}-style integer assignment.
@@ -124,7 +124,7 @@
% second, rounding any remainder. Ties are rounded away from zero.
% Note that this is identical to using
% |/| directly in an \meta{integer expression}. The result is left in
-% the input stream as a \meta{integer denotation} after two expansions.
+% the input stream as an \meta{integer denotation} after two expansions.
% \end{function}
%
% \begin{function}[EXP, updated = 2012-02-09]{\int_div_truncate:nn}
@@ -134,7 +134,7 @@
% Evaluates the two \meta{integer expressions} as described earlier,
% then calculates the result of dividing the first value by the
% second, truncating any remainder. Note that division using |/|
-% rounds the result. The result is left in the input stream as a
+% rounds the result. The result is left in the input stream as an
% \meta{integer denotation} after two expansions.
% \end{function}
%
@@ -202,10 +202,10 @@
% \int_gset_eq:NN, \int_gset_eq:cN, \int_gset_eq:Nc, \int_gset_eq:cc
% }
% \begin{syntax}
-% \cs{int_set_eq:NN} \meta{integer1} \meta{integer2}
+% \cs{int_set_eq:NN} \meta{integer_1} \meta{integer_2}
% \end{syntax}
-% Sets the content of \meta{integer1} equal to that of
-% \meta{integer2}.
+% Sets the content of \meta{integer_1} equal to that of
+% \meta{integer_2}.
% \end{function}
%
% \begin{function}[EXP, pTF, added=2012-03-03]
@@ -268,9 +268,9 @@
% \begin{syntax}
% \cs{int_use:N} \meta{integer}
% \end{syntax}
-% Recovers the content of a \meta{integer} and places it directly
+% Recovers the content of an \meta{integer} and places it directly
% in the input stream. An error will be raised if the variable does
-% not exist or if it is invalid. Can be omitted in places where a
+% not exist or if it is invalid. Can be omitted in places where an
% \meta{integer} is required (such as in the first and third arguments
% of \cs{int_compare:nNnTF}).
% \begin{texnote}
@@ -302,9 +302,9 @@
%
% \begin{function}[EXP,pTF]{\int_compare:n}
% \begin{syntax}
-% \cs{int_compare_p:n} \{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \} \\
+% \cs{int_compare_p:n} \{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \\
% \cs{int_compare:nTF}
-% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \}
+% ~~\{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \}
% ~~\Arg{true code} \Arg{false code}
% \end{syntax}
% This function first evaluates each of the \meta{integer expressions}
@@ -322,6 +322,36 @@
% \end{center}
% \end{function}
%
+% \begin{function}[added = 2012-06-03, EXP]{\int_case:nnn}
+% \begin{syntax}
+% \cs{int_case:nnn} \Arg{test integer expression} \\
+% ~~|{| \\
+% ~~~~\Arg{intexpr case_1} \Arg{code case_1} \\
+% ~~~~\Arg{intexpr case_2} \Arg{code case_2} \\
+% ~~~~\ldots \\
+% ~~~~\Arg{intexpr case_n} \Arg{code case_n} \\
+% ~~|}| \\
+% ~~\Arg{else code}
+% \end{syntax}
+% This function evaluates the \meta{test integer expression} and
+% compares this in turn to each of the
+% \meta{integer expression cases}. If the two are equal then the
+% associated \meta{code} is left in the input stream. If none of
+% the tests are \texttt{true} then the \texttt{else code} will be
+% left in the input stream. For example
+% \begin{verbatim}
+% \int_case:nnn
+% { 2 * 5 }
+% {
+% { 5 } { Small }
+% { 4 + 6 } { Medium }
+% { -2 * 10 } { Negative }
+% }
+% { No idea! }
+% \end{verbatim}
+% will leave \enquote{\texttt{Medium}} in the input stream.
+% \end{function}
+%
% \begin{function}[EXP,pTF]{\int_if_even:n, \int_if_odd:n}
% \begin{syntax}
% \cs{int_if_odd_p:n} \Arg{integer expression}
@@ -390,7 +420,7 @@
% \begin{function}[rEXP]{\int_do_while:nn}
% \begin{syntax}
% \cs{int_do_while:nn}
-% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \} \Arg{code}
+% ~~\{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \Arg{code}
% \end{syntax}
% Evaluates the relationship between the two \meta{integer expressions}
% as described for \cs{int_compare:nTF}, and then places the
@@ -403,7 +433,7 @@
% \begin{function}[rEXP]{\int_do_until:nn}
% \begin{syntax}
% \cs{int_do_until:nn}
-% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \} \Arg{code}
+% ~~\{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \Arg{code}
% \end{syntax}
% Evaluates the relationship between the two \meta{integer expressions}
% as described for \cs{int_compare:nTF}, and then places the
@@ -416,7 +446,7 @@
% \begin{function}[rEXP]{\int_until_do:nn}
% \begin{syntax}
% \cs{int_until_do:nn}
-% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \} \Arg{code}
+% ~~\{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \Arg{code}
% \end{syntax}
% Places the \meta{code} in the input stream for \TeX\ to process, and
% then evaluates the relationship between the two
@@ -429,7 +459,7 @@
% \begin{function}[rEXP]{\int_while_do:nn}
% \begin{syntax}
% \cs{int_while_do:nn} \
-% ~~\{ \meta{intexpr1} \meta{relation} \meta{intexpr2} \} \Arg{code}
+% ~~\{ \meta{intexpr_1} \meta{relation} \meta{intexpr_2} \} \Arg{code}
% \end{syntax}
% Places the \meta{code} in the input stream for \TeX{} to process, and
% then evaluates the relationship between the two
@@ -439,6 +469,59 @@
% \meta{relation} is \texttt{false}.
% \end{function}
%
+% \section{Integer step functions}
+%
+% \begin{function}[added = 2012-06-04, updated = 2012-06-29, rEXP]
+% {\int_step_function:nnnN}
+% \begin{syntax}
+% \cs{int_step_function:nnnN} \Arg{initial value} \Arg{step} \Arg{final value} \meta{function}
+% \end{syntax}
+% This function first evaluates the \meta{initial value}, \meta{step}
+% and \meta{final value}, all of which should be integer expressions.
+% The \meta{function} is then placed in front of each \meta{value}
+% from the \meta{initial value} to the \meta{final value} in turn
+% (using \meta{step} between each \meta{value}). Thus \meta{function}
+% should absorb one numerical argument. For example
+% \begin{verbatim}
+% \cs_set:Npn \my_func:n #1 { [I~saw~#1] \quad }
+% \int_step_function:nnnN { 1 } { 1 } { 5 } \my_func:n
+% \end{verbatim}
+% would print
+% \begin{quote}
+% [I saw 1] \quad
+% [I saw 2] \quad
+% [I saw 3] \quad
+% [I saw 4] \quad
+% [I saw 5] \quad
+% \end{quote}
+% \end{function}
+%
+% \begin{function}[added = 2012-06-04, updated = 2012-06-29]
+% {\int_step_inline:nnnn}
+% \begin{syntax}
+% \cs{int_step_inline:nnnn} \Arg{initial value} \Arg{step} \Arg{final value} \Arg{code}
+% \end{syntax}
+% This function first evaluates the \meta{initial value}, \meta{step}
+% and \meta{final value}, all of which should be integer expressions.
+% The \meta{code} is then placed in front of each \meta{value}
+% from the \meta{initial value} to the \meta{final value} in turn
+% (using \meta{step} between each \meta{value}). Thus the \meta{code}
+% should define a function of one argument (|#1|).
+% \end{function}
+%
+% \begin{function}[added = 2012-06-04, updated = 2012-06-29]
+% {\int_step_variable:nnnNn}
+% \begin{syntax}
+% \cs{int_step_variable:nnnNn} \\
+% ~~\Arg{initial value} \Arg{step} \Arg{final value} \meta{tl~var} \Arg{code}
+% \end{syntax}
+% This function first evaluates the \meta{initial value}, \meta{step}
+% and \meta{final value}, all of which should be integer expressions.
+% The \meta{code} is inserted into the input stream, with the
+% \meta{tl~var} defined as the current \meta{value}. Thus the
+% \meta{code} should make use of the \meta{tl~var}.
+% \end{function}
+%
% \section{Formatting integers}
%
% Integers can be placed into the output stream with formatting. These
@@ -626,7 +709,7 @@
% Displays the value of the \meta{integer} on the terminal.
% \end{function}
%
-% \begin{function}[added = 2011-11-22]{\int_show:n}
+% \begin{function}[added = 2011-11-22, updated = 2012-05-27]{\int_show:n}
% \begin{syntax}
% \cs{int_show:n} \meta{integer expression}
% \end{syntax}
@@ -678,7 +761,7 @@
%
% \section{Scratch integers}
%
-% \begin{variable}{\l_tmpa_int, \l_tmpb_int, \l_tmpc_int}
+% \begin{variable}{\l_tmpa_int, \l_tmpb_int}
% Scratch integer for local assignment. These are never used by
% the kernel code, and so are safe for use with any \LaTeX3-defined
% function. However, they may be overwritten by other non-kernel
@@ -692,57 +775,11 @@
% code and so should only be used for short-term storage.
% \end{variable}
%
-% \section{Internal functions}
-%
-% \begin{function}[EXP]{\int_get_digits:n}
-% \begin{syntax}
-% \cs{int_get_digits:n} \meta{value}
-% \end{syntax}
-% Parses the \meta{value} to leave the absolute \meta{value}
-% in the input stream. This may therefore be used
-% to remove multiple sign tokens from the \meta{value}
-% (which may be symbolic).
-% \end{function}
-%
-% \begin{function}[rEXP]{\int_get_sign:n}
-% \begin{syntax}
-% \cs{int_get_sign:n} \meta{value}
-% \end{syntax}
-% Parses the \meta{value} to leave a single sign token
-% (either |+| or |-|) in the input stream. This may therefore be used
-% to sanitise sign tokens from the \meta{value} (which may be symbolic).
-% \end{function}
-%
-% \begin{function}[updated = 2011-09-17, EXP]{\int_to_letter:n}
-% \begin{syntax}
-% \cs{int_to_letter:n} \meta{integer value}
-% \end{syntax}
-% For \meta{integer values} from $0$ to $9$, leaves the \meta{value}
-% in the input stream unchanged. For \meta{integer values} from
-% $10$ to $35$, leaves the appropriate upper case letter (from the
-% standard English alphabet) in the input stream: for example,
-% $10$ is converted to |A|, $11$ to |B|, \emph{etc.}
-% \end{function}
+% \section{Primitive conditionals}
%
-% \begin{function}[EXP]{\int_to_roman:w}
+% \begin{function}[EXP]{\if_int_compare:w}
% \begin{syntax}
-% \cs{int_to_roman:w} \meta{integer} \meta{space} \textit{or} \meta{non-expandable token}
-% \end{syntax}
-% Converts \meta{integer} to it lower case Roman representation. Expansion
-% ends when a space or non-expandable token is found.
-% Note that this function produces a string of letters with category code
-% $12$ and that protected functions \emph{are} expanded by this
-% process. Negative \meta{integer} values result in no output, although
-% the function does not terminate expansion until a suitable endpoint
-% is found in the same way as for positive numbers.
-% \begin{texnote}
-% This is the \TeX{} primitive \tn{romannumeral} renamed.
-% \end{texnote}
-% \end{function}
-%
-% \begin{function}[EXP]{\if_num:w, \if_int_compare:w}
-% \begin{syntax}
-% \cs{if_num:w} \meta{integer1} \meta{relation} \meta{integer2}
+% \cs{if_int_compare:w} \meta{integer_1} \meta{relation} \meta{integer_2}
% ~~\meta{true code}
% \cs{else:}
% ~~\meta{false code}
@@ -758,15 +795,15 @@
%
% \begin{function}[EXP]{\if_case:w, \or:}
% \begin{syntax}
-% \cs{if_case:w} \meta{integer} \meta{case0}
-% ~~\cs{or:} \meta{case1}
+% \cs{if_case:w} \meta{integer} \meta{case_0}
+% ~~\cs{or:} \meta{case_1}
% ~~\cs{or:} |...|
% ~~\cs{else:} \meta{default}
% \cs{fi:}
% \end{syntax}
% Selects a case to execute based on the value of the \meta{integer}. The
-% first case (\meta{case0}) is executed if \meta{integer} is $0$, the second
-% (\meta{case1}) if the \meta{integer} is $1$, \emph{etc.} The
+% first case (\meta{case_0}) is executed if \meta{integer} is $0$, the second
+% (\meta{case_1}) if the \meta{integer} is $1$, \emph{etc.} The
% \meta{integer} may be a literal, a constant or an integer
% expression (\emph{e.g.}~using \cs{int_eval:n}).
% \begin{texnote}
@@ -774,10 +811,44 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}[EXP]{\int_value:w}
+% \begin{function}[EXP]{\if_int_odd:w}
+% \begin{syntax}
+% \cs{if_int_odd:w} \meta{tokens} \meta{optional space}
+% ~~\meta{true code}
+% \cs{else:}
+% ~~\meta{true code}
+% \cs{fi:}
+% \end{syntax}
+% Expands \meta{tokens} until a non-numeric token or a space is found, and
+% tests whether the resulting \meta{integer} is odd. If so, \meta{true code}
+% is executed. The \cs{else:} branch is optional.
+% \begin{texnote}
+% This is the \TeX{} primitive \tn{ifodd}.
+% \end{texnote}
+% \end{function}
+%
+% \section{Internal functions}
+%
+% \begin{function}[EXP]{\__int_to_roman:w}
+% \begin{syntax}
+% \cs{__int_to_roman:w} \meta{integer} \meta{space} \textit{or} \meta{non-expandable token}
+% \end{syntax}
+% Converts \meta{integer} to it lower case Roman representation. Expansion
+% ends when a space or non-expandable token is found.
+% Note that this function produces a string of letters with category code
+% $12$ and that protected functions \emph{are} expanded by this
+% process. Negative \meta{integer} values result in no output, although
+% the function does not terminate expansion until a suitable endpoint
+% is found in the same way as for positive numbers.
+% \begin{texnote}
+% This is the \TeX{} primitive \tn{romannumeral} renamed.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]{\__int_value:w}
% \begin{syntax}
-% \cs{int_value:w} \meta{integer}
-% \cs{int_value:w} \meta{tokens} \meta{optional space}
+% \cs{__int_value:w} \meta{integer}
+% \cs{__int_value:w} \meta{tokens} \meta{optional space}
% \end{syntax}
% Expands \meta{tokens} until an \meta{integer} is formed. One space may be
% gobbled in the process.
@@ -786,35 +857,29 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}[EXP]{\int_eval:w, \int_eval_end:}
+% \begin{function}[EXP]{\__int_eval:w, \__int_eval_end:}
% \begin{syntax}
-% \cs{int_eval:w} \meta{intexpr} \cs{int_eval_end:}
+% \cs{__int_eval:w} \meta{intexpr} \cs{__int_eval_end:}
% \end{syntax}
% Evaluates \meta{integer expression} as described for \cs{int_eval:n}.
% The evaluation stops when an unexpandable token which is not a valid
-% part of an integer is read or when \cs{int_eval_end:} is
+% part of an integer is read or when \cs{__int_eval_end:} is
% reached. The latter is gobbled by the scanner mechanism:
-% \cs{int_eval_end:} itself is unexpandable but used correctly
+% \cs{__int_eval_end:} itself is unexpandable but used correctly
% the entire construct is expandable.
% \begin{texnote}
% This is the \eTeX{} primitive \tn{numexpr}.
% \end{texnote}
% \end{function}
%
-% \begin{function}[EXP]{\if_int_odd:w}
+% \begin{function}{\__prg_compare_error:, \__prg_compare_error:Nw}
% \begin{syntax}
-% \cs{if_int_odd:w} \meta{tokens} \meta{optional space}
-% ~~\meta{true code}
-% \cs{else:}
-% ~~\meta{true code}
-% \cs{fi:}
+% \cs{__prg_compare_error:}
+% \cs{__prg_compare_error:Nw} \meta{token}
% \end{syntax}
-% Expands \meta{tokens} until a non-numeric token or a space is found, and
-% tests whether the resulting \meta{integer} is odd. If so, \meta{true code}
-% is executed. The \cs{else:} branch is optional.
-% \begin{texnote}
-% This is the \TeX{} primitive \tn{ifodd}.
-% \end{texnote}
+% These are used within \cs{int_compare:n(TF)}, \cs{dim_compare:n(TF)}
+% and so on to recover correctly if the \texttt{n}-type argument does not
+% contain a properly-formed relation.
% \end{function}
%
% \end{documentation}
@@ -827,58 +892,59 @@
%<*initex|package>
% \end{macrocode}
%
+% \begin{macrocode}
+%<@@=int>
+% \end{macrocode}
+%
% \TestFiles{m3int001,m3int002,m3int03}
%
% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
-% \begin{macro}{\int_to_roman:w}
+% \begin{macro}{\@@_to_roman:w}
% \begin{macro}{\if_int_compare:w}
% Done in \pkg{l3basics}.
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\int_value:w}
-% \begin{macro}{\int_eval:w}
-% \begin{macro}{\int_eval_end:}
-% \begin{macro}{\if_num:w}
+% \begin{macro}{\@@_value:w}
+% \begin{macro}{\@@_eval:w}
+% \begin{macro}{\@@_eval_end:}
% \begin{macro}{\if_int_odd:w}
% \begin{macro}{\if_case:w}
% Here are the remaining primitives for number comparisons and
% expressions.
% \begin{macrocode}
-\cs_new_eq:NN \int_value:w \tex_number:D
-\cs_new_eq:NN \int_eval:w \etex_numexpr:D
-\cs_new_eq:NN \int_eval_end: \tex_relax:D
-\cs_new_eq:NN \if_num:w \tex_ifnum:D
-\cs_new_eq:NN \if_int_odd:w \tex_ifodd:D
-\cs_new_eq:NN \if_case:w \tex_ifcase:D
+\cs_new_eq:NN \@@_value:w \tex_number:D
+\cs_new_eq:NN \@@_eval:w \etex_numexpr:D
+\cs_new_eq:NN \@@_eval_end: \tex_relax:D
+\cs_new_eq:NN \if_int_odd:w \tex_ifodd:D
+\cs_new_eq:NN \if_case:w \tex_ifcase:D
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
-% \end{macro}
%
% \subsection{Integer expressions}
%
% \begin{macro}{\int_eval:n}
-% Wrapper for \cs{int_eval:w}. Can be used in an integer expression
+% Wrapper for \cs{@@_eval:w}. Can be used in an integer expression
% or directly in the input stream. In format mode, there is already
% a definition in \pkg{l3alloc} for bookstrapping, which is therefore
% corrected to the \enquote{real} version here.
% \begin{macrocode}
%<*initex>
-\cs_set:Npn \int_eval:n #1 { \int_value:w \int_eval:w #1 \int_eval_end: }
+\cs_set:Npn \int_eval:n #1 { \@@_value:w \@@_eval:w #1 \@@_eval_end: }
%</initex>
%<*package>
-\cs_new:Npn \int_eval:n #1 { \int_value:w \int_eval:w #1 \int_eval_end: }
+\cs_new:Npn \int_eval:n #1 { \@@_value:w \@@_eval:w #1 \@@_eval_end: }
%</package>
% \end{macrocode}
% \end{macro}
@@ -893,33 +959,33 @@
% \begin{macrocode}
\cs_new:Npn \int_abs:n #1
{
- \int_value:w
- \if_int_compare:w \int_eval:w #1 < \c_zero
+ \@@_value:w
+ \if_int_compare:w \@@_eval:w #1 < \c_zero
-
\fi:
- \int_eval:w #1 \int_eval_end:
+ \@@_eval:w #1 \@@_eval_end:
}
\cs_new:Npn \int_max:nn #1#2
{
- \int_value:w \int_eval:w
+ \@@_value:w \@@_eval:w
\if_int_compare:w
- \int_eval:w #1 > \int_eval:w #2 \int_eval_end:
+ \@@_eval:w #1 > \@@_eval:w #2 \@@_eval_end:
#1
\else:
#2
\fi:
- \int_eval_end:
+ \@@_eval_end:
}
\cs_new:Npn \int_min:nn #1#2
{
- \int_value:w \int_eval:w
+ \@@_value:w \@@_eval:w
\if_int_compare:w
- \int_eval:w #1 < \int_eval:w #2 \int_eval_end:
+ \@@_eval:w #1 < \@@_eval:w #2 \@@_eval_end:
#1
\else:
#2
\fi:
- \int_eval_end:
+ \@@_eval_end:
}
% \end{macrocode}
% \end{macro}
@@ -932,12 +998,12 @@
% \UnitTested
% \begin{macro}[EXP]{\int_mod:nn}
% \UnitTested
-% \begin{macro}[aux, EXP]{\int_div_truncate_aux:NwNw}
-% As \cs{int_eval:w} rounds the result of a division we also provide a
+% \begin{macro}[aux, EXP]{\@@_div_truncate:NwNw}
+% As \cs{@@_eval:w} rounds the result of a division we also provide a
% version that truncates the result. We use an auxiliary to make sure
% numerator and denominator are only evaluated once: this comes in
% handy when those are more expressions are expensive to evaluate
-% (\emph{e.g.}, \cs{tl_length:n}). If the numerator |#1#2| is $0$,
+% (\emph{e.g.}, \cs{tl_count:n}). If the numerator |#1#2| is $0$,
% then we divide $0$ by the denominator (this ensures that $0/0$ is
% correctly reported as an error). Otherwise, shift the numerator
% |#1#2| towards $0$ by $(\left\vert\texttt{\#3\#4}\right\vert-1)/2$, which we
@@ -948,13 +1014,13 @@
% \begin{macrocode}
\cs_new:Npn \int_div_truncate:nn #1#2
{
- \int_use:N \int_eval:w
- \exp_after:wN \int_div_truncate_aux:NwNw
- \int_use:N \int_eval:w #1 \exp_after:wN ;
- \int_use:N \int_eval:w #2 ;
- \int_eval_end:
+ \int_use:N \@@_eval:w
+ \exp_after:wN \@@_div_truncate:NwNw
+ \int_use:N \@@_eval:w #1 \exp_after:wN ;
+ \int_use:N \@@_eval:w #2 ;
+ \@@_eval_end:
}
-\cs_new:Npn \int_div_truncate_aux:NwNw #1#2; #3#4;
+\cs_new:Npn \@@_div_truncate:NwNw #1#2; #3#4;
{
\if_meaning:w 0 #1
\c_zero
@@ -976,9 +1042,9 @@
% \begin{macrocode}
\cs_new:Npn \int_mod:nn #1#2
{
- \int_value:w \int_eval:w
+ \@@_value:w \@@_eval:w
#1 - \int_div_truncate:nn {#1} {#2} * ( #2 )
- \int_eval_end:
+ \@@_eval_end:
}
% \end{macrocode}
% \end{macro}
@@ -996,7 +1062,7 @@
%<*package>
\cs_new_protected:Npn \int_new:N #1
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\newcount #1
}
%</package>
@@ -1005,8 +1071,8 @@
% \end{macro}
%
% \begin{macro}{\int_const:Nn, \int_const:cn}
-% \begin{macro}[aux]{\int_constdef:Nw}
-% \begin{variable}{\c_max_const_int}
+% \begin{macro}[aux]{\@@_constdef:Nw}
+% \begin{variable}{\c__max_constdef_int}
% \UnitTested
% As stated, most constants can be defined as \tn{chardef} or
% \tn{mathchardef} but that's engine dependent. As a result, there is some
@@ -1016,15 +1082,15 @@
{
\int_compare:nNnTF {#2} > \c_minus_one
{
- \int_compare:nNnTF {#2} > \c_max_const_int
+ \int_compare:nNnTF {#2} > \c__max_constdef_int
{
\int_new:N #1
\int_gset:Nn #1 {#2}
}
{
- \chk_if_free_cs:N #1
- \tex_global:D \int_constdef:Nw #1 =
- \int_eval:w #2 \int_eval_end:
+ \__chk_if_free_cs:N #1
+ \tex_global:D \@@_constdef:Nw #1 =
+ \@@_eval:w #2 \@@_eval_end:
}
}
{
@@ -1035,12 +1101,12 @@
\cs_generate_variant:Nn \int_const:Nn { c }
\pdftex_if_engine:TF
{
- \cs_new_eq:NN \int_constdef:Nw \tex_mathchardef:D
- \tex_mathchardef:D \c_max_const_int 32 767 ~
+ \cs_new_eq:NN \@@_constdef:Nw \tex_mathchardef:D
+ \tex_mathchardef:D \c__max_constdef_int 32 767 ~
}
{
- \cs_new_eq:NN \int_constdef:Nw \tex_chardef:D
- \tex_chardef:D \c_max_const_int 1 114 111 ~
+ \cs_new_eq:NN \@@_constdef:Nw \tex_chardef:D
+ \tex_chardef:D \c__max_constdef_int 1 114 111 ~
}
% \end{macrocode}
% \end{variable}
@@ -1119,9 +1185,9 @@
% Adding and subtracting to and from a counter \ldots
% \begin{macrocode}
\cs_new_protected:Npn \int_add:Nn #1#2
- { \tex_advance:D #1 by \int_eval:w #2 \int_eval_end: }
+ { \tex_advance:D #1 by \@@_eval:w #2 \@@_eval_end: }
\cs_new_protected:Npn \int_sub:Nn #1#2
- { \tex_advance:D #1 by - \int_eval:w #2 \int_eval_end: }
+ { \tex_advance:D #1 by - \@@_eval:w #2 \@@_eval_end: }
\cs_new_protected_nopar:Npn \int_gadd:Nn
{ \tex_global:D \int_add:Nn }
\cs_new_protected_nopar:Npn \int_gsub:Nn
@@ -1174,7 +1240,7 @@
% code seen with token list variables.
% \begin{macrocode}
\cs_new_protected:Npn \int_set:Nn #1#2
- { #1 ~ \int_eval:w #2\int_eval_end: }
+ { #1 ~ \@@_eval:w #2\@@_eval_end: }
\cs_new_protected_nopar:Npn \int_gset:Nn { \tex_global:D \int_set:Nn }
\cs_generate_variant:Nn \int_set:Nn { c }
\cs_generate_variant:Nn \int_gset:Nn { c }
@@ -1195,30 +1261,30 @@
%
% \subsection{Integer expression conditionals}
%
-% \begin{macro}[aux, EXP]{\kernel_compare_error:, \kernel_compare_error:NNw}
+% \begin{macro}[aux, EXP]{\__prg_compare_error:, \__prg_compare_error:NNw}
% Those functions are used for comparison tests which use a simple
% syntax where only one set of braces is required and additional
% operators such as |!=| and |>=| are supported. The tests first
% evaluate their left-hand side, with a trailing
-% \cs{kernel_compare_error:}. This marker is normally not expanded,
+% \cs{__prg_compare_error:}. This marker is normally not expanded,
% but if the relation symbol is missing from the test's argument, then
% the marker inserts |=| (and itself) after triggering the relevant
% \TeX{} error. If the first token which appears after evaluating and
% removing the left-hand side is not a known relation symbol, then a
-% judiciously placed \cs{kernel_compare_error:Nw} gets expanded,
+% judiciously placed \cs{__prg_compare_error:Nw} gets expanded,
% cleaning up the end of the test and telling the user what the
% problem was.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \kernel_compare_error:
+\cs_new_protected_nopar:Npn \__prg_compare_error:
{
- \if_num:w \c_zero \c_zero \fi:
+ \if_int_compare:w \c_zero \c_zero \fi:
=
- \kernel_compare_error:
+ \__prg_compare_error:
}
-\cs_new:Npn \kernel_compare_error:Nw
+\cs_new:Npn \__prg_compare_error:Nw
#1#2 \prg_return_true: \else: \prg_return_false: \fi:
{
- \msg_expandable_kernel_error:nnn
+ \__msg_kernel_expandable_error:nnn
{ kernel } { unknown-comparison } {#1}
\prg_return_false:
}
@@ -1226,31 +1292,31 @@
% \end{macro}
%
% \begin{macro}[pTF, EXP]{\int_compare:n}
-% \begin{macro}[aux, EXP]{\int_compare_aux:Nw, \int_compare_aux:NNw}
+% \begin{macro}[aux, EXP]{\@@_compare_aux:Nw, \@@_compare_aux:NNw}
% \begin{macro}[aux, EXP]
% {
-% \int_compare_=:NNw,
-% \int_compare_<:NNw,
-% \int_compare_>:NNw,
-% \int_compare_==:NNw,
-% \int_compare_!=:NNw,
-% \int_compare_<=:NNw,
-% \int_compare_>=:NNw
+% \@@_compare_=:NNw,
+% \@@_compare_<:NNw,
+% \@@_compare_>:NNw,
+% \@@_compare_==:NNw,
+% \@@_compare_!=:NNw,
+% \@@_compare_<=:NNw,
+% \@@_compare_>=:NNw
% }
% Comparison tests using a simple syntax where only one set of braces
% is required and additional operators such as |!=| and |>=| are
% supported. We can start evaluating from the left using
-% \cs{int_eval:w}, and we know that since the relation symbols |<|,
+% \cs{@@_eval:w}, and we know that since the relation symbols |<|,
% |>|, |=| and |!| are not allowed in such expressions, they will
% terminate the expression. Therefore, we first let \TeX{} evaluate
% this left hand side of the (in)equality. We also insert at that
-% stage the end of the test: \cs{int_eval_end:} will end the
+% stage the end of the test: \cs{@@_eval_end:} will end the
% evaluation of the right-hand side.
% \begin{macrocode}
\prg_new_conditional:Npnn \int_compare:n #1 { p , T , F , TF }
{
- \exp_after:wN \int_compare_aux:Nw \int_use:N \int_eval:w #1
- \kernel_compare_error: \int_eval_end:
+ \exp_after:wN \@@_compare_aux:Nw \int_use:N \@@_eval:w #1
+ \__prg_compare_error: \@@_eval_end:
\prg_return_true:
\else:
\prg_return_false:
@@ -1258,47 +1324,47 @@
}
% \end{macrocode}
% We have just evaluated the left-hand side. To access the relation
-% symbol, we remove the number by applying \cs{int_to_roman:w}, after
+% symbol, we remove the number by applying \cs{@@_to_roman:w}, after
% making sure that the argument becomes non-positive: its roman
-% numeral representation is then empty. The \cs{int_compare_aux:NNw}
+% numeral representation is then empty. The \cs{@@_compare_aux:NNw}
% auxiliary then probes the first two tokens to determine the relation
% symbol, building a control sequence from it. All the extended forms
% have an extra |=| hence the test for that as a second token. If the
% relation symbol is unknown, then the control sequence is turned by
-% \TeX{} into \cs{scan_stop:}, and \cs{kernel_compare_error:Nw}
+% \TeX{} into \cs{scan_stop:}, and \cs{__prg_compare_error:Nw}
% raises an error.
% \begin{macrocode}
-\cs_new:Npn \int_compare_aux:Nw #1#2 \kernel_compare_error:
+\cs_new:Npn \@@_compare_aux:Nw #1#2 \__prg_compare_error:
{
- \exp_after:wN \int_compare_aux:NNw
- \int_to_roman:w - 0 #2 ?? \q_mark
+ \exp_after:wN \@@_compare_aux:NNw
+ \@@_to_roman:w - 0 #2 ?? \q_mark
#1#2
}
-\cs_new:Npn \int_compare_aux:NNw #1#2#3 \q_mark
+\cs_new:Npn \@@_compare_aux:NNw #1#2#3 \q_mark
{
- \use:c { int_compare_ #1 \if_meaning:w = #2 = \fi: :NNw }
- \kernel_compare_error:Nw #1
+ \use:c { @@_compare_ #1 \if_meaning:w = #2 = \fi: :NNw }
+ \__prg_compare_error:Nw #1
}
% \end{macrocode}
% The actual comparisons are then simple function calls, using the
% relation as delimiter for a delimited argument and discarding
-% \cs{kernel_compare_error:Nw} \meta{token} responsible for error
+% \cs{__prg_compare_error:Nw} \meta{token} responsible for error
% detection.
% \begin{macrocode}
-\cs_new:cpn { int_compare_=:NNw } #1#2#3 =
- { \if_int_compare:w #3 = \int_eval:w }
-\cs_new:cpn { int_compare_<:NNw } #1#2#3 <
- { \if_int_compare:w #3 < \int_eval:w }
-\cs_new:cpn { int_compare_>:NNw } #1#2#3 >
- { \if_int_compare:w #3 > \int_eval:w }
-\cs_new:cpn { int_compare_==:NNw } #1#2#3 ==
- { \if_int_compare:w #3 = \int_eval:w }
-\cs_new:cpn { int_compare_!=:NNw } #1#2#3 !=
- { \reverse_if:N \if_int_compare:w #3 = \int_eval:w }
-\cs_new:cpn { int_compare_<=:NNw } #1#2#3 <=
- { \reverse_if:N \if_int_compare:w #3 > \int_eval:w }
-\cs_new:cpn { int_compare_>=:NNw } #1#2#3 >=
- { \reverse_if:N \if_int_compare:w #3 < \int_eval:w }
+\cs_new:cpn { @@_compare_=:NNw } #1#2#3 =
+ { \if_int_compare:w #3 = \@@_eval:w }
+\cs_new:cpn { @@_compare_<:NNw } #1#2#3 <
+ { \if_int_compare:w #3 < \@@_eval:w }
+\cs_new:cpn { @@_compare_>:NNw } #1#2#3 >
+ { \if_int_compare:w #3 > \@@_eval:w }
+\cs_new:cpn { @@_compare_==:NNw } #1#2#3 ==
+ { \if_int_compare:w #3 = \@@_eval:w }
+\cs_new:cpn { @@_compare_!=:NNw } #1#2#3 !=
+ { \reverse_if:N \if_int_compare:w #3 = \@@_eval:w }
+\cs_new:cpn { @@_compare_<=:NNw } #1#2#3 <=
+ { \reverse_if:N \if_int_compare:w #3 > \@@_eval:w }
+\cs_new:cpn { @@_compare_>=:NNw } #1#2#3 >=
+ { \reverse_if:N \if_int_compare:w #3 < \@@_eval:w }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1308,9 +1374,9 @@
% \UnitTested
% More efficient but less natural in typing.
% \begin{macrocode}
-\prg_new_conditional:Npnn \int_compare:nNn #1#2#3 { p , T , F , TF}
+\prg_new_conditional:Npnn \int_compare:nNn #1#2#3 { p , T , F , TF }
{
- \if_int_compare:w \int_eval:w #1 #2 \int_eval:w #3 \int_eval_end:
+ \if_int_compare:w \@@_eval:w #1 #2 \@@_eval:w #3 \@@_eval_end:
\prg_return_true:
\else:
\prg_return_false:
@@ -1319,6 +1385,35 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\int_case:nnn}
+% \begin{macro}[aux]{\@@_case:nnn}
+% \begin{macro}[aux]{\@@_case:nw, \@@_case_end:nw}
+% For integer cases, the first task to fully expand the check
+% condition. After that, a loop is started to compare each possible
+% value and stop if the test is true. The tested value is put at the
+% end to ensure that there is necessarily a match, which will fire the
+% \enquote{else} pathway. The leading \tn{romannumeral} triggers an
+% expansion which is then stopped in \cs{@@_case_end:nw}.
+% \begin{macrocode}
+\cs_new:Npn \int_case:nnn #1
+ {
+ \tex_romannumeral:D
+ \exp_args:Nf \@@_case:nnn { \int_eval:n {#1} }
+ }
+\cs_new:Npn \@@_case:nnn #1#2#3
+ { \@@_case:nw {#1} #2 {#1} {#3} \q_recursion_stop }
+\cs_new:Npn \@@_case:nw #1#2#3
+ {
+ \int_compare:nNnTF {#1} = {#2}
+ { \@@_case_end:nw {#3} }
+ { \@@_case:nw {#1} }
+ }
+\cs_new_eq:NN \@@_case_end:nw \__prg_case_end:nw
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}[pTF]{\int_if_odd:n}
% \UnitTested
% \begin{macro}[pTF]{\int_if_even:n}
@@ -1327,7 +1422,7 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \int_if_odd:n #1 { p , T , F , TF}
{
- \if_int_odd:w \int_eval:w #1 \int_eval_end:
+ \if_int_odd:w \@@_eval:w #1 \@@_eval_end:
\prg_return_true:
\else:
\prg_return_false:
@@ -1335,7 +1430,7 @@
}
\prg_new_conditional:Npnn \int_if_even:n #1 { p , T , F , TF}
{
- \if_int_odd:w \int_eval:w #1 \int_eval_end:
+ \if_int_odd:w \@@_eval:w #1 \@@_eval_end:
\prg_return_false:
\else:
\prg_return_true:
@@ -1437,6 +1532,86 @@
% \end{macro}
% \end{macro}
%
+% \subsection{Integer step functions}
+%
+% \begin{macro}{\int_step_function:nnnN}
+% \begin{macro}[aux]{\@@_step:NnnnN}
+% Repeating a function by steps first needs a check on the direction
+% of the steps. After that, do the function for the start value
+% then step and loop around. It would be more symmetrical to test
+% for a step size of zero before checking the sign, but we optimize
+% for the most frequent case (positive step).
+% \begin{macrocode}
+\cs_new:Npn \int_step_function:nnnN #1#2#3#4
+ {
+ \int_compare:nNnTF {#2} > \c_zero
+ { \exp_args:NNf \@@_step:NnnnN > }
+ {
+ \int_compare:nNnTF {#2} = \c_zero
+ {
+ \__msg_kernel_expandable_error:nnn { kernel } { zero-step } {#4}
+ \use_none:nnnn
+ }
+ { \exp_args:NNf \@@_step:NnnnN < }
+ }
+ { \int_eval:n {#1} } {#2} {#3} #4
+ }
+\cs_new:Npn \@@_step:NnnnN #1#2#3#4#5
+ {
+ \int_compare:nNnF {#2} #1 {#4}
+ {
+ #5 {#2}
+ \exp_args:NNf \@@_step:NnnnN
+ #1 { \int_eval:n { #2 + #3 } } {#3} {#4} #5
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\int_step_inline:nnnn}
+% \begin{macro}{\int_step_variable:nnnNn}
+% \UnitTested
+% \begin{macro}[aux]{\@@_step:NNnnnn}
+% The approach here is to build a function, with a global integer
+% required to make the nesting safe (as seen in other in line
+% functions), and map that function using \cs{int_step_function:nnnN}.
+% We put a \cs{__prg_break_point:Nn} so that \texttt{map_break}
+% functions from other modules correctly decrement \cs{g__prg_map_int}
+% before looking for their own break point. The first argument is
+% \cs{scan_stop:}, so no breaking function will recognize this break
+% point as its own.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \int_step_inline:nnnn
+ {
+ \int_gincr:N \g__prg_map_int
+ \exp_args:NNc \@@_step:NNnnnn
+ \cs_gset_nopar:Npn
+ { __prg_map_ \int_use:N \g__prg_map_int :w }
+ }
+\cs_new_protected:Npn \int_step_variable:nnnNn #1#2#3#4#5
+ {
+ \int_gincr:N \g__prg_map_int
+ \exp_args:NNc \@@_step:NNnnnn
+ \cs_gset_nopar:Npx
+ { __prg_map_ \int_use:N \g__prg_map_int :w }
+ {#1}{#2}{#3}
+ {
+ \tl_set:Nn \exp_not:N #4 {##1}
+ \exp_not:n {#5}
+ }
+ }
+\cs_new_protected:Npn \@@_step:NNnnnn #1#2#3#4#5#6
+ {
+ #1 #2 ##1 {#6}
+ \int_step_function:nnnN {#3} {#4} {#5} #2
+ \__prg_break_point:Nn \scan_stop: { \int_gdecr:N \g__prg_map_int }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Formatting integers}
%
% \begin{macro}{\int_to_arabic:n}
@@ -1449,6 +1624,7 @@
%
% \begin{macro}{\int_to_symbols:nnn}
% \UnitTested
+% \begin{macro}[aux]{\@@_to_symbols:nnnn}
% For conversion of integers to arbitrary symbols the method is in
% general as follows. The input number (|#1|) is compared to the total
% number of symbols available at each place (|#2|). If the input is larger
@@ -1463,17 +1639,17 @@
{
\int_compare:nNnTF {#1} > {#2}
{
- \exp_args:NNo \exp_args:No \int_to_symbols_aux:nnnn
+ \exp_args:NNo \exp_args:No \@@_to_symbols:nnnn
{
- \prg_case_int:nnn
+ \int_case:nnn
{ 1 + \int_mod:nn { #1 - 1 } {#2} }
{#3} { }
}
{#1} {#2} {#3}
}
- { \prg_case_int:nnn {#1} {#3} { } }
+ { \int_case:nnn {#1} {#3} { } }
}
-\cs_new:Npn \int_to_symbols_aux:nnnn #1#2#3#4
+\cs_new:Npn \@@_to_symbols:nnnn #1#2#3#4
{
\exp_args:Nf \int_to_symbols:nnn
{ \int_div_truncate:nn { #2 - 1 } {#3} } {#3} {#4}
@@ -1481,6 +1657,7 @@
}
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\int_to_alph:n,\int_to_Alph:n}
% \UnitTested
@@ -1556,9 +1733,9 @@
%
% \begin{macro}{\int_to_base:nn}
% \UnitTested
-% \begin{macro}[aux]{\int_to_base_aux_i:nn,
-% \int_to_base_aux_ii:nnN,\int_to_base_aux_iii:nnnN}
-% \begin{macro}[int]{\int_to_letter:n}
+% \begin{macro}[aux]{\@@_to_base:nn,
+% \@@_to_base:nnN,\@@_to_base:nnnN}
+% \begin{macro}[aux]{\@@_to_letter:n}
% \UnitTested
% Converting from base ten (|#1|) to a second base (|#2|) starts with
% computing |#1|: if it is a complicated calculation, we shouldn't
@@ -1567,12 +1744,12 @@
% function.
% \begin{macrocode}
\cs_new:Npn \int_to_base:nn #1
- { \exp_args:Nf \int_to_base_aux_i:nn { \int_eval:n {#1} } }
-\cs_new:Npn \int_to_base_aux_i:nn #1#2
+ { \exp_args:Nf \@@_to_base:nn { \int_eval:n {#1} } }
+\cs_new:Npn \@@_to_base:nn #1#2
{
\int_compare:nNnTF {#1} < \c_zero
- { \exp_args:No \int_to_base_aux_ii:nnN { \use_none:n #1 } {#2} - }
- { \int_to_base_aux_ii:nnN {#1} {#2} \c_empty_tl }
+ { \exp_args:No \@@_to_base:nnN { \use_none:n #1 } {#2} - }
+ { \@@_to_base:nnN {#1} {#2} \c_empty_tl }
}
% \end{macrocode}
% Here, the idea is to provide a recursive system to deal with the
@@ -1585,21 +1762,21 @@
% modulus is converted to a symbol and put on the right,
% and the remainder is carried forward to the next round.
% \begin{macrocode}
-\cs_new:Npn \int_to_base_aux_ii:nnN #1#2#3
+\cs_new:Npn \@@_to_base:nnN #1#2#3
{
\int_compare:nNnTF {#1} < {#2}
- { \exp_last_unbraced:Nf #3 { \int_to_letter:n {#1} } }
+ { \exp_last_unbraced:Nf #3 { \@@_to_letter:n {#1} } }
{
- \exp_args:Nf \int_to_base_aux_iii:nnnN
- { \int_to_letter:n { \int_mod:nn {#1} {#2} } }
+ \exp_args:Nf \@@_to_base:nnnN
+ { \@@_to_letter:n { \int_mod:nn {#1} {#2} } }
{#1}
{#2}
#3
}
}
-\cs_new:Npn \int_to_base_aux_iii:nnnN #1#2#3#4
+\cs_new:Npn \@@_to_base:nnnN #1#2#3#4
{
- \exp_args:Nf \int_to_base_aux_ii:nnN
+ \exp_args:Nf \@@_to_base:nnN
{ \int_div_truncate:nn {#2} {#3} }
{#3}
#4
@@ -1607,7 +1784,7 @@
}
% \end{macrocode}
% Convert to a letter only if necessary, otherwise simply return the
-% value unchanged. It would be cleaner to use \cs{prg_case_int:nnn},
+% value unchanged. It would be cleaner to use \cs{int_case:nnn},
% but in our case, the cases are contiguous, so it is forty times faster
% to use the \cs{if_case:w} primitive. The first \cs{exp_after:wN}
% expands the conditional, jumping to the correct case, the second one
@@ -1615,10 +1792,10 @@
% Since |#1| might be an expression, and not directly a single digit,
% we need to evaluate it properly, and expand the trailing \cs{fi:}.
% \begin{macrocode}
-\cs_new:Npn \int_to_letter:n #1
+\cs_new:Npn \@@_to_letter:n #1
{
\exp_after:wN \exp_after:wN
- \if_case:w \int_eval:w #1 - \c_ten \int_eval_end:
+ \if_case:w \@@_eval:w #1 - \c_ten \@@_eval_end:
A
\or: B
\or: C
@@ -1645,7 +1822,7 @@
\or: X
\or: Y
\or: Z
- \else: \int_value:w \int_eval:w #1 \exp_after:wN \int_eval_end:
+ \else: \@@_value:w \@@_eval:w #1 \exp_after:wN \@@_eval_end:
\fi:
}
% \end{macrocode}
@@ -1668,17 +1845,17 @@
%
% \begin{macro}{\int_to_roman:n, \int_to_Roman:n}
% \UnitTested
-% \begin{macro}[aux]{\int_to_roman_aux:N, \int_to_roman_aux:N}
+% \begin{macro}[aux]{\@@_to_roman:N, \@@_to_roman:N}
% \begin{macro}[aux]
% {
-% \int_to_roman_i:w, \int_to_roman_v:w, \int_to_roman_x:w,
-% \int_to_roman_l:w, \int_to_roman_c:w, \int_to_roman_d:w,
-% \int_to_roman_m:w, \int_to_roman_Q:w,
-% \int_to_Roman_i:w, \int_to_Roman_v:w, \int_to_Roman_x:w,
-% \int_to_Roman_l:w, \int_to_Roman_c:w, \int_to_Roman_d:w,
-% \int_to_Roman_m:w, \int_to_Roman_Q:w,
+% \@@_to_roman_i:w, \@@_to_roman_v:w, \@@_to_roman_x:w,
+% \@@_to_roman_l:w, \@@_to_roman_c:w, \@@_to_roman_d:w,
+% \@@_to_roman_m:w, \@@_to_roman_Q:w,
+% \@@_to_Roman_i:w, \@@_to_Roman_v:w, \@@_to_Roman_x:w,
+% \@@_to_Roman_l:w, \@@_to_Roman_c:w, \@@_to_Roman_d:w,
+% \@@_to_Roman_m:w, \@@_to_Roman_Q:w,
% }
-% The \cs{int_to_roman:w} primitive creates tokens of category
+% The \cs{@@_to_roman:w} primitive creates tokens of category
% code $12$ (other). Usually, what is actually wanted is letters.
% The approach here is to convert the output of the primitive into
% letters using appropriate control sequence names. That keeps
@@ -1687,40 +1864,40 @@
% \begin{macrocode}
\cs_new:Npn \int_to_roman:n #1
{
- \exp_after:wN \int_to_roman_aux:N
- \int_to_roman:w \int_eval:n {#1} Q
+ \exp_after:wN \@@_to_roman:N
+ \@@_to_roman:w \int_eval:n {#1} Q
}
-\cs_new:Npn \int_to_roman_aux:N #1
+\cs_new:Npn \@@_to_roman:N #1
{
- \use:c { int_to_roman_ #1 :w }
- \int_to_roman_aux:N
+ \use:c { @@_to_roman_ #1 :w }
+ \@@_to_roman:N
}
\cs_new:Npn \int_to_Roman:n #1
{
- \exp_after:wN \int_to_Roman_aux:N
- \int_to_roman:w \int_eval:n {#1} Q
+ \exp_after:wN \@@_to_Roman_aux:N
+ \@@_to_roman:w \int_eval:n {#1} Q
}
-\cs_new:Npn \int_to_Roman_aux:N #1
+\cs_new:Npn \@@_to_Roman_aux:N #1
{
- \use:c { int_to_Roman_ #1 :w }
- \int_to_Roman_aux:N
+ \use:c { @@_to_Roman_ #1 :w }
+ \@@_to_Roman_aux:N
}
-\cs_new_nopar:Npn \int_to_roman_i:w { i }
-\cs_new_nopar:Npn \int_to_roman_v:w { v }
-\cs_new_nopar:Npn \int_to_roman_x:w { x }
-\cs_new_nopar:Npn \int_to_roman_l:w { l }
-\cs_new_nopar:Npn \int_to_roman_c:w { c }
-\cs_new_nopar:Npn \int_to_roman_d:w { d }
-\cs_new_nopar:Npn \int_to_roman_m:w { m }
-\cs_new_nopar:Npn \int_to_roman_Q:w #1 { }
-\cs_new_nopar:Npn \int_to_Roman_i:w { I }
-\cs_new_nopar:Npn \int_to_Roman_v:w { V }
-\cs_new_nopar:Npn \int_to_Roman_x:w { X }
-\cs_new_nopar:Npn \int_to_Roman_l:w { L }
-\cs_new_nopar:Npn \int_to_Roman_c:w { C }
-\cs_new_nopar:Npn \int_to_Roman_d:w { D }
-\cs_new_nopar:Npn \int_to_Roman_m:w { M }
-\cs_new:Npn \int_to_Roman_Q:w #1 { }
+\cs_new_nopar:Npn \@@_to_roman_i:w { i }
+\cs_new_nopar:Npn \@@_to_roman_v:w { v }
+\cs_new_nopar:Npn \@@_to_roman_x:w { x }
+\cs_new_nopar:Npn \@@_to_roman_l:w { l }
+\cs_new_nopar:Npn \@@_to_roman_c:w { c }
+\cs_new_nopar:Npn \@@_to_roman_d:w { d }
+\cs_new_nopar:Npn \@@_to_roman_m:w { m }
+\cs_new_nopar:Npn \@@_to_roman_Q:w #1 { }
+\cs_new_nopar:Npn \@@_to_Roman_i:w { I }
+\cs_new_nopar:Npn \@@_to_Roman_v:w { V }
+\cs_new_nopar:Npn \@@_to_Roman_x:w { X }
+\cs_new_nopar:Npn \@@_to_Roman_l:w { L }
+\cs_new_nopar:Npn \@@_to_Roman_c:w { C }
+\cs_new_nopar:Npn \@@_to_Roman_d:w { D }
+\cs_new_nopar:Npn \@@_to_Roman_m:w { M }
+\cs_new:Npn \@@_to_Roman_Q:w #1 { }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1728,54 +1905,54 @@
%
% \subsection{Converting from other formats to integers}
%
-% \begin{macro}[int]{\int_get_sign:n}
-% \begin{macro}[int]{\int_get_digits:n}
+% \begin{macro}[int]{\@@_get_sign:n}
+% \begin{macro}[int]{\@@_get_digits:n}
% \begin{macro}[aux]
-% {\int_get_sign_and_digits_aux:nNNN, \int_get_sign_and_digits_aux:oNNN}
+% {\@@_get_sign_and_digits:nNNN, \@@_get_sign_and_digits:oNNN}
% Finding a number and its sign requires dealing with an arbitrary
% list of |+| and |-| symbols. This is done by working through token
% by token until there is something else at the start of the input.
% The sign of the input is tracked by the first Boolean used by the
% auxiliary function.
% \begin{macrocode}
-\cs_new:Npn \int_get_sign:n #1
+\cs_new:Npn \@@_get_sign:n #1
{
- \int_get_sign_and_digits_aux:nNNN {#1}
+ \@@_get_sign_and_digits:nNNN {#1}
\c_true_bool \c_true_bool \c_false_bool
}
-\cs_new:Npn \int_get_digits:n #1
+\cs_new:Npn \@@_get_digits:n #1
{
- \int_get_sign_and_digits_aux:nNNN {#1}
+ \@@_get_sign_and_digits:nNNN {#1}
\c_true_bool \c_false_bool \c_true_bool
}
% \end{macrocode}
% The auxiliary loops through, finding sign tokens and removing them.
% The sign itself is carried through as a flag.
% \begin{macrocode}
-\cs_new:Npn \int_get_sign_and_digits_aux:nNNN #1#2#3#4
+\cs_new:Npn \@@_get_sign_and_digits:nNNN #1#2#3#4
{
\exp_args:Nf \tl_if_head_eq_charcode:nNTF {#1} -
{
\bool_if:NTF #2
{
- \int_get_sign_and_digits_aux:oNNN
+ \@@_get_sign_and_digits:oNNN
{ \use_none:n #1 } \c_false_bool #3#4
}
{
- \int_get_sign_and_digits_aux:oNNN
+ \@@_get_sign_and_digits:oNNN
{ \use_none:n #1 } \c_true_bool #3#4
}
}
{
\exp_args:Nf \tl_if_head_eq_charcode:nNTF {#1} +
- { \int_get_sign_and_digits_aux:oNNN { \use_none:n #1 } #2#3#4 }
+ { \@@_get_sign_and_digits:oNNN { \use_none:n #1 } #2#3#4 }
{
\bool_if:NT #3 { \bool_if:NF #2 - }
\bool_if:NT #4 {#1}
}
}
}
-\cs_generate_variant:Nn \int_get_sign_and_digits_aux:nNNN { o }
+\cs_generate_variant:Nn \@@_get_sign_and_digits:nNNN { o }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1783,9 +1960,9 @@
%
% \begin{macro}{\int_from_alph:n}
% \UnitTested
-% \begin{macro}[aux]{\int_from_alph_aux:n}
-% \begin{macro}[aux]{\int_from_alph_aux:nN}
-% \begin{macro}[aux]{\int_from_alph_aux:N}
+% \begin{macro}[aux]{\@@_from_alph:n}
+% \begin{macro}[aux]{\@@_from_alph:nN}
+% \begin{macro}[aux]{\@@_from_alph:N}
% The aim here is to iterate through the input, converting one letter at
% a time to a number. The same approach is also used for base
% conversion, but this needs a different final auxiliary.
@@ -1794,22 +1971,22 @@
{
\int_eval:n
{
- \int_get_sign:n {#1}
- \exp_args:Nf \int_from_alph_aux:n { \int_get_digits:n {#1} }
+ \@@_get_sign:n {#1}
+ \exp_args:Nf \@@_from_alph:n { \@@_get_digits:n {#1} }
}
}
-\cs_new:Npn \int_from_alph_aux:n #1
- { \int_from_alph_aux:nN { 0 } #1 \q_nil }
-\cs_new:Npn \int_from_alph_aux:nN #1#2
+\cs_new:Npn \@@_from_alph:n #1
+ { \@@_from_alph:nN { 0 } #1 \q_nil }
+\cs_new:Npn \@@_from_alph:nN #1#2
{
\quark_if_nil:NTF #2
{#1}
{
- \exp_args:Nf \int_from_alph_aux:nN
- { \int_eval:n { #1 * 26 + \int_from_alph_aux:N #2 } }
+ \exp_args:Nf \@@_from_alph:nN
+ { \int_eval:n { #1 * 26 + \@@_from_alph:N #2 } }
}
}
-\cs_new:Npn \int_from_alph_aux:N #1
+\cs_new:Npn \@@_from_alph:N #1
{ \int_eval:n { `#1 - \int_compare:nNnTF { `#1 } < { 91 } { 64 } { 96 } } }
% \end{macrocode}
% \end{macro}
@@ -1819,9 +1996,9 @@
%
% \begin{macro}{\int_from_base:nn}
% \UnitTested
-% \begin{macro}[aux]{\int_from_base_aux:nn}
-% \begin{macro}[aux]{\int_from_base_aux:nnN}
-% \begin{macro}[aux]{\int_from_base_aux:N}
+% \begin{macro}[aux]{\@@_from_base:nn}
+% \begin{macro}[aux]{\@@_from_base:nnN}
+% \begin{macro}[aux]{\@@_from_base:N}
% Conversion to base ten means stripping off the sign then iterating
% through the input one token at a time. The total number is then added
% up as the code loops.
@@ -1830,20 +2007,20 @@
{
\int_eval:n
{
- \int_get_sign:n {#1}
- \exp_args:Nf \int_from_base_aux:nn
- { \int_get_digits:n {#1} } {#2}
+ \@@_get_sign:n {#1}
+ \exp_args:Nf \@@_from_base:nn
+ { \@@_get_digits:n {#1} } {#2}
}
}
-\cs_new:Npn \int_from_base_aux:nn #1#2
- { \int_from_base_aux:nnN { 0 } { #2 } #1 \q_nil }
-\cs_new:Npn \int_from_base_aux:nnN #1#2#3
+\cs_new:Npn \@@_from_base:nn #1#2
+ { \@@_from_base:nnN { 0 } { #2 } #1 \q_nil }
+\cs_new:Npn \@@_from_base:nnN #1#2#3
{
\quark_if_nil:NTF #3
{#1}
{
- \exp_args:Nf \int_from_base_aux:nnN
- { \int_eval:n { #1 * #2 + \int_from_base_aux:N #3 } }
+ \exp_args:Nf \@@_from_base:nnN
+ { \int_eval:n { #1 * #2 + \@@_from_base:N #3 } }
{#2}
}
}
@@ -1852,7 +2029,7 @@
% them into the appropriate number, hence the two-part nature of the
% function.
% \begin{macrocode}
-\cs_new:Npn \int_from_base_aux:N #1
+\cs_new:Npn \@@_from_base:N #1
{
\int_compare:nNnTF { `#1 } < { 58 }
{#1}
@@ -1882,40 +2059,40 @@
%
% \begin{variable}
% {
-% \c_int_from_roman_i_int, \c_int_from_roman_v_int,
-% \c_int_from_roman_x_int, \c_int_from_roman_l_int,
-% \c_int_from_roman_c_int, \c_int_from_roman_d_int,
-% \c_int_from_roman_m_int,
-% \c_int_from_roman_I_int, \c_int_from_roman_V_int,
-% \c_int_from_roman_X_int, \c_int_from_roman_L_int,
-% \c_int_from_roman_C_int, \c_int_from_roman_D_int,
-% \c_int_from_roman_M_int
+% \c_@@_from_roman_i_int, \c_@@_from_roman_v_int,
+% \c_@@_from_roman_x_int, \c_@@_from_roman_l_int,
+% \c_@@_from_roman_c_int, \c_@@_from_roman_d_int,
+% \c_@@_from_roman_m_int,
+% \c_@@_from_roman_I_int, \c_@@_from_roman_V_int,
+% \c_@@_from_roman_X_int, \c_@@_from_roman_L_int,
+% \c_@@_from_roman_C_int, \c_@@_from_roman_D_int,
+% \c_@@_from_roman_M_int
% }
% Constants used to convert from Roman numerals to integers.
% \begin{macrocode}
-\int_const:cn { c_int_from_roman_i_int } { 1 }
-\int_const:cn { c_int_from_roman_v_int } { 5 }
-\int_const:cn { c_int_from_roman_x_int } { 10 }
-\int_const:cn { c_int_from_roman_l_int } { 50 }
-\int_const:cn { c_int_from_roman_c_int } { 100 }
-\int_const:cn { c_int_from_roman_d_int } { 500 }
-\int_const:cn { c_int_from_roman_m_int } { 1000 }
-\int_const:cn { c_int_from_roman_I_int } { 1 }
-\int_const:cn { c_int_from_roman_V_int } { 5 }
-\int_const:cn { c_int_from_roman_X_int } { 10 }
-\int_const:cn { c_int_from_roman_L_int } { 50 }
-\int_const:cn { c_int_from_roman_C_int } { 100 }
-\int_const:cn { c_int_from_roman_D_int } { 500 }
-\int_const:cn { c_int_from_roman_M_int } { 1000 }
+\int_const:cn { c_@@_from_roman_i_int } { 1 }
+\int_const:cn { c_@@_from_roman_v_int } { 5 }
+\int_const:cn { c_@@_from_roman_x_int } { 10 }
+\int_const:cn { c_@@_from_roman_l_int } { 50 }
+\int_const:cn { c_@@_from_roman_c_int } { 100 }
+\int_const:cn { c_@@_from_roman_d_int } { 500 }
+\int_const:cn { c_@@_from_roman_m_int } { 1000 }
+\int_const:cn { c_@@_from_roman_I_int } { 1 }
+\int_const:cn { c_@@_from_roman_V_int } { 5 }
+\int_const:cn { c_@@_from_roman_X_int } { 10 }
+\int_const:cn { c_@@_from_roman_L_int } { 50 }
+\int_const:cn { c_@@_from_roman_C_int } { 100 }
+\int_const:cn { c_@@_from_roman_D_int } { 500 }
+\int_const:cn { c_@@_from_roman_M_int } { 1000 }
% \end{macrocode}
% \end{variable}
%
% \begin{macro}{\int_from_roman:n}
% \UnitTested
% \TestMissing{boundary cases / wrong input?}
-% \begin{macro}[aux]{\int_from_roman_aux:NN}
-% \begin{macro}[aux]{\int_from_roman_end:w}
-% \begin{macro}[aux]{\int_from_roman_clean_up:w}
+% \begin{macro}[aux]{\@@_from_roman:NN}
+% \begin{macro}[aux]{\@@_from_roman_end:w}
+% \begin{macro}[aux]{\@@_from_roman_clean_up:w}
% The method here is to iterate through the input, finding the
% appropriate value for each letter and building up a sum. This is
% then evaluated by \TeX{}.
@@ -1924,48 +2101,48 @@
{
\tl_if_blank:nF {#1}
{
- \exp_after:wN \int_from_roman_end:w
- \int_value:w \int_eval:w
- \int_from_roman_aux:NN #1 Q \q_stop
+ \exp_after:wN \@@_from_roman_end:w
+ \@@_value:w \@@_eval:w
+ \@@_from_roman:NN #1 Q \q_stop
}
}
-\cs_new:Npn \int_from_roman_aux:NN #1#2
+\cs_new:Npn \@@_from_roman:NN #1#2
{
\str_if_eq:nnTF {#1} { Q }
{#1#2}
{
\str_if_eq:nnTF {#2} { Q }
{
- \int_if_exist:cF { c_int_from_roman_ #1 _int }
- { \int_from_roman_clean_up:w }
+ \int_if_exist:cF { c_@@_from_roman_ #1 _int }
+ { \@@_from_roman_clean_up:w }
+
- \use:c { c_int_from_roman_ #1 _int }
+ \use:c { c_@@_from_roman_ #1 _int }
#2
}
{
- \int_if_exist:cF { c_int_from_roman_ #1 _int }
- { \int_from_roman_clean_up:w }
- \int_if_exist:cF { c_int_from_roman_ #2 _int }
- { \int_from_roman_clean_up:w }
+ \int_if_exist:cF { c_@@_from_roman_ #1 _int }
+ { \@@_from_roman_clean_up:w }
+ \int_if_exist:cF { c_@@_from_roman_ #2 _int }
+ { \@@_from_roman_clean_up:w }
\int_compare:nNnTF
- { \use:c { c_int_from_roman_ #1 _int } }
+ { \use:c { c_@@_from_roman_ #1 _int } }
<
- { \use:c { c_int_from_roman_ #2 _int } }
+ { \use:c { c_@@_from_roman_ #2 _int } }
{
- + \use:c { c_int_from_roman_ #2 _int }
- - \use:c { c_int_from_roman_ #1 _int }
- \int_from_roman_aux:NN
+ + \use:c { c_@@_from_roman_ #2 _int }
+ - \use:c { c_@@_from_roman_ #1 _int }
+ \@@_from_roman:NN
}
{
- + \use:c { c_int_from_roman_ #1 _int }
- \int_from_roman_aux:NN #2
+ + \use:c { c_@@_from_roman_ #1 _int }
+ \@@_from_roman:NN #2
}
}
}
}
-\cs_new:Npn \int_from_roman_end:w #1 Q #2 \q_stop
+\cs_new:Npn \@@_from_roman_end:w #1 Q #2 \q_stop
{ \tl_if_empty:nTF {#2} {#1} {#2} }
-\cs_new:Npn \int_from_roman_clean_up:w #1 Q { + 0 Q -1 }
+\cs_new:Npn \@@_from_roman_clean_up:w #1 Q { + 0 Q -1 }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1977,16 +2154,19 @@
% \begin{macro}{\int_show:N,\int_show:c}
% \UnitTested
% \begin{macrocode}
-\cs_new_eq:NN \int_show:N \kernel_register_show:N
-\cs_new_eq:NN \int_show:c \kernel_register_show:c
+\cs_new_eq:NN \int_show:N \__kernel_register_show:N
+\cs_new_eq:NN \int_show:c \__kernel_register_show:c
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\int_show:n}
% \UnitTested
+% We don't use the \TeX{} primitive \tn{showthe} to show integer
+% expressions: this gives a more unified output, since the closing
+% brace is read by the integer expression in all cases.
% \begin{macrocode}
\cs_new_protected:Npn \int_show:n #1
- { \tex_showthe:D \int_eval:w #1 \int_eval_end: }
+ { \etex_showtokens:D \exp_after:wN { \int_use:N \@@_eval:w #1 } }
% \end{macrocode}
% \end{macro}
%
@@ -2064,14 +2244,13 @@
%
% \subsection{Scratch integers}
%
-% \begin{variable}{\l_tmpa_int, \l_tmpb_int, \l_tmpc_int}
+% \begin{variable}{\l_tmpa_int, \l_tmpb_int}
% \begin{variable}{\g_tmpa_int, \g_tmpb_int}
-% We provide three local and two global scratch counters, maybe we
+% We provide two local and two global scratch counters, maybe we
% need more or less.
% \begin{macrocode}
\int_new:N \l_tmpa_int
\int_new:N \l_tmpb_int
-\int_new:N \l_tmpc_int
\int_new:N \g_tmpa_int
\int_new:N \g_tmpb_int
% \end{macrocode}
@@ -2147,6 +2326,35 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\if_num:w}
+% Deprecated 2012-05-30 for removal after 2012-11-30.
+% \begin{macrocode}
+\cs_new_eq:NN \if_num:w \if_int_compare:w
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_tmpc_int}
+% Deprecated 2012-07-04 for removal after 2012-12-31.
+% \begin{macrocode}
+\int_new:N \l_tmpc_int
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}{\int_eval:w, \int_eval_end:}
+% Deprecated 2012-07-13 for removal after 2012-12-31.
+% \begin{macrocode}
+\cs_new_eq:NN \int_eval:w \@@_eval:w
+\cs_new_eq:NN \int_eval_end: \@@_eval_end:
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\int_value:w}
+% Deprecated 2012-07-14 for removal after 2012-12-31.
+% \begin{macrocode}
+\cs_new_eq:NN \int_value:w \@@_value:w
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
index e0becb45696..7e3cc783af2 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3keys.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3keys.dtx Copyright (C) 2006-2011 The LaTeX3 Project
+%% File: l3keys.dtx Copyright (C) 2006-2012 The LaTeX3 Project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -35,7 +35,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3keys.dtx 3487 2012-03-03 19:36:51Z bruno $
+\GetIdInfo$Id: l3keys.dtx 3986 2012-07-15 19:23:51Z joseph $
{L3 Experimental key-value interfaces}
%</driver|package>
%<*driver>
@@ -170,27 +170,18 @@
% arbitrary \meta{key}, which when used may be supplied with a
% \meta{value}. All key \emph{definitions} are local.
%
-% \begin{function}{.bool_set:N}
+% \begin{function}{.bool_set:N, .bool_gset:N}
% \begin{syntax}
% \meta{key} .bool_set:N = \meta{boolean}
% \end{syntax}
% Defines \meta{key} to set \meta{boolean} to \meta{value} (which
% must be either \texttt{true} or \texttt{false}). If the variable
% does not exist, it will be created at the point that the key is
-% set up. The \meta{boolean} will be assigned locally.
+% set up.
% \end{function}
%
-% \begin{function}{.bool_gset:N}
-% \begin{syntax}
-% \meta{key} .bool_gset:N = \meta{boolean}
-% \end{syntax}
-% Defines \meta{key} to set \meta{boolean} to \meta{value} (which
-% must be either \texttt{true} or \texttt{false}). If the variable
-% does not exist, it will be created at the point that the key is
-% set up. The \meta{boolean} will be assigned globally.
-% \end{function}
-%
-% \begin{function}[added = 2011-08-28]{.bool_set_inverse:N}
+% \begin{function}[added = 2011-08-28]
+% {.bool_set_inverse:N, .bool_gset_inverse:N}
% \begin{syntax}
% \meta{key} .bool_set_inverse:N = \meta{boolean}
% \end{syntax}
@@ -198,22 +189,7 @@
% inverse of \meta{value} (which must be either \texttt{true} or
% \texttt{false}).
% If the \meta{boolean} does not exist, it will be created at the point
-% that the key is set up. The \meta{boolean} will be assigned locally.
-%
-% \textbf{This property is experimental.}
-% \end{function}
-%
-% \begin{function}{.bool_gset_inverse:N}
-% \begin{syntax}
-% \meta{key} .bool_gset_inverse:N = \meta{boolean}
-% \end{syntax}
-% Defines \meta{key} to set \meta{boolean} to the logical
-% inverse of \meta{value} (which must be either \texttt{true} or
-% \texttt{false}).
-% If the \meta{boolean} does not exist, it will be created at the point
-% that the key is set up. The \meta{boolean} will be assigned globally.
-%
-% \textbf{This property is experimental.}
+% that the key is set up.
% \end{function}
%
% \begin{function}{.choice:}
@@ -233,10 +209,8 @@
% which are implemented using the \meta{code}. Inside \meta{code},
% \cs{l_keys_choice_tl} will be the name of the choice made, and
% \cs{l_keys_choice_int} will be the position of the choice in the list
-% of \meta{choices} (indexed from $0$).
+% of \meta{choices} (indexed from~$1$).
% Choices are discussed in detail in section~\ref{sec:choice}.
-%
-% \textbf{This property is experimental.}
% \end{function}
%
% \begin{function}{.choice_code:n, .choice_code:x}
@@ -251,21 +225,12 @@
% detail in section~\ref{sec:choice}.
% \end{function}
%
-% \begin{function}[added=2011/09/11]{.clist_set:N, .clist_set:c}
+% \begin{function}[added=2011/09/11]
+% {.clist_set:N, .clist_set:c, .clist_gset:N, .clist_gset:c}
% \begin{syntax}
% \meta{key} .clist_set:N = \meta{comma list variable}
% \end{syntax}
-% Defines \meta{key} to locally set \meta{comma list variable} to \meta{value}.
-% Spaces around commas and empty items will be stripped.
-% If the variable does not exist, it
-% will be created at the point that the key is set up.
-% \end{function}
-%
-% \begin{function}[added=2011/09/11]{.clist_gset:N, .clist_gset:c}
-% \begin{syntax}
-% \meta{key} .clist_gset:N = \meta{comma list variable}
-% \end{syntax}
-% Defines \meta{key} to globally set \meta{comma list variable} to \meta{value}.
+% Defines \meta{key} to set \meta{comma list variable} to \meta{value}.
% Spaces around commas and empty items will be stripped.
% If the variable does not exist, it
% will be created at the point that the key is set up.
@@ -304,44 +269,22 @@
% \end{verbatim}
% \end{function}
%
-% \begin{function}{.dim_set:N, .dim_set:c}
+% \begin{function}{.dim_set:N, .dim_set:c, .dim_gset:N, .dim_gset:c}
% \begin{syntax}
% \meta{key} .dim_set:N = \meta{dimension}
% \end{syntax}
% Defines \meta{key} to set \meta{dimension} to \meta{value} (which
% must a dimension expression). If the variable does not exist, it
-% will be created at the point that the key is set up. The
-% \meta{dimension} will be assigned locally.
-% \end{function}
-%
-% \begin{function}{.dim_gset:N, .dim_gset:c}
-% \begin{syntax}
-% \meta{key} .dim_gset:N = \meta{dimension}
-% \end{syntax}
-% Defines \meta{key} to set \meta{dimension} to \meta{value} (which
-% must a dimension expression). If the variable does not exist, it
-% will be created at the point that the key is set up. The
-% \meta{dimension} will be assigned globally.
+% will be created at the point that the key is set up.
% \end{function}
%
-% \begin{function}{.fp_set:N, .fp_set:c}
+% \begin{function}{.fp_set:N, .fp_set:c, .fp_gset:N, .fp_gset:c}
% \begin{syntax}
% \meta{key} .fp_set:N = \meta{floating point}
% \end{syntax}
% Defines \meta{key} to set \meta{floating point} to \meta{value}
% (which must a floating point number). If the variable does not exist,
-% it will be created at the point that the key is set up. The
-% \meta{integer} will be assigned locally.
-% \end{function}
-%
-% \begin{function}{.fp_gset:N, .fp_gset:c}
-% \begin{syntax}
-% \meta{key} .fp_gset:N = \meta{floating point}
-% \end{syntax}
-% Defines \meta{key} to set \meta{floating-point} to \meta{value}
-% (which must a floating point number). If the variable does not exist,
-% it will be created at the point that the key is set up. The
-% \meta{integer} will be assigned globally.
+% it will be created at the point that the key is set up.
% \end{function}
%
% \begin{function}{.generate_choices:n}
@@ -355,25 +298,24 @@
% \texttt{.choice_code:n} (or \texttt{.choice_code:x}). Choices are
% discussed in detail in section~\ref{sec:choice}.
% \end{function}
-%
-% \begin{function}{.int_set:N, .int_set:c}
+%
+% \begin{function}[added = 2012-06-02]{.initial:n, .initial:V}
% \begin{syntax}
-% \meta{key} .int_set:N = \meta{integer}
+% \meta{key} .initial:n = \meta{value}
% \end{syntax}
-% Defines \meta{key} to set \meta{integer} to \meta{value} (which
-% must be an integer expression). If the variable does not exist, it
-% will be created at the point that the key is set up. The
-% \meta{integer} will be assigned locally.
+% Initialises the \meta{key} with the \meta{value}, equivalent to
+% \begin{quote}
+% \cs{keys_set:nn} \marg{module} \{ \meta{key} = \meta{value} \}
+% \end{quote}
% \end{function}
%
-% \begin{function}{.int_gset:N, .int_gset:c}
+% \begin{function}{.int_set:N, .int_set:c, .int_gset:N, .int_gset:c}
% \begin{syntax}
-% \meta{key} .int_gset:N = \meta{integer}
+% \meta{key} .int_set:N = \meta{integer}
% \end{syntax}
% Defines \meta{key} to set \meta{integer} to \meta{value} (which
% must be an integer expression). If the variable does not exist, it
-% will be created at the point that the key is set up. The
-% \meta{integer} will be assigned globally.
+% will be created at the point that the key is set up.
% \end{function}
%
% \begin{function}{.meta:n, .meta:x}
@@ -397,81 +339,47 @@
% \textbf{This property is experimental.}
% \end{function}
%
-% \begin{function}[added = 2011-08-21]{.multichoice:nn}
+% \begin{function}[added = 2011-08-21]{.multichoices:nn}
% \begin{syntax}
-% \meta{key} .multichoice:nn \meta{choices} \meta{code}
+% \meta{key} .multichoices:nn \meta{choices} \meta{code}
% \end{syntax}
% Sets \meta{key} to act as a multiple choice key, and defines a series
% \meta{choices}
% which are implemented using the \meta{code}. Inside \meta{code},
% \cs{l_keys_choice_tl} will be the name of the choice made, and
% \cs{l_keys_choice_int} will be the position of the choice in the list
-% of \meta{choices} (indexed from $0$).
+% of \meta{choices} (indexed from~$1$).
% Choices are discussed in detail in section~\ref{sec:choice}.
%
% \textbf{This property is experimental.}
% \end{function}
%
-% \begin{function}{.skip_set:N, .skip_set:c}
+% \begin{function}{.skip_set:N, .skip_set:c, .skip_gset:N, .skip_gset:c}
% \begin{syntax}
% \meta{key} .skip_set:N = \meta{skip}
% \end{syntax}
% Defines \meta{key} to set \meta{skip} to \meta{value} (which
% must be a skip expression). If the variable does not exist, it
-% will be created at the point that the key is set up. The
-% \meta{skip} will be assigned locally.
-% \end{function}
-%
-% \begin{function}{.skip_gset:N, .skip_gset:c}
-% \begin{syntax}
-% \meta{key} .skip_gset:N = \meta{skip}
-% \end{syntax}
-% Defines \meta{key} to set \meta{skip} to \meta{value} (which
-% must be a skip expression). If the variable does not exist, it
-% will be created at the point that the key is set up. The
-% \meta{skip} will be assigned globally.
+% will be created at the point that the key is set up.
% \end{function}
%
-% \begin{function}{.tl_set:N, .tl_set:c}
+% \begin{function}{.tl_set:N, .tl_set:c, .tl_gset:N, .tl_gset:c}
% \begin{syntax}
% \meta{key} .tl_set:N = \meta{token list variable}
% \end{syntax}
% Defines \meta{key} to set \meta{token list variable} to \meta{value}.
% If the variable does not exist, it will be created at the point that
-% the key is set up. The \meta{token list variable} will be assigned
-% locally.
-% \end{function}
-%
-% \begin{function}{.tl_gset:N, .tl_gset:c}
-% \begin{syntax}
-% \meta{key} .tl_gset:N = \meta{token list variable}
-% \end{syntax}
-% Defines \meta{key} to set \meta{token list variable} to \meta{value}.
-% If the variable does not exist, it will be created at the point that
-% the key is set up. The \meta{token list variable} will be assigned
-% globally.
+% the key is set up.
% \end{function}
%
-% \begin{function}{.tl_set_x:N, .tl_set_x:c}
+% \begin{function}{.tl_set_x:N, .tl_set_x:c, .tl_gset_x:N, .tl_gset_x:c}
% \begin{syntax}
% \meta{key} .tl_set_x:N = \meta{token list variable}
% \end{syntax}
% Defines \meta{key} to set \meta{token list variable} to \meta{value},
% which will be subjected to an \texttt{x}-type expansion
% (\emph{i.e.}~using \cs{tl_set:Nx}). If the variable does not exist,
-% it will be created at the point that the key is set up. The
-% \meta{token list variable} will be assigned locally.
-% \end{function}
-%
-% \begin{function}{.tl_gset_x:N, .tl_gset_x:c}
-% \begin{syntax}
-% \meta{key} .tl_gset_x:N = \meta{token list variable}
-% \end{syntax}
-% Defines \meta{key} to set \meta{token list variable} to \meta{value},
-% which will be subjected to an \texttt{x}-type expansion
-% (\emph{i.e.}~using \cs{tl_set:Nx}). If the variable does not exist,
-% it will be created at the point that the key is set up. The
-% \meta{token list variable} will be assigned globally.
+% it will be created at the point that the key is set up.
% \end{function}
%
% \begin{function}{.value_forbidden:}
@@ -552,9 +460,7 @@
% }
% \end{verbatim}
% Following common computing practice, \cs{l_keys_choice_int} is
-% indexed from $0$ (as an offset), so that the value of
-% \cs{l_keys_choice_int} for the first choice in a list will be
-% zero.
+% indexed from~$1$.
%
% The same approach is also implemented by the \emph{experimental}
% property \texttt{.choices:nn}. This combines the functionality of
@@ -691,9 +597,6 @@
%
% \section{Setting known keys only}
%
-% The functionality described in this section is experimental and may be
-% altered or removed, depending on feedback.
-%
% \begin{function}[added = 2011-08-23]
% {
% \keys_set_known:nnN, \keys_set_known:nVN,
@@ -720,7 +623,7 @@
% has been defined for \meta{key}.
% \end{function}
%
-% \begin{function}[added = 2011-08-21,EXP,pTF]{\keys_if_choice_exist:nn}
+% \begin{function}[added = 2011-08-21,EXP,pTF]{\keys_if_choice_exist:nnn}
% \begin{syntax}
% \cs{keys_if_choice_exist_p:nnn} \meta{module} \meta{key} \meta{choice} \\
% \cs{keys_if_choice_exist:nnnTF} \meta{module} \meta{key} \meta{choice} \Arg{true code} \Arg{false code}
@@ -782,15 +685,15 @@
%
% \begin{function}[updated = 2011-09-08]{\keyval_parse:NNn}
% \begin{syntax}
-% \cs{keyval_parse:NNn} \meta{function1} \meta{function2} \Arg{key--value list}
+% \cs{keyval_parse:NNn} \meta{function_1} \meta{function_2} \Arg{key--value list}
% \end{syntax}
% Parses the \meta{key--value list} into a series of \meta{keys} and
% associated \meta{values}, or keys alone (if no \meta{value} was
-% given). \meta{function1} should take one argument, while
-% \meta{function2} should absorb two arguments. After
+% given). \meta{function_1} should take one argument, while
+% \meta{function_2} should absorb two arguments. After
% \cs{keyval_parse:NNn} has parsed the \meta{key--value list},
-% \meta{function1} will be used to process keys given with no value
-% and \meta{function2} will be used to process keys given with a
+% \meta{function_1} will be used to process keys given with no value
+% and \meta{function_2} will be used to process keys given with a
% value. The order of the \meta{keys} in the \meta{key--value list}
% will be preserved. Thus
% \begin{verbatim}
@@ -825,41 +728,43 @@
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
% \subsection{Low-level interface}
+%
+%<@@=keyval>
%
% For historical reasons this code uses the `keyval' module prefix.
%
-% \begin{variable}{\g_keyval_level_int}
+% \begin{variable}{\g_@@_level_int}
% For nesting purposes an integer is needed for the current level.
% \begin{macrocode}
-\int_new:N \g_keyval_level_int
+\int_new:N \g_@@_level_int
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_keyval_key_tl, \l_keyval_value_tl}
+% \begin{variable}{\l_@@_key_tl, \l_@@_value_tl}
% The current key name and value.
% \begin{macrocode}
-\tl_new:N \l_keyval_key_tl
-\tl_new:N \l_keyval_value_tl
+\tl_new:N \l_@@_key_tl
+\tl_new:N \l_@@_value_tl
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_keyval_sanitise_tl}
-% \begin{variable}{\l_keyval_parse_tl}
+% \begin{variable}{\l_@@_sanitise_tl}
+% \begin{variable}{\l_@@_parse_tl}
% Token list variables for dealing with awkward category codes in the
% input.
% \begin{macrocode}
-\tl_new:N \l_keyval_sanitise_tl
-\tl_new:N \l_keyval_parse_tl
+\tl_new:N \l_@@_sanitise_tl
+\tl_new:N \l_@@_parse_tl
% \end{macrocode}
%\end{variable}
%\end{variable}
%
-% \begin{macro}{\keyval_parse:n}
+% \begin{macro}{\@@_parse:n}
% The parsing function first deals with the category codes for
% |=| and |,|, so that there are no odd events. The input is then
% handed off to the element by element system.
@@ -872,49 +777,49 @@
\tl_to_lowercase:n
{
\group_end:
- \cs_new_protected:Npn \keyval_parse:n #1
+ \cs_new_protected:Npn \@@_parse:n #1
{
\group_begin:
- \tl_clear:N \l_keyval_sanitise_tl
- \tl_set:Nn \l_keyval_sanitise_tl {#1}
- \tl_replace_all:Nnn \l_keyval_sanitise_tl { = } { 8 }
- \tl_replace_all:Nnn \l_keyval_sanitise_tl { , } { 9 }
- \tl_clear:N \l_keyval_parse_tl
- \exp_after:wN \keyval_parse_elt:w \exp_after:wN
- \q_no_value \l_keyval_sanitise_tl 9 \q_nil 9
+ \tl_clear:N \l_@@_sanitise_tl
+ \tl_set:Nn \l_@@_sanitise_tl {#1}
+ \tl_replace_all:Nnn \l_@@_sanitise_tl { = } { 8 }
+ \tl_replace_all:Nnn \l_@@_sanitise_tl { , } { 9 }
+ \tl_clear:N \l_@@_parse_tl
+ \exp_after:wN \@@_parse_elt:w \exp_after:wN
+ \q_no_value \l_@@_sanitise_tl 9 \q_nil 9
\exp_after:wN \group_end:
- \l_keyval_parse_tl
+ \l_@@_parse_tl
}
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\keyval_parse_elt:w}
+% \begin{macro}{\@@_parse_elt:w}
% Each item to be parsed will have \cs{q_no_value} added to the front.
% Hence the blank test here can always be used to find a totally
% empty argument. If this is the case, the system loops round. If there
% is something to parse, there is a check for the \cs{q_nil} marker
% and if not a hand-off.
% \begin{macrocode}
-\cs_new_protected:Npn \keyval_parse_elt:w #1 ,
+\cs_new_protected:Npn \@@_parse_elt:w #1 ,
{
\tl_if_blank:oTF { \use_none:n #1 }
- { \keyval_parse_elt:w \q_no_value }
+ { \@@_parse_elt:w \q_no_value }
{
\quark_if_nil:oF { \use_ii:nn #1 }
{
- \keyval_split_key_value:w #1 = = \q_stop
- \keyval_parse_elt:w \q_no_value
+ \@@_split_key_value:w #1 = = \q_stop
+ \@@_parse_elt:w \q_no_value
}
}
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\keyval_split_key_value:w}
-% \begin{macro}[aux]{\keyval_split_key_value_aux:wTF}
+% \begin{macro}{\@@_split_key_value:w}
+% \begin{macro}[aux]{\@@_split_key_value:wTF}
% The key and value are handled separately. First the key is grabbed and
-% saved as \cs{l_keyval_key_tl}. Then a check is need to see if there is
+% saved as \cs{l_@@_key_tl}. Then a check is need to see if there is
% a value at all: if not then the key name is simply added to the output.
% If there is a value then there is a check to ensure that there was
% only one |=| in the input (remembering some extra ones are around at
@@ -922,84 +827,84 @@
% hand-off to find the value: the \cs{q_nil} is there to prevent loss
% of braces.
% \begin{macrocode}
-\cs_new_protected:Npn \keyval_split_key_value:w #1 = #2 \q_stop
+\cs_new_protected:Npn \@@_split_key_value:w #1 = #2 \q_stop
{
- \keyval_split_key:w #1 \q_stop
+ \@@_split_key:w #1 \q_stop
\str_if_eq:nnTF {#2} { = }
{
- \tl_put_right:Nx \l_keyval_parse_tl
+ \tl_put_right:Nx \l_@@_parse_tl
{
\exp_not:c
- { keyval_key_no_value_elt_ \int_use:N \g_keyval_level_int :n }
- { \exp_not:o \l_keyval_key_tl }
+ { @@_key_no_value_elt_ \int_use:N \g_@@_level_int :n }
+ { \exp_not:o \l_@@_key_tl }
}
}
{
- \keyval_split_key_value_aux:wTF #2 \q_no_value \q_stop
- { \keyval_split_value:w \q_nil #2 }
- { \msg_kernel_error:nn { keyval } { misplaced-equals-sign } }
+ \@@_split_key_value:wTF #2 \q_no_value \q_stop
+ { \@@_split_value:w \q_nil #2 }
+ { \__msg_kernel_error:nn { kernel } { misplaced-equals-sign } }
}
}
-\cs_new:Npn \keyval_split_key_value_aux:wTF #1 = #2#3 \q_stop
+\cs_new:Npn \@@_split_key_value:wTF #1 = #2#3 \q_stop
{ \tl_if_head_eq_meaning:nNTF {#3} \q_no_value }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\keyval_split_key:w}
+% \begin{macro}{\@@_split_key:w}
% The aim here is to remove spaces and also exactly one set of braces.
% There is also a quark to remove, hence the \cs{use_none:n} appearing before
% application of \cs{tl_trim_spaces:n}.
% \begin{macrocode}
-\cs_new_protected:Npn \keyval_split_key:w #1 \q_stop
+\cs_new_protected:Npn \@@_split_key:w #1 \q_stop
{
- \tl_set:Nx \l_keyval_key_tl
+ \tl_set:Nx \l_@@_key_tl
{ \exp_after:wN \tl_trim_spaces:n \exp_after:wN { \use_none:n #1 } }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\keyval_split_value:w}
+% \begin{macro}{\@@_split_value:w}
% Here the value has to be separated from the equals signs and the
% leading \cs{q_nil} added in to keep the brace levels. Fist the
% processing function can be added to the output list. If there is no
-% value, setting \cs{l_keyval_value_tl} with three groups removed will
+% value, setting \cs{l_@@_value_tl} with three groups removed will
% leave nothing at all, and so an empty group can be added to the
% parsed list. On the other hand, if the value is entirely contained
-% within a set of braces then \cs{l_keyval_value_tl} will contain
+% within a set of braces then \cs{l_@@_value_tl} will contain
% \cs{q_nil} only. In that case, strip off the leading quark using
% \cs{use_ii:nnn}, which also deals with any spaces.
% \begin{macrocode}
-\cs_new_protected:Npn \keyval_split_value:w #1 = =
+\cs_new_protected:Npn \@@_split_value:w #1 = =
{
- \tl_put_right:Nx \l_keyval_parse_tl
+ \tl_put_right:Nx \l_@@_parse_tl
{
\exp_not:c
- { keyval_key_value_elt_ \int_use:N \g_keyval_level_int :nn }
- { \exp_not:o \l_keyval_key_tl }
+ { @@_key_value_elt_ \int_use:N \g_@@_level_int :nn }
+ { \exp_not:o \l_@@_key_tl }
}
- \tl_set:Nx \l_keyval_value_tl
+ \tl_set:Nx \l_@@_value_tl
{ \exp_not:o { \use_none:nnn #1 \q_nil \q_nil } }
- \tl_if_empty:NTF \l_keyval_value_tl
- { \tl_put_right:Nn \l_keyval_parse_tl { { } } }
+ \tl_if_empty:NTF \l_@@_value_tl
+ { \tl_put_right:Nn \l_@@_parse_tl { { } } }
{
- \quark_if_nil:NTF \l_keyval_value_tl
+ \quark_if_nil:NTF \l_@@_value_tl
{
- \tl_put_right:Nx \l_keyval_parse_tl
+ \tl_put_right:Nx \l_@@_parse_tl
{ { \exp_not:o { \use_ii:nnn #1 \q_nil } } }
}
- { \keyval_split_value_aux:w #1 \q_stop }
+ { \@@_split_value_aux:w #1 \q_stop }
}
}
% \end{macrocode}
% A similar idea to the key code: remove the spaces from each end and
% deal with one set of braces.
% \begin{macrocode}
-\cs_new_protected:Npn \keyval_split_value_aux:w \q_nil #1 \q_stop
+\cs_new_protected:Npn \@@_split_value_aux:w \q_nil #1 \q_stop
{
- \tl_set:Nx \l_keyval_value_tl { \tl_trim_spaces:n {#1} }
- \tl_put_right:Nx \l_keyval_parse_tl
- { { \exp_not:o \l_keyval_value_tl } }
+ \tl_set:Nx \l_@@_value_tl { \tl_trim_spaces:n {#1} }
+ \tl_put_right:Nx \l_@@_parse_tl
+ { { \exp_not:o \l_@@_value_tl } }
}
% \end{macrocode}
% \end{macro}
@@ -1010,20 +915,20 @@
% \begin{macrocode}
\cs_new_protected:Npn \keyval_parse:NNn #1#2#3
{
- \int_gincr:N \g_keyval_level_int
+ \int_gincr:N \g_@@_level_int
\cs_gset_eq:cN
- { keyval_key_no_value_elt_ \int_use:N \g_keyval_level_int :n } #1
+ { @@_key_no_value_elt_ \int_use:N \g_@@_level_int :n } #1
\cs_gset_eq:cN
- { keyval_key_value_elt_ \int_use:N \g_keyval_level_int :nn } #2
- \keyval_parse:n {#3}
- \int_gdecr:N \g_keyval_level_int
+ { @@_key_value_elt_ \int_use:N \g_@@_level_int :nn } #2
+ \@@_parse:n {#3}
+ \int_gdecr:N \g_@@_level_int
}
% \end{macrocode}
% \end{macro}
%
% One message for the low level parsing system.
% \begin{macrocode}
-\msg_kernel_new:nnnn { keyval } { misplaced-equals-sign }
+\__msg_kernel_new:nnnn { kernel } { misplaced-equals-sign }
{ Misplaced~equals~sign~in~key-value~input~\msg_line_number: }
{
LaTeX~is~attempting~to~parse~some~key-value~input~but~found~
@@ -1032,36 +937,40 @@
% \end{macrocode}
%
% \subsection{Constants and variables}
+%
+% \begin{macrocode}
+%<@@=keys>
+% \end{macrocode}
%
-% \begin{variable}{\c_keys_code_root_tl, \c_keys_vars_root_tl}
+% \begin{variable}{\c_@@_code_root_tl, \c_@@_vars_root_tl}
% The prefixes for the code and variables of the keys themselves.
% \begin{macrocode}
-\tl_const:Nn \c_keys_code_root_tl { key~code~>~ }
-\tl_const:Nn \c_keys_vars_root_tl { key~var~>~ }
+\tl_const:Nn \c_@@_code_root_tl { key~code~>~ }
+\tl_const:Nn \c_@@_vars_root_tl { key~var~>~ }
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\c_keys_props_root_tl}
+% \begin{variable}{\c_@@_props_root_tl}
% The prefix for storing properties.
% \begin{macrocode}
-\tl_const:Nn \c_keys_props_root_tl { key~prop~>~ }
+\tl_const:Nn \c_@@_props_root_tl { key~prop~>~ }
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\c_keys_value_forbidden_tl, \c_keys_value_required_tl}
+% \begin{variable}{\c_@@_value_forbidden_tl, \c_@@_value_required_tl}
% Two marker token lists.
% \begin{macrocode}
-\tl_const:Nn \c_keys_value_forbidden_tl { forbidden }
-\tl_const:Nn \c_keys_value_required_tl { required }
+\tl_const:Nn \c_@@_value_forbidden_tl { forbidden }
+\tl_const:Nn \c_@@_value_required_tl { required }
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_keys_choice_int, \l_keys_choices_tl}
+% \begin{variable}{\l_keys_choice_int, \l_keys_choice_tl}
% Publicly accessible data on which choice is being used when several
% are generated as a set.
% \begin{macrocode}
\int_new:N \l_keys_choice_int
-\tl_new:N \l_keys_choices_tl
+\tl_new:N \l_keys_choice_tl
% \end{macrocode}
% \end{variable}
%
@@ -1072,18 +981,18 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_keys_module_tl}
+% \begin{variable}{\l_@@_module_tl}
% The module for an entire set of keys.
% \begin{macrocode}
-\tl_new:N \l_keys_module_tl
+\tl_new:N \l_@@_module_tl
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_keys_no_value_bool}
+% \begin{variable}{\l_@@_no_value_bool}
% A marker is needed internally to show if only a key or a key plus a
% value was seen: this is recorded here.
% \begin{macrocode}
-\bool_new:N \l_keys_no_value_bool
+\bool_new:N \l_@@_no_value_bool
% \end{macrocode}
% \end{variable}
%
@@ -1095,18 +1004,18 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_keys_property_tl}
+% \begin{variable}{\l_@@_property_tl}
% The \enquote{property} begin set for a key at definition time is
% stored here.
% \begin{macrocode}
-\tl_new:N \l_keys_property_tl
+\tl_new:N \l_@@_property_tl
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_keys_unknown_clist}
+% \begin{variable}{\l_@@_unknown_clist}
% Used when setting only known keys to store those left over.
% \begin{macrocode}
-\tl_new:N \l_keys_unknown_clist
+\tl_new:N \l_@@_unknown_clist
% \end{macrocode}
% \end{variable}
%
@@ -1120,51 +1029,51 @@
% \subsection{The key defining mechanism}
%
% \begin{macro}{\keys_define:nn}
-% \begin{macro}[aux]{\keys_define_aux:nnn, \keys_define_aux:onn}
+% \begin{macro}[aux]{\@@_define:nnn, \@@_define:onn}
% The public function for definitions is just a wrapper for the lower
% level mechanism, more or less. The outer function is designed to
% keep a track of the current module, to allow safe nesting. The module is set
% removing any leading |/| (which is not needed here).
% \begin{macrocode}
\cs_new_protected:Npn \keys_define:nn
- { \keys_define_aux:onn \l_keys_module_tl }
-\cs_new_protected:Npn \keys_define_aux:nnn #1#2#3
+ { \@@_define:onn \l_@@_module_tl }
+\cs_new_protected:Npn \@@_define:nnn #1#2#3
{
- \tl_set:Nx \l_keys_module_tl { \tl_to_str:n {#2} }
- \keyval_parse:NNn \keys_define_elt:n \keys_define_elt:nn {#3}
- \tl_set:Nn \l_keys_module_tl {#1}
+ \tl_set:Nx \l_@@_module_tl { \tl_to_str:n {#2} }
+ \keyval_parse:NNn \@@_define_elt:n \@@_define_elt:nn {#3}
+ \tl_set:Nn \l_@@_module_tl {#1}
}
-\cs_generate_variant:Nn \keys_define_aux:nnn { o }
+\cs_generate_variant:Nn \@@_define:nnn { o }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\keys_define_elt:n}
-% \begin{macro}[int]{\keys_define_elt:nn}
-% \begin{macro}[aux]{\keys_define_elt_aux:nn}
+% \begin{macro}[int]{\@@_define_elt:n}
+% \begin{macro}[int]{\@@_define_elt:nn}
+% \begin{macro}[aux]{\@@_define_elt_aux:nn}
% The outer functions here record whether a value was given and then
% converge on a common internal mechanism. There is first a search for
% a property in the current key name, then a check to make sure it is
% known before the code hands off to the next step.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_define_elt:n #1
+\cs_new_protected:Npn \@@_define_elt:n #1
{
- \bool_set_true:N \l_keys_no_value_bool
- \keys_define_elt_aux:nn {#1} { }
+ \bool_set_true:N \l_@@_no_value_bool
+ \@@_define_elt_aux:nn {#1} { }
}
-\cs_new_protected:Npn \keys_define_elt:nn #1#2
+\cs_new_protected:Npn \@@_define_elt:nn #1#2
{
- \bool_set_false:N \l_keys_no_value_bool
- \keys_define_elt_aux:nn {#1} {#2}
+ \bool_set_false:N \l_@@_no_value_bool
+ \@@_define_elt_aux:nn {#1} {#2}
}
-\cs_new_protected:Npn \keys_define_elt_aux:nn #1#2
+\cs_new_protected:Npn \@@_define_elt_aux:nn #1#2
{
- \keys_property_find:n {#1}
- \cs_if_exist:cTF { \c_keys_props_root_tl \l_keys_property_tl }
- { \keys_define_key:n {#2} }
+ \@@_property_find:n {#1}
+ \cs_if_exist:cTF { \c_@@_props_root_tl \l_@@_property_tl }
+ { \@@_define_key:n {#2} }
{
- \msg_kernel_error:nnxx { keys } { property-unknown }
- { \l_keys_property_tl } { \l_keys_path_tl }
+ \__msg_kernel_error:nnxx { kernel } { property-unknown }
+ { \l_@@_property_tl } { \l_keys_path_tl }
}
}
% \end{macrocode}
@@ -1172,57 +1081,57 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\keys_property_find:n}
-% \begin{macro}[aux]{\keys_property_find_aux:w}
+% \begin{macro}[int]{\@@_property_find:n}
+% \begin{macro}[aux]{\@@_property_find:w}
% Searching for a property means finding the last |.| in the input,
% and storing the text before and after it. Everything is turned into
% strings, so there is no problem using an \texttt{x}-type expansion.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_property_find:n #1
+\cs_new_protected:Npn \@@_property_find:n #1
{
- \tl_set:Nx \l_keys_path_tl { \l_keys_module_tl / }
+ \tl_set:Nx \l_keys_path_tl { \l_@@_module_tl / }
\tl_if_in:nnTF {#1} { . }
- { \keys_property_find_aux:w #1 \q_stop }
- { \msg_kernel_error:nnx { keys } { key-no-property } {#1} }
+ { \@@_property_find:w #1 \q_stop }
+ { \__msg_kernel_error:nnx { kernel } { key-no-property } {#1} }
}
-\cs_new_protected:Npn \keys_property_find_aux:w #1 . #2 \q_stop
+\cs_new_protected:Npn \@@_property_find:w #1 . #2 \q_stop
{
\tl_set:Nx \l_keys_path_tl { \l_keys_path_tl \tl_to_str:n {#1} }
\tl_if_in:nnTF {#2} { . }
{
\tl_set:Nx \l_keys_path_tl { \l_keys_path_tl . }
- \keys_property_find_aux:w #2 \q_stop
+ \@@_property_find:w #2 \q_stop
}
- { \tl_set:Nn \l_keys_property_tl { . #2 } }
+ { \tl_set:Nn \l_@@_property_tl { . #2 } }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\keys_define_key:n}
-% \begin{macro}[aux]{\keys_define_key_aux:w}
+% \begin{macro}[int]{\@@_define_key:n}
+% \begin{macro}[aux]{\@@_define_key:w}
% Two possible cases. If there is a value for the key, then just use
% the function. If not, then a check to make sure there is no need for
% a value with the property. If there should be one then complain,
% otherwise execute it. There is no need to check for a |:| as if it
% is missing the earlier tests will have failed.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_define_key:n #1
+\cs_new_protected:Npn \@@_define_key:n #1
{
- \bool_if:NTF \l_keys_no_value_bool
+ \bool_if:NTF \l_@@_no_value_bool
{
- \exp_after:wN \keys_define_key_aux:w
- \l_keys_property_tl \q_stop
- { \use:c { \c_keys_props_root_tl \l_keys_property_tl } }
+ \exp_after:wN \@@_define_key:w
+ \l_@@_property_tl \q_stop
+ { \use:c { \c_@@_props_root_tl \l_@@_property_tl } }
{
- \msg_kernel_error:nnxx { keys }
- { property-requires-value } { \l_keys_property_tl }
+ \__msg_kernel_error:nnxx { kernel }
+ { property-requires-value } { \l_@@_property_tl }
{ \l_keys_path_tl }
}
}
- { \use:c { \c_keys_props_root_tl \l_keys_property_tl } {#1} }
+ { \use:c { \c_@@_props_root_tl \l_@@_property_tl } {#1} }
}
-\cs_new_protected:Npn \keys_define_key_aux:w #1 : #2 \q_stop
+\cs_new_protected:Npn \@@_define_key:w #1 : #2 \q_stop
{ \tl_if_empty:nTF {#2} }
% \end{macrocode}
% \end{macro}
@@ -1230,226 +1139,246 @@
%
% \subsection{Turning properties into actions}
%
-% \begin{macro}[int]{\keys_bool_set:NN}
+% \begin{macro}[int]{\@@_bool_set:NN}
% Boolean keys are really just choices, but all done by hand. The
% second argument here is the scope: either empty or \texttt{g} for
% global.
% \begin{macrocode}
-\cs_new:Npn \keys_bool_set:NN #1#2
+\cs_new:Npn \@@_bool_set:NN #1#2
{
\bool_if_exist:NF #1 { \bool_new:N #1 }
- \keys_choice_make:
- \keys_cmd_set:nx { \l_keys_path_tl / true }
+ \@@_choice_make:
+ \@@_cmd_set:nx { \l_keys_path_tl / true }
{ \exp_not:c { bool_ #2 set_true:N } \exp_not:N #1 }
- \keys_cmd_set:nx { \l_keys_path_tl / false }
+ \@@_cmd_set:nx { \l_keys_path_tl / false }
{ \exp_not:c { bool_ #2 set_false:N } \exp_not:N #1 }
- \keys_cmd_set:nn { \l_keys_path_tl / unknown }
+ \@@_cmd_set:nn { \l_keys_path_tl / unknown }
{
- \msg_kernel_error:nnx { keys } { boolean-values-only }
+ \__msg_kernel_error:nnx { kernel } { boolean-values-only }
{ \l_keys_key_tl }
}
- \keys_default_set:n { true }
+ \@@_default_set:n { true }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\keys_bool_set_inverse:NN}
+% \begin{macro}[int]{\@@_bool_set_inverse:NN}
% Inverse boolean setting is much the same.
% \begin{macrocode}
-\cs_new:Npn \keys_bool_set_inverse:NN #1#2
+\cs_new:Npn \@@_bool_set_inverse:NN #1#2
{
\bool_if_exist:NF #1 { \bool_new:N #1 }
- \keys_choice_make:
- \keys_cmd_set:nx { \l_keys_path_tl / true }
+ \@@_choice_make:
+ \@@_cmd_set:nx { \l_keys_path_tl / true }
{ \exp_not:c { bool_ #2 set_false:N } \exp_not:N #1 }
- \keys_cmd_set:nx { \l_keys_path_tl / false }
+ \@@_cmd_set:nx { \l_keys_path_tl / false }
{ \exp_not:c { bool_ #2 set_true:N } \exp_not:N #1 }
- \keys_cmd_set:nn { \l_keys_path_tl / unknown }
+ \@@_cmd_set:nn { \l_keys_path_tl / unknown }
{
- \msg_kernel_error:nnx { keys } { boolean-values-only }
+ \__msg_kernel_error:nnx { kernel } { boolean-values-only }
{ \l_keys_key_tl }
}
- \keys_default_set:n { true }
+ \@@_default_set:n { true }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\keys_choice_make:}
+% \begin{macro}[int]{\@@_choice_make:}
% To make a choice from a key, two steps: set the code, and set the
% unknown key.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \keys_choice_make:
+\cs_new_protected_nopar:Npn \@@_choice_make:
{
- \keys_cmd_set:nn { \l_keys_path_tl }
- { \keys_choice_find:n {##1} }
- \keys_cmd_set:nn { \l_keys_path_tl / unknown }
+ \@@_cmd_set:nn { \l_keys_path_tl }
+ { \@@_choice_find:n {##1} }
+ \@@_cmd_set:nn { \l_keys_path_tl / unknown }
{
- \msg_kernel_error:nnxx { keys } { choice-unknown }
+ \__msg_kernel_error:nnxx { kernel } { key-choice-unknown }
{ \l_keys_path_tl } {##1}
}
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\keys_choices_make:nn}
+% \begin{macro}[int]{\@@_choices_make:nn}
% Auto-generating choices means setting up the root key as a choice, then
% defining each choice in turn.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_choices_make:nn #1#2
+\cs_new_protected:Npn \@@_choices_make:nn #1#2
{
- \keys_choice_make:
+ \@@_choice_make:
\int_zero:N \l_keys_choice_int
\clist_map_inline:nn {#1}
{
- \keys_cmd_set:nx { \l_keys_path_tl / ##1 }
+ \int_incr:N \l_keys_choice_int
+ \@@_cmd_set:nx { \l_keys_path_tl / ##1 }
{
\tl_set:Nn \exp_not:N \l_keys_choice_tl {##1}
\int_set:Nn \exp_not:N \l_keys_choice_int
{ \int_use:N \l_keys_choice_int }
\exp_not:n {#2}
}
- \int_incr:N \l_keys_choice_int
}
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\keys_choices_generate:n}
-% \begin{macro}[aux]{\keys_choices_generate_aux:n}
+% \begin{macro}[int]{\@@_choices_generate:n}
+% \begin{macro}[aux]{\@@_choices_generate_aux:n}
% Creating multiple-choices means setting up the \enquote{indicator}
% code, then applying whatever the user wanted.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_choices_generate:n #1
+\cs_new_protected:Npn \@@_choices_generate:n #1
{
\cs_if_exist:cTF
- { \c_keys_vars_root_tl \l_keys_path_tl .choice~code }
+ { \c_@@_vars_root_tl \l_keys_path_tl .choice~code }
{
- \keys_choice_make:
+ \@@_choice_make:
\int_zero:N \l_keys_choice_int
- \clist_map_function:nN {#1} \keys_choices_generate_aux:n
+ \clist_map_function:nN {#1} \@@_choices_generate_aux:n
}
{
- \msg_kernel_error:nnx { keys }
+ \__msg_kernel_error:nnx { kernel }
{ generate-choices-before-code } { \l_keys_path_tl }
}
}
-\cs_new_protected:Npn \keys_choices_generate_aux:n #1
+\cs_new_protected:Npn \@@_choices_generate_aux:n #1
{
- \keys_cmd_set:nx { \l_keys_path_tl / #1 }
+ \int_incr:N \l_keys_choice_int
+ \@@_cmd_set:nx { \l_keys_path_tl / #1 }
{
\tl_set:Nn \exp_not:N \l_keys_choice_tl {#1}
\int_set:Nn \exp_not:N \l_keys_choice_int
{ \int_use:N \l_keys_choice_int }
\exp_not:v
- { \c_keys_vars_root_tl \l_keys_path_tl .choice~code }
+ { \c_@@_vars_root_tl \l_keys_path_tl .choice~code }
}
- \int_incr:N \l_keys_choice_int
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\keys_choice_code_store:x}
+% \begin{macro}[int]{\@@_choice_code_store:n, \@@_choice_code_store:x}
% The code for making multiple choices is stored in a token list.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_choice_code_store:x #1
+\cs_new_protected:Npn \@@_choice_code_store:n #1
{
\cs_if_exist:cF
- { \c_keys_vars_root_tl \l_keys_path_tl .choice~code }
+ { \c_@@_vars_root_tl \l_keys_path_tl .choice~code }
{
\tl_new:c
- { \c_keys_vars_root_tl \l_keys_path_tl .choice~code }
+ { \c_@@_vars_root_tl \l_keys_path_tl .choice~code }
}
- \tl_set:cx { \c_keys_vars_root_tl \l_keys_path_tl .choice~code }
+ \tl_set:cn { \c_@@_vars_root_tl \l_keys_path_tl .choice~code }
{#1}
}
+\cs_generate_variant:Nn \@@_choice_code_store:n { x }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\keys_cmd_set:nn, \keys_cmd_set:nx}
-% \begin{macro}[aux]{\keys_cmd_set_aux:n}
+% \begin{macro}[int]{\@@_cmd_set:nn, \@@_cmd_set:nx, \@@_cmd_set:Vo}
+% \begin{macro}[aux]{\@@_cmd_set:n}
% Creating a new command means tidying up the properties and then making
% the internal function which actually does the work.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_cmd_set:nn #1#2
+\cs_new_protected:Npn \@@_cmd_set:nn #1#2
{
- \keys_cmd_set_aux:n {#1}
- \cs_set:cpn { \c_keys_code_root_tl #1 } ##1 {#2}
+ \@@_cmd_set:n {#1}
+ \cs_set:cpn { \c_@@_code_root_tl #1 } ##1 {#2}
}
-\cs_new_protected:Npn \keys_cmd_set:nx #1#2
+\cs_new_protected:Npn \@@_cmd_set:nx #1#2
{
- \keys_cmd_set_aux:n {#1}
- \cs_set:cpx { \c_keys_code_root_tl #1 } ##1 {#2}
+ \@@_cmd_set:n {#1}
+ \cs_set:cpx { \c_@@_code_root_tl #1 } ##1 {#2}
}
-\cs_new_protected:Npn \keys_cmd_set_aux:n #1
+\cs_generate_variant:Nn \@@_cmd_set:nn { Vo }
+\cs_new_protected:Npn \@@_cmd_set:n #1
{
- \tl_clear_new:c { \c_keys_vars_root_tl #1 .default }
- \tl_set:cn { \c_keys_vars_root_tl #1 .default } { \q_no_value }
- \tl_clear_new:c { \c_keys_vars_root_tl #1 .req }
+ \tl_clear_new:c { \c_@@_vars_root_tl #1 .default }
+ \tl_set:cn { \c_@@_vars_root_tl #1 .default } { \q_no_value }
+ \tl_clear_new:c { \c_@@_vars_root_tl #1 .req }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\keys_default_set:n, \keys_default_set:V}
+% \begin{macro}[int]{\@@_default_set:n, \@@_default_set:V}
% Setting a default value is easy.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_default_set:n #1
- { \tl_set:cn { \c_keys_vars_root_tl \l_keys_path_tl .default } {#1} }
-\cs_generate_variant:Nn \keys_default_set:n { V }
+\cs_new_protected:Npn \@@_default_set:n #1
+ { \tl_set:cn { \c_@@_vars_root_tl \l_keys_path_tl .default } {#1} }
+\cs_generate_variant:Nn \@@_default_set:n { V }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_initialise:n, \@@_initialise:V}
+% \begin{macro}[aux, EXP]{\@@_initialise:wn}
+% A set up for initialisation from which the key system requires that
+% the path is split up into a module and a key name. At this stage,
+% \cs{l_keys_path_tl} will contain \texttt{/} so a split is easy to do.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_initialise:n #1
+ {
+ \use:x
+ { \exp_after:wN \@@_initialise:wn \l_keys_path_tl \q_stop {#1} }
+ }
+\cs_generate_variant:Nn \@@_initialise:n { V }
+\cs_new:Npn \@@_initialise:wn #1 / #2 \q_stop #3
+ { \keys_set:nn {#1} { #2 = \exp_not:n { {#3} } } }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
-% \begin{macro}{\keys_meta_make:n, \keys_meta_make:x}
+% \begin{macro}{\@@_meta_make:n, \@@_meta_make:x}
% To create a meta-key, simply set up to pass data through.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_meta_make:n #1
+\cs_new_protected:Npn \@@_meta_make:n #1
{
- \exp_args:NNo \keys_cmd_set:nn \l_keys_path_tl
- { \exp_after:wN \keys_set:nn \exp_after:wN { \l_keys_module_tl } {#1} }
+ \@@_cmd_set:Vo \l_keys_path_tl
+ { \exp_after:wN \keys_set:nn \exp_after:wN { \l_@@_module_tl } {#1} }
}
-\cs_new_protected:Npn \keys_meta_make:x #1
+\cs_new_protected:Npn \@@_meta_make:x #1
{
- \keys_cmd_set:nx { \l_keys_path_tl }
- { \exp_not:N \keys_set:nn { \l_keys_module_tl } {#1} }
+ \@@_cmd_set:nx { \l_keys_path_tl }
+ { \exp_not:N \keys_set:nn { \l_@@_module_tl } {#1} }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\keys_multichoice_find:n}
-% \begin{macro}[int]{\keys_multichoice_make:}
-% \begin{macro}[int]{\keys_multichoices_make:nn}
+% \begin{macro}[int]{\@@_multichoice_find:n}
+% \begin{macro}[int]{\@@_multichoice_make:}
+% \begin{macro}[int]{\@@_multichoices_make:nn}
% Choices where several values can be selected are very similar to normal
% exclusive choices. There is just a slight change in implementation to
% map across a comma-separated list. This then requires that the appropriate
% set up takes place elsewhere.
% \begin{macrocode}
-\cs_new:Npn \keys_multichoice_find:n #1
- { \clist_map_function:nN {#1} \keys_choice_find:n }
-\cs_new_protected_nopar:Npn \keys_multichoice_make:
+\cs_new:Npn \@@_multichoice_find:n #1
+ { \clist_map_function:nN {#1} \@@_choice_find:n }
+\cs_new_protected_nopar:Npn \@@_multichoice_make:
{
- \keys_cmd_set:nn { \l_keys_path_tl }
- { \keys_multichoice_find:n {##1} }
- \keys_cmd_set:nn { \l_keys_path_tl / unknown }
+ \@@_cmd_set:nn { \l_keys_path_tl }
+ { \@@_multichoice_find:n {##1} }
+ \@@_cmd_set:nn { \l_keys_path_tl / unknown }
{
- \msg_kernel_error:nnxx { keys } { choice-unknown }
+ \__msg_kernel_error:nnxx { kernel } { key-choice-unknown }
{ \l_keys_path_tl } {##1}
}
}
-\cs_new_protected:Npn \keys_multichoices_make:nn #1#2
+\cs_new_protected:Npn \@@_multichoices_make:nn #1#2
{
- \keys_multichoice_make:
+ \@@_multichoice_make:
\int_zero:N \l_keys_choice_int
\clist_map_inline:nn {#1}
{
- \keys_cmd_set:nx { \l_keys_path_tl / ##1 }
+ \int_incr:N \l_keys_choice_int
+ \@@_cmd_set:nx { \l_keys_path_tl / ##1 }
{
\tl_set:Nn \exp_not:N \l_keys_choice_tl {##1}
\int_set:Nn \exp_not:N \l_keys_choice_int
{ \int_use:N \l_keys_choice_int }
\exp_not:n {#2}
}
- \int_incr:N \l_keys_choice_int
}
}
% \end{macrocode}
@@ -1457,36 +1386,36 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\keys_value_requirement:n}
+% \begin{macro}[int]{\@@_value_requirement:n}
% Values can be required or forbidden by having the appropriate marker
% set.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_value_requirement:n #1
+\cs_new_protected:Npn \@@_value_requirement:n #1
{
\tl_set_eq:cc
- { \c_keys_vars_root_tl \l_keys_path_tl .req }
- { c_keys_value_ #1 _tl }
+ { \c_@@_vars_root_tl \l_keys_path_tl .req }
+ { c_@@_value_ #1 _tl }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\keys_variable_set:NnNN, \keys_variable_set:cnNN}
-% \begin{macro}[int]{\keys_variable_set:NnN, \keys_variable_set:cnN}
+% \begin{macro}[int]{\@@_variable_set:NnNN, \@@_variable_set:cnNN}
+% \begin{macro}[int]{\@@_variable_set:NnN, \@@_variable_set:cnN}
% Setting a variable takes the type and scope separately so that
% it is easy to make a new variable if needed. The three-argument
% version is set up so that the use of |{ }| as an \texttt{N}-type
% variable is only done once!
% \begin{macrocode}
-\cs_new_protected:Npn \keys_variable_set:NnNN #1#2#3#4
+\cs_new_protected:Npn \@@_variable_set:NnNN #1#2#3#4
{
\use:c { #2_if_exist:NF } #1 { \use:c { #2 _new:N } #1 }
- \keys_cmd_set:nx { \l_keys_path_tl }
+ \@@_cmd_set:nx { \l_keys_path_tl }
{ \exp_not:c { #2 _ #3 set:N #4 } \exp_not:N #1 {##1} }
}
-\cs_new_protected:Npn \keys_variable_set:NnN #1#2#3
- { \keys_variable_set:NnNN #1 {#2} { } #3 }
-\cs_generate_variant:Nn \keys_variable_set:NnNN { c }
-\cs_generate_variant:Nn \keys_variable_set:NnN { c }
+\cs_new_protected:Npn \@@_variable_set:NnN #1#2#3
+ { \@@_variable_set:NnNN #1 {#2} { } #3 }
+\cs_generate_variant:Nn \@@_variable_set:NnNN { c }
+\cs_generate_variant:Nn \@@_variable_set:NnN { c }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1500,10 +1429,10 @@
% \begin{macro}{.bool_gset:N}
% One function for this.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .bool_set:N } #1
- { \keys_bool_set:NN #1 { } }
-\cs_new_protected:cpn { \c_keys_props_root_tl .bool_gset:N } #1
- { \keys_bool_set:NN #1 g }
+\cs_new_protected:cpn { \c_@@_props_root_tl .bool_set:N } #1
+ { \@@_bool_set:NN #1 { } }
+\cs_new_protected:cpn { \c_@@_props_root_tl .bool_gset:N } #1
+ { \@@_bool_set:NN #1 g }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1512,10 +1441,10 @@
% \begin{macro}{.bool_gset_inverse:N}
% One function for this.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .bool_set_inverse:N } #1
- { \keys_bool_set_inverse:NN #1 { } }
-\cs_new_protected:cpn { \c_keys_props_root_tl .bool_gset_inverse:N } #1
- { \keys_bool_set_inverse:NN #1 g }
+\cs_new_protected:cpn { \c_@@_props_root_tl .bool_set_inverse:N } #1
+ { \@@_bool_set_inverse:NN #1 { } }
+\cs_new_protected:cpn { \c_@@_props_root_tl .bool_gset_inverse:N } #1
+ { \@@_bool_set_inverse:NN #1 g }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1524,8 +1453,8 @@
% Making a choice is handled internally, as it is also needed by
% \texttt{.generate_choices:n}.
% \begin{macrocode}
-\cs_new_protected_nopar:cpn { \c_keys_props_root_tl .choice: }
- { \keys_choice_make: }
+\cs_new_protected_nopar:cpn { \c_@@_props_root_tl .choice: }
+ { \@@_choice_make: }
% \end{macrocode}
% \end{macro}
%
@@ -1534,8 +1463,8 @@
% Here, |#1| will consist of two separate
% arguments, hence the slightly odd-looking implementation.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .choices:nn } #1
- { \keys_choices_make:nn #1 }
+\cs_new_protected:cpn { \c_@@_props_root_tl .choices:nn } #1
+ { \@@_choices_make:nn #1 }
% \end{macrocode}
% \end{macro}
%
@@ -1543,35 +1472,34 @@
% Creating code is simply a case of passing through to the underlying
% \texttt{set} function.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .code:n } #1
- { \keys_cmd_set:nn { \l_keys_path_tl } {#1} }
-\cs_new_protected:cpn { \c_keys_props_root_tl .code:x } #1
- { \keys_cmd_set:nx { \l_keys_path_tl } {#1} }
+\cs_new_protected:cpn { \c_@@_props_root_tl .code:n } #1
+ { \@@_cmd_set:nn { \l_keys_path_tl } {#1} }
+\cs_new_protected:cpn { \c_@@_props_root_tl .code:x } #1
+ { \@@_cmd_set:nx { \l_keys_path_tl } {#1} }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{.choice_code:n, .choice_code:x}
-% Storing the code for choices, using \cs{exp_not:n} to avoid needing
-% two internal functions.
+% Storing the code for choices
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .choice_code:n } #1
- { \keys_choice_code_store:x { \exp_not:n {#1} } }
-\cs_new_protected:cpn { \c_keys_props_root_tl .choice_code:x } #1
- { \keys_choice_code_store:x {#1} }
+\cs_new_protected:cpn { \c_@@_props_root_tl .choice_code:n } #1
+ { \@@_choice_code_store:n {#1} }
+\cs_new_protected:cpn { \c_@@_props_root_tl .choice_code:x } #1
+ { \@@_choice_code_store:x {#1} }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{.clist_set:N, .clist_set:c}
% \begin{macro}{.clist_gset:N, .clist_gset:c}
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .clist_set:N } #1
- { \keys_variable_set:NnN #1 { clist } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .clist_set:c } #1
- { \keys_variable_set:cnN {#1} { clist } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .clist_gset:N } #1
- { \keys_variable_set:NnNN #1 { clist } g n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .clist_gset:c } #1
- { \keys_variable_set:cnNN {#1} { clist } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .clist_set:N } #1
+ { \@@_variable_set:NnN #1 { clist } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .clist_set:c } #1
+ { \@@_variable_set:cnN {#1} { clist } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .clist_gset:N } #1
+ { \@@_variable_set:NnNN #1 { clist } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .clist_gset:c } #1
+ { \@@_variable_set:cnNN {#1} { clist } g n }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1579,10 +1507,10 @@
% \begin{macro}{.default:n, .default:V}
% Expansion is left to the internal functions.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .default:n } #1
- { \keys_default_set:n {#1} }
-\cs_new_protected:cpn { \c_keys_props_root_tl .default:V } #1
- { \keys_default_set:V #1 }
+\cs_new_protected:cpn { \c_@@_props_root_tl .default:n } #1
+ { \@@_default_set:n {#1} }
+\cs_new_protected:cpn { \c_@@_props_root_tl .default:V } #1
+ { \@@_default_set:V #1 }
% \end{macrocode}
% \end{macro}
%
@@ -1590,14 +1518,14 @@
% \begin{macro}{.dim_gset:N, .dim_gset:c}
% Setting a variable is very easy: just pass the data along.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .dim_set:N } #1
- { \keys_variable_set:NnN #1 { dim } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .dim_set:c } #1
- { \keys_variable_set:cnN {#1} { dim } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .dim_gset:N } #1
- { \keys_variable_set:NnNN #1 { dim } g n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .dim_gset:c } #1
- { \keys_variable_set:cnNN {#1} { dim } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .dim_set:N } #1
+ { \@@_variable_set:NnN #1 { dim } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .dim_set:c } #1
+ { \@@_variable_set:cnN {#1} { dim } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .dim_gset:N } #1
+ { \@@_variable_set:NnNN #1 { dim } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .dim_gset:c } #1
+ { \@@_variable_set:cnNN {#1} { dim } g n }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1606,14 +1534,14 @@
% \begin{macro}{.fp_gset:N, .fp_gset:c}
% Setting a variable is very easy: just pass the data along.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .fp_set:N } #1
- { \keys_variable_set:NnN #1 { fp } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .fp_set:c } #1
- { \keys_variable_set:cnN {#1} { fp } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .fp_gset:N } #1
- { \keys_variable_set:NnNN #1 { fp } g n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .fp_gset:c } #1
- { \keys_variable_set:cnNN {#1} { fp } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .fp_set:N } #1
+ { \@@_variable_set:NnN #1 { fp } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .fp_set:c } #1
+ { \@@_variable_set:cnN {#1} { fp } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .fp_gset:N } #1
+ { \@@_variable_set:NnNN #1 { fp } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .fp_gset:c } #1
+ { \@@_variable_set:cnNN {#1} { fp } g n }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1621,8 +1549,18 @@
% \begin{macro}{.generate_choices:n}
% Making choices is easy.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .generate_choices:n } #1
- { \keys_choices_generate:n {#1} }
+\cs_new_protected:cpn { \c_@@_props_root_tl .generate_choices:n } #1
+ { \@@_choices_generate:n {#1} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{.initial:n, .initial:V}
+% The standard hand-off approach.
+% \begin{macrocode}
+\cs_new_protected:cpn { \c_@@_props_root_tl .initial:n } #1
+ { \@@_initialise:n {#1} }
+\cs_new_protected:cpn { \c_@@_props_root_tl .initial:V } #1
+ { \@@_initialise:V #1 }
% \end{macrocode}
% \end{macro}
%
@@ -1630,14 +1568,14 @@
% \begin{macro}{.int_gset:N, .int_gset:c}
% Setting a variable is very easy: just pass the data along.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .int_set:N } #1
- { \keys_variable_set:NnN #1 { int } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .int_set:c } #1
- { \keys_variable_set:cnN {#1} { int } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .int_gset:N } #1
- { \keys_variable_set:NnNN #1 { int } g n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .int_gset:c } #1
- { \keys_variable_set:cnNN {#1} { int } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .int_set:N } #1
+ { \@@_variable_set:NnN #1 { int } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .int_set:c } #1
+ { \@@_variable_set:cnN {#1} { int } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .int_gset:N } #1
+ { \@@_variable_set:NnNN #1 { int } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .int_gset:c } #1
+ { \@@_variable_set:cnNN {#1} { int } g n }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1645,10 +1583,10 @@
%\begin{macro}{.meta:n, .meta:x}
% Making a meta is handled internally.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .meta:n } #1
- { \keys_meta_make:n {#1} }
-\cs_new_protected:cpn { \c_keys_props_root_tl .meta:x } #1
- { \keys_meta_make:x {#1} }
+\cs_new_protected:cpn { \c_@@_props_root_tl .meta:n } #1
+ { \@@_meta_make:n {#1} }
+\cs_new_protected:cpn { \c_@@_props_root_tl .meta:x } #1
+ { \@@_meta_make:x {#1} }
% \end{macrocode}
% \end{macro}
%
@@ -1657,10 +1595,10 @@
% The same idea as \texttt{.choice:} and \texttt{.choices:nn}, but
% where more than one choice is allowed.
% \begin{macrocode}
-\cs_new_protected_nopar:cpn { \c_keys_props_root_tl .multichoice: }
- { \keys_multichoice_make: }
-\cs_new_protected:cpn { \c_keys_props_root_tl .multichoices:nn } #1
- { \keys_multichoices_make:nn #1 }
+\cs_new_protected_nopar:cpn { \c_@@_props_root_tl .multichoice: }
+ { \@@_multichoice_make: }
+\cs_new_protected:cpn { \c_@@_props_root_tl .multichoices:nn } #1
+ { \@@_multichoices_make:nn #1 }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1669,14 +1607,14 @@
% \begin{macro}{.skip_gset:N, .skip_gset:c}
% Setting a variable is very easy: just pass the data along.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .skip_set:N } #1
- { \keys_variable_set:NnN #1 { skip } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .skip_set:c } #1
- { \keys_variable_set:cnN {#1} { skip } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .skip_gset:N } #1
- { \keys_variable_set:NnNN #1 { skip } g n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .skip_gset:c } #1
- { \keys_variable_set:cnNN {#1} { skip } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .skip_set:N } #1
+ { \@@_variable_set:NnN #1 { skip } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .skip_set:c } #1
+ { \@@_variable_set:cnN {#1} { skip } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .skip_gset:N } #1
+ { \@@_variable_set:NnNN #1 { skip } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .skip_gset:c } #1
+ { \@@_variable_set:cnNN {#1} { skip } g n }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1688,22 +1626,22 @@
% \begin{macro}{.tl_gset_x:N, .tl_gset_x:c}
% Setting a variable is very easy: just pass the data along.
% \begin{macrocode}
-\cs_new_protected:cpn { \c_keys_props_root_tl .tl_set:N } #1
- { \keys_variable_set:NnN #1 { tl } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .tl_set:c } #1
- { \keys_variable_set:cnN {#1} { tl } n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .tl_set_x:N } #1
- { \keys_variable_set:NnN #1 { tl } x }
-\cs_new_protected:cpn { \c_keys_props_root_tl .tl_set_x:c } #1
- { \keys_variable_set:cnN {#1} { tl } x }
-\cs_new_protected:cpn { \c_keys_props_root_tl .tl_gset:N } #1
- { \keys_variable_set:NnNN #1 { tl } g n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .tl_gset:c } #1
- { \keys_variable_set:cnNN {#1} { tl } g n }
-\cs_new_protected:cpn { \c_keys_props_root_tl .tl_gset_x:N } #1
- { \keys_variable_set:NnNN #1 { tl } g x }
-\cs_new_protected:cpn { \c_keys_props_root_tl .tl_gset_x:c } #1
- { \keys_variable_set:cnNN {#1} { tl } g x }
+\cs_new_protected:cpn { \c_@@_props_root_tl .tl_set:N } #1
+ { \@@_variable_set:NnN #1 { tl } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .tl_set:c } #1
+ { \@@_variable_set:cnN {#1} { tl } n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .tl_set_x:N } #1
+ { \@@_variable_set:NnN #1 { tl } x }
+\cs_new_protected:cpn { \c_@@_props_root_tl .tl_set_x:c } #1
+ { \@@_variable_set:cnN {#1} { tl } x }
+\cs_new_protected:cpn { \c_@@_props_root_tl .tl_gset:N } #1
+ { \@@_variable_set:NnNN #1 { tl } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .tl_gset:c } #1
+ { \@@_variable_set:cnNN {#1} { tl } g n }
+\cs_new_protected:cpn { \c_@@_props_root_tl .tl_gset_x:N } #1
+ { \@@_variable_set:NnNN #1 { tl } g x }
+\cs_new_protected:cpn { \c_@@_props_root_tl .tl_gset_x:c } #1
+ { \@@_variable_set:cnNN {#1} { tl } g x }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1714,10 +1652,10 @@
% \begin{macro}{.value_required:}
% These are very similar, so both call the same function.
% \begin{macrocode}
-\cs_new_protected_nopar:cpn { \c_keys_props_root_tl .value_forbidden: }
- { \keys_value_requirement:n { forbidden } }
-\cs_new_protected_nopar:cpn { \c_keys_props_root_tl .value_required: }
- { \keys_value_requirement:n { required } }
+\cs_new_protected_nopar:cpn { \c_@@_props_root_tl .value_forbidden: }
+ { \@@_value_requirement:n { forbidden } }
+\cs_new_protected_nopar:cpn { \c_@@_props_root_tl .value_required: }
+ { \@@_value_requirement:n { required } }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1725,19 +1663,19 @@
% \subsection{Setting keys}
%
% \begin{macro}{\keys_set:nn, \keys_set:nV, \keys_set:nv, \keys_set:no}
-% \begin{macro}[aux]{\keys_set_aux:nnn, \keys_set_aux:onn}
+% \begin{macro}[aux]{\@@_set:nnn, \@@_set:onn}
% A simple wrapper again.
% \begin{macrocode}
\cs_new_protected:Npn \keys_set:nn
- { \keys_set_aux:onn { \l_keys_module_tl } }
-\cs_new_protected:Npn \keys_set_aux:nnn #1#2#3
+ { \@@_set:onn { \l_@@_module_tl } }
+\cs_new_protected:Npn \@@_set:nnn #1#2#3
{
- \tl_set:Nx \l_keys_module_tl { \tl_to_str:n {#2} }
- \keyval_parse:NNn \keys_set_elt:n \keys_set_elt:nn {#3}
- \tl_set:Nn \l_keys_module_tl {#1}
+ \tl_set:Nx \l_@@_module_tl { \tl_to_str:n {#2} }
+ \keyval_parse:NNn \@@_set_elt:n \@@_set_elt:nn {#3}
+ \tl_set:Nn \l_@@_module_tl {#1}
}
\cs_generate_variant:Nn \keys_set:nn { nV , nv , no }
-\cs_generate_variant:Nn \keys_set_aux:nnn { o }
+\cs_generate_variant:Nn \@@_set:nnn { o }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1747,89 +1685,89 @@
% \keys_set_known:nnN, \keys_set_known:nVN,
% \keys_set_known:nvN, \keys_set_known:noN
% }
-% \begin{macro}[aux]{\keys_set_known_aux:nnnN, \keys_set_known_aux:onnN}
+% \begin{macro}[aux]{\@@_set_known:nnnN, \@@_set_known:onnN}
% \begin{macrocode}
\cs_new_protected:Npn \keys_set_known:nnN
- { \keys_set_known_aux:onnN { \l_keys_module_tl } }
-\cs_new_protected:Npn \keys_set_known_aux:nnnN #1#2#3#4
+ { \@@_set_known:onnN { \l_@@_module_tl } }
+\cs_new_protected:Npn \@@_set_known:nnnN #1#2#3#4
{
- \tl_set:Nx \l_keys_module_tl { \tl_to_str:n {#2} }
- \clist_clear:N \l_keys_unknown_clist
- \cs_set_eq:NN \keys_execute_unknown: \keys_execute_unknown_alt:
- \keyval_parse:NNn \keys_set_elt:n \keys_set_elt:nn {#3}
- \cs_set_eq:NN \keys_execute_unknown: \keys_execute_unknown_std:
- \tl_set:Nn \l_keys_module_tl {#1}
- \clist_set_eq:NN #4 \l_keys_unknown_clist
+ \tl_set:Nx \l_@@_module_tl { \tl_to_str:n {#2} }
+ \clist_clear:N \l_@@_unknown_clist
+ \cs_set_eq:NN \@@_execute_unknown: \@@_execute_unknown_alt:
+ \keyval_parse:NNn \@@_set_elt:n \@@_set_elt:nn {#3}
+ \cs_set_eq:NN \@@_execute_unknown: \@@_execute_unknown_std:
+ \tl_set:Nn \l_@@_module_tl {#1}
+ \clist_set_eq:NN #4 \l_@@_unknown_clist
}
\cs_generate_variant:Nn \keys_set_known:nnN { nV , nv , no }
-\cs_generate_variant:Nn \keys_set_known_aux:nnnN { o }
+\cs_generate_variant:Nn \@@_set_known:nnnN { o }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\keys_set_elt:n, \keys_set_elt:nn}
-% \begin{macro}[aux]{\keys_set_elt_aux:nn}
+% \begin{macro}[int]{\@@_set_elt:n, \@@_set_elt:nn}
+% \begin{macro}[aux]{\@@_set_elt_aux:nn}
% A shared system once again. First, set the current path and add a
% default if needed. There are then checks to see if the a value is
% required or forbidden. If everything passes, move on to execute the
% code.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_set_elt:n #1
+\cs_new_protected:Npn \@@_set_elt:n #1
{
- \bool_set_true:N \l_keys_no_value_bool
- \keys_set_elt_aux:nn {#1} { }
+ \bool_set_true:N \l_@@_no_value_bool
+ \@@_set_elt_aux:nn {#1} { }
}
-\cs_new_protected:Npn \keys_set_elt:nn #1#2
+\cs_new_protected:Npn \@@_set_elt:nn #1#2
{
- \bool_set_false:N \l_keys_no_value_bool
- \keys_set_elt_aux:nn {#1} {#2}
+ \bool_set_false:N \l_@@_no_value_bool
+ \@@_set_elt_aux:nn {#1} {#2}
}
-\cs_new_protected:Npn \keys_set_elt_aux:nn #1#2
+\cs_new_protected:Npn \@@_set_elt_aux:nn #1#2
{
\tl_set:Nx \l_keys_key_tl { \tl_to_str:n {#1} }
- \tl_set:Nx \l_keys_path_tl { \l_keys_module_tl / \l_keys_key_tl }
- \keys_value_or_default:n {#2}
+ \tl_set:Nx \l_keys_path_tl { \l_@@_module_tl / \l_keys_key_tl }
+ \@@_value_or_default:n {#2}
\bool_if:nTF
{
- \keys_if_value_p:n { required } &&
- \l_keys_no_value_bool
+ \@@_if_value_p:n { required } &&
+ \l_@@_no_value_bool
}
{
- \msg_kernel_error:nnx { keys } { value-required }
+ \__msg_kernel_error:nnx { kernel } { value-required }
{ \l_keys_path_tl }
}
{
\bool_if:nTF
{
- \keys_if_value_p:n { forbidden } &&
- ! \l_keys_no_value_bool
+ \@@_if_value_p:n { forbidden } &&
+ ! \l_@@_no_value_bool
}
{
- \msg_kernel_error:nnxx { keys } { value-forbidden }
+ \__msg_kernel_error:nnxx { kernel } { value-forbidden }
{ \l_keys_path_tl } { \l_keys_value_tl }
}
- { \keys_execute: }
+ { \@@_execute: }
}
}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\keys_value_or_default:n}
+% \begin{macro}[int]{\@@_value_or_default:n}
% If a value is given, return it as |#1|, otherwise send a default if
% available.
% \begin{macrocode}
-\cs_new_protected:Npn \keys_value_or_default:n #1
+\cs_new_protected:Npn \@@_value_or_default:n #1
{
\tl_set:Nn \l_keys_value_tl {#1}
- \bool_if:NT \l_keys_no_value_bool
+ \bool_if:NT \l_@@_no_value_bool
{
- \quark_if_no_value:cF { \c_keys_vars_root_tl \l_keys_path_tl .default }
+ \quark_if_no_value:cF { \c_@@_vars_root_tl \l_keys_path_tl .default }
{
- \cs_if_exist:cT { \c_keys_vars_root_tl \l_keys_path_tl .default }
+ \cs_if_exist:cT { \c_@@_vars_root_tl \l_keys_path_tl .default }
{
\tl_set_eq:Nc \l_keys_value_tl
- { \c_keys_vars_root_tl \l_keys_path_tl .default }
+ { \c_@@_vars_root_tl \l_keys_path_tl .default }
}
}
}
@@ -1837,57 +1775,57 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\keys_if_value_p:n}
+% \begin{macro}[int]{\@@_if_value_p:n}
% To test if a value is required or forbidden. A simple check for
% the existence of the appropriate marker.
% \begin{macrocode}
-\prg_new_conditional:Npnn \keys_if_value:n #1 { p }
+\prg_new_conditional:Npnn \@@_if_value:n #1 { p }
{
- \tl_if_eq:ccTF { c_keys_value_ #1 _tl }
- { \c_keys_vars_root_tl \l_keys_path_tl .req }
+ \tl_if_eq:ccTF { c_@@_value_ #1 _tl }
+ { \c_@@_vars_root_tl \l_keys_path_tl .req }
{ \prg_return_true: }
{ \prg_return_false: }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\keys_execute:}
+% \begin{macro}[int]{\@@_execute:}
% \begin{macro}[aux]
% {
-% \keys_execute_unknown:,
-% \keys_execute_unknown_std:,
-% \keys_execute_unknown_alt:
+% \@@_execute_unknown:,
+% \@@_execute_unknown_std:,
+% \@@_execute_unknown_alt:
% }
-% \begin{macro}[aux]{\keys_execute:nn}
+% \begin{macro}[aux]{\@@_execute:nn}
% Actually executing a key is done in two parts. First, look for the
% key itself, then look for the \texttt{unknown} key with the same
% path. If both of these fail, complain.
% \begin{macrocode}
-\cs_new_nopar:Npn \keys_execute:
- { \keys_execute:nn { \l_keys_path_tl } { \keys_execute_unknown: } }
-\cs_new_nopar:Npn \keys_execute_unknown:
+\cs_new_nopar:Npn \@@_execute:
+ { \@@_execute:nn { \l_keys_path_tl } { \@@_execute_unknown: } }
+\cs_new_nopar:Npn \@@_execute_unknown:
{
- \keys_execute:nn { \l_keys_module_tl / unknown }
+ \@@_execute:nn { \l_@@_module_tl / unknown }
{
- \msg_kernel_error:nnxx { keys } { key-unknown }
- { \l_keys_path_tl } { \l_keys_module_tl }
+ \__msg_kernel_error:nnxx { kernel } { key-unknown }
+ { \l_keys_path_tl } { \l_@@_module_tl }
}
}
-\cs_new_eq:NN \keys_execute_unknown_std: \keys_execute_unknown:
-\cs_new_nopar:Npn \keys_execute_unknown_alt:
+\cs_new_eq:NN \@@_execute_unknown_std: \@@_execute_unknown:
+\cs_new_nopar:Npn \@@_execute_unknown_alt:
{
- \clist_put_right:Nx \l_keys_unknown_clist
+ \clist_put_right:Nx \l_@@_unknown_clist
{
\exp_not:o \l_keys_key_tl
- \bool_if:NF \l_keys_no_value_bool
+ \bool_if:NF \l_@@_no_value_bool
{ = { \exp_not:o \l_keys_value_tl } }
}
}
-\cs_new:Npn \keys_execute:nn #1#2
+\cs_new:Npn \@@_execute:nn #1#2
{
- \cs_if_exist:cTF { \c_keys_code_root_tl #1 }
+ \cs_if_exist:cTF { \c_@@_code_root_tl #1 }
{
- \exp_args:Nc \exp_args:No { \c_keys_code_root_tl #1 }
+ \exp_args:Nc \exp_args:No { \c_@@_code_root_tl #1 }
\l_keys_value_tl
}
{#2}
@@ -1897,15 +1835,15 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\keys_choice_find:n}
+% \begin{macro}[int]{\@@_choice_find:n}
% Executing a choice has two parts. First, try the choice given, then
% if that fails call the unknown key. That will exist, as it is created
% when a choice is first made. So there is no need for any escape code.
% \begin{macrocode}
-\cs_new:Npn \keys_choice_find:n #1
+\cs_new:Npn \@@_choice_find:n #1
{
- \keys_execute:nn { \l_keys_path_tl / \tl_to_str:n {#1} }
- { \keys_execute:nn { \l_keys_path_tl / unknown } { } }
+ \@@_execute:nn { \l_keys_path_tl / \tl_to_str:n {#1} }
+ { \@@_execute:nn { \l_keys_path_tl / unknown } { } }
}
% \end{macrocode}
% \end{macro}
@@ -1917,7 +1855,7 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \keys_if_exist:nn #1#2 { p , T , F , TF }
{
- \cs_if_exist:cTF { \c_keys_code_root_tl #1 / #2 }
+ \cs_if_exist:cTF { \c_@@_code_root_tl #1 / #2 }
{ \prg_return_true: }
{ \prg_return_false: }
}
@@ -1929,7 +1867,7 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \keys_if_choice_exist:nnn #1#2#3 { p , T , F , TF }
{
- \cs_if_exist:cTF { \c_keys_code_root_tl #1 / #2 / #3 }
+ \cs_if_exist:cTF { \c_@@_code_root_tl #1 / #2 / #3 }
{ \prg_return_true: }
{ \prg_return_false: }
}
@@ -1940,7 +1878,7 @@
% Showing a key is just a question of using the correct name.
% \begin{macrocode}
\cs_new:Npn \keys_show:nn #1#2
- { \cs_show:c { \c_keys_code_root_tl #1 / \tl_to_str:n {#2} } }
+ { \cs_show:c { \c_@@_code_root_tl #1 / \tl_to_str:n {#2} } }
% \end{macrocode}
% \end{macro}
%
@@ -1948,23 +1886,23 @@
%
% For when there is a need to complain.
% \begin{macrocode}
-\msg_kernel_new:nnnn { keys } { boolean-values-only }
+\__msg_kernel_new:nnnn { kernel } { boolean-values-only }
{ Key~'#1'~accepts~boolean~values~only. }
{ The~key~'#1'~only~accepts~the~values~'true'~and~'false'. }
-\msg_kernel_new:nnnn { keys } { choice-unknown }
+\__msg_kernel_new:nnnn { kernel } { choice-unknown }
{ Choice~'#2'~unknown~for~key~'#1'. }
{
The~key~'#1'~takes~a~limited~number~of~values.\\
The~input~given,~'#2',~is~not~on~the~list~accepted.
}
-\msg_kernel_new:nnnn { keys } { generate-choices-before-code }
+\__msg_kernel_new:nnnn { kernel } { generate-choices-before-code }
{ No~code~available~to~generate~choices~for~key~'#1'. }
{
\c_msg_coding_error_text_tl
Before~using~.generate_choices:n~the~code~should~be~defined~
with~'.choice_code:n'~or~'.choice_code:x'.
}
-\msg_kernel_new:nnnn { keys } { key-no-property }
+\__msg_kernel_new:nnnn { kernel } { key-no-property }
{ No~property~given~in~definition~of~key~'#1'. }
{
\c_msg_coding_error_text_tl
@@ -1973,39 +1911,33 @@
~ ~ #1 .<property> \\
LaTeX~did~not~find~a~'.'~to~indicate~the~start~of~a~property.
}
-\msg_kernel_new:nnnn { keys } { key-unknown }
+\__msg_kernel_new:nnnn { kernel } { key-unknown }
{ The~key~'#1'~is~unknown~and~is~being~ignored. }
{
The~module~'#2'~does~not~have~a~key~called~#1'.\\
Check~that~you~have~spelled~the~key~name~correctly.
}
-\msg_kernel_new:nnnn { keys } { option-unknown }
- { Unknown~option~'#1'~for~package~#2. }
- {
- LaTeX~has~been~asked~to~set~an~option~called~'#1'~
- but~the~#2~package~has~not~created~an~option~with~this~name.
- }
-\msg_kernel_new:nnnn { keys } { property-requires-value }
+\__msg_kernel_new:nnnn { kernel } { property-requires-value }
{ The~property~'#1'~requires~a~value. }
{
\c_msg_coding_error_text_tl
LaTeX~was~asked~to~set~property~'#2'~for~key~'#1'.\\
No~value~was~given~for~the~property,~and~one~is~required.
}
-\msg_kernel_new:nnnn { keys } { property-unknown }
+\__msg_kernel_new:nnnn { kernel } { property-unknown }
{ The~key~property~'#1'~is~unknown. }
{
\c_msg_coding_error_text_tl
LaTeX~has~been~asked~to~set~the~property~'#1'~for~key~'#2':~
this~property~is~not~defined.
}
-\msg_kernel_new:nnnn { keys } { value-forbidden }
+\__msg_kernel_new:nnnn { kernel } { value-forbidden }
{ The~key~'#1'~does~not~taken~a~value. }
{
The~key~'#1'~should~be~given~without~a~value.\\
LaTeX~will~ignore~the~given~value~'#2'.
}
-\msg_kernel_new:nnnn { keys } { value-required }
+\__msg_kernel_new:nnnn { kernel } { value-required }
{ The~key~'#1'~requires~a~value. }
{
The~key~'#1'~must~have~a~value.\\
@@ -2031,6 +1963,12 @@
% \end{macro}
% \end{macro}
% \end{macro}
+%
+% Internal material for removal by 2012-12-31.
+%
+% \begin{macrocode}
+\cs_new_eq:NN \c_keys_code_root_tl \c__keys_code_root_tl
+% \end{macrocode}
%
% \begin{macrocode}
%</initex|package>
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
index 212c953b2aa..5fbaea8cbd6 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3luatex.dtx
@@ -35,7 +35,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3luatex.dtx 3355 2012-02-09 07:18:22Z joseph $
+\GetIdInfo$Id: l3luatex.dtx 3986 2012-07-15 19:23:51Z joseph $
{L3 Experimental LuaTeX-specific functions}
%</driver|package>
%<*driver>
@@ -158,7 +158,7 @@
% \cs{cctab_gset:Nn} \meta{category code table} \Arg{category code set up}
% \end{syntax}
% Sets the \meta{category code table} to apply the category codes
-% which apply when the prevailing regime is modified by the
+% which apply when the prevailing r{\'e}gime is modified by the
% \meta{category code set up}. Thus within a standard code block
% the starting point will be the code applied by \cs{c_code_cctab}.
% The assignment of the table is global: the underlying primitive does
@@ -226,27 +226,17 @@
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
-% An error message.
-% \begin{macrocode}
-\msg_kernel_new:nnnn { luatex } { bad-engine }
- { LuaTeX~engine~not~in~use!~Ignoring~#1. }
- {
- The~feature~you~are~using~is~only~available~
- with~the~LuaTeX~engine.~LaTeX3~ignored~`#1#2'.
- }
-% \end{macrocode}
-%
% \begin{macro}{\lua_now:n, \lua_now:x}
% \begin{macro}{\lua_shipout_x:n, \lua_shipout_x:x}
% \begin{macro}{\lua_shipout:n, \lua_shipout:x}
% When \LuaTeX{} is in use, this is all a question of primitives with new
% names. On the other hand, for \pdfTeX{} and \XeTeX{} the argument should
% be removed from the input stream before issuing an error. This is
-% expandable, using \cs{msg_expandable_kernel_error:nnn}
+% expandable, using \cs{__msg_kernel_expandable_error:nnn}
% as done for \texttt{V}-type expansion in \pkg{l3expan}.
% \begin{macrocode}
\luatex_if_engine:TF
@@ -257,13 +247,13 @@
{
\cs_new:Npn \lua_now:x #1
{
- \msg_expandable_kernel_error:nnn
- { luatex } { bad-engine } { \lua_now:x }
+ \__msg_kernel_expandable_error:nnn
+ { kernel } { bad-engine } { \lua_now:x }
}
\cs_new_protected:Npn \lua_shipout_x:n #1
{
- \msg_expandable_kernel_error:nnn
- { luatex } { bad-engine } { \lua_shipout_x:n }
+ \__msg_kernel_expandable_error:nnn
+ { kernel } { bad-engine } { \lua_shipout_x:n }
}
}
\cs_new:Npn \lua_now:n #1
@@ -279,17 +269,21 @@
%
% \subsection{Category code tables}
%
-% \begin{variable}{\g_cctab_allocate_int}
-% \begin{variable}{\g_cctab_stack_int}
-% \begin{variable}{\g_cctab_stack_seq}
+% \begin{macrocode}
+%<@@=cctab>
+% \end{macrocode}
+%
+% \begin{variable}{\g_@@_allocate_int}
+% \begin{variable}{\g_@@_stack_int}
+% \begin{variable}{\g_@@_stack_seq}
% To allocate category code tables, both the read-only and stack
% tables need to be followed. There is also a sequence stack for the
% dynamic tables themselves.
% \begin{macrocode}
-\int_new:N \g_cctab_allocate_int
-\int_set:Nn \g_cctab_allocate_int { \c_minus_one }
-\int_new:N \g_cctab_stack_int
-\seq_new:N \g_cctab_stack_seq
+\int_new:N \g_@@_allocate_int
+\int_set:Nn \g_@@_allocate_int { \c_minus_one }
+\int_new:N \g_@@_stack_int
+\seq_new:N \g_@@_stack_seq
% \end{macrocode}
% \end{variable}
% \end{variable}
@@ -306,21 +300,21 @@
% \begin{macrocode}
\cs_new_protected:Npn \cctab_new:N #1
{
- \chk_if_free_cs:N #1
- \int_gadd:Nn \g_cctab_allocate_int { \c_two }
+ \__chk_if_free_cs:N #1
+ \int_gadd:Nn \g_@@_allocate_int { \c_two }
\int_compare:nNnTF
- \g_cctab_allocate_int < { \c_max_register_int + \c_one }
+ \g_@@_allocate_int < { \c_max_register_int + \c_one }
{
- \tex_global:D \tex_chardef:D #1 \g_cctab_allocate_int
+ \tex_global:D \tex_chardef:D #1 \g_@@_allocate_int
\luatex_initcatcodetable:D #1
}
- { \msg_kernel_fatal:nnx { kernel } { out-of-registers } { cctab } }
+ { \__msg_kernel_fatal:nnx { kernel } { out-of-registers } { cctab } }
}
\luatex_if_engine:F
{
\cs_set_protected:Npn \cctab_new:N #1
{
- \msg_kernel_error:nnx { luatex } { bad-engine }
+ \__msg_kernel_error:nnx { kernel } { bad-engine }
{ \exp_not:N \cctab_new:N }
}
}
@@ -329,7 +323,7 @@
{
\cs_set_protected:Npn \cctab_new:N #1
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\newcatcodetable #1
\luatex_initcatcodetable:D #1
}
@@ -340,39 +334,39 @@
%
% \begin{macro}{\cctab_begin:N}
% \begin{macro}{\cctab_end:}
-% \begin{variable}{\l_cctab_internal_tl}
+% \begin{variable}{\l_@@_internal_tl}
% The aim here is to ensure that the saved tables are read-only. This is
% done by using a stack of tables which are not read only, and actually
% having them as \enquote{in use} copies.
% \begin{macrocode}
\cs_new_protected:Npn \cctab_begin:N #1
{
- \seq_gpush:Nx \g_cctab_stack_seq { \tex_the:D \luatex_catcodetable:D }
+ \seq_gpush:Nx \g_@@_stack_seq { \tex_the:D \luatex_catcodetable:D }
\luatex_catcodetable:D #1
- \int_gadd:Nn \g_cctab_stack_int { \c_two }
- \int_compare:nNnT \g_cctab_stack_int > \c_max_register_int
- { \msg_kernel_fatal:nn { code } { cctab-stack-full } }
- \luatex_savecatcodetable:D \g_cctab_stack_int
- \luatex_catcodetable:D \g_cctab_stack_int
+ \int_gadd:Nn \g_@@_stack_int { \c_two }
+ \int_compare:nNnT \g_@@_stack_int > \c_max_register_int
+ { \__msg_kernel_fatal:nn { kernel } { cctab-stack-full } }
+ \luatex_savecatcodetable:D \g_@@_stack_int
+ \luatex_catcodetable:D \g_@@_stack_int
}
\cs_new_protected_nopar:Npn \cctab_end:
{
- \int_gsub:Nn \g_cctab_stack_int { \c_two }
- \seq_if_empty:NTF \g_cctab_stack_seq
- { \tl_set:Nn \l_cctab_internal_tl { 0 } }
- { \seq_gpop:NN \g_cctab_stack_seq \l_cctab_internal_tl }
- \luatex_catcodetable:D \l_cctab_internal_tl \scan_stop:
+ \int_gsub:Nn \g_@@_stack_int { \c_two }
+ \seq_if_empty:NTF \g_@@_stack_seq
+ { \tl_set:Nn \l_@@_internal_tl { 0 } }
+ { \seq_gpop:NN \g_@@_stack_seq \l_@@_internal_tl }
+ \luatex_catcodetable:D \l_@@_internal_tl \scan_stop:
}
\luatex_if_engine:F
{
\cs_set_protected:Npn \cctab_begin:N #1
{
- \msg_kernel_error:nnxx { luatex } { bad-engine }
+ \__msg_kernel_error:nnxx { kernel } { bad-engine }
{ \exp_not:N \cctab_begin:N } {#1}
}
\cs_set_protected_nopar:Npn \cctab_end:
{
- \msg_kernel_error:nnx { luatex } { bad-engine }
+ \__msg_kernel_error:nnx { kernel } { bad-engine }
{ \exp_not:N \cctab_end: }
}
}
@@ -383,7 +377,7 @@
\cs_set_protected_nopar:Npn \cctab_end: { \EndCatcodeRegime }
}
%</package>
-\tl_new:N \l_cctab_internal_tl
+\tl_new:N \l_@@_internal_tl
% \end{macrocode}
% \end{variable}
% \end{macro}
@@ -405,7 +399,7 @@
{
\cs_set_protected:Npn \cctab_gset:Nn #1#2
{
- \msg_kernel_error:nnxx { luatex } { bad-engine }
+ \__msg_kernel_error:nnxx { kernel } { bad-engine }
{ \exp_not:N \cctab_gset:Nn } { #1 {#2} }
}
}
@@ -454,12 +448,12 @@
}
\cctab_gset:Nn \c_other_cctab
{
- \prg_stepwise_inline:nnnn { 0 } { 1 } { 127 }
+ \int_step_inline:nnnn { 0 } { 1 } { 127 }
{ \char_set_catcode_other:n {#1} }
}
\cctab_gset:Nn \c_str_cctab
{
- \prg_stepwise_inline:nnnn { 0 } { 1 } { 127 }
+ \int_step_inline:nnnn { 0 } { 1 } { 127 }
{ \char_set_catcode_other:n {#1} }
\char_set_catcode_space:n { 32 }
}
@@ -471,6 +465,23 @@
% \end{variable}
% \end{variable}
% \end{variable}
+%
+% \subsection{Messages}
+%
+% \begin{macrocode}
+\__msg_kernel_new:nnnn { kernel } { bad-engine }
+ { LuaTeX~engine~not~in~use!~Ignoring~#1. }
+ {
+ The~feature~you~are~using~is~only~available~
+ with~the~LuaTeX~engine.~LaTeX3~ignored~`#1#2'.
+ }
+\__msg_kernel_new:nnnn { kernel } { cctab-stack-full }
+ { The~category~code~table~stack~is~exhausted. }
+ {
+ LaTeX~has~been~asked~to~switch~to~a~new~category~code~table,~
+ but~there~is~no~more~space~to~do~this!
+ }
+% \end{macrocode}
%
% \subsection{Deprecated functions}
%
@@ -478,7 +489,9 @@
%
% \begin{variable}{\c_string_cctab}
% \begin{macrocode}
+%<*deprecated>
\cs_new_eq:NN \c_string_cctab \c_str_cctab
+%</deprecated>
% \end{macrocode}
% \end{variable}
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
index 89362b7e7d4..a545ab5e126 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3msg.dtx 3568 2012-04-23 13:23:58Z joseph $
- {L3 Experimental messages}
+\GetIdInfo$Id: l3msg.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Messages}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -91,12 +91,7 @@
%
% \section{Creating new messages}
%
-% ^^A Wrong: "\msg_new:nnnn" is (as it should) global.
-% ^^A However, redirections are indeed local.
-% All messages have to be created before they can be used. All message
-% setting is local, with the general assumption that messages will
-% be managed as part of module set up outside of any \TeX{} grouping.
-%
+% All messages have to be created before they can be used.
% The text of messages will automatically by wrapped to the length
% available in the console. As a result, formatting is only needed
% where it will help to show meaning. In particular, |\\| may be
@@ -124,9 +119,8 @@
% \meta{more text} if the user requests it. If no \meta{more text} is
% available then a standard text is given instead. Within \meta{text}
% and \meta{more text} four parameters (|#1| to |#4|) can be used:
-% these will be supplied at the time the message is used. The
-% parameters will be expanded when the message is used. An error will
-% be raised if the \meta{message} already exists.
+% these will be supplied at the time the message is
+% used. An error will be raised if the \meta{message} already exists.
% \end{function}
%
% \begin{function}{\msg_set:nnnn, \msg_set:nnn, \msg_gset:nnnn, \msg_gset:nnn}
@@ -138,11 +132,10 @@
% \meta{more text} if the user requests it. If no \meta{more text} is
% available then a standard text is given instead. Within \meta{text}
% and \meta{more text} four parameters (|#1| to |#4|) can be used:
-% these will be supplied at the time the message is used. The
-% parameters will be expanded when the message is used.
+% these will be supplied at the time the message is used.
% \end{function}
%
-% \begin{function}[EXP,pTF, added=2012-03-03]{\msg_if_exist:nn}
+% \begin{function}[EXP, pTF, added = 2012-03-03]{\msg_if_exist:nn}
% \begin{syntax}
% \cs{msg_if_exist_p:nn} \Arg{module} \Arg{message}
% \cs{msg_if_exist:nnTF} \Arg{module} \Arg{message} \Arg{true code} \Arg{false code}
@@ -169,33 +162,15 @@
% Prints the current line number when a message is given.
% \end{function}
%
-% \begin{variable}{\c_msg_return_text_tl}
-% Standard text to indicate that the user should try pressing
-% \meta{return} to continue. The standard definition reads:
-% \begin{verbatim}
-% Try typing <return> to proceed.
-%
-% If that doesn't work, type X <return> to quit.
-% \end{verbatim}
-% \end{variable}
-%
-% \begin{variable}{\c_msg_trouble_text_tl}
-% Standard text to indicate that the more errors are likely and
-% that aborting the run is advised. The standard definition reads:
-% \begin{verbatim}
-% More errors will almost certainly follow:
-% the LaTeX run should be aborted.
-% \end{verbatim}
-% \end{variable}
-%
% \begin{function}[EXP]{\msg_fatal_text:n}
% \begin{syntax}
% \cs{msg_fatal_text:n} \Arg{module}
% \end{syntax}
-% Produces the standard text:
-% \begin{verbatim}
-% Fatal <module> error
-% \end{verbatim}
+% Produces the standard text
+% \begin{quote}
+% \ttfamily
+% Fatal \meta{module} error
+% \end{quote}
% This function can be redefined to alter the language in which the
% message is given, using |#1| as the name of the \meta{module} to
% be included.
@@ -205,10 +180,11 @@
% \begin{syntax}
% \cs{msg_critical_text:n} \Arg{module}
% \end{syntax}
-% Produces the standard text:
-% \begin{verbatim}
-% Critical <module> error
-% \end{verbatim}
+% Produces the standard text
+% \begin{quote}
+% \ttfamily
+% Critical \meta{module} error
+% \end{quote}
% This function can be redefined to alter the language in which the
% message is given, using |#1| as the name of the \meta{module} to
% be included.
@@ -218,10 +194,11 @@
% \begin{syntax}
% \cs{msg_error_text:n} \Arg{module}
% \end{syntax}
-% Produces the standard text:
-% \begin{verbatim}
-% <module> error
-% \end{verbatim}
+% Produces the standard text
+% \begin{quote}
+% \ttfamily
+% \meta{module} error
+% \end{quote}
% This function can be redefined to alter the language in which the
% message is given, using |#1| as the name of the \meta{module} to
% be included.
@@ -231,10 +208,11 @@
% \begin{syntax}
% \cs{msg_warning_text:n} \Arg{module}
% \end{syntax}
-% Produces the standard text:
-% \begin{verbatim}
-% <module> warning
-% \end{verbatim}
+% Produces the standard text
+% \begin{quote}
+% \ttfamily
+% \meta{module} warning
+% \end{quote}
% This function can be redefined to alter the language in which the
% message is given, using |#1| as the name of the \meta{module} to
% be included.
@@ -245,161 +223,184 @@
% \cs{msg_info_text:n} \Arg{module}
% \end{syntax}
% Produces the standard text:
-% \begin{verbatim}
-% <module> info
-% \end{verbatim}
+% \begin{quote}
+% \ttfamily
+% \meta{module} info
+% \end{quote}
% This function can be redefined to alter the language in which the
% message is given, using |#1| as the name of the \meta{module} to
% be included.
% \end{function}
-%
-% \section{Issuing messages}
-%
-% Messages behave differently depending on the message class. A number
-% of standard message classes are supplied, but more can be
-% created.
-%
-% When issuing messages, any arguments passed should use
-% \cs{tl_to_str:n} or \cs{token_to_str:N} to prevent unwanted expansion
-% of the material.
-%
-% \begin{function}[updated = 2012-04-12]{\msg_class_set:nn}
+%
+% \begin{function}[EXP]{\msg_see_documentation_text:n}
% \begin{syntax}
-% \cs{msg_class_set:nn} \Arg{class} \Arg{code}
+% \cs{msg_see_documentation_text:n} \Arg{module}
% \end{syntax}
-% Sets a \meta{class} to output a message, using \meta{code}
-% to process the message text. The \meta{class} should be a text
-% value, while the \meta{code} may be any arbitrary material.
-% The \meta{code} will receive~$6$ arguments: the module
-% name (|#1|), the message name (|#2|) and the four arguments
-% taken by the message text (|#3| to |#6|).
-% ^^A Add an example? An application could be that an IDE redirects
-% ^^A classes from 'error' to 'IDEerror', 'warning' to 'IDEwarning',
-% ^^A etc, and defines 'IDEerror' and 'IDEwarning' to produce messages
-% ^^A which are simpler to parse.
+% Produces the standard text
+% \begin{quote}
+% \ttfamily
+%
+% See the \meta{module} documentation for further information.
+% \end{quote}
+% This function can be redefined to alter the language in which the
+% message is given, using |#1| as the name of the \meta{module} to
+% be included.
% \end{function}
%
-% The kernel defines several common message classes. The following
-% describes the standard behaviour of each class if no redirection of
-% the class or message is active. In all cases, the message may be
-% issued supplying~$0$ to~$4$ arguments. The code will
-% ensure that there an no errors if the number of arguments supplied
-% here does not match the number in the definition of the message
-% (although of course the sense of the message may be impaired).
+% \section{Issuing messages}
+%
+% Messages behave differently depending on the message class. In all cases,
+% the message may be issued supplying~$0$ to~$4$ arguments. If the number of
+% arguments supplied here does not match the number in the definition of the
+% message, extra arguments will be ignored, or empty arguments added (of
+% course the sense of the message may be impaired). The four arguments will
+% be converted to strings before being added to the message text: the
+% \texttt{x}-type variants should be used to expand material.
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {
+% \msg_fatal:nnnnnn ,
+% \msg_fatal:nnnnn ,
+% \msg_fatal:nnnn ,
+% \msg_fatal:nnn ,
+% \msg_fatal:nn ,
% \msg_fatal:nnxxxx ,
% \msg_fatal:nnxxx ,
% \msg_fatal:nnxx ,
-% \msg_fatal:nnx ,
-% \msg_fatal:nn
+% \msg_fatal:nnx
% }
% \begin{syntax}
-% \cs{msg_fatal:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{msg_fatal:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Issues \meta{module} error \meta{message}, passing \meta{arg one} to
% \meta{arg four} to the text-creating functions. After issuing a
% fatal error the \TeX{} run will halt.
% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {
+% \msg_critical:nnnnnn ,
+% \msg_critical:nnnnn ,
+% \msg_critical:nnnn ,
+% \msg_critical:nnn ,
+% \msg_critical:nn ,
% \msg_critical:nnxxxx ,
% \msg_critical:nnxxx ,
% \msg_critical:nnxx ,
-% \msg_critical:nnx ,
-% \msg_critical:nn
+% \msg_critical:nnx
% }
% \begin{syntax}
-% \cs{msg_critical:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{msg_critical:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Issues \meta{module} error \meta{message}, passing \meta{arg one} to
-% \meta{arg four} to the text-creating functions. After issuing the
-% message reading the current input file will stop. This may halt
-% the \TeX{} run (if the current file is the main file) or
-% may abort reading a sub-file.
+% \meta{arg four} to the text-creating functions. After issuing a
+% critical error, \TeX{} will stop reading the current input file.
+% This may halt the \TeX{} run (if the current file is the main file)
+% or may abort reading a sub-file.
+% \begin{texnote}
+% The \TeX{} \tn{endinput} primitive is used to exit the file. In
+% particular, the rest of the current line remains in the input
+% stream. ^^A Can we fix that?
+% \end{texnote}
% \end{function}
-% ^^A Perhaps add detection that we are in the main file to really do
-% ^^A '\tex_end:D' in that case?
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {
+% \msg_error:nnnnnn ,
+% \msg_error:nnnnn ,
+% \msg_error:nnnn ,
+% \msg_error:nnn ,
+% \msg_error:nn ,
% \msg_error:nnxxxx ,
% \msg_error:nnxxx ,
% \msg_error:nnxx ,
-% \msg_error:nnx ,
-% \msg_error:nn
+% \msg_error:nnx
% }
% \begin{syntax}
-% \cs{msg_error:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{msg_error:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Issues \meta{module} error \meta{message}, passing \meta{arg one} to
-% \meta{arg four} to the text-creating functions. The error will
-% stop processing and issue the text at the terminal. After user input,
-% the run will continue.
+% \meta{arg four} to the text-creating functions. The error will
+% interrupt processing and issue the text at the terminal. After user
+% input, the run will continue.
% \end{function}
%
-% \begin{function}
-% {
-% \msg_warning:nnxxxx ,
-% \msg_warning:nnxxx ,
-% \msg_warning:nnxx ,
-% \msg_warning:nnx ,
-% \msg_warning:nn
-% }
-% \begin{syntax}
-% \cs{msg_warning:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
-% \end{syntax}
-% Issues \meta{module} warning \meta{message}, passing \meta{arg one} to
-% \meta{arg four} to the text-creating functions. The warning text
-% will be added to the log file, but the \TeX{} run will not be
-% interrupted.
-% \end{function}
+% \begin{function}[updated = 2012-06-29]
+% {
+% \msg_warning:nnnnnn ,
+% \msg_warning:nnnnn ,
+% \msg_warning:nnnn ,
+% \msg_warning:nnn ,
+% \msg_warning:nn ,
+% \msg_warning:nnxxxx ,
+% \msg_warning:nnxxx ,
+% \msg_warning:nnxx ,
+% \msg_warning:nnx
+% }
+% \begin{syntax}
+% \cs{msg_warning:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \end{syntax}
+% Issues \meta{module} warning \meta{message}, passing \meta{arg one}
+% to \meta{arg four} to the text-creating functions. The warning text
+% will be added to the log file and the terminal, but the \TeX{} run
+% will not be interrupted.
+% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {
+% \msg_info:nnnnnn ,
+% \msg_info:nnnnn ,
+% \msg_info:nnnn ,
+% \msg_info:nnn ,
+% \msg_info:nn ,
% \msg_info:nnxxxx ,
% \msg_info:nnxxx ,
% \msg_info:nnxx ,
-% \msg_info:nnx ,
-% \msg_info:nn
+% \msg_info:nnx
% }
% \begin{syntax}
-% \cs{msg_info:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{msg_info:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Issues \meta{module} information \meta{message}, passing
% \meta{arg one} to \meta{arg four} to the text-creating functions.
% The information text will be added to the log file.
% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-07-14]
% {
+% \msg_log:nnnnnn ,
+% \msg_log:nnnnn ,
+% \msg_log:nnnn ,
+% \msg_log:nnn ,
+% \msg_log:nn ,
% \msg_log:nnxxxx ,
% \msg_log:nnxxx ,
% \msg_log:nnxx ,
-% \msg_log:nnx ,
-% \msg_log:nn
+% \msg_log:nnx
% }
% \begin{syntax}
-% \cs{msg_log:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{msg_log:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Issues \meta{module} information \meta{message}, passing
% \meta{arg one} to \meta{arg four} to the text-creating functions.
% The information text will be added to the log file: the output
-% is briefer than \cs{msg_info:nnxxxx}.
+% is briefer than \cs{msg_info:nnnnnn}.
% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {
+% \msg_none:nnnnnn ,
+% \msg_none:nnnnn ,
+% \msg_none:nnnn ,
+% \msg_none:nnn ,
+% \msg_none:nn ,
% \msg_none:nnxxxx ,
% \msg_none:nnxxx ,
% \msg_none:nnxx ,
-% \msg_none:nnx ,
-% \msg_none:nn
+% \msg_none:nnx
% }
% \begin{syntax}
-% \cs{msg_none:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{msg_none:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Does nothing: used as a message class to prevent any output at
% all (see the discussion of message redirection).
@@ -434,18 +435,23 @@
% it is possible to select out an individual message for special treatment
% even if the entire class is already redirected.
%
-% \begin{function}[updated = 2012-04-12]{\msg_redirect_class:nn}
+% Multiple redirections are possible. Redirections can be cancelled by
+% providing an empty argument for the target class. Redirection to a
+% missing class will raise errors immediately. Infinite loops are
+% prevented by eliminating the redirection starting from the target of
+% the redirection that caused the loop to appear. Namely, if
+% redirections are requested as $A \to B$, $B \to C$ and $C \to A$ in
+% this order, then the $A \to B$ redirection is cancelled.
+%
+% \begin{function}[updated = 2012-04-27]{\msg_redirect_class:nn}
% \begin{syntax}
% \cs{msg_redirect_class:nn} \Arg{class one} \Arg{class two}
% \end{syntax}
% Changes the behaviour of messages of \meta{class one} so that they
-% are processed using the code for those of \meta{class two}. Multiple
-% redirections are possible. Redirection to a missing class or
-% infinite loops will raise errors when the messages are used,
-% rather than at the point of redirection.
+% are processed using the code for those of \meta{class two}.
% \end{function}
%
-% \begin{function}[updated = 2012-04-12]{\msg_redirect_module:nnn}
+% \begin{function}[updated = 2012-04-27]{\msg_redirect_module:nnn}
% \begin{syntax}
% \cs{msg_redirect_module:nnn} \Arg{module} \Arg{class one} \Arg{class two}
% \end{syntax}
@@ -460,14 +466,14 @@
% \end{verbatim}
% \end{function}
%
-% \begin{function}[updated = 2012-04-12]{\msg_redirect_name:nnn}
+% \begin{function}[updated = 2012-04-27]{\msg_redirect_name:nnn}
% \begin{syntax}
% \cs{msg_redirect_name:nnn} \Arg{module} \Arg{message} \Arg{class}
% \end{syntax}
-% Redirects a specific \meta{message} from a specific \meta{module}
-% to act as a member of \meta{class} of messages. This function can
-% be used to make a selected message \enquote{silent} without
-% changing global parameters:
+% Redirects a specific \meta{message} from a specific \meta{module} to
+% act as a member of \meta{class} of messages. No further redirection
+% is performed. This function can be used to make a selected message
+% \enquote{silent} without changing global parameters:
% \begin{verbatim}
% \msg_redirect_name:nnn { module } { annoying-message } { none }
% \end{verbatim}
@@ -479,18 +485,9 @@
% higher-level system. However, there are occasions where direct
% access to these functions is desirable.
%
-% \begin{function}[EXP]{\msg_newline:, \msg_two_newlines:}
-% \begin{syntax}
-% \cs{msg_newline:}
-% \end{syntax}
-% Forces a new line in a message. This is a low-level function, which
-% will not include any additional printing information in the message:
-% contrast with |\\| in messages. The |two| version adds two lines.
-% \end{function}
-%
-% \begin{function}{\msg_interrupt:xxx}
+% \begin{function}[added = 2012-06-28]{\msg_interrupt:nnn}
% \begin{syntax}
-% \cs{msg_interrupt:xxx} \Arg{first line} \Arg{text} \Arg{extra text}
+% \cs{msg_interrupt:nnn} \Arg{first line} \Arg{text} \Arg{extra text}
% \end{syntax}
% Interrupts the \TeX{} run, issuing a formatted message comprising
% \meta{first line} and \meta{text} laid out in the format
@@ -511,13 +508,15 @@
% | <extra text>
% |...............................................
% \end{verbatim}
-% where the \meta{extra text} will be wrapped to fit within the current
-% line length.
+% where the \meta{extra text} will be wrapped within the current
+% line length. Wrapping of both \meta{text} and \meta{more text} takes place
+% using \cs{iow_wrap:nnnN}; the documentation for the latter should be
+% consulted for full details.
% \end{function}
%
-% \begin{function}{\msg_log:x}
+% \begin{function}[added = 2012-06-28]{\msg_log:n}
% \begin{syntax}
-% \cs{msg_log:x} \Arg{text}
+% \cs{msg_log:n} \Arg{text}
% \end{syntax}
% Writes to the log file with the \meta{text} laid out in the format
% \begin{verbatim}
@@ -526,12 +525,13 @@
% .................................................
% \end{verbatim}
% where the \meta{text} will be wrapped to fit within the current
-% line length.
+% line length. Wrapping takes place using \cs{iow_wrap:nnnN}; the
+% documentation for the latter should be consulted for full details.
% \end{function}
%
-% \begin{function}{\msg_term:x}
+% \begin{function}[added = 2012-06-28]{\msg_term:n}
% \begin{syntax}
-% \cs{msg_term:x} \Arg{text}
+% \cs{msg_term:n} \Arg{text}
% \end{syntax}
% Writes to the terminal and log file with the \meta{text} laid out in the
% format
@@ -541,7 +541,8 @@
% *************************************************
% \end{verbatim}
% where the \meta{text} will be wrapped to fit within the current
-% line length.
+% line length. Wrapping takes place using \cs{iow_wrap:nnnN}; the
+% documentation for the latter should be consulted for full details.
% \end{function}
%
% \section{Kernel-specific functions}
@@ -551,59 +552,65 @@
% and also ensures that serious errors can be handled properly.
%
% \begin{function}[updated = 2011-08-16]
-% {\msg_kernel_new:nnnn, \msg_kernel_new:nnn}
+% {\__msg_kernel_new:nnnn, \__msg_kernel_new:nnn}
% \begin{syntax}
-% \cs{msg_kernel_new:nnnn} \Arg{module} \Arg{message} \Arg{text} \Arg{more text}
+% \cs{__msg_kernel_new:nnnn} \Arg{module} \Arg{message} \Arg{text} \Arg{more text}
% \end{syntax}
% Creates a kernel \meta{message} for a given \meta{module}.
% The message will be defined to first give \meta{text} and then
% \meta{more text} if the user requests it. If no \meta{more text} is
% available then a standard text is given instead. Within \meta{text}
% and \meta{more text} four parameters (|#1| to |#4|) can be used:
-% these will be supplied at the time the message is used. The
-% parameters will be expanded when the message is used. An error will
-% be raised if the \meta{message} already exists.
+% these will be supplied and expanded at the time the message is used.
+% An error will be raised if the \meta{message} already exists.
% \end{function}
%
-% \begin{function}{\msg_kernel_set:nnnn, \msg_kernel_set:nnn}
+% \begin{function}{\__msg_kernel_set:nnnn, \__msg_kernel_set:nnn}
% \begin{syntax}
-% \cs{msg_kernel_set:nnnn} \Arg{module} \Arg{message} \Arg{text} \Arg{more text}
+% \cs{__msg_kernel_set:nnnn} \Arg{module} \Arg{message} \Arg{text} \Arg{more text}
% \end{syntax}
% Sets up the text for a kernel \meta{message} for a given \meta{module}.
% The message will be defined to first give \meta{text} and then
% \meta{more text} if the user requests it. If no \meta{more text} is
% available then a standard text is given instead. Within \meta{text}
% and \meta{more text} four parameters (|#1| to |#4|) can be used:
-% these will be supplied at the time the message is used. The
-% parameters will be expanded when the message is used.
+% these will be supplied and expanded at the time the message is used.
% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {
-% \msg_kernel_fatal:nnxxxx ,
-% \msg_kernel_fatal:nnxxx ,
-% \msg_kernel_fatal:nnxx ,
-% \msg_kernel_fatal:nnx ,
-% \msg_kernel_fatal:nn
+% \__msg_kernel_fatal:nnnnnn ,
+% \__msg_kernel_fatal:nnnnn ,
+% \__msg_kernel_fatal:nnnn ,
+% \__msg_kernel_fatal:nnn ,
+% \__msg_kernel_fatal:nn ,
+% \__msg_kernel_fatal:nnxxxx ,
+% \__msg_kernel_fatal:nnxxx ,
+% \__msg_kernel_fatal:nnxx ,
+% \__msg_kernel_fatal:nnx
% }
% \begin{syntax}
-% \cs{msg_kernel_fatal:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{__msg_kernel_fatal:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Issues kernel \meta{module} error \meta{message}, passing \meta{arg one}
% to \meta{arg four} to the text-creating functions. After issuing a
% fatal error the \TeX{} run will halt. Cannot be redirected.
% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {
-% \msg_kernel_error:nnxxxx ,
-% \msg_kernel_error:nnxxx ,
-% \msg_kernel_error:nnxx ,
-% \msg_kernel_error:nnx ,
-% \msg_kernel_error:nn
+% \__msg_kernel_error:nnnnnn ,
+% \__msg_kernel_error:nnnnn ,
+% \__msg_kernel_error:nnnn ,
+% \__msg_kernel_error:nnn ,
+% \__msg_kernel_error:nn ,
+% \__msg_kernel_error:nnxxxx ,
+% \__msg_kernel_error:nnxxx ,
+% \__msg_kernel_error:nnxx ,
+% \__msg_kernel_error:nnx
% }
% \begin{syntax}
-% \cs{msg_kernel_error:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{__msg_kernel_error:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Issues kernel \meta{module} error \meta{message}, passing \meta{arg one}
% to
@@ -612,34 +619,42 @@
% the run will continue. Cannot be redirected.
% \end{function}
%
-% \begin{function}
-% {
-% \msg_kernel_warning:nnxxxx ,
-% \msg_kernel_warning:nnxxx ,
-% \msg_kernel_warning:nnxx ,
-% \msg_kernel_warning:nnx ,
-% \msg_kernel_warning:nn
-% }
-% \begin{syntax}
-% \cs{msg_kernel_warning:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
-% \end{syntax}
-% Issues kernel \meta{module} warning \meta{message}, passing
-% \meta{arg one} to
-% \meta{arg four} to the text-creating functions. The warning text
-% will be added to the log file, but the \TeX{} run will not be
-% interrupted.
-% \end{function}
+% \begin{function}[updated = 2012-06-29]
+% {
+% \__msg_kernel_warning:nnnnnn ,
+% \__msg_kernel_warning:nnnnn ,
+% \__msg_kernel_warning:nnnn ,
+% \__msg_kernel_warning:nnn ,
+% \__msg_kernel_warning:nn ,
+% \__msg_kernel_warning:nnxxxx ,
+% \__msg_kernel_warning:nnxxx ,
+% \__msg_kernel_warning:nnxx ,
+% \__msg_kernel_warning:nnx
+% }
+% \begin{syntax}
+% \cs{__msg_kernel_warning:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \end{syntax}
+% Issues kernel \meta{module} warning \meta{message}, passing
+% \meta{arg one} to
+% \meta{arg four} to the text-creating functions. The warning text
+% will be added to the log file, but the \TeX{} run will not be
+% interrupted.
+% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-06-29]
% {
-% \msg_kernel_info:nnxxxx ,
-% \msg_kernel_info:nnxxx ,
-% \msg_kernel_info:nnxx ,
-% \msg_kernel_info:nnx ,
-% \msg_kernel_info:nn
+% \__msg_kernel_info:nnnnnn ,
+% \__msg_kernel_info:nnnnn ,
+% \__msg_kernel_info:nnnn ,
+% \__msg_kernel_info:nnn ,
+% \__msg_kernel_info:nn ,
+% \__msg_kernel_info:nnxxxx ,
+% \__msg_kernel_info:nnxxx ,
+% \__msg_kernel_info:nnxx ,
+% \__msg_kernel_info:nnx
% }
% \begin{syntax}
-% \cs{msg_kernel_info:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{__msg_kernel_info:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Issues kernel \meta{module} information \meta{message}, passing
% \meta{arg one} to \meta{arg four} to the text-creating functions.
@@ -658,14 +673,14 @@
%
% \begin{function}[EXP, added = 2011-11-23]
% {
-% \msg_expandable_kernel_error:nnnnnn,
-% \msg_expandable_kernel_error:nnnnn,
-% \msg_expandable_kernel_error:nnnn,
-% \msg_expandable_kernel_error:nnn,
-% \msg_expandable_kernel_error:nn
+% \__msg_kernel_expandable_error:nnnnnn,
+% \__msg_kernel_expandable_error:nnnnn,
+% \__msg_kernel_expandable_error:nnnn,
+% \__msg_kernel_expandable_error:nnn,
+% \__msg_kernel_expandable_error:nn
% }
% \begin{syntax}
-% \cs{msg_expandable_kernel_error:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{__msg_kernel_expandable_error:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
% Issues an error, passing \meta{arg one} to \meta{arg four}
% to the text-creating functions. The resulting string must
@@ -673,9 +688,9 @@
% \end{function}
%
% \begin{function}[EXP, added = 2011-08-11, updated = 2011-08-13]
-% {\msg_expandable_error:n}
+% {\__msg_expandable_error:n}
% \begin{syntax}
-% \cs{msg_expandable_error:n} \Arg{error message}
+% \cs{__msg_expandable_error:n} \Arg{error message}
% \end{syntax}
% Issues an \enquote{Undefined error} message from \TeX{} itself,
% and prints the \meta{error message}. The \meta{error message}
@@ -692,30 +707,53 @@
%
% The following functions are used in several kernel modules.
%
-% \begin{function}{\msg_aux_use:nn, \msg_aux_use:nnxxxx}
+% \begin{function}
+% {
+% \__msg_term:nnnnnn,
+% \__msg_term:nnnnnV,
+% \__msg_term:nnnnn,
+% \__msg_term:nnn ,
+% \__msg_term:nn
+% }
% \begin{syntax}
-% \cs{msg_aux_use:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
+% \cs{__msg_term:nnnnnn} \Arg{module} \Arg{message} \Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four}
% \end{syntax}
-% Prints the \meta{message} from \meta{module} in the terminal,
-% without formatting.
+% Prints the \meta{message} from \meta{module} in the terminal without
+% formatting. Used in messages which print complex variable contents
+% completely.
% \end{function}
-%
-% \begin{function}{\msg_aux_show:x}
+%
+% \begin{function}{\__msg_show_variable:Nnn, \__msg_show_variable:Nnx}
% \begin{syntax}
-% \cs{msg_aux_show:x} \Arg{formatted string}
+% \cs{__msg_show_variable:Nnn} \meta{variable} \Arg{type} \Arg{formatted content}
+% \end{syntax}
+% Displays the \meta{formatted content} of the \meta{variable} of \meta{type}
+% in the terminal. The \meta{formatted content} will typically be generated
+% by \texttt{x}-type expansion using the \cs{__msg_show_variable:Nnx} variant:
+% the nature of the formatting is dependent on the calling module.
+% \end{function}
+%
+% \begin{function}{\__msg_show_variable:n, \__msg_show_variable:x}
+% \begin{syntax}
+% \cs{__msg_show_variable:n} \Arg{formatted string}
% \end{syntax}
% Shows the \meta{formatted string} on the terminal. After expansion,
% unless it is empty, the \meta{formatted string} must contain |>|,
% and the part of \meta{formatted string} before the first |>| is
% removed. Failure to do so causes low-level \TeX{} errors.
% \end{function}
-%
-% \begin{function}{\msg_aux_show:Nnx}
+%
+% \begin{function}
+% {\__msg_show_item:n, \__msg_show_item:nn, \__msg_show_item_unbraced:nn}
% \begin{syntax}
-% \cs{msg_aux_show:Nnx} \meta{variable} \Arg{module} \Arg{token list}
+% \cs{__msg_show_item:n} \meta{item}
+% \cs{__msg_show_item:nn} \meta{item-key} \meta{item-value}
% \end{syntax}
-% Auxiliary common to \pkg{l3clist}, \pkg{l3prop} and \pkg{seq},
-% which displays an appropriate message and the contents of the variable.
+% Auxiliary functions used within the argument of
+% \cs{__msg_show_variable:Nnx} to format variable items correctly for
+% display. The \cs{__msg_show_item:n} version is used for simple lists,
+% the \cs{__msg_show_item:nn} and \cs{__msg_show_item_ubraced:nn} versions
+% for key--value like data structures.
% \end{function}
%
% \end{documentation}
@@ -727,19 +765,23 @@
% \begin{macrocode}
%<*initex|package>
% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=msg>
+% \end{macrocode}
%
% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
-% \begin{variable}{\l_msg_internal_tl}
+% \begin{variable}{\l_@@_internal_tl}
% A general scratch for the module.
% \begin{macrocode}
-\tl_new:N \l_msg_internal_tl
+\tl_new:N \l_@@_internal_tl
% \end{macrocode}
% \end{variable}
%
@@ -749,11 +791,11 @@
% the code here. First, a mechanism for creating message text.
% This is pretty simple, as there is not actually a lot to do.
%
-% \begin{variable}{\c_msg_text_prefix_tl, \c_msg_more_text_prefix_tl}
+% \begin{variable}{\c_@@_text_prefix_tl, \c_@@_more_text_prefix_tl}
% Locations for the text of messages.
% \begin{macrocode}
-\tl_const:Nn \c_msg_text_prefix_tl { msg~text~>~ }
-\tl_const:Nn \c_msg_more_text_prefix_tl { msg~extra~text~>~ }
+\tl_const:Nn \c_@@_text_prefix_tl { msg~text~>~ }
+\tl_const:Nn \c_@@_more_text_prefix_tl { msg~extra~text~>~ }
% \end{macrocode}
% \end{variable}
%
@@ -763,37 +805,37 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \msg_if_exist:nn #1#2 { p , T , F , TF }
{
- \cs_if_exist:cTF { \c_msg_text_prefix_tl #1 / #2 }
+ \cs_if_exist:cTF { \c_@@_text_prefix_tl #1 / #2 }
{ \prg_return_true: } { \prg_return_false: }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\chk_if_free_msg:nn}
-% This auxiliary is similar to \cs{chk_if_free_cs:N}, and is used when
+% \begin{macro}[aux]{\__chk_if_free_msg:nn}
+% This auxiliary is similar to \cs{__chk_if_free_cs:N}, and is used when
% defining messages with \cs{msg_new:nnnn}. It could be inlined in
% \cs{msg_new:nnnn}, but the experimental \pkg{l3trace} module needs
% to disable this check when reloading a package with the extra
% tracing information.
% \begin{macrocode}
-\cs_new_protected:Npn \chk_if_free_msg:nn #1#2
+\cs_new_protected:Npn \__chk_if_free_msg:nn #1#2
{
\msg_if_exist:nnT {#1} {#2}
{
- \msg_kernel_error:nnxx { msg } { message-already-defined }
+ \@@_kernel_error:nnxx { kernel } { message-already-defined }
{#1} {#2}
}
}
%<*package>
\tex_ifodd:D \l@expl@log@functions@bool
- \cs_gset_protected:Npn \chk_if_free_msg:nn #1#2
+ \cs_gset_protected:Npn \__chk_if_free_msg:nn #1#2
{
\msg_if_exist:nnT {#1} {#2}
{
- \msg_kernel_error:nnxx { msg } { message-already-defined }
+ \@@_kernel_error:nnxx { kernel } { message-already-defined }
{#1} {#2}
}
- \iow_log:x { Defining~message~#1/#2~ \msg_line_context: }
+ \iow_log:x { Defining~message~ #1 / #2 ~\msg_line_context: }
}
\fi:
%</package>
@@ -808,25 +850,25 @@
% \begin{macrocode}
\cs_new_protected:Npn \msg_new:nnnn #1#2
{
- \chk_if_free_msg:nn {#1} {#2}
+ \__chk_if_free_msg:nn {#1} {#2}
\msg_gset:nnnn {#1} {#2}
}
\cs_new_protected:Npn \msg_new:nnn #1#2#3
{ \msg_new:nnnn {#1} {#2} {#3} { } }
\cs_new_protected:Npn \msg_set:nnnn #1#2#3#4
{
- \cs_set:cpn { \c_msg_text_prefix_tl #1 / #2 }
+ \cs_set:cpn { \c_@@_text_prefix_tl #1 / #2 }
##1##2##3##4 {#3}
- \cs_set:cpn { \c_msg_more_text_prefix_tl #1 / #2 }
+ \cs_set:cpn { \c_@@_more_text_prefix_tl #1 / #2 }
##1##2##3##4 {#4}
}
\cs_new_protected:Npn \msg_set:nnn #1#2#3
{ \msg_set:nnnn {#1} {#2} {#3} { } }
\cs_new_protected:Npn \msg_gset:nnnn #1#2#3#4
{
- \cs_gset:cpn { \c_msg_text_prefix_tl #1 / #2 }
+ \cs_gset:cpn { \c_@@_text_prefix_tl #1 / #2 }
##1##2##3##4 {#3}
- \cs_gset:cpn { \c_msg_more_text_prefix_tl #1 / #2 }
+ \cs_gset:cpn { \c_@@_more_text_prefix_tl #1 / #2 }
##1##2##3##4 {#4}
}
\cs_new_protected:Npn \msg_gset:nnn #1#2#3
@@ -887,15 +929,7 @@
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}{\msg_newline:, \msg_two_newlines:}
-% New lines are printed in the same way as for low-level file writing.
-% \begin{macrocode}
-\cs_new_nopar:Npn \msg_newline: { ^^J }
-\cs_new_nopar:Npn \msg_two_newlines: { ^^J ^^J }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\msg_line_number, \msg_line_context:}
+% \begin{macro}{\msg_line_number:, \msg_line_context:}
% For writing the line number nicely. \cs{msg_line_context:} was set up
% earlier, so this is not \texttt{new}.
% \begin{macrocode}
@@ -911,7 +945,7 @@
%
% \subsection{Showing messages: low level mechanism}
%
-% \begin{macro}{\msg_interrupt:xxx}
+% \begin{macro}{\msg_interrupt:nnn}
% The low-level interruption macro is rather opaque, unfortunately.
% Depending on the availability of more information there is a choice
% of how to set up the further help. We feed the extra help text and
@@ -919,36 +953,36 @@
% must first setup \TeX{}'s \tn{errhelp} register before issuing an
% \tn{errmessage}.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_interrupt:xxx #1#2#3
+\cs_new_protected:Npn \msg_interrupt:nnn #1#2#3
{
\tl_if_empty:nTF {#3}
{
- \msg_interrupt_wrap:xx { \\ \c_msg_no_info_text_tl }
+ \@@_interrupt_wrap:nn { \\ \c_msg_no_info_text_tl }
{#1 \\\\ #2 \\\\ \c_msg_continue_text_tl }
}
{
- \msg_interrupt_wrap:xx { \\ #3 }
+ \@@_interrupt_wrap:nn { \\ #3 }
{#1 \\\\ #2 \\\\ \c_msg_help_text_tl }
}
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[aux]{\msg_interrupt_wrap:xx}
-% \begin{macro}[aux]{\msg_interrupt_more_text:n}
+% \begin{macro}[aux]{\@@_interrupt_wrap:nn}
+% \begin{macro}[aux]{\@@_interrupt_more_text:n}
% First setup \TeX{}'s \tn{errhelp} register with the extra help |#1|,
% then build a nice-looking error message with |#2|. Everything is
% done using \texttt{x}-type expansion as the new line markers are
% different for the two type of text and need to be correctly set up.
-% The auxiliary \cs{msg_interrupt_more_text:n} recieves its argument
+% The auxiliary \cs{@@_interrupt_more_text:n} receives its argument
% as a line-wrapped string, which is thus unaffected by expansion.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_interrupt_wrap:xx #1#2
+\cs_new_protected:Npn \@@_interrupt_wrap:nn #1#2
{
- \iow_wrap:xnnnN {#1} { | ~ } { 2 } { } \msg_interrupt_more_text:n
- \iow_wrap:xnnnN {#2} { ! ~ } { 2 } { } \msg_interrupt_text:n
+ \iow_wrap:nnnN {#1} { | ~ } { } \@@_interrupt_more_text:n
+ \iow_wrap:nnnN {#2} { ! ~ } { } \@@_interrupt_text:n
}
-\cs_new_protected:Npn \msg_interrupt_more_text:n #1
+\cs_new_protected:Npn \@@_interrupt_more_text:n #1
{
\exp_args:Nx \tex_errhelp:D
{
@@ -961,17 +995,16 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux]{\msg_interrupt_text:n}
-% \begin{variable}{\c_msg_hide_tl<dots>}
+% \begin{macro}[aux]{\@@_interrupt_text:n}
% The business end of the process starts by producing some visual
% separation of the message from the main part of the log. The error
% message needs to be printed with everything made
% \enquote{invisible}: \TeX{}'s own information involves the macro in
% which \tn{errmessage} is called, and the end of the argument of the
% \tn{errmessage}, including the closing brace. We use an active |!|
-% to call the \tn{errmessage} primitive, and end its argument with an
-% odd \cs{c_msg_hide_tl<dots>} which fills the output with dots. The
-% trailing closing brace is turned into a space to hide it as well.
+% to call the \tn{errmessage} primitive, and end its argument with
+% \cs{use_none:n} \Arg{dots} which fills the output with dots. Two
+% trailing closing braces are turned into spaces to hide them as well.
% The group in which we alter the definition of the active |!| is
% closed before producing the message: this ensures that tokens
% inserted by typing |I| in the command-line will bee inserted after
@@ -982,13 +1015,10 @@
\char_set_lccode:nn {`\}} {`\ }
\char_set_lccode:nn {`\&} {`\!}
\char_set_catcode_active:N \&
- \char_set_catcode_letter:N \.
- \tl_new:N
- \c_msg_hide_tl............................................
\tl_to_lowercase:n
{
\group_end:
- \cs_new_protected:Npn \msg_interrupt_text:n #1
+ \cs_new_protected:Npn \@@_interrupt_text:n #1
{
\iow_term:x
{
@@ -1003,7 +1033,8 @@
\tex_errmessage:D
{
#1
- \c_msg_hide_tl............................................
+ \use_none:n
+ { ............................................ }
}
}
\exp_after:wN
@@ -1012,27 +1043,24 @@
}
}
% \end{macrocode}
-% \end{variable}
% \end{macro}
%
-% \begin{macro}{\msg_log:x}
-% \begin{macro}{\msg_term:x}
+% \begin{macro}{\msg_log:n}
+% \begin{macro}{\msg_term:n}
% Printing to the log or terminal without a stop is rather easier.
% A bit of simple visual work sets things off nicely.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_log:x #1
+\cs_new_protected:Npn \msg_log:n #1
{
- \iow_log:x { ................................................. }
- \iow_wrap:xnnnN { . ~ #1} { . ~ } { 2 } { }
- \iow_log:x
- \iow_log:x { ................................................. }
+ \iow_log:n { ................................................. }
+ \iow_wrap:nnnN { . ~ #1} { . ~ } { } \iow_log:n
+ \iow_log:n { ................................................. }
}
-\cs_new_protected:Npn \msg_term:x #1
+\cs_new_protected:Npn \msg_term:n #1
{
- \iow_term:x { ************************************************* }
- \iow_wrap:xnnnN { * ~ #1} { * ~ } { 2 } { }
- \iow_term:x
- \iow_term:x { ************************************************* }
+ \iow_term:n { ************************************************* }
+ \iow_wrap:nnnN { * ~ #1} { * ~ } { } \iow_term:n
+ \iow_term:n { ************************************************* }
}
% \end{macrocode}
% \end{macro}
@@ -1041,8 +1069,12 @@
% \subsection{Displaying messages}
%
% \LaTeX{} is handling error messages and so the \TeX{} ones are disabled.
+% This is already done by the \LaTeXe{} kernel, so to avoid messing up any
+% deliberate change by a user this is only set in format mode.
% \begin{macrocode}
-\int_gset:Nn \tex_errorcontextlines:D { -1 }
+%<*initex>
+\int_gset_eq:NN \tex_errorcontextlines:D \c_minus_one
+%</initex>
% \end{macrocode}
%
% \begin{macro}
@@ -1054,7 +1086,7 @@
% \msg_info_text:n
% }
% A function for issuing messages: both the text and order could
-% in principal vary.
+% in principle vary.
% \begin{macrocode}
\cs_new:Npn \msg_fatal_text:n #1 { Fatal~#1~error }
\cs_new:Npn \msg_critical_text:n #1 { Critical~#1~error }
@@ -1065,591 +1097,637 @@
% \end{macro}
%
% \begin{macro}{\msg_see_documentation_text:n}
-% Contextual footer information.
+% Contextual footer information. The \LaTeX{} module only comprises
+% \LaTeX3 code, so we refer to the \LaTeX3 documentation rather than
+% simply \enquote{\LaTeX{}}.
% \begin{macrocode}
\cs_new:Npn \msg_see_documentation_text:n #1
- { \\ \\ See~the~#1~documentation~for~further~information. }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\msg_class_set:nn}
-% Setting up a message class does two tasks. Any existing redirection
-% is cleared, and the various message functions are created
-% to simply use the code stored for the message.
-% \begin{macrocode}
-\cs_new_protected:Npn \msg_class_set:nn #1#2
{
- \prop_clear_new:c { l_msg_redirect_ #1 _prop }
- \cs_set_protected:cpn { msg_ #1 :nnxxxx } ##1##2##3##4##5##6
- { \msg_use:nnnnxxxx {#1} {#2} {##1} {##2} {##3} {##4} {##5} {##6} }
- \cs_set_protected:cpx { msg_ #1 :nnxxx } ##1##2##3##4##5
- { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} {##5} { } }
- \cs_set_protected:cpx { msg_ #1 :nnxx } ##1##2##3##4
- { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} { } { } }
- \cs_set_protected:cpx { msg_ #1 :nnx } ##1##2##3
- { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} { } { } { } }
- \cs_set_protected:cpx { msg_ #1 :nn } ##1##2
- { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} { } { } { } { } }
+ \\ \\ See~the~
+ \str_if_eq:nnTF {#1} { LaTeX } { LaTeX3 } {#1} ~
+ documentation~for~further~information.
}
% \end{macrocode}
% \end{macro}
-%
-% \begin{macro}[pTF]{\msg_if_more_text:N, \msg_if_more_text:c}
-% \begin{macro}[aux]{\msg_no_more_text:xxxx}
-% A test to see if any more text is available, using a
-% permanently-empty text function.
-% ^^A It would be more efficient to not define the more-text when absent.
+%
+% \begin{macro}{\@@_class_new:nn}
% \begin{macrocode}
-\prg_new_conditional:Npnn \msg_if_more_text:N #1 { p , T , F , TF }
- {
- \cs_if_eq:NNTF #1 \msg_no_more_text:xxxx
- { \prg_return_false: }
- { \prg_return_true: }
- }
-\cs_new:Npn \msg_no_more_text:xxxx #1#2#3#4 { }
-\cs_generate_variant:Nn \msg_if_more_text_p:N { c }
-\cs_generate_variant:Nn \msg_if_more_text:NT { c }
-\cs_generate_variant:Nn \msg_if_more_text:NF { c }
-\cs_generate_variant:Nn \msg_if_more_text:NTF { c }
+\group_begin:
+ \cs_set_protected:Npn \@@_class_new:nn #1#2
+ {
+ \prop_new:c { l_@@_redirect_ #1 _prop }
+ \cs_new_protected:cpn { @@_ #1 _code:nnnnnn } ##1##2##3##4##5##6 {#2}
+ \cs_new_protected:cpn { msg_ #1 :nnnnnn } ##1##2##3##4##5##6
+ {
+ \@@_use:nnnnnnn {#1} {##1} {##2}
+ { \tl_to_str:n {##3} } { \tl_to_str:n {##4} }
+ { \tl_to_str:n {##5} } { \tl_to_str:n {##6} }
+ }
+ \cs_new_protected:cpx { msg_ #1 :nnnnn } ##1##2##3##4##5
+ { \exp_not:c { msg_ #1 :nnnnnn } {##1} {##2} {##3} {##4} {##5} { } }
+ \cs_new_protected:cpx { msg_ #1 :nnnn } ##1##2##3##4
+ { \exp_not:c { msg_ #1 :nnnnnn } {##1} {##2} {##3} {##4} { } { } }
+ \cs_new_protected:cpx { msg_ #1 :nnn } ##1##2##3
+ { \exp_not:c { msg_ #1 :nnnnnn } {##1} {##2} {##3} { } { } { } }
+ \cs_new_protected:cpx { msg_ #1 :nn } ##1##2
+ { \exp_not:c { msg_ #1 :nnnnnn } {##1} {##2} { } { } { } { } }
+ \cs_new_protected:cpn { msg_ #1 :nnxxxx } ##1##2##3##4##5##6
+ {
+ \use:x
+ {
+ \@@_use:nnnnnnn
+ { \exp_not:n {#1} } { \exp_not:n {##1} } { \exp_not:n {##2} }
+ {##3} {##4} {##5} {##6}
+ }
+ }
+ \cs_new_protected:cpx { msg_ #1 :nnxxx } ##1##2##3##4##5
+ { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} {##5} { } }
+ \cs_new_protected:cpx { msg_ #1 :nnxx } ##1##2##3##4
+ { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} { } { } }
+ \cs_new_protected:cpx { msg_ #1 :nnx } ##1##2##3
+ { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} { } { } { } }
+ }
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \begin{macro}
-% {
-% \msg_fatal:nnxxxx ,
-% \msg_fatal:nnxxx ,
-% \msg_fatal:nnxx ,
-% \msg_fatal:nnx ,
-% \msg_fatal:nn
-% }
+% {
+% \msg_fatal:nnnnnn ,
+% \msg_fatal:nnnnn ,
+% \msg_fatal:nnnn ,
+% \msg_fatal:nnn ,
+% \msg_fatal:nn ,
+% \msg_fatal:nnxxxx ,
+% \msg_fatal:nnxxx ,
+% \msg_fatal:nnxx ,
+% \msg_fatal:nnx
+% }
% For fatal errors, after the error message \TeX{} bails out.
% \begin{macrocode}
-\msg_class_set:nn { fatal }
- {
- \msg_interrupt:xxx
- { \msg_fatal_text:n {#1} : ~ "#2" }
- {
- \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
- \msg_see_documentation_text:n {#1}
- }
- { \c_msg_fatal_text_tl }
- \tex_end:D
- }
+ \@@_class_new:nn { fatal }
+ {
+ \msg_interrupt:nnn
+ { \msg_fatal_text:n {#1} : ~ "#2" }
+ {
+ \use:c { \c_@@_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
+ \msg_see_documentation_text:n {#1}
+ }
+ { \c_msg_fatal_text_tl }
+ \tex_end:D
+ }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}
% {
+% \msg_critical:nnnnnn ,
+% \msg_critical:nnnnn ,
+% \msg_critical:nnnn ,
+% \msg_critical:nnn ,
+% \msg_critical:nn ,
% \msg_critical:nnxxxx ,
% \msg_critical:nnxxx ,
% \msg_critical:nnxx ,
-% \msg_critical:nnx ,
-% \msg_critical:nn
-% }
+% \msg_critical:nnx
+% }
% Not quite so bad: just end the current file.
% \begin{macrocode}
-\msg_class_set:nn { critical }
- {
- \msg_interrupt:xxx
- { \msg_critical_text:n {#1} : ~ "#2" }
- {
- \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
- \msg_see_documentation_text:n {#1}
- }
- { \c_msg_critical_text_tl }
- \tex_endinput:D
- }
+ \@@_class_new:nn { critical }
+ {
+ \msg_interrupt:nnn
+ { \msg_critical_text:n {#1} : ~ "#2" }
+ {
+ \use:c { \c_@@_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
+ \msg_see_documentation_text:n {#1}
+ }
+ { \c_msg_critical_text_tl }
+ \tex_endinput:D
+ }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}
% {
+% \msg_error:nnnnnn ,
+% \msg_error:nnnnn ,
+% \msg_error:nnnn ,
+% \msg_error:nnn ,
+% \msg_error:nn ,
% \msg_error:nnxxxx ,
% \msg_error:nnxxx ,
% \msg_error:nnxx ,
-% \msg_error:nnx ,
-% \msg_error:nn
+% \msg_error:nnx
% }
-% For an error, the interrupt routine is called, then any recovery code
-% is tried.
+% \begin{macro}[aux]{\@@_error:cnnnnn, \@@_no_more_text:nnnn}
+% For an error, the interrupt routine is called. We check if there is
+% a \enquote{more text} by comparing that control sequence with a
+% permanently empty text.
% \begin{macrocode}
-\msg_class_set:nn { error }
- {
- \msg_if_more_text:cTF { \c_msg_more_text_prefix_tl #1 / #2 }
- {
- \msg_interrupt:xxx
- { \msg_error_text:n {#1} : ~ "#2" }
- {
- \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
- \msg_see_documentation_text:n {#1}
- }
- { \use:c { \c_msg_more_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} }
- }
- {
- \msg_interrupt:xxx
- { \msg_error_text:n {#1} : ~ "#2" }
- {
- \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
- \msg_see_documentation_text:n {#1}
- }
- { }
- }
- }
+ \@@_class_new:nn { error }
+ {
+ \@@_error:cnnnnn
+ { \c_@@_more_text_prefix_tl #1 / #2 }
+ {#3} {#4} {#5} {#6}
+ {
+ \msg_interrupt:nnn
+ { \msg_error_text:n {#1} : ~ "#2" }
+ {
+ \use:c { \c_@@_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
+ \msg_see_documentation_text:n {#1}
+ }
+ }
+ }
+ \cs_new_protected:Npn \@@_error:cnnnnn #1#2#3#4#5#6
+ {
+ \cs_if_eq:cNTF {#1} \@@_no_more_text:nnnn
+ { #6 { } }
+ { #6 { \use:c {#1} {#2} {#3} {#4} {#5} } }
+ }
+ \cs_new:Npn \@@_no_more_text:nnnn #1#2#3#4 { }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}
% {
+% \msg_warning:nnnnnn ,
+% \msg_warning:nnnnn ,
+% \msg_warning:nnnn ,
+% \msg_warning:nnn ,
+% \msg_warning:nn ,
% \msg_warning:nnxxxx ,
% \msg_warning:nnxxx ,
% \msg_warning:nnxx ,
-% \msg_warning:nnx ,
-% \msg_warning:nn
+% \msg_warning:nnx
% }
% Warnings are printed to the terminal.
% \begin{macrocode}
-\msg_class_set:nn { warning }
- {
- \msg_term:x
- {
- \msg_warning_text:n {#1} : ~ "#2" \\ \\
- \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
- }
- }
+ \@@_class_new:nn { warning }
+ {
+ \msg_term:n
+ {
+ \msg_warning_text:n {#1} : ~ "#2" \\ \\
+ \use:c { \c_@@_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
+ }
+ }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}
% {
+% \msg_info:nnnnnn ,
+% \msg_info:nnnnn ,
+% \msg_info:nnnn ,
+% \msg_info:nnn ,
+% \msg_info:nn ,
% \msg_info:nnxxxx ,
% \msg_info:nnxxx ,
% \msg_info:nnxx ,
-% \msg_info:nnx ,
-% \msg_info:nn
+% \msg_info:nnx
% }
% Information only goes into the log.
% \begin{macrocode}
-\msg_class_set:nn { info }
- {
- \msg_log:x
- {
- \msg_info_text:n {#1} : ~ "#2" \\ \\
- \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
- }
- }
+ \@@_class_new:nn { info }
+ {
+ \msg_log:n
+ {
+ \msg_info_text:n {#1} : ~ "#2" \\ \\
+ \use:c { \c_@@_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6}
+ }
+ }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}
% {
+% \msg_log:nnnnnn ,
+% \msg_log:nnnnn ,
+% \msg_log:nnnn ,
+% \msg_log:nnn ,
+% \msg_log:nn ,
% \msg_log:nnxxxx ,
% \msg_log:nnxxx ,
% \msg_log:nnxx ,
-% \msg_log:nnx ,
-% \msg_log:nn
+% \msg_log:nnx
% }
% \enquote{Log} data is very similar to information, but with no extras
% added.
% \begin{macrocode}
-\msg_class_set:nn { log }
- {
- \msg_log:x
- { \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} }
- }
+ \@@_class_new:nn { log }
+ {
+ \iow_wrap:nnnN
+ { \use:c { \c_@@_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} }
+ { } { } \iow_log:n
+ }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}
% {
+% \msg_none:nnnnnn ,
+% \msg_none:nnnnn ,
+% \msg_none:nnnn ,
+% \msg_none:nnn ,
+% \msg_none:nn ,
% \msg_none:nnxxxx ,
% \msg_none:nnxxx ,
% \msg_none:nnxx ,
-% \msg_none:nnx ,
-% \msg_none:nn
+% \msg_none:nnx
% }
% The \texttt{none} message type is needed so that input can be gobbled.
% \begin{macrocode}
-\msg_class_set:nn { none } { }
+ \@@_class_new:nn { none } { }
% \end{macrocode}
% \end{macro}
%
-% \begin{variable}{\l_msg_class_tl, \l_msg_current_class_tl}
+% End the group to eliminate \cs{@@_class_new:nn}.
+% \begin{macrocode}
+\group_end:
+% \end{macrocode}
+%
+% \begin{macro}[aux]{\@@_class_chk_exist:nT}
+% Checking that a message class exists. We build this from
+% \cs{cs_if_free:cTF} rather than \cs{cs_if_exist:cTF} because that
+% avoids reading the second argument earlier than necessary.
+% \begin{macrocode}
+\cs_new:Npn \@@_class_chk_exist:nT #1
+ {
+ \cs_if_free:cTF { @@_ #1 _code:nnnnnn }
+ { \@@_kernel_error:nnx { kernel } { message-class-unknown } {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{variable}{\l_@@_class_tl, \l_@@_current_class_tl}
% Support variables needed for the redirection system.
% \begin{macrocode}
-\tl_new:N \l_msg_class_tl
-\tl_new:N \l_msg_current_class_tl
+\tl_new:N \l_@@_class_tl
+\tl_new:N \l_@@_current_class_tl
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_msg_redirect_classes_prop, \l_msg_redirect_names_prop}
-% For filtering messages, a list of all messages and of those which have
-% to be modified is required.
+% \begin{variable}{\l_@@_redirect_prop}
+% For redirection of individually-named messages
% \begin{macrocode}
-\prop_new:N \l_msg_redirect_classes_prop
-\prop_new:N \l_msg_redirect_names_prop
+\prop_new:N \l_@@_redirect_prop
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_msg_redirect_prop}
-% For redirection of individually-named messages
+% \begin{variable}{\l_@@_hierarchy_seq}
+% During redirection, split the message name into a sequence with
+% items |{/module/submodule}|, |{/module}|, and |{}|.
% \begin{macrocode}
-\prop_new:N \l_msg_redirect_prop
+\seq_new:N \l_@@_hierarchy_seq
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_msg_use_direct_bool}
-% Used to force redirection when a name is given directly.
+% \begin{variable}{\l_@@_class_loop_seq}
+% Classes encountered when following redirections to check for loops.
% \begin{macrocode}
-\bool_new:N \l_msg_use_direct_bool
+\seq_new:N \l_@@_class_loop_seq
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}[int]{\msg_use:nnnnxxxx}
-% \begin{macro}[aux]{\msg_use_code:, \msg_use_or_change_class:}
-% \begin{macro}[aux]{\msg_use_aux_i:nn, \msg_use_aux_ii:nn}
-% \begin{macro}[aux]{\msg_use_aux_iii:w}
-% \begin{macro}[aux]{\msg_use_aux_iv:w}
-% \begin{macro}[aux]{\msg_use_aux_v:}
-% Actually using a message is a multi-step process. First, some safety
-% checks on the message and class requested. The code and arguments are
-% then stored to avoid passing them around.
+% \begin{macro}[int]{\@@_use:nnnnnnn}
+% \begin{macro}[aux]
+% {
+% \@@_use_redirect_name:n , \@@_use_hierarchy:nwwN ,
+% \@@_use_redirect_module:n, \@@_use_code:
+% }
+% Actually using a message is a multi-step process. First, some
+% safety checks on the message and class requested. The code and
+% arguments are then stored to avoid passing them around. The
+% assignment to \cs{@@_use_code:} is similar to \cs{tl_set:Nn}.
+% The message is eventually produced with whatever \cs{l_@@_class_tl}
+% is when \cs{@@_use_code:} is called.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_use:nnnnxxxx #1#2#3#4#5#6#7#8
+\cs_new_protected:Npn \@@_use:nnnnnnn #1#2#3#4#5#6#7
{
- \msg_if_exist:nnTF {#3} {#4}
+ \msg_if_exist:nnTF {#2} {#3}
{
- \cs_if_exist:cTF { msg_ #1 :nnxxxx }
+ \@@_class_chk_exist:nT {#1}
{
- \tl_set:Nn \l_msg_current_class_tl {#1}
- \cs_set_protected_nopar:Npx \msg_use_code: { \exp_not:n {#2} }
- \cs_set_protected_nopar:Npn \msg_use_or_change_class:
+ \tl_set:Nn \l_@@_current_class_tl {#1}
+ \cs_set_protected_nopar:Npx \@@_use_code:
{
- \tl_if_eq:NNTF \l_msg_current_class_tl \l_msg_class_tl
- { \msg_use_code: }
+ \exp_not:n
{
- \use:c { msg_ \l_msg_class_tl :nnxxxx }
- {#3} {#4} {#5} {#6} {#7} {#8}
+ \use:c { @@_ \l_@@_class_tl _code:nnnnnn }
+ {#2} {#3} {#4} {#5} {#6} {#7}
}
}
- \bool_if:NTF \l_msg_use_direct_bool
- {
- \bool_set_false:N \l_msg_use_direct_bool
- \msg_use_code:
- }
- { \msg_use_aux_i:nn {#3} {#4} }
+ \@@_use_redirect_name:n { #2 / #3 }
}
- { \msg_kernel_error:nnx { msg } { message-class-unknown } {#1} }
}
- { \msg_kernel_error:nnxx { msg } { message-unknown } {#3} {#4} }
+ { \@@_kernel_error:nnxx { kernel } { message-unknown } {#2} {#3} }
}
-\cs_new_protected_nopar:Npn \msg_use_code: { }
-\cs_new_protected_nopar:Npn \msg_use_or_change_class: { }
+\cs_new_protected_nopar:Npn \@@_use_code: { }
% \end{macrocode}
-% The first check is for a individual message redirection. If this applies
-% then no further redirection is attempted.
+% The first check is for a individual message redirection. If this
+% applies then no further redirection is attempted. Otherwise, split
+% the message name into \texttt{module/submodule/message} (with an
+% arbitrary number of slashes), and store |{/module/submodule}|,
+% |{/module}| and |{}| into \cs{l_@@_hierarchy_seq}. We will then
+% map through this sequence, applying the most specific redirection.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_use_aux_i:nn #1#2
+\cs_new_protected:Npn \@@_use_redirect_name:n #1
{
- \prop_get:NnNTF \l_msg_redirect_prop { #1 / #2 } \l_msg_class_tl
+ \prop_get:NnNTF \l_@@_redirect_prop { / #1 } \l_@@_class_tl
+ { \@@_use_code: }
{
- \bool_set_true:N \l_msg_use_direct_bool
- \msg_use_or_change_class:
+ \seq_clear:N \l_@@_hierarchy_seq
+ \@@_use_hierarchy:nwwN { }
+ #1 \q_mark \@@_use_hierarchy:nwwN
+ / \q_mark \use_none_delimit_by_q_stop:w
+ \q_stop
+ \@@_use_redirect_module:n { }
}
- { \msg_use_aux_ii:nn {#1} {#2} }
}
-% \end{macrocode}
-% Next check if there is a redirection by module or by submodule.
-% \begin{macrocode}
-\cs_new_protected:Npn \msg_use_aux_ii:nn #1#2
+\cs_new_protected:Npn \@@_use_hierarchy:nwwN #1#2 / #3 \q_mark #4
{
- \prop_get:coNTF { l_msg_redirect_ \l_msg_current_class_tl _ prop }
- { \msg_use_aux_iii:w #1 / #2 / \q_stop } \l_msg_class_tl
- { \msg_use_or_change_class: }
- {
- \prop_get:coNTF { l_msg_redirect_ \l_msg_current_class_tl _ prop }
- { \msg_use_aux_iv:w #1 / #2 \q_stop } \l_msg_class_tl
- { \msg_use_or_change_class: }
- { \msg_use_aux_v: }
- }
+ \seq_put_left:Nn \l_@@_hierarchy_seq {#1}
+ #4 { #1 / #2 } #3 \q_mark #4
}
-\cs_new:Npn \msg_use_aux_iii:w #1 / #2 / #3 \q_stop { #1 / #2 }
-\cs_new:Npn \msg_use_aux_iv:w #1 / #2 \q_stop { #1 }
% \end{macrocode}
-% Finally test for redirection of an entire class.
+% At this point, the items of \cs{l_@@_hierarchy_seq} are the
+% various levels at which we should look for a redirection.
+% Redirections which are less specific than the argument of
+% \cs{@@_use_redirect_module:n} are not attempted. This argument is
+% empty for a class redirection, \texttt{/module} for a module
+% redirection, \emph{etc.} Loop through the sequence to find the most
+% specific redirection, with module |##1|. The loop is interrupted
+% after testing for a redirection for |##1| equal to the argument |#1|
+% (least specific redirection allowed). When a redirection is found,
+% break the mapping, then if the redirection targets the same class,
+% output the code with that class, and otherwise set the target as the
+% new current class, and search for further redirections. Those
+% redirections should be at least as specific as |##1|.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_use_aux_v:
+\cs_new_protected:Npn \@@_use_redirect_module:n #1
{
- \prop_get:cnNF { l_msg_redirect_ \l_msg_current_class_tl _ prop }
- { * } \l_msg_class_tl
- { \tl_set_eq:NN \l_msg_class_tl \l_msg_current_class_tl }
- \msg_use_or_change_class:
+ \seq_map_inline:Nn \l_@@_hierarchy_seq
+ {
+ \prop_get:cnNTF { l_@@_redirect_ \l_@@_current_class_tl _prop }
+ {##1} \l_@@_class_tl
+ {
+ \seq_map_break:n
+ {
+ \tl_if_eq:NNTF \l_@@_current_class_tl \l_@@_class_tl
+ { \@@_use_code: }
+ {
+ \tl_set_eq:NN \l_@@_current_class_tl \l_@@_class_tl
+ \@@_use_redirect_module:n {##1}
+ }
+ }
+ }
+ {
+ \str_if_eq:nnT {##1} {#1}
+ {
+ \tl_set_eq:NN \l_@@_class_tl \l_@@_current_class_tl
+ \seq_map_break:n { \@@_use_code: }
+ }
+ }
+ }
}
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\msg_redirect_class:nn}
-% \begin{macro}[aux]{\msg_redirect_class_aux:nnn, \msg_redirect_class_aux:nVn}
-% Converts class one into class two.
+% \begin{macro}{\msg_redirect_name:nnn}
+% Named message will always use the given class even if that class is
+% redirected further. An empty target class cancels any existing
+% redirection for that message.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_redirect_class:nn #1#2
- {
- \cs_if_exist:cTF { msg_ #1 :nnxxxx }
- {
- \cs_if_exist:cTF { msg_ #2 :nnxxxx }
- {
- \tl_set:Nn \l_msg_current_class_tl {#1}
- \msg_redirect_class_aux:nnn {#1} {#2} {#2}
- }
- { \msg_kernel_error:nnx { msg } { message-class-unknown } {#2} }
- }
- { \msg_kernel_error:nnx { msg } { message-class-unknown } {#1} }
- }
-\cs_new_protected:Npn \msg_redirect_class_aux:nnn #1#2#3
+\cs_new_protected:Npn \msg_redirect_name:nnn #1#2#3
{
- \prop_get:cnNTF { l_msg_redirect_ #2 _prop } { * } \l_msg_class_tl
+ \tl_if_empty:nTF {#3}
+ { \prop_remove:Nn \l_@@_redirect_prop { / #1 / #2 } }
{
- \tl_if_eq:NNTF \l_msg_class_tl \l_msg_current_class_tl
- { \msg_kernel_error:nnxx { msg } { message-loop } {#1} {#3} }
- { \msg_redirect_class_aux:nVn {#1} \l_msg_class_tl {#3} }
+ \@@_class_chk_exist:nT {#3}
+ { \prop_put:Nnn \l_@@_redirect_prop { / #1 / #2 } {#3} }
}
- { \prop_put:cnn { l_msg_redirect_ #1 _prop } { * } {#3} }
}
-\cs_generate_variant:Nn \msg_redirect_class_aux:nnn { nV }
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\msg_redirect_module:nnn}
-% \begin{macro}[aux]
-% {\msg_redirect_module_aux:nnnn, \msg_redirect_module_aux:nnVn}
-% For when all messages of a class should be altered for a given module.
+% \begin{macro}{\msg_redirect_class:nn, \msg_redirect_module:nnn}
+% \begin{macro}[aux]{\@@_redirect:nnn, \@@_redirect_loop_chk:nnn}
+% \begin{macro}[aux]{\@@_redirect_loop_list:n}
+% If the target class is empty, eliminate the corresponding
+% redirection. Otherwise, add the redirection. We must then check
+% for a loop: as an initialization, we start by storing the initial
+% class in \cs{l_@@_current_class_tl}.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_redirect_module:nnn #1#2#3
+\cs_new_protected_nopar:Npn \msg_redirect_class:nn
+ { \@@_redirect:nnn { } }
+\cs_new_protected:Npn \msg_redirect_module:nnn #1
+ { \@@_redirect:nnn { / #1 } }
+\cs_new_protected:Npn \@@_redirect:nnn #1#2#3
{
- \cs_if_exist:cTF { msg_ #2 :nnxxxx }
+ \@@_class_chk_exist:nT {#2}
{
- \cs_if_exist:cTF { msg_ #3 :nnxxxx }
+ \tl_if_empty:nTF {#3}
+ { \prop_remove:cn { l_@@_redirect_ #2 _prop } {#1} }
{
- \tl_set:Nn \l_msg_current_class_tl {#1}
- \msg_redirect_module_aux:nnnn {#1} {#2} {#3} {#3}
+ \@@_class_chk_exist:nT {#3}
+ {
+ \prop_put:cnn { l_@@_redirect_ #2 _prop } {#1} {#3}
+ \tl_set:Nn \l_@@_current_class_tl {#2}
+ \seq_clear:N \l_@@_class_loop_seq
+ \@@_redirect_loop_chk:nnn {#2} {#3} {#1}
+ }
}
- { \msg_kernel_error:nnx { msg } { message-class-unknown } {#3} }
}
- { \msg_kernel_error:nnx { msg } { message-class-unknown } {#2} }
}
-\cs_new_protected:Npn \msg_redirect_module_aux:nnnn #1#2#3#4
+% \end{macrocode}
+% Since multiple redirections can only happen with increasing
+% specificity, a loop requires that all steps are of the same
+% specificity. The new redirection can thus only create a loop with
+% other redirections for the exact same module, |#1|, and not
+% submodules. After some initialization above, follow redirections
+% with \cs{l_@@_class_tl}, and keep track in
+% \cs{l_@@_class_loop_seq} of the various classes encountered. A
+% redirection from a class to itself, or the absence of redirection
+% both mean that there is no loop. A redirection to the initial class
+% marks a loop. To break it, we must decide which redirection to
+% cancel. The user most likely wants the newly added redirection to
+% hold with no further redirection. We thus remove the redirection
+% starting from |#2|, target of the new redirection. Note that no
+% message is emitted by any of the underlying functions: otherwise we
+% may get an infinite loop because of a message from the message
+% system itself.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_redirect_loop_chk:nnn #1#2#3
{
- \prop_get:cnNTF { l_msg_redirect_ #3 _prop } {#1} \l_msg_class_tl
+ \seq_put_right:Nn \l_@@_class_loop_seq {#1}
+ \prop_get:cnNT { l_@@_redirect_ #1 _prop } {#3} \l_@@_class_tl
{
- \tl_if_eq:NNTF \l_msg_class_tl \l_msg_current_class_tl
- { \msg_kernel_error:nnxx { msg } { message-loop } {#2} {#4} }
- { \msg_redirect_moduel_aux:nVn {#1} {#2} \l_msg_class_tl {#4} }
+ \str_if_eq_x:nnF { \l_@@_class_tl } {#1}
+ {
+ \tl_if_eq:NNTF \l_@@_class_tl \l_@@_current_class_tl
+ {
+ \prop_put:cnn { l_@@_redirect_ #2 _prop } {#3} {#2}
+ \@@_kernel_warning:nnxxxx { kernel } { message-redirect-loop }
+ { \seq_item:Nn \l_@@_class_loop_seq { \c_one } }
+ { \seq_item:Nn \l_@@_class_loop_seq { \c_two } }
+ {#3}
+ {
+ \seq_map_function:NN \l_@@_class_loop_seq
+ \@@_redirect_loop_list:n
+ { \seq_item:Nn \l_@@_class_loop_seq { \c_one } }
+ }
+ }
+ { \@@_redirect_loop_chk:onn \l_@@_class_tl {#2} {#3} }
+ }
}
- { \prop_put:cnn { l_msg_redirect_ #2 _prop } {#1} {#4} }
}
-\cs_generate_variant:Nn \msg_redirect_module_aux:nnnn { nnV }
+\cs_generate_variant:Nn \@@_redirect_loop_chk:nnn { o }
+\cs_new:Npn \@@_redirect_loop_list:n #1 { {#1} ~ => ~ }
% \end{macrocode}
% \end{macro}
% \end{macro}
-%
-% \begin{macro}{\msg_redirect_name:nnn}
-% Named message will always use the given class even if that class is
-% redirected further.
-% \begin{macrocode}
-\cs_new_protected:Npn \msg_redirect_name:nnn #1#2#3
- {
- \cs_if_exist:cTF { msg_ #3 :nnxxxx }
- { \prop_put:Nnn \l_msg_redirect_prop { #1 / #2 } {#3} }
- { \msg_kernel_error:nnx { msg } { message-class-unknown } {#3} }
- }
-% \end{macrocode}
% \end{macro}
%
% \subsection{Kernel-specific functions}
%
-% \begin{macro}{\msg_kernel_new:nnnn}
-% \begin{macro}{\msg_kernel_new:nnn}
-% \begin{macro}{\msg_kernel_set:nnnn}
-% \begin{macro}{\msg_kernel_set:nnn}
+% \begin{macro}{\@@_kernel_new:nnnn, \@@_kernel_new:nnn}
+% \begin{macro}{\@@_kernel_set:nnnn, \@@_kernel_set:nnn}
% The kernel needs some messages of its own. These are created using
% pre-built functions. Two functions are provided: one more general
% and one which only has the short text part.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_kernel_new:nnnn #1#2
+\cs_new_protected:Npn \@@_kernel_new:nnnn #1#2
{ \msg_new:nnnn { LaTeX } { #1 / #2 } }
-\cs_new_protected:Npn \msg_kernel_new:nnn #1#2
+\cs_new_protected:Npn \@@_kernel_new:nnn #1#2
{ \msg_new:nnn { LaTeX } { #1 / #2 } }
-\cs_new_protected:Npn \msg_kernel_set:nnnn #1#2
+\cs_new_protected:Npn \@@_kernel_set:nnnn #1#2
{ \msg_set:nnnn { LaTeX } { #1 / #2 } }
-\cs_new_protected:Npn \msg_kernel_set:nnn #1#2
+\cs_new_protected:Npn \@@_kernel_set:nnn #1#2
{ \msg_set:nnn { LaTeX } { #1 / #2 } }
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\msg_kernel_fatal:nnxxxx}
-% \begin{macro}{\msg_kernel_fatal:nnxxx}
-% \begin{macro}{\msg_kernel_fatal:nnxx}
-% \begin{macro}{\msg_kernel_fatal:nnx}
-% \begin{macro}{\msg_kernel_fatal:nn}
-% Fatal kernel errors cannot be re-defined.
+% \begin{macro}[aux]{\@@_kernel_class_new:nn}
+% \begin{macro}[aux]{\@@_kernel_class_new_aux:nn}
+% All the functions for kernel messages come in variants ranging
+% from~$0$ to~$4$ arguments. Those with less than~$4$ arguments are
+% defined in terms of the $4$-argument variant, in a way very similar
+% to \cs{msg_class_set:nn}. This auxiliary is destroyed at the end of
+% the group.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_kernel_fatal:nnxxxx #1#2#3#4#5#6
- {
- \msg_interrupt:xxx
- { \msg_fatal_text:n { LaTeX } : ~ "#1 / #2" }
- {
- \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
- {#3} {#4} {#5} {#6}
- \msg_see_documentation_text:n { LaTeX3 }
- }
- { \c_msg_fatal_text_tl }
- \tex_end:D
- }
-\cs_new_protected:Npn \msg_kernel_fatal:nnxxx #1#2#3#4#5
- {\msg_kernel_fatal:nnxxxx {#1} {#2} {#3} {#4} {#5} { } }
-\cs_new_protected:Npn \msg_kernel_fatal:nnxx #1#2#3#4
- { \msg_kernel_fatal:nnxxxx {#1} {#2} {#3} {#4} { } { } }
-\cs_new_protected:Npn \msg_kernel_fatal:nnx #1#2#3
- { \msg_kernel_fatal:nnxxxx {#1} {#2} {#3} { } { } { } }
-\cs_new_protected:Npn \msg_kernel_fatal:nn #1#2
- { \msg_kernel_fatal:nnxxxx {#1} {#2} { } { } { } { } }
+\group_begin:
+ \cs_set_protected:Npn \@@_kernel_class_new:nn #1
+ { \@@_kernel_class_new_aux:nn { kernel_ #1 } }
+ \cs_set_protected:Npn \@@_kernel_class_new_aux:nn #1#2
+ {
+ \cs_new_protected:cpn { @@_ #1 :nnnnnn } ##1##2 {#2}
+ \cs_new_protected:cpx { @@_ #1 :nnnnn } ##1##2##3##4##5
+ { \exp_not:c { @@_ #1 :nnnnnn } {##1} {##2} {##3} {##4} {##5} { } }
+ \cs_new_protected:cpx { @@_ #1 :nnnn } ##1##2##3##4
+ { \exp_not:c { @@_ #1 :nnnnnn } {##1} {##2} {##3} {##4} { } { } }
+ \cs_new_protected:cpx { @@_ #1 :nnn } ##1##2##3
+ { \exp_not:c { @@_ #1 :nnnnnn } {##1} {##2} {##3} { } { } { } }
+ \cs_new_protected:cpx { @@_ #1 :nn } ##1##2
+ { \exp_not:c { @@_ #1 :nnnnnn } {##1} {##2} { } { } { } { } }
+ \cs_new_protected:cpx { @@_ #1 :nnxxxx } ##1##2##3##4##5##6
+ {
+ \use:x
+ {
+ \exp_not:c { @@_ #1 :nnnnnn }
+ { \exp_not:N \exp_not:n {##1} }
+ { \exp_not:N \exp_not:n {##2} }
+ {##3} {##4} {##5} {##6}
+ }
+ }
+ \cs_new_protected:cpx { @@_ #1 :nnxxx } ##1##2##3##4##5
+ { \exp_not:c { @@_ #1 :nnxxxx } {##1} {##2} {##3} {##4} {##5} { } }
+ \cs_new_protected:cpx { @@_ #1 :nnxx } ##1##2##3##4
+ { \exp_not:c { @@_ #1 :nnxxxx } {##1} {##2} {##3} {##4} { } { } }
+ \cs_new_protected:cpx { @@_ #1 :nnx } ##1##2##3
+ { \exp_not:c { @@_ #1 :nnxxxx } {##1} {##2} {##3} { } { } { } }
+ }
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\msg_kernel_error:nnxxxx}
-% \begin{macro}{\msg_kernel_error:nnxxx}
-% \begin{macro}{\msg_kernel_error:nnxx}
-% \begin{macro}{\msg_kernel_error:nnx}
-% \begin{macro}{\msg_kernel_error:nn}
-% Neither can kernel errors.
+% \begin{macro}
+% {
+% \@@_kernel_fatal:nnnnnn ,
+% \@@_kernel_fatal:nnnnn ,
+% \@@_kernel_fatal:nnnn ,
+% \@@_kernel_fatal:nnn ,
+% \@@_kernel_fatal:nn ,
+% \@@_kernel_fatal:nnxxxx ,
+% \@@_kernel_fatal:nnxxx ,
+% \@@_kernel_fatal:nnxx ,
+% \@@_kernel_fatal:nnx ,
+% \@@_kernel_error:nnnnnn ,
+% \@@_kernel_error:nnnnn ,
+% \@@_kernel_error:nnnn ,
+% \@@_kernel_error:nnn ,
+% \@@_kernel_error:nn ,
+% \@@_kernel_error:nnxxxx ,
+% \@@_kernel_error:nnxxx ,
+% \@@_kernel_error:nnxx ,
+% \@@_kernel_error:nnx
+% }
+% Neither fatal kernel errors nor kernel errors can be redirected. We
+% directly use the code for (non-kernel) fatal errors and errors,
+% adding the \enquote{\LaTeX{}} module name. Three functions are
+% already defined by \pkg{l3basics}; we need to undefine them to avoid
+% errors.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_kernel_error:nnxxxx #1#2#3#4#5#6
- {
- \msg_if_more_text:cTF { \c_msg_more_text_prefix_tl LaTeX / #1 / #2 }
- {
- \msg_interrupt:xxx
- { \msg_error_text:n { LaTeX } : ~ " #1 / #2 " }
- {
- \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
- {#3} {#4} {#5} {#6}
- \msg_see_documentation_text:n { LaTeX3 }
- }
- {
- \use:c { \c_msg_more_text_prefix_tl LaTeX / #1 / #2 }
- {#3} {#4} {#5} {#6}
- }
- }
- {
- \msg_interrupt:xxx
- { \msg_error_text:n { LaTeX } : ~ " #1 / #2 " }
- {
- \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
- {#3} {#4} {#5} {#6}
- \msg_see_documentation_text:n { LaTeX3 }
- }
- { }
- }
- }
-\cs_new_protected:Npn \msg_kernel_error:nnxxx #1#2#3#4#5
- {\msg_kernel_error:nnxxxx {#1} {#2} {#3} {#4} {#5} { } }
-\cs_gset_protected:Npn \msg_kernel_error:nnxx #1#2#3#4
- { \msg_kernel_error:nnxxxx {#1} {#2} {#3} {#4} { } { } }
-\cs_gset_protected:Npn \msg_kernel_error:nnx #1#2#3
- { \msg_kernel_error:nnxxxx {#1} {#2} {#3} { } { } { } }
-\cs_gset_protected:Npn \msg_kernel_error:nn #1#2
- { \msg_kernel_error:nnxxxx {#1} {#2} { } { } { } { } }
+ \@@_kernel_class_new:nn { fatal }
+ { \@@_fatal_code:nnnnnn { LaTeX } { #1 / #2 } }
+ \cs_undefine:N \@@_kernel_error:nnxx
+ \cs_undefine:N \@@_kernel_error:nnx
+ \cs_undefine:N \@@_kernel_error:nn
+ \@@_kernel_class_new:nn { error }
+ { \@@_error_code:nnnnnn { LaTeX } { #1 / #2 } }
% \end{macrocode}
% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
%
-% \begin{macro}{\msg_kernel_warning:nnxxxx}
-% \begin{macro}{\msg_kernel_warning:nnxxx}
-% \begin{macro}{\msg_kernel_warning:nnxx}
-% \begin{macro}{\msg_kernel_warning:nnx}
-% \begin{macro}{\msg_kernel_warning:nn}
-% \begin{macro}{\msg_kernel_info:nnxxxx}
-% \begin{macro}{\msg_kernel_info:nnxxx}
-% \begin{macro}{\msg_kernel_info:nnxx}
-% \begin{macro}{\msg_kernel_info:nnx}
-% \begin{macro}{\msg_kernel_info:nn}
-% Kernel messages which can be redirected.
+% \begin{macro}
+% {
+% \@@_kernel_warning:nnnnnn ,
+% \@@_kernel_warning:nnnnn ,
+% \@@_kernel_warning:nnnn ,
+% \@@_kernel_warning:nnn ,
+% \@@_kernel_warning:nn ,
+% \@@_kernel_warning:nnxxxx ,
+% \@@_kernel_warning:nnxxx ,
+% \@@_kernel_warning:nnxx ,
+% \@@_kernel_warning:nnx ,
+% \@@_kernel_info:nnnnnn ,
+% \@@_kernel_info:nnnnn ,
+% \@@_kernel_info:nnnn ,
+% \@@_kernel_info:nnn ,
+% \@@_kernel_info:nn ,
+% \@@_kernel_info:nnxxxx ,
+% \@@_kernel_info:nnxxx ,
+% \@@_kernel_info:nnxx ,
+% \@@_kernel_info:nnx
+% }
+% Kernel messages which can be redirected simply use the machinery for
+% normal messages, with the module name \enquote{\LaTeX{}}.
% \begin{macrocode}
-\prop_new:N \l_msg_redirect_kernel_warning_prop
-\cs_new_protected:Npn \msg_kernel_warning:nnxxxx #1#2#3#4#5#6
- {
- \msg_use:nnnnxxxx { warning }
- {
- \msg_term:x
- {
- \msg_warning_text:n { LaTeX } : ~ " #1 / #2 " \\ \\
- \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
- {#3} {#4} {#5} {#6}
- }
- }
- { LaTeX } { #1 / #2 } {#3} {#4} {#5} {#6}
- }
-\cs_new_protected:Npn \msg_kernel_warning:nnxxx #1#2#3#4#5
- { \msg_kernel_warning:nnxxxx {#1} {#2} {#3} {#4} {#5} { } }
-\cs_new_protected:Npn \msg_kernel_warning:nnxx #1#2#3#4
- { \msg_kernel_warning:nnxxxx {#1} {#2} {#3} {#4} { } { } }
-\cs_new_protected:Npn \msg_kernel_warning:nnx #1#2#3
- { \msg_kernel_warning:nnxxxx {#1} {#2} {#3} { } { } { } }
-\cs_new_protected:Npn \msg_kernel_warning:nn #1#2
- { \msg_kernel_warning:nnxxxx {#1} {#2} { } { } { } { } }
-\prop_new:N \l_msg_redirect_kernel_info_prop
-\cs_new_protected:Npn \msg_kernel_info:nnxxxx #1#2#3#4#5#6
- {
- \msg_use:nnnnxxxx { info }
- {
- \msg_log:x
- {
- \msg_info_text:n { LaTeX } : ~ " #1 / #2 " \\ \\
- \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
- {#3} {#4} {#5} {#6}
- }
- }
- { LaTeX } { #1 / #2 } {#3} {#4} {#5} {#6}
- }
-\cs_new_protected:Npn \msg_kernel_info:nnxxx #1#2#3#4#5
- { \msg_kernel_info:nnxxxx {#1} {#2} {#3} {#4} {#5} { } }
-\cs_new_protected:Npn \msg_kernel_info:nnxx #1#2#3#4
- { \msg_kernel_info:nnxxxx {#1} {#2} {#3} {#4} { } { } }
-\cs_new_protected:Npn \msg_kernel_info:nnx #1#2#3
- { \msg_kernel_info:nnxxxx {#1} {#2} {#3} { } { } { } }
-\cs_new_protected:Npn \msg_kernel_info:nn #1#2
- { \msg_kernel_info:nnxxxx {#1} {#2} { } { } { } { } }
+ \@@_kernel_class_new:nn { warning }
+ { \msg_warning:nnxxxx { LaTeX } { #1 / #2 } }
+ \@@_kernel_class_new:nn { info }
+ { \msg_info:nnxxxx { LaTeX } { #1 / #2 } }
% \end{macrocode}
% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+%
+% End the group to eliminate \cs{@@_kernel_class_new:nn}.
+% \begin{macrocode}
+\group_end:
+% \end{macrocode}
%
% Error messages needed to actually implement the message system
% itself.
% \begin{macrocode}
-\msg_kernel_new:nnnn { msg } { message-already-defined }
+\@@_kernel_new:nnnn { kernel } { message-already-defined }
{ Message~'#2'~for~module~'#1'~already~defined. }
{
\c_msg_coding_error_text_tl
@@ -1657,41 +1735,45 @@
by~the~module~'#1':~this~message~already~exists.
\c_msg_return_text_tl
}
-\msg_kernel_new:nnnn { msg } { message-unknown }
+\@@_kernel_new:nnnn { kernel } { message-unknown }
{ Unknown~message~'#2'~for~module~'#1'. }
{
\c_msg_coding_error_text_tl
LaTeX~was~asked~to~display~a~message~called~'#2'\\
- by~the~module~'#1'~module:~this~message~does~not~exist.
+ by~the~module~'#1':~this~message~does~not~exist.
\c_msg_return_text_tl
}
-\msg_kernel_new:nnnn { msg } { message-class-unknown }
+\@@_kernel_new:nnnn { kernel } { message-class-unknown }
{ Unknown~message~class~'#1'. }
{
LaTeX~has~been~asked~to~redirect~messages~to~a~class~'#1':\\
this~was~never~defined.
\c_msg_return_text_tl
}
-\msg_kernel_new:nnnn { msg } { redirect-loop }
- { Message~redirection~loop~for~message~class~'#1'. }
+\@@_kernel_new:nnnn { kernel } { message-redirect-loop }
+ {
+ Message~redirection~loop~caused~by~ {#1} ~=>~ {#2}
+ \tl_if_empty:nF {#3} { ~for~module~' \use_none:n #3 ' } .
+ }
{
- LaTeX~has~been~asked~to~redirect~messages~in~an~infinite~loop.\\
- The~original~message~here~has~been~lost.
- \c_msg_return_text_tl
+ Adding~the~message~redirection~ {#1} ~=>~ {#2}
+ \tl_if_empty:nF {#3} { ~for~the~module~' \use_none:n #3 ' } ~
+ created~an~infinite~loop\\\\
+ \iow_indent:n { #4 \\\\ }
}
% \end{macrocode}
%
% Messages for earlier kernel modules.
% \begin{macrocode}
-\msg_kernel_new:nnnn { kernel } { bad-number-of-arguments }
+\@@_kernel_new:nnnn { kernel } { bad-number-of-arguments }
{ Function~'#1'~cannot~be~defined~with~#2~arguments. }
{
\c_msg_coding_error_text_tl
LaTeX~has~been~asked~to~define~a~function~'#1'~with~
- #2~arguments. \\
+ #2~arguments.~
TeX~allows~between~0~and~9~arguments~for~a~single~function.
}
-\msg_kernel_new:nnnn { kernel } { command-already-defined }
+\@@_kernel_new:nnnn { kernel } { command-already-defined }
{ Control~sequence~#1~already~defined. }
{
\c_msg_coding_error_text_tl
@@ -1700,102 +1782,123 @@
The~current~meaning~is:\\
\ \ #2
}
-\msg_kernel_new:nnnn { kernel } { command-not-defined }
+\@@_kernel_new:nnnn { kernel } { command-not-defined }
{ Control~sequence~#1~undefined. }
{
\c_msg_coding_error_text_tl
LaTeX~has~been~asked~to~use~a~command~#1,~but~this~has~not~
been~defined~yet.
}
-\msg_kernel_new:nnnn { kernel } { out-of-registers }
+\@@_kernel_new:nnnn { kernel } { empty-search-pattern }
+ { Empty~search~pattern. }
+ {
+ \c_msg_coding_error_text_tl
+ LaTeX~has~been~asked~to~replace~an~empty~pattern~by~'#1':~that~
+ would~lead~to~an~infinite~loop!
+ }
+\@@_kernel_new:nnnn { kernel } { out-of-registers }
{ No~room~for~a~new~#1. }
{
TeX~only~supports~\int_use:N \c_max_register_int \
of~each~type.~All~the~#1~registers~have~been~used.~
This~run~will~be~aborted~now.
}
-\msg_kernel_new:nnnn { kernel } { variable-not-defined }
- { Variable~#1~undefined. }
+\@@_kernel_new:nnnn { kernel } { missing-colon }
+ { Function~'#1'~contains~no~':'. }
{
\c_msg_coding_error_text_tl
- LaTeX~has~been~asked~to~show~a~variable~#1,~but~this~has~not~
- been~defined~yet.
+ Code-level~functions~must~contain~':'~to~separate~the~
+ argument~specification~from~the~function~name.~This~is~
+ needed~when~defining~conditionals~or~when~building~a~
+ parameter~text~from~the~number~of~arguments~of~the~function.
}
-\msg_kernel_new:nnnn { seq } { empty-sequence }
- { Empty~sequence~#1. }
+\@@_kernel_new:nnnn { kernel } { protected-predicate }
+ { Predicate~'#1'~must~be~expandable. }
{
\c_msg_coding_error_text_tl
- LaTeX~has~been~asked~to~recover~an~entry~from~a~sequence~that~
- has~no~content:~that~cannot~happen!
+ LaTeX~has~been~asked~to~define~'#1'~as~a~protected~predicate.~
+ Only~expandable~tests~can~have~a~predicate~version.
}
-\msg_kernel_new:nnnn { tl } { empty-search-pattern }
- { Empty~search~pattern. }
+\@@_kernel_new:nnnn { kernel } { conditional-form-unknown }
+ { Conditional~form~'#1'~for~function~'#2'~unknown. }
{
\c_msg_coding_error_text_tl
- LaTeX~has~been~asked~to~replace~an~empty~pattern~by~'#1':~that~%
- would~lead~to~an~infinite~loop!
+ LaTeX~has~been~asked~to~define~the~conditional~form~'#1'~of~
+ the~function~'#2',~but~only~'TF',~'T',~'F',~and~'p'~forms~exist.
}
-\msg_kernel_new:nnnn { scan } { already-defined }
+\@@_kernel_new:nnnn { kernel } { scanmark-already-defined }
{ Scan~mark~#1~already~defined. }
{
\c_msg_coding_error_text_tl
LaTeX~has~been~asked~to~create~a~new~scan~mark~'#1'~
but~this~name~has~already~been~used~for~a~scan~mark.
}
+\@@_kernel_new:nnnn { kernel } { variable-not-defined }
+ { Variable~#1~undefined. }
+ {
+ \c_msg_coding_error_text_tl
+ LaTeX~has~been~asked~to~show~a~variable~#1,~but~this~has~not~
+ been~defined~yet.
+ }
+\@@_kernel_new:nnnn { kernel } { variant-too-long }
+ { Variant~form~'#1'~longer~than~base~signature~of~'#2'. }
+ {
+ \c_msg_coding_error_text_tl
+ LaTeX~has~been~asked~to~create~a~variant~of~the~function~'#2'~
+ with~a~signature~starting~with~'#1',~but~that~is~longer~than~
+ the~signature~(part~after~the~colon)~of~'#2'.
+ }
% \end{macrocode}
%
% Some errors only appear in expandable settings,
% hence don't need a \enquote{more-text} argument.
% \begin{macrocode}
-\msg_kernel_new:nnn { seq } { misused }
- { A~sequence~was~misused. }
-\msg_kernel_new:nnn { kernel } { bad-var }
+\@@_kernel_new:nnn { kernel } { bad-variable }
{ Erroneous~variable~#1 used! }
-\msg_kernel_new:nnn { prg } { zero-step }
- { Zero~step~size~for~stepwise~function~#1. }
-\msg_kernel_new:nnn { prg } { replicate-neg }
+\@@_kernel_new:nnn { kernel } { misused-sequence }
+ { A~sequence~was~misused. }
+\@@_kernel_new:nnn { kernel } { negative-replication }
{ Negative~argument~for~\prg_replicate:nn. }
-\msg_kernel_new:nnn { kernel } { unknown-comparison }
+\@@_kernel_new:nnn { kernel } { unknown-comparison }
{ Relation~symbol~'#1'~unknown:~use~=,~<,~>,~==,~!=,~<=,~>=. }
+\@@_kernel_new:nnn { kernel } { zero-step }
+ { Zero~step~size~for~step~function~#1. }
% \end{macrocode}
%
% Messages used by the \enquote{\texttt{show}} functions.
% \begin{macrocode}
-\msg_kernel_new:nnn { seq } { show }
+\@@_kernel_new:nnn { kernel } { show-clist }
{
- The~sequence~\token_to_str:N #1~
- \seq_if_empty:NTF #1
+ The~comma~list~
+ \str_if_eq:nnF {#1} { \l__clist_internal_clist } { \token_to_str:N #1~}
+ \clist_if_empty:NTF #1
{ is~empty }
{ contains~the~items~(without~outer~braces): }
}
-\msg_kernel_new:nnn { prop } { show }
+\@@_kernel_new:nnn { kernel } { show-prop }
{
The~property~list~\token_to_str:N #1~
\prop_if_empty:NTF #1
{ is~empty }
{ contains~the~pairs~(without~outer~braces): }
}
-\msg_kernel_new:nnn { clist } { show }
+\@@_kernel_new:nnn { kernel } { show-seq }
{
- The~comma~list~
- \str_if_eq:nnF {#1} { \l_clist_internal_clist } { \token_to_str:N #1~}
- \clist_if_empty:NTF #1
+ The~sequence~\token_to_str:N #1~
+ \seq_if_empty:NTF #1
{ is~empty }
{ contains~the~items~(without~outer~braces): }
}
-\msg_kernel_new:nnn { ior } { show-no-stream }
- { No~input~streams~are~open }
-\msg_kernel_new:nnn { ior } { show-open-streams }
- { The~following~input~streams~are~in~use: }
-\msg_kernel_new:nnn { iow } { show-no-stream }
- { No~output~streams~are~open }
-\msg_kernel_new:nnn { iow } { show-open-streams }
- { The~following~output~streams~are~in~use: }
+\@@_kernel_new:nnn { kernel } { show-no-stream }
+ { No~ #1 ~streams~are~open }
+\@@_kernel_new:nnn { kernel } { show-open-streams }
+ { The~following~ #1 ~streams~are~in~use: }
% \end{macrocode}
%
% \subsection{Expandable errors}
%
-% \begin{macro}[int]{\msg_expandable_error:n}
+% \begin{macro}[int]{\@@_expandable_error:n}
+% \begin{macro}[aux]{\@@_expandable_error:w}
% In expansion only context, we cannot use the normal means of
% reporting errors. Instead, we feed \TeX{} an undefined control
% sequence, \cs{LaTeX3 error:}. It is thus interrupted, and shows
@@ -1806,7 +1909,7 @@
% \end{verbatim}
% In other words, \TeX{} is processing the argument of \cs{use:n},
% which is \cs{LaTeX3 error:} \meta{error message}.
-% Then \cs{msg_expandable_error_aux:w} cleans up. In fact, there
+% Then \cs{@@_expandable_error:w} cleans up. In fact, there
% is an extra subtlety: if the user inserts tokens for error recovery,
% they should be kept. Thus we also use an odd space character
% (with category code $7$) and keep tokens until that space character,
@@ -1816,70 +1919,71 @@
% \begin{macrocode}
\group_begin:
\char_set_catcode_math_superscript:N \^
-\char_set_lccode:nn {`^} {`\ }
-\char_set_lccode:nn {`L} {`L}
-\char_set_lccode:nn {`T} {`T}
-\char_set_lccode:nn {`X} {`X}
+\char_set_lccode:nn { `^ } { `\ }
+\char_set_lccode:nn { `L } { `L }
+\char_set_lccode:nn { `T } { `T }
+\char_set_lccode:nn { `X } { `X }
\tl_to_lowercase:n
{
- \cs_new:Npx \msg_expandable_error:n #1
+ \cs_new:Npx \@@_expandable_error:n #1
{
\exp_not:n
{
\tex_romannumeral:D
\exp_after:wN \exp_after:wN
- \exp_after:wN \msg_expandable_error_aux:w
+ \exp_after:wN \@@_expandable_error:w
\exp_after:wN \exp_after:wN
\exp_after:wN \c_zero
}
\exp_not:N \use:n { \exp_not:c { LaTeX3~error: } ^ #1 } ^
}
- \cs_new:Npn \msg_expandable_error_aux:w #1 ^ #2 ^ { #1 }
+ \cs_new:Npn \@@_expandable_error:w #1 ^ #2 ^ { #1 }
}
\group_end:
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}
% {
-% \msg_expandable_kernel_error:nnnnnn,
-% \msg_expandable_kernel_error:nnnnn,
-% \msg_expandable_kernel_error:nnnn,
-% \msg_expandable_kernel_error:nnn,
-% \msg_expandable_kernel_error:nn
+% \@@_kernel_expandable_error:nnnnnn,
+% \@@_kernel_expandable_error:nnnnn,
+% \@@_kernel_expandable_error:nnnn,
+% \@@_kernel_expandable_error:nnn,
+% \@@_kernel_expandable_error:nn
% }
% The command built from the csname
-% |\c_msg_text_prefix_tl LaTeX / #1 / #2|
+% |\c_@@_text_prefix_tl LaTeX / #1 / #2|
% takes four arguments and builds the error text, which is fed to
-% \cs{msg_expandable_error:n}.
+% \cs{@@_expandable_error:n}.
% \begin{macrocode}
-\cs_new:Npn \msg_expandable_kernel_error:nnnnnn #1#2#3#4#5#6
+\cs_new:Npn \@@_kernel_expandable_error:nnnnnn #1#2#3#4#5#6
{
- \exp_args:Nf \msg_expandable_error:n
+ \exp_args:Nf \@@_expandable_error:n
{
\exp_args:NNc \exp_after:wN \exp_stop_f:
- { \c_msg_text_prefix_tl LaTeX / #1 / #2 }
+ { \c_@@_text_prefix_tl LaTeX / #1 / #2 }
{#3} {#4} {#5} {#6}
}
}
-\cs_new:Npn \msg_expandable_kernel_error:nnnnn #1#2#3#4#5
+\cs_new:Npn \@@_kernel_expandable_error:nnnnn #1#2#3#4#5
{
- \msg_expandable_kernel_error:nnnnnn
+ \@@_kernel_expandable_error:nnnnnn
{#1} {#2} {#3} {#4} {#5} { }
}
-\cs_new:Npn \msg_expandable_kernel_error:nnnn #1#2#3#4
+\cs_new:Npn \@@_kernel_expandable_error:nnnn #1#2#3#4
{
- \msg_expandable_kernel_error:nnnnnn
+ \@@_kernel_expandable_error:nnnnnn
{#1} {#2} {#3} {#4} { } { }
}
-\cs_new:Npn \msg_expandable_kernel_error:nnn #1#2#3
+\cs_new:Npn \@@_kernel_expandable_error:nnn #1#2#3
{
- \msg_expandable_kernel_error:nnnnnn
+ \@@_kernel_expandable_error:nnnnnn
{#1} {#2} {#3} { } { } { }
}
-\cs_new:Npn \msg_expandable_kernel_error:nn #1#2
+\cs_new:Npn \@@_kernel_expandable_error:nn #1#2
{
- \msg_expandable_kernel_error:nnnnnn
+ \@@_kernel_expandable_error:nnnnnn
{#1} {#2} { } { } { } { }
}
% \end{macrocode}
@@ -1888,93 +1992,103 @@
% \subsection{Showing variables}
%
% Functions defined in this section are used for diagnostic functions
-% in \pkg{l3clist}, \pkg{l3io}, \pkg{l3prop}, \pkg{l3seq}, \pkg{xtemplate}
-%
-% \begin{macro}[aux]{\msg_aux_use:nn}
-% \begin{macro}[aux]{\msg_aux_use:nnxxxx}
-% Print the text of a message to the terminal, without formatting.
+% in \pkg{l3clist}, \pkg{l3file}, \pkg{l3prop}, \pkg{l3seq}, \pkg{xtemplate}
+%
+% \begin{macro}[int]
+% {\@@_term:nnnnnn, \@@_term:nnnnnV}
+% \begin{macro}[int]{\@@_term:nnnnn}
+% \begin{macro}[int]{\@@_term:nnn}
+% \begin{macro}[int]{\@@_term:nn}
+% Print the text of a message to the terminal without formatting:
+% short cuts around \cs{iow_wrap:nnnN}.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_aux_use:nn #1#2
- { \msg_aux_use:nnxxxx {#1} {#2} { } { } { } { } }
-\cs_new_protected:Npn \msg_aux_use:nnxxxx #1#2#3#4#5#6
- {
- \iow_wrap:xnnnN
- {
- \use:c { \c_msg_text_prefix_tl #1 / #2 }
- {#3} {#4} {#5} {#6}
- }
- { } \c_zero { } \iow_term:x
- }
+\cs_new_protected:Npn \@@_term:nnnnnn #1#2#3#4#5#6
+ {
+ \iow_wrap:nnnN
+ { \use:c { \c_@@_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} }
+ { } { } \iow_term:n
+ }
+\cs_generate_variant:Nn \@@_term:nnnnnn { nnnnnV }
+\cs_new_protected:Npn \@@_term:nnnnn #1#2#3#4#5
+ { \@@_term:nnnnnn {#1} {#2} {#3} {#4} {#5} { } }
+\cs_new_protected:Npn \@@_term:nnn #1#2#3
+ { \@@_term:nnnnnn {#1} {#2} {#3} { } { } { } }
+\cs_new_protected:Npn \@@_term:nn #1#2
+ { \@@_term:nnnnnn {#1} {#2} { } { } { } { } }
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
+% \end{macro}
%
-% \begin{macro}[int]{\msg_aux_show:Nnx}
-% \begin{macro}[aux]{\msg_aux_show:x}
-% \begin{macro}[aux,EXP]{\msg_aux_show:w}
-% The arguments of \cs{msg_aux_show:Nnx} are
+% \begin{macro}[int]{\@@_show_variable:Nnn, \@@_show_variable:Nnn}
+% \begin{macro}[int]{\@@_show_variable:n, \@@_show_variable:x}
+% \begin{macro}[aux,EXP]{\@@_show_variable:w}
+% The arguments of \cs{@@_show_variable:Nnn} are
% \begin{itemize}
-% \item The \meta{variable} to be shown.
-% \item The \texttt{TF} emptyness conditional for that type of variables.
-% \item The type of the variable.
-% \item A mapping of the form \cs{seq_map_function:NN} \meta{variable}
-% \cs{msg_aux_show:n}, which produces the formatted string.
+% \item The \meta{variable} to be shown.
+% \item The \texttt{TF} emptiness conditional for that type of variables.
+% \item The type of the variable.
+% \item A mapping of the form \cs{seq_map_function:NN} \meta{variable}
+% \cs{@@_show_item:n}, which produces the formatted string.
% \end{itemize}
% We remove a new line and \verb*|> | from the first item using
% a \texttt{w}-type auxiliary, and the fact that \texttt{f}-expansion
% removes a space. To avoid a low-level \TeX{} error if there is
% an empty argument, a simple test is used to keep the output
-% \enquote{clean}. The odd \cs{exp_after:wN} and trailing
-% \cs{prg_do_nothing:} improve the output slightly.
+% \enquote{clean}. The odd \cs{exp_after:wN} which expands the closing
+% brace improves the output slightly.
% \begin{macrocode}
-\cs_new_protected:Npn \msg_aux_show:Nnx #1#2#3
+\cs_new_protected:Npn \@@_show_variable:Nnn #1#2#3
{
\cs_if_exist:NTF #1
{
- \msg_aux_use:nnxxxx { LaTeX / #2 } { show } {#1} { } { } { }
- \msg_aux_show:x {#3}
+ \@@_term:nnn { LaTeX / kernel } { show- #2 } {#1}
+ \@@_show_variable:x {#3}
}
{
- \msg_kernel_error:nnx { kernel } { variable-not-defined }
+ \@@_kernel_error:nnx { kernel } { variable-not-defined }
{ \token_to_str:N #1 }
}
}
-\cs_new_protected:Npn \msg_aux_show:x #1
+\cs_generate_variant:Nn \@@_show_variable:Nnn { Nnx }
+\cs_new_protected:Npn \@@_show_variable:n #1
{
- \tl_set:Nx \l_msg_internal_tl {#1}
- \tl_if_empty:NT \l_msg_internal_tl
- { \tl_set:Nx \l_msg_internal_tl { > } }
- \exp_args:Nf \etex_showtokens:D
+ \tl_set:Nn \l_@@_internal_tl {#1}
+ \tl_if_empty:NTF \l_@@_internal_tl
+ { \etex_showtokens:D \exp_after:wN { } }
{
- \exp_after:wN \exp_after:wN
- \exp_after:wN \msg_aux_show:w
- \exp_after:wN \l_msg_internal_tl
- \exp_after:wN
+ \exp_args:Nf \etex_showtokens:D
+ {
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_show_variable:w
+ \exp_after:wN \l_@@_internal_tl
+ }
}
- \prg_do_nothing:
}
-\cs_new:Npn \msg_aux_show:w #1 > { }
+\cs_generate_variant:Nn \@@_show_variable:n { x }
+\cs_new:Npn \@@_show_variable:w #1 > { }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux,EXP]{\msg_aux_show:n}
-% \begin{macro}[aux,EXP]{\msg_aux_show:nn}
-% \begin{macro}[aux,EXP]{\msg_aux_show_unbraced:nn}
+% \begin{macro}[int,EXP]{\@@_show_item:n}
+% \begin{macro}[int,EXP]{\@@_show_item:nn}
+% \begin{macro}[int,EXP]{\@@_show_item_unbraced:nn}
% Each item in the variable is formatted using one of
% the following functions.
% \begin{macrocode}
-\cs_new:Npn \msg_aux_show:n #1
+\cs_new:Npn \@@_show_item:n #1
{
\iow_newline: > \c_space_tl \c_space_tl { \exp_not:n {#1} }
}
-\cs_new:Npn \msg_aux_show:nn #1#2
+\cs_new:Npn \@@_show_item:nn #1#2
{
\iow_newline: > \c_space_tl \c_space_tl { \exp_not:n {#1} }
\c_space_tl \c_space_tl => \c_space_tl \c_space_tl { \exp_not:n {#2} }
}
-\cs_new:Npn \msg_aux_show_unbraced:nn #1#2
+\cs_new:Npn \@@_show_item_unbraced:nn #1#2
{
\iow_newline: > \c_space_tl \c_space_tl \exp_not:n {#1}
\c_space_tl \c_space_tl => \c_space_tl \c_space_tl \exp_not:n {#2}
@@ -2042,22 +2156,22 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\msg_kernel_bug:x}
-% \begin{variable}{\c_msg_kernel_bug_text_tl, \c_msg_kernel_bug_more_text_tl}
+% \begin{macro}{\@@_kernel_bug:x}
+% \begin{variable}{\c_@@_kernel_bug_text_tl, \c_@@_kernel_bug_more_text_tl}
% \begin{macrocode}
%<*deprecated>
-\cs_set_protected:Npn \msg_kernel_bug:x #1
+\cs_set_protected:Npn \@@_kernel_bug:x #1
{
- \msg_interrupt:xxx { \c_msg_kernel_bug_text_tl }
+ \msg_interrupt:nnn { \c_@@_kernel_bug_text_tl }
{
#1
\msg_see_documentation_text:n { LaTeX3 }
}
- { \c_msg_kernel_bug_more_text_tl }
+ { \c_@@_kernel_bug_more_text_tl }
}
-\tl_const:Nn \c_msg_kernel_bug_text_tl
+\tl_const:Nn \c_@@_kernel_bug_text_tl
{ This~is~a~LaTeX~bug:~check~coding! }
-\tl_const:Nn \c_msg_kernel_bug_more_text_tl
+\tl_const:Nn \c_@@_kernel_bug_more_text_tl
{
There~is~a~coding~bug~somewhere~around~here. \\
This~probably~needs~examining~by~an~expert.
@@ -2067,6 +2181,55 @@
% \end{macrocode}
% \end{variable}
% \end{macro}
+%
+% Deprecated on 2012-06-28, for removal by 2012-12-31.
+%
+% \begin{macro}{\msg_newline:, \msg_two_newlines:}
+% New lines are printed in the same way as for low-level file writing.
+% \begin{macrocode}
+\cs_new_nopar:Npn \msg_newline: { ^^J }
+\cs_new_nopar:Npn \msg_two_newlines: { ^^J ^^J }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\msg_log:x, \msg_term:x}
+% \begin{macro}{\msg_interrupt:xxx}
+% These were all misnamed.
+% \begin{macrocode}
+\cs_generate_variant:Nn \msg_log:n { x }
+\cs_generate_variant:Nn \msg_term:n { x }
+\cs_generate_variant:Nn \msg_interrupt:nnn { xxx }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% Deprecated on 2012-06-29, for removal by 2012-12-31.
+%
+% \begin{macro}{\msg_class_set:nn}
+% Setting up a message class does two tasks. Any existing redirection
+% is cleared, and the various message functions are created
+% to simply use the code stored for the message.
+% \begin{macrocode}
+\cs_new_protected:Npn \msg_class_set:nn #1#2
+ {
+ \cs_if_exist:cTF { @@_ #1 _code:nnnnnn }
+ \cs_set_protected:cpn
+ \cs_new_protected:cpn
+ { @@_ #1 _code:nnnnnn } ##1##2##3##4##5##6 {#2}
+ \prop_clear_new:c { l_@@_redirect_ #1 _prop }
+ \cs_set_protected_nopar:cpn { msg_ #1 :nnxxxx }
+ { \@@_use:nnnnnnn {#1} }
+ \cs_set_protected:cpx { msg_ #1 :nnxxx } ##1##2##3##4##5
+ { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} {##5} { } }
+ \cs_set_protected:cpx { msg_ #1 :nnxx } ##1##2##3##4
+ { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} { } { } }
+ \cs_set_protected:cpx { msg_ #1 :nnx } ##1##2##3
+ { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} { } { } { } }
+ \cs_set_protected:cpx { msg_ #1 :nn } ##1##2
+ { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} { } { } { } { } }
+ }
+% \end{macrocode}
+% \end{macro}
%
% \begin{macrocode}
%</initex|package>
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
index 13d403f4633..a77f3103063 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3names.dtx Copyright (C) 1990-2011 The LaTeX3 project
+%% File: l3names.dtx Copyright (C) 1990-2012 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
@@ -34,9 +34,9 @@
%% -----------------------------------------------------------------------
%
%<*package>
-\RequirePackage{l3bootstrap}[2011-12-29]
-\GetIdInfo$Id: l3names.dtx 3494 2012-03-04 09:58:29Z joseph $
- {L3 Experimental namespace for primitives}
+\RequirePackage{l3bootstrap}[2012/07/15]
+\GetIdInfo$Id: l3names.dtx 3990 2012-07-16 07:46:03Z joseph $
+ {L3 Namespace for primitives}
%</package>
%<*driver>
\documentclass[full]{l3doc}
@@ -73,7 +73,7 @@
% performs the following tasks:
% \begin{itemize}
% \item defines new names for all \TeX{} primitives;
-% \item switches to the category code regime for programming;
+% \item switches to the category code r{\'e}gime for programming;
% \item provides support settings for building the code as a \TeX{} format.
% \end{itemize}
%
@@ -111,12 +111,12 @@
%
% The code here simply renames all of the primitives to new, internal,
% names. In format mode, it also deletes all of the existing names (although
-% some od come back later).
+% some do come back later).
%
% \begin{macro}{\tex_undefined:D}
-% This function does not exist at all, but is the name used by the
-% plain \TeX{} format for an undefined function. So it should
-% be marked here as \enquote{taken}.
+% This function does not exist at all, but is the name used by the
+% plain \TeX{} format for an undefined function. So it should
+% be marked here as \enquote{taken}.
% \end{macro}
%
% The \tn{let} primitive is renamed by hand first as it is essential for
@@ -127,17 +127,17 @@
\let \tex_let:D \let
% \end{macrocode}
%
-% Everything is inside a (rather long) group, which kees \cs{name_primitve:NN}
-% trapped.
+% Everything is inside a (rather long) group, which keeps
+% \cs{__expl_primitive:NN} trapped.
% \begin{macrocode}
\begingroup
% \end{macrocode}
%
-% \begin{macro}[aux]{\name_primitive:NN}
+% \begin{macro}[aux]{\__expl_primitive:NN}
% A temporary function to actually do the renaming. This also allows the
% original names to be removed in format mode.
% \begin{macrocode}
- \long \def \name_primitive:NN #1#2
+ \long \def \__expl_primitive:NN #1#2
{
\tex_global:D \tex_let:D #2 #1
%<*initex>
@@ -153,406 +153,406 @@
% These are given modified new names, so that they may be entered
% without catcode tricks.
% \begin{macrocode}
- \name_primitive:NN \ \tex_space:D
- \name_primitive:NN \/ \tex_italiccor:D
- \name_primitive:NN \- \tex_hyphen:D
+ \__expl_primitive:NN \ \tex_space:D
+ \__expl_primitive:NN \/ \tex_italiccorrection:D
+ \__expl_primitive:NN \- \tex_hyphen:D
% \end{macrocode}
%
% Now all the other primitives.
% \begin{macrocode}
- \name_primitive:NN \let \tex_let:D
- \name_primitive:NN \def \tex_def:D
- \name_primitive:NN \edef \tex_edef:D
- \name_primitive:NN \gdef \tex_gdef:D
- \name_primitive:NN \xdef \tex_xdef:D
- \name_primitive:NN \chardef \tex_chardef:D
- \name_primitive:NN \countdef \tex_countdef:D
- \name_primitive:NN \dimendef \tex_dimendef:D
- \name_primitive:NN \skipdef \tex_skipdef:D
- \name_primitive:NN \muskipdef \tex_muskipdef:D
- \name_primitive:NN \mathchardef \tex_mathchardef:D
- \name_primitive:NN \toksdef \tex_toksdef:D
- \name_primitive:NN \futurelet \tex_futurelet:D
- \name_primitive:NN \advance \tex_advance:D
- \name_primitive:NN \divide \tex_divide:D
- \name_primitive:NN \multiply \tex_multiply:D
- \name_primitive:NN \font \tex_font:D
- \name_primitive:NN \fam \tex_fam:D
- \name_primitive:NN \global \tex_global:D
- \name_primitive:NN \long \tex_long:D
- \name_primitive:NN \outer \tex_outer:D
- \name_primitive:NN \setlanguage \tex_setlanguage:D
- \name_primitive:NN \globaldefs \tex_globaldefs:D
- \name_primitive:NN \afterassignment \tex_afterassignment:D
- \name_primitive:NN \aftergroup \tex_aftergroup:D
- \name_primitive:NN \expandafter \tex_expandafter:D
- \name_primitive:NN \noexpand \tex_noexpand:D
- \name_primitive:NN \begingroup \tex_begingroup:D
- \name_primitive:NN \endgroup \tex_endgroup:D
- \name_primitive:NN \halign \tex_halign:D
- \name_primitive:NN \valign \tex_valign:D
- \name_primitive:NN \cr \tex_cr:D
- \name_primitive:NN \crcr \tex_crcr:D
- \name_primitive:NN \noalign \tex_noalign:D
- \name_primitive:NN \omit \tex_omit:D
- \name_primitive:NN \span \tex_span:D
- \name_primitive:NN \tabskip \tex_tabskip:D
- \name_primitive:NN \everycr \tex_everycr:D
- \name_primitive:NN \if \tex_if:D
- \name_primitive:NN \ifcase \tex_ifcase:D
- \name_primitive:NN \ifcat \tex_ifcat:D
- \name_primitive:NN \ifnum \tex_ifnum:D
- \name_primitive:NN \ifodd \tex_ifodd:D
- \name_primitive:NN \ifdim \tex_ifdim:D
- \name_primitive:NN \ifeof \tex_ifeof:D
- \name_primitive:NN \ifhbox \tex_ifhbox:D
- \name_primitive:NN \ifvbox \tex_ifvbox:D
- \name_primitive:NN \ifvoid \tex_ifvoid:D
- \name_primitive:NN \ifx \tex_ifx:D
- \name_primitive:NN \iffalse \tex_iffalse:D
- \name_primitive:NN \iftrue \tex_iftrue:D
- \name_primitive:NN \ifhmode \tex_ifhmode:D
- \name_primitive:NN \ifmmode \tex_ifmmode:D
- \name_primitive:NN \ifvmode \tex_ifvmode:D
- \name_primitive:NN \ifinner \tex_ifinner:D
- \name_primitive:NN \else \tex_else:D
- \name_primitive:NN \fi \tex_fi:D
- \name_primitive:NN \or \tex_or:D
- \name_primitive:NN \immediate \tex_immediate:D
- \name_primitive:NN \closeout \tex_closeout:D
- \name_primitive:NN \openin \tex_openin:D
- \name_primitive:NN \openout \tex_openout:D
- \name_primitive:NN \read \tex_read:D
- \name_primitive:NN \write \tex_write:D
- \name_primitive:NN \closein \tex_closein:D
- \name_primitive:NN \newlinechar \tex_newlinechar:D
- \name_primitive:NN \input \tex_input:D
- \name_primitive:NN \endinput \tex_endinput:D
- \name_primitive:NN \inputlineno \tex_inputlineno:D
- \name_primitive:NN \errmessage \tex_errmessage:D
- \name_primitive:NN \message \tex_message:D
- \name_primitive:NN \show \tex_show:D
- \name_primitive:NN \showthe \tex_showthe:D
- \name_primitive:NN \showbox \tex_showbox:D
- \name_primitive:NN \showlists \tex_showlists:D
- \name_primitive:NN \errhelp \tex_errhelp:D
- \name_primitive:NN \errorcontextlines \tex_errorcontextlines:D
- \name_primitive:NN \tracingcommands \tex_tracingcommands:D
- \name_primitive:NN \tracinglostchars \tex_tracinglostchars:D
- \name_primitive:NN \tracingmacros \tex_tracingmacros:D
- \name_primitive:NN \tracingonline \tex_tracingonline:D
- \name_primitive:NN \tracingoutput \tex_tracingoutput:D
- \name_primitive:NN \tracingpages \tex_tracingpages:D
- \name_primitive:NN \tracingparagraphs \tex_tracingparagraphs:D
- \name_primitive:NN \tracingrestores \tex_tracingrestores:D
- \name_primitive:NN \tracingstats \tex_tracingstats:D
- \name_primitive:NN \pausing \tex_pausing:D
- \name_primitive:NN \showboxbreadth \tex_showboxbreadth:D
- \name_primitive:NN \showboxdepth \tex_showboxdepth:D
- \name_primitive:NN \batchmode \tex_batchmode:D
- \name_primitive:NN \errorstopmode \tex_errorstopmode:D
- \name_primitive:NN \nonstopmode \tex_nonstopmode:D
- \name_primitive:NN \scrollmode \tex_scrollmode:D
- \name_primitive:NN \end \tex_end:D
- \name_primitive:NN \csname \tex_csname:D
- \name_primitive:NN \endcsname \tex_endcsname:D
- \name_primitive:NN \ignorespaces \tex_ignorespaces:D
- \name_primitive:NN \relax \tex_relax:D
- \name_primitive:NN \the \tex_the:D
- \name_primitive:NN \mag \tex_mag:D
- \name_primitive:NN \language \tex_language:D
- \name_primitive:NN \mark \tex_mark:D
- \name_primitive:NN \topmark \tex_topmark:D
- \name_primitive:NN \firstmark \tex_firstmark:D
- \name_primitive:NN \botmark \tex_botmark:D
- \name_primitive:NN \splitfirstmark \tex_splitfirstmark:D
- \name_primitive:NN \splitbotmark \tex_splitbotmark:D
- \name_primitive:NN \fontname \tex_fontname:D
- \name_primitive:NN \escapechar \tex_escapechar:D
- \name_primitive:NN \endlinechar \tex_endlinechar:D
- \name_primitive:NN \mathchoice \tex_mathchoice:D
- \name_primitive:NN \delimiter \tex_delimiter:D
- \name_primitive:NN \mathaccent \tex_mathaccent:D
- \name_primitive:NN \mathchar \tex_mathchar:D
- \name_primitive:NN \mskip \tex_mskip:D
- \name_primitive:NN \radical \tex_radical:D
- \name_primitive:NN \vcenter \tex_vcenter:D
- \name_primitive:NN \mkern \tex_mkern:D
- \name_primitive:NN \above \tex_above:D
- \name_primitive:NN \abovewithdelims \tex_abovewithdelims:D
- \name_primitive:NN \atop \tex_atop:D
- \name_primitive:NN \atopwithdelims \tex_atopwithdelims:D
- \name_primitive:NN \over \tex_over:D
- \name_primitive:NN \overwithdelims \tex_overwithdelims:D
- \name_primitive:NN \displaystyle \tex_displaystyle:D
- \name_primitive:NN \textstyle \tex_textstyle:D
- \name_primitive:NN \scriptstyle \tex_scriptstyle:D
- \name_primitive:NN \scriptscriptstyle \tex_scriptscriptstyle:D
- \name_primitive:NN \nonscript \tex_nonscript:D
- \name_primitive:NN \eqno \tex_eqno:D
- \name_primitive:NN \leqno \tex_leqno:D
- \name_primitive:NN \abovedisplayshortskip \tex_abovedisplayshortskip:D
- \name_primitive:NN \abovedisplayskip \tex_abovedisplayskip:D
- \name_primitive:NN \belowdisplayshortskip \tex_belowdisplayshortskip:D
- \name_primitive:NN \belowdisplayskip \tex_belowdisplayskip:D
- \name_primitive:NN \displaywidowpenalty \tex_displaywidowpenalty:D
- \name_primitive:NN \displayindent \tex_displayindent:D
- \name_primitive:NN \displaywidth \tex_displaywidth:D
- \name_primitive:NN \everydisplay \tex_everydisplay:D
- \name_primitive:NN \predisplaysize \tex_predisplaysize:D
- \name_primitive:NN \predisplaypenalty \tex_predisplaypenalty:D
- \name_primitive:NN \postdisplaypenalty \tex_postdisplaypenalty:D
- \name_primitive:NN \mathbin \tex_mathbin:D
- \name_primitive:NN \mathclose \tex_mathclose:D
- \name_primitive:NN \mathinner \tex_mathinner:D
- \name_primitive:NN \mathop \tex_mathop:D
- \name_primitive:NN \displaylimits \tex_displaylimits:D
- \name_primitive:NN \limits \tex_limits:D
- \name_primitive:NN \nolimits \tex_nolimits:D
- \name_primitive:NN \mathopen \tex_mathopen:D
- \name_primitive:NN \mathord \tex_mathord:D
- \name_primitive:NN \mathpunct \tex_mathpunct:D
- \name_primitive:NN \mathrel \tex_mathrel:D
- \name_primitive:NN \overline \tex_overline:D
- \name_primitive:NN \underline \tex_underline:D
- \name_primitive:NN \left \tex_left:D
- \name_primitive:NN \right \tex_right:D
- \name_primitive:NN \binoppenalty \tex_binoppenalty:D
- \name_primitive:NN \relpenalty \tex_relpenalty:D
- \name_primitive:NN \delimitershortfall \tex_delimitershortfall:D
- \name_primitive:NN \delimiterfactor \tex_delimiterfactor:D
- \name_primitive:NN \nulldelimiterspace \tex_nulldelimiterspace:D
- \name_primitive:NN \everymath \tex_everymath:D
- \name_primitive:NN \mathsurround \tex_mathsurround:D
- \name_primitive:NN \medmuskip \tex_medmuskip:D
- \name_primitive:NN \thinmuskip \tex_thinmuskip:D
- \name_primitive:NN \thickmuskip \tex_thickmuskip:D
- \name_primitive:NN \scriptspace \tex_scriptspace:D
- \name_primitive:NN \noboundary \tex_noboundary:D
- \name_primitive:NN \accent \tex_accent:D
- \name_primitive:NN \char \tex_char:D
- \name_primitive:NN \discretionary \tex_discretionary:D
- \name_primitive:NN \hfil \tex_hfil:D
- \name_primitive:NN \hfilneg \tex_hfilneg:D
- \name_primitive:NN \hfill \tex_hfill:D
- \name_primitive:NN \hskip \tex_hskip:D
- \name_primitive:NN \hss \tex_hss:D
- \name_primitive:NN \vfil \tex_vfil:D
- \name_primitive:NN \vfilneg \tex_vfilneg:D
- \name_primitive:NN \vfill \tex_vfill:D
- \name_primitive:NN \vskip \tex_vskip:D
- \name_primitive:NN \vss \tex_vss:D
- \name_primitive:NN \unskip \tex_unskip:D
- \name_primitive:NN \kern \tex_kern:D
- \name_primitive:NN \unkern \tex_unkern:D
- \name_primitive:NN \hrule \tex_hrule:D
- \name_primitive:NN \vrule \tex_vrule:D
- \name_primitive:NN \leaders \tex_leaders:D
- \name_primitive:NN \cleaders \tex_cleaders:D
- \name_primitive:NN \xleaders \tex_xleaders:D
- \name_primitive:NN \lastkern \tex_lastkern:D
- \name_primitive:NN \lastskip \tex_lastskip:D
- \name_primitive:NN \indent \tex_indent:D
- \name_primitive:NN \par \tex_par:D
- \name_primitive:NN \noindent \tex_noindent:D
- \name_primitive:NN \vadjust \tex_vadjust:D
- \name_primitive:NN \baselineskip \tex_baselineskip:D
- \name_primitive:NN \lineskip \tex_lineskip:D
- \name_primitive:NN \lineskiplimit \tex_lineskiplimit:D
- \name_primitive:NN \clubpenalty \tex_clubpenalty:D
- \name_primitive:NN \widowpenalty \tex_widowpenalty:D
- \name_primitive:NN \exhyphenpenalty \tex_exhyphenpenalty:D
- \name_primitive:NN \hyphenpenalty \tex_hyphenpenalty:D
- \name_primitive:NN \linepenalty \tex_linepenalty:D
- \name_primitive:NN \doublehyphendemerits \tex_doublehyphendemerits:D
- \name_primitive:NN \finalhyphendemerits \tex_finalhyphendemerits:D
- \name_primitive:NN \adjdemerits \tex_adjdemerits:D
- \name_primitive:NN \hangafter \tex_hangafter:D
- \name_primitive:NN \hangindent \tex_hangindent:D
- \name_primitive:NN \parshape \tex_parshape:D
- \name_primitive:NN \hsize \tex_hsize:D
- \name_primitive:NN \lefthyphenmin \tex_lefthyphenmin:D
- \name_primitive:NN \righthyphenmin \tex_righthyphenmin:D
- \name_primitive:NN \leftskip \tex_leftskip:D
- \name_primitive:NN \rightskip \tex_rightskip:D
- \name_primitive:NN \looseness \tex_looseness:D
- \name_primitive:NN \parskip \tex_parskip:D
- \name_primitive:NN \parindent \tex_parindent:D
- \name_primitive:NN \uchyph \tex_uchyph:D
- \name_primitive:NN \emergencystretch \tex_emergencystretch:D
- \name_primitive:NN \pretolerance \tex_pretolerance:D
- \name_primitive:NN \tolerance \tex_tolerance:D
- \name_primitive:NN \spaceskip \tex_spaceskip:D
- \name_primitive:NN \xspaceskip \tex_xspaceskip:D
- \name_primitive:NN \parfillskip \tex_parfillskip:D
- \name_primitive:NN \everypar \tex_everypar:D
- \name_primitive:NN \prevgraf \tex_prevgraf:D
- \name_primitive:NN \spacefactor \tex_spacefactor:D
- \name_primitive:NN \shipout \tex_shipout:D
- \name_primitive:NN \vsize \tex_vsize:D
- \name_primitive:NN \interlinepenalty \tex_interlinepenalty:D
- \name_primitive:NN \brokenpenalty \tex_brokenpenalty:D
- \name_primitive:NN \topskip \tex_topskip:D
- \name_primitive:NN \maxdeadcycles \tex_maxdeadcycles:D
- \name_primitive:NN \maxdepth \tex_maxdepth:D
- \name_primitive:NN \output \tex_output:D
- \name_primitive:NN \deadcycles \tex_deadcycles:D
- \name_primitive:NN \pagedepth \tex_pagedepth:D
- \name_primitive:NN \pagestretch \tex_pagestretch:D
- \name_primitive:NN \pagefilstretch \tex_pagefilstretch:D
- \name_primitive:NN \pagefillstretch \tex_pagefillstretch:D
- \name_primitive:NN \pagefilllstretch \tex_pagefilllstretch:D
- \name_primitive:NN \pageshrink \tex_pageshrink:D
- \name_primitive:NN \pagegoal \tex_pagegoal:D
- \name_primitive:NN \pagetotal \tex_pagetotal:D
- \name_primitive:NN \outputpenalty \tex_outputpenalty:D
- \name_primitive:NN \hoffset \tex_hoffset:D
- \name_primitive:NN \voffset \tex_voffset:D
- \name_primitive:NN \insert \tex_insert:D
- \name_primitive:NN \holdinginserts \tex_holdinginserts:D
- \name_primitive:NN \floatingpenalty \tex_floatingpenalty:D
- \name_primitive:NN \insertpenalties \tex_insertpenalties:D
- \name_primitive:NN \lower \tex_lower:D
- \name_primitive:NN \moveleft \tex_moveleft:D
- \name_primitive:NN \moveright \tex_moveright:D
- \name_primitive:NN \raise \tex_raise:D
- \name_primitive:NN \copy \tex_copy:D
- \name_primitive:NN \lastbox \tex_lastbox:D
- \name_primitive:NN \vsplit \tex_vsplit:D
- \name_primitive:NN \unhbox \tex_unhbox:D
- \name_primitive:NN \unhcopy \tex_unhcopy:D
- \name_primitive:NN \unvbox \tex_unvbox:D
- \name_primitive:NN \unvcopy \tex_unvcopy:D
- \name_primitive:NN \setbox \tex_setbox:D
- \name_primitive:NN \hbox \tex_hbox:D
- \name_primitive:NN \vbox \tex_vbox:D
- \name_primitive:NN \vtop \tex_vtop:D
- \name_primitive:NN \prevdepth \tex_prevdepth:D
- \name_primitive:NN \badness \tex_badness:D
- \name_primitive:NN \hbadness \tex_hbadness:D
- \name_primitive:NN \vbadness \tex_vbadness:D
- \name_primitive:NN \hfuzz \tex_hfuzz:D
- \name_primitive:NN \vfuzz \tex_vfuzz:D
- \name_primitive:NN \overfullrule \tex_overfullrule:D
- \name_primitive:NN \boxmaxdepth \tex_boxmaxdepth:D
- \name_primitive:NN \splitmaxdepth \tex_splitmaxdepth:D
- \name_primitive:NN \splittopskip \tex_splittopskip:D
- \name_primitive:NN \everyhbox \tex_everyhbox:D
- \name_primitive:NN \everyvbox \tex_everyvbox:D
- \name_primitive:NN \nullfont \tex_nullfont:D
- \name_primitive:NN \textfont \tex_textfont:D
- \name_primitive:NN \scriptfont \tex_scriptfont:D
- \name_primitive:NN \scriptscriptfont \tex_scriptscriptfont:D
- \name_primitive:NN \fontdimen \tex_fontdimen:D
- \name_primitive:NN \hyphenchar \tex_hyphenchar:D
- \name_primitive:NN \skewchar \tex_skewchar:D
- \name_primitive:NN \defaulthyphenchar \tex_defaulthyphenchar:D
- \name_primitive:NN \defaultskewchar \tex_defaultskewchar:D
- \name_primitive:NN \number \tex_number:D
- \name_primitive:NN \romannumeral \tex_romannumeral:D
- \name_primitive:NN \string \tex_string:D
- \name_primitive:NN \lowercase \tex_lowercase:D
- \name_primitive:NN \uppercase \tex_uppercase:D
- \name_primitive:NN \meaning \tex_meaning:D
- \name_primitive:NN \penalty \tex_penalty:D
- \name_primitive:NN \unpenalty \tex_unpenalty:D
- \name_primitive:NN \lastpenalty \tex_lastpenalty:D
- \name_primitive:NN \special \tex_special:D
- \name_primitive:NN \dump \tex_dump:D
- \name_primitive:NN \patterns \tex_patterns:D
- \name_primitive:NN \hyphenation \tex_hyphenation:D
- \name_primitive:NN \time \tex_time:D
- \name_primitive:NN \day \tex_day:D
- \name_primitive:NN \month \tex_month:D
- \name_primitive:NN \year \tex_year:D
- \name_primitive:NN \jobname \tex_jobname:D
- \name_primitive:NN \everyjob \tex_everyjob:D
- \name_primitive:NN \count \tex_count:D
- \name_primitive:NN \dimen \tex_dimen:D
- \name_primitive:NN \skip \tex_skip:D
- \name_primitive:NN \toks \tex_toks:D
- \name_primitive:NN \muskip \tex_muskip:D
- \name_primitive:NN \box \tex_box:D
- \name_primitive:NN \wd \tex_wd:D
- \name_primitive:NN \ht \tex_ht:D
- \name_primitive:NN \dp \tex_dp:D
- \name_primitive:NN \catcode \tex_catcode:D
- \name_primitive:NN \delcode \tex_delcode:D
- \name_primitive:NN \sfcode \tex_sfcode:D
- \name_primitive:NN \lccode \tex_lccode:D
- \name_primitive:NN \uccode \tex_uccode:D
- \name_primitive:NN \mathcode \tex_mathcode:D
+ \__expl_primitive:NN \let \tex_let:D
+ \__expl_primitive:NN \def \tex_def:D
+ \__expl_primitive:NN \edef \tex_edef:D
+ \__expl_primitive:NN \gdef \tex_gdef:D
+ \__expl_primitive:NN \xdef \tex_xdef:D
+ \__expl_primitive:NN \chardef \tex_chardef:D
+ \__expl_primitive:NN \countdef \tex_countdef:D
+ \__expl_primitive:NN \dimendef \tex_dimendef:D
+ \__expl_primitive:NN \skipdef \tex_skipdef:D
+ \__expl_primitive:NN \muskipdef \tex_muskipdef:D
+ \__expl_primitive:NN \mathchardef \tex_mathchardef:D
+ \__expl_primitive:NN \toksdef \tex_toksdef:D
+ \__expl_primitive:NN \futurelet \tex_futurelet:D
+ \__expl_primitive:NN \advance \tex_advance:D
+ \__expl_primitive:NN \divide \tex_divide:D
+ \__expl_primitive:NN \multiply \tex_multiply:D
+ \__expl_primitive:NN \font \tex_font:D
+ \__expl_primitive:NN \fam \tex_fam:D
+ \__expl_primitive:NN \global \tex_global:D
+ \__expl_primitive:NN \long \tex_long:D
+ \__expl_primitive:NN \outer \tex_outer:D
+ \__expl_primitive:NN \setlanguage \tex_setlanguage:D
+ \__expl_primitive:NN \globaldefs \tex_globaldefs:D
+ \__expl_primitive:NN \afterassignment \tex_afterassignment:D
+ \__expl_primitive:NN \aftergroup \tex_aftergroup:D
+ \__expl_primitive:NN \expandafter \tex_expandafter:D
+ \__expl_primitive:NN \noexpand \tex_noexpand:D
+ \__expl_primitive:NN \begingroup \tex_begingroup:D
+ \__expl_primitive:NN \endgroup \tex_endgroup:D
+ \__expl_primitive:NN \halign \tex_halign:D
+ \__expl_primitive:NN \valign \tex_valign:D
+ \__expl_primitive:NN \cr \tex_cr:D
+ \__expl_primitive:NN \crcr \tex_crcr:D
+ \__expl_primitive:NN \noalign \tex_noalign:D
+ \__expl_primitive:NN \omit \tex_omit:D
+ \__expl_primitive:NN \span \tex_span:D
+ \__expl_primitive:NN \tabskip \tex_tabskip:D
+ \__expl_primitive:NN \everycr \tex_everycr:D
+ \__expl_primitive:NN \if \tex_if:D
+ \__expl_primitive:NN \ifcase \tex_ifcase:D
+ \__expl_primitive:NN \ifcat \tex_ifcat:D
+ \__expl_primitive:NN \ifnum \tex_ifnum:D
+ \__expl_primitive:NN \ifodd \tex_ifodd:D
+ \__expl_primitive:NN \ifdim \tex_ifdim:D
+ \__expl_primitive:NN \ifeof \tex_ifeof:D
+ \__expl_primitive:NN \ifhbox \tex_ifhbox:D
+ \__expl_primitive:NN \ifvbox \tex_ifvbox:D
+ \__expl_primitive:NN \ifvoid \tex_ifvoid:D
+ \__expl_primitive:NN \ifx \tex_ifx:D
+ \__expl_primitive:NN \iffalse \tex_iffalse:D
+ \__expl_primitive:NN \iftrue \tex_iftrue:D
+ \__expl_primitive:NN \ifhmode \tex_ifhmode:D
+ \__expl_primitive:NN \ifmmode \tex_ifmmode:D
+ \__expl_primitive:NN \ifvmode \tex_ifvmode:D
+ \__expl_primitive:NN \ifinner \tex_ifinner:D
+ \__expl_primitive:NN \else \tex_else:D
+ \__expl_primitive:NN \fi \tex_fi:D
+ \__expl_primitive:NN \or \tex_or:D
+ \__expl_primitive:NN \immediate \tex_immediate:D
+ \__expl_primitive:NN \closeout \tex_closeout:D
+ \__expl_primitive:NN \openin \tex_openin:D
+ \__expl_primitive:NN \openout \tex_openout:D
+ \__expl_primitive:NN \read \tex_read:D
+ \__expl_primitive:NN \write \tex_write:D
+ \__expl_primitive:NN \closein \tex_closein:D
+ \__expl_primitive:NN \newlinechar \tex_newlinechar:D
+ \__expl_primitive:NN \input \tex_input:D
+ \__expl_primitive:NN \endinput \tex_endinput:D
+ \__expl_primitive:NN \inputlineno \tex_inputlineno:D
+ \__expl_primitive:NN \errmessage \tex_errmessage:D
+ \__expl_primitive:NN \message \tex_message:D
+ \__expl_primitive:NN \show \tex_show:D
+ \__expl_primitive:NN \showthe \tex_showthe:D
+ \__expl_primitive:NN \showbox \tex_showbox:D
+ \__expl_primitive:NN \showlists \tex_showlists:D
+ \__expl_primitive:NN \errhelp \tex_errhelp:D
+ \__expl_primitive:NN \errorcontextlines \tex_errorcontextlines:D
+ \__expl_primitive:NN \tracingcommands \tex_tracingcommands:D
+ \__expl_primitive:NN \tracinglostchars \tex_tracinglostchars:D
+ \__expl_primitive:NN \tracingmacros \tex_tracingmacros:D
+ \__expl_primitive:NN \tracingonline \tex_tracingonline:D
+ \__expl_primitive:NN \tracingoutput \tex_tracingoutput:D
+ \__expl_primitive:NN \tracingpages \tex_tracingpages:D
+ \__expl_primitive:NN \tracingparagraphs \tex_tracingparagraphs:D
+ \__expl_primitive:NN \tracingrestores \tex_tracingrestores:D
+ \__expl_primitive:NN \tracingstats \tex_tracingstats:D
+ \__expl_primitive:NN \pausing \tex_pausing:D
+ \__expl_primitive:NN \showboxbreadth \tex_showboxbreadth:D
+ \__expl_primitive:NN \showboxdepth \tex_showboxdepth:D
+ \__expl_primitive:NN \batchmode \tex_batchmode:D
+ \__expl_primitive:NN \errorstopmode \tex_errorstopmode:D
+ \__expl_primitive:NN \nonstopmode \tex_nonstopmode:D
+ \__expl_primitive:NN \scrollmode \tex_scrollmode:D
+ \__expl_primitive:NN \end \tex_end:D
+ \__expl_primitive:NN \csname \tex_csname:D
+ \__expl_primitive:NN \endcsname \tex_endcsname:D
+ \__expl_primitive:NN \ignorespaces \tex_ignorespaces:D
+ \__expl_primitive:NN \relax \tex_relax:D
+ \__expl_primitive:NN \the \tex_the:D
+ \__expl_primitive:NN \mag \tex_mag:D
+ \__expl_primitive:NN \language \tex_language:D
+ \__expl_primitive:NN \mark \tex_mark:D
+ \__expl_primitive:NN \topmark \tex_topmark:D
+ \__expl_primitive:NN \firstmark \tex_firstmark:D
+ \__expl_primitive:NN \botmark \tex_botmark:D
+ \__expl_primitive:NN \splitfirstmark \tex_splitfirstmark:D
+ \__expl_primitive:NN \splitbotmark \tex_splitbotmark:D
+ \__expl_primitive:NN \fontname \tex_fontname:D
+ \__expl_primitive:NN \escapechar \tex_escapechar:D
+ \__expl_primitive:NN \endlinechar \tex_endlinechar:D
+ \__expl_primitive:NN \mathchoice \tex_mathchoice:D
+ \__expl_primitive:NN \delimiter \tex_delimiter:D
+ \__expl_primitive:NN \mathaccent \tex_mathaccent:D
+ \__expl_primitive:NN \mathchar \tex_mathchar:D
+ \__expl_primitive:NN \mskip \tex_mskip:D
+ \__expl_primitive:NN \radical \tex_radical:D
+ \__expl_primitive:NN \vcenter \tex_vcenter:D
+ \__expl_primitive:NN \mkern \tex_mkern:D
+ \__expl_primitive:NN \above \tex_above:D
+ \__expl_primitive:NN \abovewithdelims \tex_abovewithdelims:D
+ \__expl_primitive:NN \atop \tex_atop:D
+ \__expl_primitive:NN \atopwithdelims \tex_atopwithdelims:D
+ \__expl_primitive:NN \over \tex_over:D
+ \__expl_primitive:NN \overwithdelims \tex_overwithdelims:D
+ \__expl_primitive:NN \displaystyle \tex_displaystyle:D
+ \__expl_primitive:NN \textstyle \tex_textstyle:D
+ \__expl_primitive:NN \scriptstyle \tex_scriptstyle:D
+ \__expl_primitive:NN \scriptscriptstyle \tex_scriptscriptstyle:D
+ \__expl_primitive:NN \nonscript \tex_nonscript:D
+ \__expl_primitive:NN \eqno \tex_eqno:D
+ \__expl_primitive:NN \leqno \tex_leqno:D
+ \__expl_primitive:NN \abovedisplayshortskip \tex_abovedisplayshortskip:D
+ \__expl_primitive:NN \abovedisplayskip \tex_abovedisplayskip:D
+ \__expl_primitive:NN \belowdisplayshortskip \tex_belowdisplayshortskip:D
+ \__expl_primitive:NN \belowdisplayskip \tex_belowdisplayskip:D
+ \__expl_primitive:NN \displaywidowpenalty \tex_displaywidowpenalty:D
+ \__expl_primitive:NN \displayindent \tex_displayindent:D
+ \__expl_primitive:NN \displaywidth \tex_displaywidth:D
+ \__expl_primitive:NN \everydisplay \tex_everydisplay:D
+ \__expl_primitive:NN \predisplaysize \tex_predisplaysize:D
+ \__expl_primitive:NN \predisplaypenalty \tex_predisplaypenalty:D
+ \__expl_primitive:NN \postdisplaypenalty \tex_postdisplaypenalty:D
+ \__expl_primitive:NN \mathbin \tex_mathbin:D
+ \__expl_primitive:NN \mathclose \tex_mathclose:D
+ \__expl_primitive:NN \mathinner \tex_mathinner:D
+ \__expl_primitive:NN \mathop \tex_mathop:D
+ \__expl_primitive:NN \displaylimits \tex_displaylimits:D
+ \__expl_primitive:NN \limits \tex_limits:D
+ \__expl_primitive:NN \nolimits \tex_nolimits:D
+ \__expl_primitive:NN \mathopen \tex_mathopen:D
+ \__expl_primitive:NN \mathord \tex_mathord:D
+ \__expl_primitive:NN \mathpunct \tex_mathpunct:D
+ \__expl_primitive:NN \mathrel \tex_mathrel:D
+ \__expl_primitive:NN \overline \tex_overline:D
+ \__expl_primitive:NN \underline \tex_underline:D
+ \__expl_primitive:NN \left \tex_left:D
+ \__expl_primitive:NN \right \tex_right:D
+ \__expl_primitive:NN \binoppenalty \tex_binoppenalty:D
+ \__expl_primitive:NN \relpenalty \tex_relpenalty:D
+ \__expl_primitive:NN \delimitershortfall \tex_delimitershortfall:D
+ \__expl_primitive:NN \delimiterfactor \tex_delimiterfactor:D
+ \__expl_primitive:NN \nulldelimiterspace \tex_nulldelimiterspace:D
+ \__expl_primitive:NN \everymath \tex_everymath:D
+ \__expl_primitive:NN \mathsurround \tex_mathsurround:D
+ \__expl_primitive:NN \medmuskip \tex_medmuskip:D
+ \__expl_primitive:NN \thinmuskip \tex_thinmuskip:D
+ \__expl_primitive:NN \thickmuskip \tex_thickmuskip:D
+ \__expl_primitive:NN \scriptspace \tex_scriptspace:D
+ \__expl_primitive:NN \noboundary \tex_noboundary:D
+ \__expl_primitive:NN \accent \tex_accent:D
+ \__expl_primitive:NN \char \tex_char:D
+ \__expl_primitive:NN \discretionary \tex_discretionary:D
+ \__expl_primitive:NN \hfil \tex_hfil:D
+ \__expl_primitive:NN \hfilneg \tex_hfilneg:D
+ \__expl_primitive:NN \hfill \tex_hfill:D
+ \__expl_primitive:NN \hskip \tex_hskip:D
+ \__expl_primitive:NN \hss \tex_hss:D
+ \__expl_primitive:NN \vfil \tex_vfil:D
+ \__expl_primitive:NN \vfilneg \tex_vfilneg:D
+ \__expl_primitive:NN \vfill \tex_vfill:D
+ \__expl_primitive:NN \vskip \tex_vskip:D
+ \__expl_primitive:NN \vss \tex_vss:D
+ \__expl_primitive:NN \unskip \tex_unskip:D
+ \__expl_primitive:NN \kern \tex_kern:D
+ \__expl_primitive:NN \unkern \tex_unkern:D
+ \__expl_primitive:NN \hrule \tex_hrule:D
+ \__expl_primitive:NN \vrule \tex_vrule:D
+ \__expl_primitive:NN \leaders \tex_leaders:D
+ \__expl_primitive:NN \cleaders \tex_cleaders:D
+ \__expl_primitive:NN \xleaders \tex_xleaders:D
+ \__expl_primitive:NN \lastkern \tex_lastkern:D
+ \__expl_primitive:NN \lastskip \tex_lastskip:D
+ \__expl_primitive:NN \indent \tex_indent:D
+ \__expl_primitive:NN \par \tex_par:D
+ \__expl_primitive:NN \noindent \tex_noindent:D
+ \__expl_primitive:NN \vadjust \tex_vadjust:D
+ \__expl_primitive:NN \baselineskip \tex_baselineskip:D
+ \__expl_primitive:NN \lineskip \tex_lineskip:D
+ \__expl_primitive:NN \lineskiplimit \tex_lineskiplimit:D
+ \__expl_primitive:NN \clubpenalty \tex_clubpenalty:D
+ \__expl_primitive:NN \widowpenalty \tex_widowpenalty:D
+ \__expl_primitive:NN \exhyphenpenalty \tex_exhyphenpenalty:D
+ \__expl_primitive:NN \hyphenpenalty \tex_hyphenpenalty:D
+ \__expl_primitive:NN \linepenalty \tex_linepenalty:D
+ \__expl_primitive:NN \doublehyphendemerits \tex_doublehyphendemerits:D
+ \__expl_primitive:NN \finalhyphendemerits \tex_finalhyphendemerits:D
+ \__expl_primitive:NN \adjdemerits \tex_adjdemerits:D
+ \__expl_primitive:NN \hangafter \tex_hangafter:D
+ \__expl_primitive:NN \hangindent \tex_hangindent:D
+ \__expl_primitive:NN \parshape \tex_parshape:D
+ \__expl_primitive:NN \hsize \tex_hsize:D
+ \__expl_primitive:NN \lefthyphenmin \tex_lefthyphenmin:D
+ \__expl_primitive:NN \righthyphenmin \tex_righthyphenmin:D
+ \__expl_primitive:NN \leftskip \tex_leftskip:D
+ \__expl_primitive:NN \rightskip \tex_rightskip:D
+ \__expl_primitive:NN \looseness \tex_looseness:D
+ \__expl_primitive:NN \parskip \tex_parskip:D
+ \__expl_primitive:NN \parindent \tex_parindent:D
+ \__expl_primitive:NN \uchyph \tex_uchyph:D
+ \__expl_primitive:NN \emergencystretch \tex_emergencystretch:D
+ \__expl_primitive:NN \pretolerance \tex_pretolerance:D
+ \__expl_primitive:NN \tolerance \tex_tolerance:D
+ \__expl_primitive:NN \spaceskip \tex_spaceskip:D
+ \__expl_primitive:NN \xspaceskip \tex_xspaceskip:D
+ \__expl_primitive:NN \parfillskip \tex_parfillskip:D
+ \__expl_primitive:NN \everypar \tex_everypar:D
+ \__expl_primitive:NN \prevgraf \tex_prevgraf:D
+ \__expl_primitive:NN \spacefactor \tex_spacefactor:D
+ \__expl_primitive:NN \shipout \tex_shipout:D
+ \__expl_primitive:NN \vsize \tex_vsize:D
+ \__expl_primitive:NN \interlinepenalty \tex_interlinepenalty:D
+ \__expl_primitive:NN \brokenpenalty \tex_brokenpenalty:D
+ \__expl_primitive:NN \topskip \tex_topskip:D
+ \__expl_primitive:NN \maxdeadcycles \tex_maxdeadcycles:D
+ \__expl_primitive:NN \maxdepth \tex_maxdepth:D
+ \__expl_primitive:NN \output \tex_output:D
+ \__expl_primitive:NN \deadcycles \tex_deadcycles:D
+ \__expl_primitive:NN \pagedepth \tex_pagedepth:D
+ \__expl_primitive:NN \pagestretch \tex_pagestretch:D
+ \__expl_primitive:NN \pagefilstretch \tex_pagefilstretch:D
+ \__expl_primitive:NN \pagefillstretch \tex_pagefillstretch:D
+ \__expl_primitive:NN \pagefilllstretch \tex_pagefilllstretch:D
+ \__expl_primitive:NN \pageshrink \tex_pageshrink:D
+ \__expl_primitive:NN \pagegoal \tex_pagegoal:D
+ \__expl_primitive:NN \pagetotal \tex_pagetotal:D
+ \__expl_primitive:NN \outputpenalty \tex_outputpenalty:D
+ \__expl_primitive:NN \hoffset \tex_hoffset:D
+ \__expl_primitive:NN \voffset \tex_voffset:D
+ \__expl_primitive:NN \insert \tex_insert:D
+ \__expl_primitive:NN \holdinginserts \tex_holdinginserts:D
+ \__expl_primitive:NN \floatingpenalty \tex_floatingpenalty:D
+ \__expl_primitive:NN \insertpenalties \tex_insertpenalties:D
+ \__expl_primitive:NN \lower \tex_lower:D
+ \__expl_primitive:NN \moveleft \tex_moveleft:D
+ \__expl_primitive:NN \moveright \tex_moveright:D
+ \__expl_primitive:NN \raise \tex_raise:D
+ \__expl_primitive:NN \copy \tex_copy:D
+ \__expl_primitive:NN \lastbox \tex_lastbox:D
+ \__expl_primitive:NN \vsplit \tex_vsplit:D
+ \__expl_primitive:NN \unhbox \tex_unhbox:D
+ \__expl_primitive:NN \unhcopy \tex_unhcopy:D
+ \__expl_primitive:NN \unvbox \tex_unvbox:D
+ \__expl_primitive:NN \unvcopy \tex_unvcopy:D
+ \__expl_primitive:NN \setbox \tex_setbox:D
+ \__expl_primitive:NN \hbox \tex_hbox:D
+ \__expl_primitive:NN \vbox \tex_vbox:D
+ \__expl_primitive:NN \vtop \tex_vtop:D
+ \__expl_primitive:NN \prevdepth \tex_prevdepth:D
+ \__expl_primitive:NN \badness \tex_badness:D
+ \__expl_primitive:NN \hbadness \tex_hbadness:D
+ \__expl_primitive:NN \vbadness \tex_vbadness:D
+ \__expl_primitive:NN \hfuzz \tex_hfuzz:D
+ \__expl_primitive:NN \vfuzz \tex_vfuzz:D
+ \__expl_primitive:NN \overfullrule \tex_overfullrule:D
+ \__expl_primitive:NN \boxmaxdepth \tex_boxmaxdepth:D
+ \__expl_primitive:NN \splitmaxdepth \tex_splitmaxdepth:D
+ \__expl_primitive:NN \splittopskip \tex_splittopskip:D
+ \__expl_primitive:NN \everyhbox \tex_everyhbox:D
+ \__expl_primitive:NN \everyvbox \tex_everyvbox:D
+ \__expl_primitive:NN \nullfont \tex_nullfont:D
+ \__expl_primitive:NN \textfont \tex_textfont:D
+ \__expl_primitive:NN \scriptfont \tex_scriptfont:D
+ \__expl_primitive:NN \scriptscriptfont \tex_scriptscriptfont:D
+ \__expl_primitive:NN \fontdimen \tex_fontdimen:D
+ \__expl_primitive:NN \hyphenchar \tex_hyphenchar:D
+ \__expl_primitive:NN \skewchar \tex_skewchar:D
+ \__expl_primitive:NN \defaulthyphenchar \tex_defaulthyphenchar:D
+ \__expl_primitive:NN \defaultskewchar \tex_defaultskewchar:D
+ \__expl_primitive:NN \number \tex_number:D
+ \__expl_primitive:NN \romannumeral \tex_romannumeral:D
+ \__expl_primitive:NN \string \tex_string:D
+ \__expl_primitive:NN \lowercase \tex_lowercase:D
+ \__expl_primitive:NN \uppercase \tex_uppercase:D
+ \__expl_primitive:NN \meaning \tex_meaning:D
+ \__expl_primitive:NN \penalty \tex_penalty:D
+ \__expl_primitive:NN \unpenalty \tex_unpenalty:D
+ \__expl_primitive:NN \lastpenalty \tex_lastpenalty:D
+ \__expl_primitive:NN \special \tex_special:D
+ \__expl_primitive:NN \dump \tex_dump:D
+ \__expl_primitive:NN \patterns \tex_patterns:D
+ \__expl_primitive:NN \hyphenation \tex_hyphenation:D
+ \__expl_primitive:NN \time \tex_time:D
+ \__expl_primitive:NN \day \tex_day:D
+ \__expl_primitive:NN \month \tex_month:D
+ \__expl_primitive:NN \year \tex_year:D
+ \__expl_primitive:NN \jobname \tex_jobname:D
+ \__expl_primitive:NN \everyjob \tex_everyjob:D
+ \__expl_primitive:NN \count \tex_count:D
+ \__expl_primitive:NN \dimen \tex_dimen:D
+ \__expl_primitive:NN \skip \tex_skip:D
+ \__expl_primitive:NN \toks \tex_toks:D
+ \__expl_primitive:NN \muskip \tex_muskip:D
+ \__expl_primitive:NN \box \tex_box:D
+ \__expl_primitive:NN \wd \tex_wd:D
+ \__expl_primitive:NN \ht \tex_ht:D
+ \__expl_primitive:NN \dp \tex_dp:D
+ \__expl_primitive:NN \catcode \tex_catcode:D
+ \__expl_primitive:NN \delcode \tex_delcode:D
+ \__expl_primitive:NN \sfcode \tex_sfcode:D
+ \__expl_primitive:NN \lccode \tex_lccode:D
+ \__expl_primitive:NN \uccode \tex_uccode:D
+ \__expl_primitive:NN \mathcode \tex_mathcode:D
% \end{macrocode}
% Since \LaTeX3 requires at least the \eTeX{} extensions,
% we also rename the additional primitives. These are all
% given the prefix |\etex_|.
% \begin{macrocode}
- \name_primitive:NN \ifdefined \etex_ifdefined:D
- \name_primitive:NN \ifcsname \etex_ifcsname:D
- \name_primitive:NN \unless \etex_unless:D
- \name_primitive:NN \eTeXversion \etex_eTeXversion:D
- \name_primitive:NN \eTeXrevision \etex_eTeXrevision:D
- \name_primitive:NN \marks \etex_marks:D
- \name_primitive:NN \topmarks \etex_topmarks:D
- \name_primitive:NN \firstmarks \etex_firstmarks:D
- \name_primitive:NN \botmarks \etex_botmarks:D
- \name_primitive:NN \splitfirstmarks \etex_splitfirstmarks:D
- \name_primitive:NN \splitbotmarks \etex_splitbotmarks:D
- \name_primitive:NN \unexpanded \etex_unexpanded:D
- \name_primitive:NN \detokenize \etex_detokenize:D
- \name_primitive:NN \scantokens \etex_scantokens:D
- \name_primitive:NN \showtokens \etex_showtokens:D
- \name_primitive:NN \readline \etex_readline:D
- \name_primitive:NN \tracingassigns \etex_tracingassigns:D
- \name_primitive:NN \tracingscantokens \etex_tracingscantokens:D
- \name_primitive:NN \tracingnesting \etex_tracingnesting:D
- \name_primitive:NN \tracingifs \etex_tracingifs:D
- \name_primitive:NN \currentiflevel \etex_currentiflevel:D
- \name_primitive:NN \currentifbranch \etex_currentifbranch:D
- \name_primitive:NN \currentiftype \etex_currentiftype:D
- \name_primitive:NN \tracinggroups \etex_tracinggroups:D
- \name_primitive:NN \currentgrouplevel \etex_currentgrouplevel:D
- \name_primitive:NN \currentgrouptype \etex_currentgrouptype:D
- \name_primitive:NN \showgroups \etex_showgroups:D
- \name_primitive:NN \showifs \etex_showifs:D
- \name_primitive:NN \interactionmode \etex_interactionmode:D
- \name_primitive:NN \lastnodetype \etex_lastnodetype:D
- \name_primitive:NN \iffontchar \etex_iffontchar:D
- \name_primitive:NN \fontcharht \etex_fontcharht:D
- \name_primitive:NN \fontchardp \etex_fontchardp:D
- \name_primitive:NN \fontcharwd \etex_fontcharwd:D
- \name_primitive:NN \fontcharic \etex_fontcharic:D
- \name_primitive:NN \parshapeindent \etex_parshapeindent:D
- \name_primitive:NN \parshapelength \etex_parshapelength:D
- \name_primitive:NN \parshapedimen \etex_parshapedimen:D
- \name_primitive:NN \numexpr \etex_numexpr:D
- \name_primitive:NN \dimexpr \etex_dimexpr:D
- \name_primitive:NN \glueexpr \etex_glueexpr:D
- \name_primitive:NN \muexpr \etex_muexpr:D
- \name_primitive:NN \gluestretch \etex_gluestretch:D
- \name_primitive:NN \glueshrink \etex_glueshrink:D
- \name_primitive:NN \gluestretchorder \etex_gluestretchorder:D
- \name_primitive:NN \glueshrinkorder \etex_glueshrinkorder:D
- \name_primitive:NN \gluetomu \etex_gluetomu:D
- \name_primitive:NN \mutoglue \etex_mutoglue:D
- \name_primitive:NN \lastlinefit \etex_lastlinefit:D
- \name_primitive:NN \interlinepenalties \etex_interlinepenalties:D
- \name_primitive:NN \clubpenalties \etex_clubpenalties:D
- \name_primitive:NN \widowpenalties \etex_widowpenalties:D
- \name_primitive:NN \displaywidowpenalties \etex_displaywidowpenalties:D
- \name_primitive:NN \middle \etex_middle:D
- \name_primitive:NN \savinghyphcodes \etex_savinghyphcodes:D
- \name_primitive:NN \savingvdiscards \etex_savingvdiscards:D
- \name_primitive:NN \pagediscards \etex_pagediscards:D
- \name_primitive:NN \splitdiscards \etex_splitdiscards:D
- \name_primitive:NN \TeXXeTstate \etex_TeXXeTstate:D
- \name_primitive:NN \beginL \etex_beginL:D
- \name_primitive:NN \endL \etex_endL:D
- \name_primitive:NN \beginR \etex_beginR:D
- \name_primitive:NN \endR \etex_endR:D
- \name_primitive:NN \predisplaydirection \etex_predisplaydirection:D
- \name_primitive:NN \everyeof \etex_everyeof:D
- \name_primitive:NN \protected \etex_protected:D
+ \__expl_primitive:NN \ifdefined \etex_ifdefined:D
+ \__expl_primitive:NN \ifcsname \etex_ifcsname:D
+ \__expl_primitive:NN \unless \etex_unless:D
+ \__expl_primitive:NN \eTeXversion \etex_eTeXversion:D
+ \__expl_primitive:NN \eTeXrevision \etex_eTeXrevision:D
+ \__expl_primitive:NN \marks \etex_marks:D
+ \__expl_primitive:NN \topmarks \etex_topmarks:D
+ \__expl_primitive:NN \firstmarks \etex_firstmarks:D
+ \__expl_primitive:NN \botmarks \etex_botmarks:D
+ \__expl_primitive:NN \splitfirstmarks \etex_splitfirstmarks:D
+ \__expl_primitive:NN \splitbotmarks \etex_splitbotmarks:D
+ \__expl_primitive:NN \unexpanded \etex_unexpanded:D
+ \__expl_primitive:NN \detokenize \etex_detokenize:D
+ \__expl_primitive:NN \scantokens \etex_scantokens:D
+ \__expl_primitive:NN \showtokens \etex_showtokens:D
+ \__expl_primitive:NN \readline \etex_readline:D
+ \__expl_primitive:NN \tracingassigns \etex_tracingassigns:D
+ \__expl_primitive:NN \tracingscantokens \etex_tracingscantokens:D
+ \__expl_primitive:NN \tracingnesting \etex_tracingnesting:D
+ \__expl_primitive:NN \tracingifs \etex_tracingifs:D
+ \__expl_primitive:NN \currentiflevel \etex_currentiflevel:D
+ \__expl_primitive:NN \currentifbranch \etex_currentifbranch:D
+ \__expl_primitive:NN \currentiftype \etex_currentiftype:D
+ \__expl_primitive:NN \tracinggroups \etex_tracinggroups:D
+ \__expl_primitive:NN \currentgrouplevel \etex_currentgrouplevel:D
+ \__expl_primitive:NN \currentgrouptype \etex_currentgrouptype:D
+ \__expl_primitive:NN \showgroups \etex_showgroups:D
+ \__expl_primitive:NN \showifs \etex_showifs:D
+ \__expl_primitive:NN \interactionmode \etex_interactionmode:D
+ \__expl_primitive:NN \lastnodetype \etex_lastnodetype:D
+ \__expl_primitive:NN \iffontchar \etex_iffontchar:D
+ \__expl_primitive:NN \fontcharht \etex_fontcharht:D
+ \__expl_primitive:NN \fontchardp \etex_fontchardp:D
+ \__expl_primitive:NN \fontcharwd \etex_fontcharwd:D
+ \__expl_primitive:NN \fontcharic \etex_fontcharic:D
+ \__expl_primitive:NN \parshapeindent \etex_parshapeindent:D
+ \__expl_primitive:NN \parshapelength \etex_parshapelength:D
+ \__expl_primitive:NN \parshapedimen \etex_parshapedimen:D
+ \__expl_primitive:NN \numexpr \etex_numexpr:D
+ \__expl_primitive:NN \dimexpr \etex_dimexpr:D
+ \__expl_primitive:NN \glueexpr \etex_glueexpr:D
+ \__expl_primitive:NN \muexpr \etex_muexpr:D
+ \__expl_primitive:NN \gluestretch \etex_gluestretch:D
+ \__expl_primitive:NN \glueshrink \etex_glueshrink:D
+ \__expl_primitive:NN \gluestretchorder \etex_gluestretchorder:D
+ \__expl_primitive:NN \glueshrinkorder \etex_glueshrinkorder:D
+ \__expl_primitive:NN \gluetomu \etex_gluetomu:D
+ \__expl_primitive:NN \mutoglue \etex_mutoglue:D
+ \__expl_primitive:NN \lastlinefit \etex_lastlinefit:D
+ \__expl_primitive:NN \interlinepenalties \etex_interlinepenalties:D
+ \__expl_primitive:NN \clubpenalties \etex_clubpenalties:D
+ \__expl_primitive:NN \widowpenalties \etex_widowpenalties:D
+ \__expl_primitive:NN \displaywidowpenalties \etex_displaywidowpenalties:D
+ \__expl_primitive:NN \middle \etex_middle:D
+ \__expl_primitive:NN \savinghyphcodes \etex_savinghyphcodes:D
+ \__expl_primitive:NN \savingvdiscards \etex_savingvdiscards:D
+ \__expl_primitive:NN \pagediscards \etex_pagediscards:D
+ \__expl_primitive:NN \splitdiscards \etex_splitdiscards:D
+ \__expl_primitive:NN \TeXXeTstate \etex_TeXXeTstate:D
+ \__expl_primitive:NN \beginL \etex_beginL:D
+ \__expl_primitive:NN \endL \etex_endL:D
+ \__expl_primitive:NN \beginR \etex_beginR:D
+ \__expl_primitive:NN \endR \etex_endR:D
+ \__expl_primitive:NN \predisplaydirection \etex_predisplaydirection:D
+ \__expl_primitive:NN \everyeof \etex_everyeof:D
+ \__expl_primitive:NN \protected \etex_protected:D
% \end{macrocode}
% The newer primitives are more complex: there are an awful lot of them,
% and we don't use them all at the moment. So the following is selective.
@@ -561,43 +561,43 @@
% there are a lot of \pdfTeX{} primitives that start \cs{pdf\ldots} but
% are not related to PDF output. These ones related to PDF output.
% \begin{macrocode}
- \name_primitive:NN \pdfcreationdate \pdftex_pdfcreationdate:D
- \name_primitive:NN \pdfcolorstack \pdftex_pdfcolorstack:D
- \name_primitive:NN \pdfcompresslevel \pdftex_pdfcompresslevel:D
- \name_primitive:NN \pdfdecimaldigits \pdftex_pdfdecimaldigits:D
- \name_primitive:NN \pdfhorigin \pdftex_pdfhorigin:D
- \name_primitive:NN \pdfinfo \pdftex_pdfinfo:D
- \name_primitive:NN \pdflastxform \pdftex_pdflastxform:D
- \name_primitive:NN \pdfliteral \pdftex_pdfliteral:D
- \name_primitive:NN \pdfminorversion \pdftex_pdfminorversion:D
- \name_primitive:NN \pdfobjcompresslevel \pdftex_pdfobjcompresslevel:D
- \name_primitive:NN \pdfoutput \pdftex_pdfoutput:D
- \name_primitive:NN \pdfrefxform \pdftex_pdfrefxform:D
- \name_primitive:NN \pdfrestore \pdftex_pdfrestore:D
- \name_primitive:NN \pdfsave \pdftex_pdfsave:D
- \name_primitive:NN \pdfsetmatrix \pdftex_pdfsetmatrix:D
- \name_primitive:NN \pdfpkresolution \pdftex_pdfpkresolution:D
- \name_primitive:NN \pdftexrevision \pdftex_pdftextrevision:D
- \name_primitive:NN \pdfvorigin \pdftex_pdfvorigin:D
- \name_primitive:NN \pdfxform \pdftex_pdfxform:D
+ \__expl_primitive:NN \pdfcreationdate \pdftex_pdfcreationdate:D
+ \__expl_primitive:NN \pdfcolorstack \pdftex_pdfcolorstack:D
+ \__expl_primitive:NN \pdfcompresslevel \pdftex_pdfcompresslevel:D
+ \__expl_primitive:NN \pdfdecimaldigits \pdftex_pdfdecimaldigits:D
+ \__expl_primitive:NN \pdfhorigin \pdftex_pdfhorigin:D
+ \__expl_primitive:NN \pdfinfo \pdftex_pdfinfo:D
+ \__expl_primitive:NN \pdflastxform \pdftex_pdflastxform:D
+ \__expl_primitive:NN \pdfliteral \pdftex_pdfliteral:D
+ \__expl_primitive:NN \pdfminorversion \pdftex_pdfminorversion:D
+ \__expl_primitive:NN \pdfobjcompresslevel \pdftex_pdfobjcompresslevel:D
+ \__expl_primitive:NN \pdfoutput \pdftex_pdfoutput:D
+ \__expl_primitive:NN \pdfrefxform \pdftex_pdfrefxform:D
+ \__expl_primitive:NN \pdfrestore \pdftex_pdfrestore:D
+ \__expl_primitive:NN \pdfsave \pdftex_pdfsave:D
+ \__expl_primitive:NN \pdfsetmatrix \pdftex_pdfsetmatrix:D
+ \__expl_primitive:NN \pdfpkresolution \pdftex_pdfpkresolution:D
+ \__expl_primitive:NN \pdftexrevision \pdftex_pdftextrevision:D
+ \__expl_primitive:NN \pdfvorigin \pdftex_pdfvorigin:D
+ \__expl_primitive:NN \pdfxform \pdftex_pdfxform:D
% \end{macrocode}
% While these are not.
% \begin{macrocode}
- \name_primitive:NN \pdfstrcmp \pdftex_strcmp:D
+ \__expl_primitive:NN \pdfstrcmp \pdftex_strcmp:D
% \end{macrocode}
% \XeTeX{}-specific primitives. Note that \XeTeX{}'s \tn{strcmp} is
% handled earlier and is \enquote{rolled up} into \tn{pdfstrcmp}.
% \begin{macrocode}
- \name_primitive:NN \XeTeXversion \xetex_XeTeXversion:D
+ \__expl_primitive:NN \XeTeXversion \xetex_XeTeXversion:D
% \end{macrocode}
% Primitives from \LuaTeX{}.
% \begin{macrocode}
- \name_primitive:NN \catcodetable \luatex_catcodetable:D
- \name_primitive:NN \directlua \luatex_directlua:D
- \name_primitive:NN \initcatcodetable \luatex_initcatcodetable:D
- \name_primitive:NN \latelua \luatex_latelua:D
- \name_primitive:NN \luatexversion \luatex_luatexversion:D
- \name_primitive:NN \savecatcodetable \luatex_savecatcodetable:D
+ \__expl_primitive:NN \catcodetable \luatex_catcodetable:D
+ \__expl_primitive:NN \directlua \luatex_directlua:D
+ \__expl_primitive:NN \initcatcodetable \luatex_initcatcodetable:D
+ \__expl_primitive:NN \latelua \luatex_latelua:D
+ \__expl_primitive:NN \luatexversion \luatex_luatexversion:D
+ \__expl_primitive:NN \savecatcodetable \luatex_savecatcodetable:D
% \end{macrocode}
% The job is done: close the group (using the primitive renamed!).
% \begin{macrocode}
@@ -612,7 +612,7 @@
\tex_let:D \tex_everymath:D \frozen@everymath
\tex_let:D \tex_hyphen:D \@@hyph
\tex_let:D \tex_input:D \@@input
-\tex_let:D \tex_italic_correction:D \@@italiccorr
+\tex_let:D \tex_italiccorrection:D \@@italiccorr
\tex_let:D \tex_underline:D \@@underline
% \end{macrocode}
% That is also true for the \pkg{luatex} package for \LaTeXe{}.
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
index 88f53e59759..6d4fb15351d 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-%% File: l3prg.dtx Copyright (C) 2005-2011 The LaTeX3 Project
+%% File: l3prg.dtx Copyright (C) 2005-2012 The LaTeX3 Project
%%
%% It may be distributed and/or modified under the conditions of the
%% LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3prg.dtx 3490 2012-03-04 01:00:53Z bruno $
- {L3 Experimental control structures}
+\GetIdInfo$Id: l3prg.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Control structures}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -78,13 +78,13 @@
% \LaTeX3 has two forms of conditional flow processing based
% on these states. The firs form is predicate functions that turn the
% returned state into a boolean \meta{true} or \meta{false}. For
-% example, the function |\cs_if_free_p:N| checks whether the control
+% example, the function \cs{cs_if_free_p:N} checks whether the control
% sequence given as its argument is free and then returns the boolean
% \meta{true} or \meta{false} values to be used in testing with
-% |\if_predicate:w| or in functions to be described below. The second form
+% \cs{if_predicate:w} or in functions to be described below. The second form
% is the kind of functions choosing a particular argument from the
% input stream based on the result of the testing as in
-% |\cs_if_free:NTF| which also takes one argument (the |N|) and then
+% \cs{cs_if_free:NTF} which also takes one argument (the |N|) and then
% executes either \texttt{true} or \texttt{false} depending on the
% result. Important to note here is that the arguments are executed
% after exiting the underlying |\if...\fi:| structure.
@@ -182,13 +182,13 @@
% This defines the function |\foo_if_bar_p:NN|, |\foo_if_bar:NNTF| and
% |\foo_if_bar:NNT| but not |\foo_if_bar:NNF| (because |F| is missing
% from the \meta{conditions} list). The return statements take care of
-% resolving the remaining |\else:| and |\fi:| before returning the
+% resolving the remaining \cs{else:} and \cs{fi:} before returning the
% state. There must be a return statement for each branch, failing to do
% so will result in an error if that branch is executed.
%
% \begin{function}{\prg_new_eq_conditional:NNn, \prg_set_eq_conditional:NNn}
% \begin{syntax}
-% \cs{prg_new_eq_conditional:NNn} \cs{\meta{name1}:\meta{arg spec1}} \cs{\meta{name2}:\meta{arg spec2}} \Arg{conditions}
+% \cs{prg_new_eq_conditional:NNn} \cs{\meta{name_1}:\meta{arg spec_1}} \cs{\meta{name_2}:\meta{arg spec_2}} \Arg{conditions}
% \end{syntax}
% These functions copies a family of conditionals. The \texttt{new} version
% will check for existing definitions (\emph{cf.}~\cs{cs_new:Npn}) whereas
@@ -214,12 +214,12 @@
% connected to conditional processing as sometimes you want to
% execute some code depending on the value of a switch
% (\emph{e.g.},~draft/final) and other times you perhaps want to use it as a
-% predicate function in an |\if_predicate:w| test. The problem of the
-% primitive |\if_false:| and |\if_true:| tokens is that it is not
+% predicate function in an \cs{if_predicate:w} test. The problem of the
+% primitive \cs{if_false:} and \cs{if_true:} tokens is that it is not
% always safe to pass them around as they may interfere with scanning
% for termination of primitive conditional processing. Therefore, we
-% employ two canonical booleans: |\c_true_bool| or
-% |\c_false_bool|. Besides preventing problems as described above, it
+% employ two canonical booleans: \cs{c_true_bool} or
+% \cs{c_false_bool}. Besides preventing problems as described above, it
% also allows us to implement a simple boolean parser supporting the
% logical operations And, Or, Not, \emph{etc.}\ which can then be used on
% both the boolean type and predicate functions.
@@ -265,12 +265,12 @@
% \bool_gset_eq:NN, \bool_gset_eq:cN, \bool_gset_eq:Nc, \bool_gset_eq:cc
% }
% \begin{syntax}
-% \cs{bool_set_eq:NN} \meta{boolean1} \meta{boolean2}
+% \cs{bool_set_eq:NN} \meta{boolean_1} \meta{boolean_2}
% \end{syntax}
-% Sets the content of \meta{boolean1} equal to that of \meta{boolean2}.
+% Sets the content of \meta{boolean_1} equal to that of \meta{boolean_2}.
% \end{function}
%
-% \begin{function}
+% \begin{function}[updated = 2012-07-08]
% {\bool_set:Nn, \bool_set:cn, \bool_gset:Nn, \bool_gset:cn}
% \begin{syntax}
% \cs{bool_set:Nn} \meta{boolean} \Arg{boolexpr}
@@ -296,7 +296,7 @@
% Displays the logical truth of the \meta{boolean} on the terminal.
% \end{function}
%
-% \begin{function}[added = 2012-02-09]{\bool_show:n}
+% \begin{function}[added = 2012-02-09, updated = 2012-07-08]{\bool_show:n}
% \begin{syntax}
% \cs{bool_show:n} \Arg{boolean expression}
% \end{syntax}
@@ -314,14 +314,14 @@
% check that the \meta{boolean} really is a boolean variable.
% \end{function}
%
-% \begin{variable}{\l_tmpa_bool}
+% \begin{variable}{\l_tmpa_bool, \l_tmpb_bool}
% A scratch boolean for local assignment. It is never used by
% the kernel code, and so is safe for use with any \LaTeX3-defined
% function. However, it may be overwritten by other non-kernel
% code and so should only be used for short-term storage.
% \end{variable}
%
-% \begin{variable}{\g_tmpa_bool}
+% \begin{variable}{\g_tmpa_bool, \g_tmpb_bool}
% A scratch boolean for global assignment. It is never used by
% the kernel code, and so is safe for use with any \LaTeX3-defined
% function. However, it may be overwritten by other non-kernel
@@ -337,7 +337,8 @@
% A boolean expression is an expression which given input in the form
% of predicate functions and boolean variables, return boolean
% \meta{true} or \meta{false}. It supports the logical operations And,
-% Or and Not as the well-known infix operators |&&|, \verb"||" and |!|. In
+% Or and Not as the well-known infix operators |&&|, \verb"||" and |!|
+% with their usual precedences. In
% addition to this, parentheses can be used to isolate
% sub-expressions. For example,
% \begin{verbatim}
@@ -354,7 +355,7 @@
% be changed any more, the remaining tests within the current group
% are skipped.
%
-% \begin{function}[EXP,pTF]{\bool_if:n}
+% \begin{function}[EXP, pTF, updated = 2012-07-08]{\bool_if:n}
% \begin{syntax}
% \cs{bool_if_p:n} \Arg{boolean expression}
% \cs{bool_if:nTF} \Arg{boolean expression} \Arg{true code} \Arg{false code}
@@ -367,7 +368,7 @@
% |!| (\enquote{Not}) and parentheses. Minimal evaluation is used
% in the processing, so that once a result is defined there is
% not further expansion of the tests. For example
-% \begin{verbatim}
+% \begin{verbatim}
% \bool_if_p:n
% {
% \int_compare_p:nNn { 1 } = { 1 }
@@ -378,17 +379,15 @@
% \int_compare_p:nNn { 1 } = { \error } % is skipped
% )
% &&
-% ! ( \int_compare_p:nNn { 2 } = { 4 } )
+% ! \int_compare_p:nNn { 2 } = { 4 }
% }
% \end{verbatim}
% will be \texttt{true} and will not evaluate
% |\int_compare_p:nNn { 1 } = { \error }|. The logical Not applies to
-% the next single predicate or group. As shown above, this means that
-% any predicates requiring an argument have to be given within
-% parentheses.
+% the next predicate or group.
% \end{function}
%
-% \begin{function}[EXP]{\bool_not_p:n}
+% \begin{function}[EXP, updated = 2012-07-08]{\bool_not_p:n}
% \begin{syntax}
% \cs{bool_not_p:n} \Arg{boolean expression}
% \end{syntax}
@@ -396,9 +395,9 @@
% expression.
% \end{function}
%
-% \begin{function}[EXP]{\bool_xor_p:nn}
+% \begin{function}[EXP, updated = 2012-07-08]{\bool_xor_p:nn}
% \begin{syntax}
-% \cs{bool_xor_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_1}
+% \cs{bool_xor_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2}
% \end{syntax}
% Implements an \enquote{exclusive or} operation between two boolean
% expressions. There is no infix operation for this logical
@@ -431,7 +430,7 @@
% until the \meta{boolean} is \texttt{false}.
% \end{function}
%
-% \begin{function}[rEXP]{\bool_until_do:nn}
+% \begin{function}[rEXP, updated = 2012-07-08]{\bool_until_do:nn}
% \begin{syntax}
% \cs{bool_until_do:nn} \Arg{boolean expression} \Arg{code}
% \end{syntax}
@@ -443,7 +442,7 @@
% then loop until the \meta{boolean expression} is \texttt{true}.
% \end{function}
%
-% \begin{function}[rEXP]{\bool_while_do:nn}
+% \begin{function}[rEXP, updated = 2012-07-08]{\bool_while_do:nn}
% \begin{syntax}
% \cs{bool_while_do:nn} \Arg{boolean expression} \Arg{code}
% \end{syntax}
@@ -455,109 +454,6 @@
% then loop until the \meta{boolean expression} is \texttt{false}.
% \end{function}
%
-% \section{Switching by case}
-%
-% For cases where a number of cases need to be considered a family of
-% case-selecting functions are available.
-%
-% \begin{function}[updated = 2011-09-17, EXP]{\prg_case_int:nnn}
-% \begin{syntax}
-% \cs{prg_case_int:nnn} \Arg{test integer expression} \\
-% ~~|{| \\
-% ~~~~\Arg{intexpr case1} \Arg{code case1} \\
-% ~~~~\Arg{intexpr case2} \Arg{code case2} \\
-% ~~~~\ldots \\
-% ~~~~\Arg{intexpr case$\sb{n}$} \Arg{code case$\sb{n}$} \\
-% ~~|}| \\
-% ~~\Arg{else case}
-% \end{syntax}
-% This function evaluates the \meta{test integer expression} and
-% compares this in turn to each of the
-% \meta{integer expression cases}. If the two are equal then the
-% associated \meta{code} is left in the input stream. If none of
-% the tests are \texttt{true} then the \texttt{else code} will be
-% left in the input stream.
-% \end{function}
-%
-% As an example of \cs{prg_case_int:nnn}:
-% \begin{verbatim}
-% \prg_case_int:nnn
-% { 2 * 5 }
-% {
-% { 5 } { Small }
-% { 4 + 6 } { Medium }
-% { -2 * 10 } { Negative }
-% }
-% { No idea! }
-% \end{verbatim}
-% will leave \enquote{\texttt{Medium}} in the input stream.
-%
-% \begin{function}[updated = 2011-07-06, EXP]{\prg_case_dim:nnn}
-% \begin{syntax}
-% \cs{prg_case_dim:nnn} \Arg{test dimension expression} \\
-% ~~|{| \\
-% ~~~~\Arg{dimexpr case1} \Arg{code case1} \\
-% ~~~~\Arg{dimexpr case2} \Arg{code case2} \\
-% ~~~~\ldots \\
-% ~~~~\Arg{dimexpr case$\sb{n}$} \Arg{code case$\sb{n}$} \\
-% ~~|}| \\
-% ~~\Arg{else case}
-% \end{syntax}
-% This function evaluates the \meta{test dimension expression} and
-% compares this in turn to each of the
-% \meta{dimension expression cases}. If the two are equal then the
-% associated \meta{code} is left in the input stream. If none of
-% the tests are \texttt{true} then the \texttt{else code} will be
-% left in the input stream.
-% \end{function}
-%
-% \begin{function}[updated = 2011-09-17, EXP]
-% {\prg_case_str:nnn, \prg_case_str:onn, \prg_case_str:xxn}
-% \begin{syntax}
-% \cs{prg_case_str:nnn} \Arg{test string} \\
-% ~~|{| \\
-% ~~~~\Arg{string case1} \Arg{code case1} \\
-% ~~~~\Arg{string case2} \Arg{code case2} \\
-% ~~~~\ldots \\
-% ~~~~\Arg{string case$\sb{n}$} \Arg{code case$\sb{n}$} \\
-% ~~|}| \\
-% ~~\Arg{else case}
-% \end{syntax}
-% This function compares the \meta{test string} in turn with each
-% of the \meta{string cases}. If the two are equal (as described for
-% \cs{str_if_eq:nnTF} then the
-% associated \meta{code} is left in the input stream. If none of
-% the tests are \texttt{true} then the \texttt{else code} will be
-% left in the input stream. The |xx| variant fully expands
-% \meta{strings} before comparing them, but does not expand the
-% corresponding \meta{code}. It is fully expandable, in the same way
-% as the underlying \cs{str_if_eq:xxTF} test.
-%^^A The \meta{test string} is expanded in each comparison, and must
-%^^A always yield the same result: in particular, random numbers should
-%^^A not be used within this string.
-% \end{function}
-%
-% \begin{function}[updated = 2011-09-17, EXP]
-% {\prg_case_tl:Nnn, \prg_case_tl:cnn}
-% \begin{syntax}
-% \cs{prg_case_tl:Nnn} \meta{test token list variable} \\
-% ~~"{" \\
-% ~~~~\meta{token list variable case1} \Arg{code case1} \\
-% ~~~~\meta{token list variable case2} \Arg{code case2} \\
-% ~~~~\ldots \\
-% ~~~~\meta{token list variable case$\sb{n}$} \Arg{code case$\sb{n}$} \\
-% ~~"}" \\
-% ~~\Arg{else case}
-% \end{syntax}
-% This function compares the \meta{test token list variable} in turn
-% with each of the \meta{token list variable cases}. If the two
-% are equal (as described for
-% \cs{tl_if_eq:nnTF}
-% then the associated \meta{code} is left in the input
-% stream. If none of the tests are \texttt{true} then the
-% \texttt{else code} will be left in the input stream.
-% \end{function}
-%
% \section{Producing $n$ copies}
%
% \begin{function}[updated = 2011-07-04, EXP]{\prg_replicate:nn}
@@ -570,54 +466,6 @@
% nesting. It yields its result after two expansion steps.
% \end{function}
%
-% \begin{function}[updated = 2011-09-06,rEXP]{\prg_stepwise_function:nnnN}
-% \begin{syntax}
-% \cs{prg_stepwise_function:nnnN} \Arg{initial value} \Arg{step} \Arg{final value} \meta{function}
-% \end{syntax}
-% This function first evaluates the \meta{initial value}, \meta{step}
-% and \meta{final value}, all of which should be integer expressions.
-% The \meta{function} is then placed in front of each \meta{value}
-% from the \meta{initial value} to the \meta{final value} in turn
-% (using \meta{step} between each \meta{value}). Thus \meta{function}
-% should absorb one numerical argument. For example
-% \begin{verbatim}
-% \cs_set:Npn \my_func:n #1 { [I~saw~#1] \quad }
-% \prg_stepwise_function:nnnN { 1 } { 1 } { 5 } \my_func:n
-% \end{verbatim}
-% would print
-% \begin{quote}
-% [I saw 1] \quad
-% [I saw 2] \quad
-% [I saw 3] \quad
-% [I saw 4] \quad
-% [I saw 5] \quad
-% \end{quote}
-% \end{function}
-%
-% \begin{function}[updated = 2011-09-06]{\prg_stepwise_inline:nnnn}
-% \begin{syntax}
-% \cs{prg_stepwise_inline:nnnn} \Arg{initial value} \Arg{step} \Arg{final value} \Arg{code}
-% \end{syntax}
-% This function first evaluates the \meta{initial value}, \meta{step}
-% and \meta{final value}, all of which should be integer expressions.
-% The \meta{code} is then placed in front of each \meta{value}
-% from the \meta{initial value} to the \meta{final value} in turn
-% (using \meta{step} between each \meta{value}). Thus the \meta{code}
-% should define a function of one argument (|#1|).
-% \end{function}
-%
-% \begin{function}[updated = 2011-09-06]{\prg_stepwise_variable:nnnNn}
-% \begin{syntax}
-% \cs{prg_stepwise_variable:nnnNn} \\
-% ~~\Arg{initial value} \Arg{step} \Arg{final value} \meta{tl~var} \Arg{code}
-% \end{syntax}
-% This function first evaluates the \meta{initial value}, \meta{step}
-% and \meta{final value}, all of which should be integer expressions.
-% The \meta{code} is inserted into the input stream, with the
-% \meta{tl~var} defined as the current \meta{value}. Thus the
-% \meta{code} should make use of the \meta{tl~var}.
-% \end{function}
-%
% \section{Detecting \TeX{}'s mode}
%
% \begin{function}[EXP,pTF]{\mode_if_horizontal:}
@@ -651,6 +499,26 @@
% Detects if \TeX{} is currently in vertical mode.
% \end{function}
%
+% \section{Primitive conditionals}
+%
+% \begin{function}[EXP]{\if_predicate:w}
+% \begin{syntax}
+% "\if_predicate:w" <predicate> <true code> "\else:" <false code> "\fi:"
+% \end{syntax}
+% This function takes a predicate function and
+% branches according to the result. (In practice this function would also
+% accept a single boolean variable in place of the <predicate> but to make the
+% coding clearer this should be done through "\if_bool:N".)
+% \end{function}
+%
+% \begin{function}[EXP]{\if_bool:N}
+% \begin{syntax}
+% "\if_bool:N" <boolean> <true code> "\else:" <false code> "\fi:"
+% \end{syntax}
+% This function takes a boolean variable and
+% branches according to the result.
+% \end{function}
+%
% \section{Internal programming functions}
%
% \begin{function}[updated = 2011-08-11, EXP]
@@ -692,61 +560,70 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}[EXP]{\prg_variable_get_scope:N}
+% \begin{function}[EXP]{\__prg_variable_get_scope:N}
% \begin{syntax}
-% \cs{prg_variable_get_scope:N} \meta{variable}
+% \cs{__prg_variable_get_scope:N} \meta{variable}
% \end{syntax}
% Returns the scope (\texttt{g} for global, blank otherwise) for the
% \meta{variable}.
% \end{function}
%
-% \begin{function}[EXP]{\prg_variable_get_type:N}
+% \begin{function}[EXP]{\__prg_variable_get_type:N}
% \begin{syntax}
-% \cs{prg_variable_get_type:N} \meta{variable}
+% \cs{__prg_variable_get_type:N} \meta{variable}
% \end{syntax}
% Returns the type of \meta{variable} (\texttt{tl}, \texttt{int},
% \emph{etc.})
% \end{function}
%
-% \begin{function}[EXP]{\if_predicate:w}
+% \begin{function}[EXP]{\__prg_break_point:Nn}
% \begin{syntax}
-% "\if_predicate:w" <predicate> <true code> "\else:" <false code> "\fi:"
+% \cs{__prg_break_point:Nn} \cs{\meta{type}_map_break:} \meta{tokens}
% \end{syntax}
-% This function takes a predicate function and
-% branches according to the result. (In practice this function would also
-% accept a single boolean variable in place of the <predicate> but to make the
-% coding clearer this should be done through "\if_bool:N".)
+% Used to mark the end of a recursion or mapping: the functions
+% \cs{\meta{type}_map_break:} and \cs{\meta{type}_map_break:n} use
+% this to break out of the loop. After the loop ends, the
+% \meta{tokens} are inserted into the input stream. This occurs even
+% if the the break functions are \emph{not} applied:
+% \cs{__prg_break_point:Nn} is functionally-equivalent in these cases
+% to \cs{use_ii:nn}.
% \end{function}
%
-% \begin{function}[EXP]{\if_bool:N}
+% \begin{function}[EXP]{\__prg_map_break:Nn}
% \begin{syntax}
-% "\if_bool:N" <boolean> <true code> "\else:" <false code> "\fi:"
+% \cs{__prg_map_break:Nn} \cs{\meta{type}_map_break:} \Arg{user code}
+% \ldots{}
+% \cs{__prg_break_point:Nn} \cs{\meta{type}_map_break:} \Arg{ending code}
% \end{syntax}
-% This function takes a boolean variable and
-% branches according to the result.
+% Breaks a recursion in mapping contexts, inserting in the input
+% stream the \meta{user code} after the \meta{ending code} for the
+% loop. The function breaks loops, inserting their \meta{ending
+% code}, until reaching a loop with the same \meta{type} as its
+% first argument. This \cs{\meta{type}_map_break:} argument is simply
+% used as a recognizable marker for the \meta{type}.
% \end{function}
%
-% \begin{function}[EXP]{\prg_break_point:n}
-% \begin{syntax}
-% \cs{prg_break_point:n} \meta{tokens}
-% \end{syntax}
-% Used to mark the end of a recursion or mapping: the functions
-% \cs{prg_map_break:} and \cs{prg_map_break:n} use this to break out
-% of the loop. After the loop ends, the \meta{tokens} are inserted into
-% the input stream. This occurs even if the the break functions are
-% \emph{not} applied: \cs{prg_break_point:n} is functionally-equivalent
-% in these cases to \cs{use:n}.
+% \begin{variable}{\g__prg_map_int}
+% This integer is used by non-expandable mapping functions to track
+% the level of nesting in force. The functions \cs{__prg_map_1:w},
+% \cs{__prg_map_2:w}, \emph{etc.}, labelled by \cs{g__prg_map_int}
+% hold functions to be mapped over various list datatypes in inline
+% and variable mappings.
+% \end{variable}
+%
+% \begin{function}[EXP]{\__prg_break_point:}
+% This copy of \cs{prg_do_nothing:} is used to mark the end of a fast
+% short-term recursions: the function \cs{__prg_break:n} uses this to
+% break out of the loop.
% \end{function}
%
-% \begin{function}[EXP]{\prg_map_break:, \prg_map_break:n}
+% \begin{function}[EXP]{\__prg_break:, \__prg_break:n}
% \begin{syntax}
-% \cs{prg_map_break:n} \Arg{user code}
-% \ldots{}
-% \cs{prg_break_point:n} \Arg{ending code}
+% \cs{__prg_break:n} \Arg{tokens} \ldots{} \cs{__prg_break_point:}
% \end{syntax}
-% Breaks a recursion in mapping contexts, inserting
-% in the input stream the \meta{user code} after the
-% \meta{ending code} for the loop.
+% Breaks a recursion which has no \meta{ending code} and which is not
+% a user-breakable mapping (see for instance \cs{prop_get:Nn}), and
+% inserts \meta{tokens} in the input stream.
% \end{function}
%
% \end{documentation}
@@ -765,7 +642,7 @@
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -815,6 +692,10 @@
%
% \subsection{The boolean data type}
%
+% \begin{macrocode}
+%<@@=bool>
+% \end{macrocode}
+%
% \begin{macro}{\bool_new:N, \bool_new:c}
% \UnitTested
% Boolean variables have to be initiated when they are created. Other
@@ -874,7 +755,7 @@
% \begin{macro}{\bool_set:Nn,\bool_set:cn}
% \begin{macro}{\bool_gset:Nn,\bool_gset:cn}
% This function evaluates a boolean expression and assigns the first
-% argument the meaning |\c_true_bool| or |\c_false_bool|.
+% argument the meaning \cs{c_true_bool} or \cs{c_false_bool}.
% \begin{macrocode}
\cs_new_protected:Npn \bool_set:Nn #1#2
{ \tex_chardef:D #1 = \bool_if_p:n {#2} }
@@ -884,6 +765,7 @@
\cs_generate_variant:Nn \bool_gset:Nn { c }
% \end{macrocode}
% \end{macro}
+% \end{macro}
%
% \begin{macro}[pTF]{\bool_if:N, \bool_if:c}
% \UnitTested
@@ -904,11 +786,10 @@
\cs_generate_variant:Nn \bool_if:NTF { c }
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \begin{macro}{\bool_show:N, \bool_show:c, \bool_show:n}
% Show the truth value of the boolean, as \texttt{true} or
-% \texttt{false}. We use \cs{msg_aux_show:x} to get a better output;
+% \texttt{false}. We use \cs{__msg_show_variable:x} to get a better output;
% this function requires its argument to start with |>|.
% \begin{macrocode}
\cs_new_protected:Npn \bool_show:N #1
@@ -916,25 +797,27 @@
\bool_if_exist:NTF #1
{ \bool_show:n {#1} }
{
- \msg_kernel_error:nnx { kernel } { variable-not-defined }
+ \__msg_kernel_error:nnx { kernel } { variable-not-defined }
{ \token_to_str:N #1 }
}
}
\cs_new_protected:Npn \bool_show:n #1
{
\bool_if:nTF {#1}
- { \msg_aux_show:x { > true } }
- { \msg_aux_show:x { > false } }
+ { \__msg_show_variable:x { > true } }
+ { \__msg_show_variable:x { > false } }
}
\cs_generate_variant:Nn \bool_show:N { c }
% \end{macrocode}
% \end{macro}
%
-% \begin{variable}{\l_tmpa_bool, \g_tmpa_bool}
+% \begin{variable}{\l_tmpa_bool, \l_tmpb_bool, \g_tmpa_bool, \g_tmpb_bool}
% A few booleans just if you need them.
% \begin{macrocode}
\bool_new:N \l_tmpa_bool
+\bool_new:N \l_tmpb_bool
\bool_new:N \g_tmpa_bool
+\bool_new:N \g_tmpb_bool
% \end{macrocode}
% \end{variable}
%
@@ -956,36 +839,12 @@
%
% \begin{macro}[pTF]{\bool_if:n}
% \UnitTested
-% \begin{macro}[aux]{\bool_get_next:N}
-% \begin{macro}[aux]{\bool_cleanup:N}
-% \begin{macro}[aux]{\bool_choose:NN}
-% \begin{macro}[aux]
-% {
-% bool_!:w,
-% \bool_Not:w,
-% \bool_Not:w,
-% \bool_(:w,
-% \bool_p:w,
-% \bool_8_1:w,
-% \bool_I_1:w,
-% \bool_8_0:w,
-% \bool_I_0:w,
-% \bool_)_0:w,
-% \bool_)_1:w,
-% \bool_S_0:w,
-% \bool_S_1:w
-% }
-% \begin{macro}[aux]
-% {
-% \bool_eval_skip_to_end:Nw, \bool_eval_skip_to_end_aux:Nw,
-% \bool_eval_skip_to_end_aux_ii:Nw
-% }
-% Evaluating the truth value of a list of predicates is done using
-% an input syntax somewhat similar to the one found in other
-% programming languages with |(| and |)| for grouping, |!| for
-% logical \enquote{Not}, |&&| for logical \enquote{And} and \verb"||"
-% for logical \enquote{Or}. We shall use the terms Not, And, Or, Open and
-% Close for these operations.
+% Evaluating the truth value of a list of predicates is done using an
+% input syntax somewhat similar to the one found in other programming
+% languages with |(| and |)| for grouping, |!| for logical
+% \enquote{Not}, |&&| for logical \enquote{And} and \verb"||" for
+% logical \enquote{Or}. We shall use the terms Not, And, Or, Open and
+% Close for these operations.
%
% Any expression is terminated by a Close operation. Evaluation
% happens from left to right in the following manner using a GetNext
@@ -993,16 +852,18 @@
% \begin{itemize}
% \item If an Open is seen, start evaluating a new expression using
% the Eval function and call GetNext again.
-% \item If a Not is seen, insert a negating function (if-even in
-% this case) and call GetNext.
-% \item If none of the above, start evaluating a new expression by
-% reinserting the token found (this is supposed to be a predicate
-% function) in front of Eval.
+% \item If a Not is seen, remove the |!| and call a GetNotNext
+% function, which eventually reverses the logic compared to
+% GetNext.
+% \item If none of the above, reinsert the token found (this is
+% supposed to be a predicate function) in front of an Eval
+% function, which evaluates it to the boolean value \meta{true} or
+% \meta{false}.
% \end{itemize}
% The Eval function then contains a post-processing operation which
-% grabs the instruction following the predicate. This is either And,
-% Or or Close. In each case the truth value is used to determine
-% where to go next. The following situations can arise:
+% grabs the instruction following the predicate. This is either And,
+% Or or Close. In each case the truth value is used to determine
+% where to go next. The following situations can arise:
% \begin{description}
% \item[\meta{true}And] Current truth value is true, logical And
% seen, continue with GetNext to examine truth value of next
@@ -1021,8 +882,8 @@
% \item[\meta{false}Close] Current truth value is false, Close
% seen, return \meta{false}.
% \end{description}
-% We introduce an additional Stop operation with the following
-% semantics:
+% We introduce an additional Stop operation with the same
+% semantics as the Close operation.
% \begin{description}
% \item[\meta{true}Stop] Current truth value is true, return
% \meta{true}.
@@ -1030,17 +891,6 @@
% \meta{false}.
% \end{description}
% The reasons for this follow below.
-%
-% Now for how these works in practice. The canonical true and false
-% values have numerical values $1$ and $0$ respectively. We evaluate
-% this using the primitive |\int_value:w:D| operation. First we
-% issue a |\group_align_safe_begin:| as we are using |&&| as syntax
-% shorthand for the And operation and we need to hide it for \TeX{}.
-% We also need to finish this special group before finally
-% returning a |\c_true_bool| or |\c_false_bool| as there might
-% otherwise be something left in front in the input stream. For
-% this we call the Stop operation, denoted simply by a |S|
-% following the last Close operation.
% \begin{macrocode}
\prg_new_conditional:Npnn \bool_if:n #1 { T , F , TF }
{
@@ -1050,178 +900,195 @@
\prg_return_false:
\fi:
}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\bool_if_p:n}
+% \begin{macro}[EXP, aux]
+% {
+% \@@_if_left_parentheses:wwwn ,
+% \@@_if_right_parentheses:wwwn ,
+% \@@_if_or:wwwn
+% }
+% First issue a \cs{group_align_safe_begin:} as we are using |&&|
+% as syntax shorthand for the And operation and we need to hide it for
+% \TeX{}. This will be closed at the end of the expression parsing
+% (see |S| below).
+%
+% Minimal (\enquote{short-circuit}) evaluation of boolean expressions
+% requires skipping to the end of the current parenthesized group when
+% \meta{true}\verb"||" is seen, but to the next \verb"||" or closing
+% parenthesis when \meta{false}|&&| is seen. To avoid having separate
+% functions for the two cases, we transform the boolean expression by
+% doubling each parenthesis and adding parenthesis around each
+% \verb"||". This ensures that |&&| will bind tighter than \verb"||".
+%
+% The replacement is done in three passes, for left and right
+% parentheses and for \verb"||". At each pass, the part of the
+% expression that has been transformed is stored before \cs{q_nil},
+% the rest lies until the first \cs{q_mark}, followed by an empty
+% brace group. A trailing marker ensures that the auxiliaries'
+% delimited arguments will not run-away. As long as the delimiter
+% matches inside the expression, material is moved before \cs{q_nil}
+% and we continue. Afterwards, the trailing marker is taken as a
+% delimiter, |#4| is the next auxiliary, immediately followed by a new
+% \cs{q_nil} delimiter, which indicates that nothing has been treated
+% at this pass. The last step calls \cs{@@_if_parse:NNNww} which
+% cleans up and triggers the evaluation of the expression itself.
+% \begin{macrocode}
\cs_new:Npn \bool_if_p:n #1
{
\group_align_safe_begin:
- \bool_get_next:N ( #1 ) S
+ \@@_if_left_parentheses:wwwn \q_nil
+ #1 \q_mark { }
+ ( \q_mark { \@@_if_right_parentheses:wwwn \q_nil }
+ ) \q_mark { \@@_if_or:wwwn \q_nil }
+ || \q_mark \@@_if_parse:NNNww
+ \q_stop
}
+\cs_new:Npn \@@_if_left_parentheses:wwwn #1 \q_nil #2 ( #3 \q_mark #4
+ { #4 \@@_if_left_parentheses:wwwn #1 #2 (( \q_nil #3 \q_mark {#4} }
+\cs_new:Npn \@@_if_right_parentheses:wwwn #1 \q_nil #2 ) #3 \q_mark #4
+ { #4 \@@_if_right_parentheses:wwwn #1 #2 )) \q_nil #3 \q_mark {#4} }
+\cs_new:Npn \@@_if_or:wwwn #1 \q_nil #2 || #3 \q_mark #4
+ { #4 \@@_if_or:wwwn #1 #2 )||( \q_nil #3 \q_mark {#4} }
% \end{macrocode}
-% The GetNext operation. We make it a switch: If not a |!| or |(|, we
-% assume it is a predicate.
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP, aux]{\@@_if_parse:NNNww}
+% After removing extra tokens from the transformation phase, start
+% evaluating. At the end, we will need to finish the special
+% \texttt{align_safe} group before finally
+% returning a \cs{c_true_bool} or \cs{c_false_bool} as there might
+% otherwise be something left in front in the input stream. For this
+% we call the Stop operation, denoted simply by a |S| following the
+% last Close operation.
% \begin{macrocode}
-\cs_new:Npn \bool_get_next:N #1
+\cs_new:Npn \@@_if_parse:NNNww #1#2#3#4 \q_mark #5 \q_stop
{
- \use:c
- {
- bool_
- \if_meaning:w !#1 ! \else: \if_meaning:w (#1 ( \else: p \fi: \fi:
- :w
- }
- #1
+ \__bool_get_next:NN \use_i:nn (( #4 )) S
}
% \end{macrocode}
-% This variant gets called when a Not has just been entered.
-% It (eventually) results in a reversal of the logic of the directly
-% following material.
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_get_next:NN}
+% The GetNext operation. This is a switch: if what follows is neither
+% |!| nor |(|, we assume it is a predicate. The first argument is
+% \cs{use_ii:nn} if the logic must eventually be reversed (after a
+% |!|), otherwise it is \cs{use_i:nn}. This function eventually
+% expand to the truth value \cs{c_true_bool} or \cs{c_false_bool} of
+% the expression which follows until the next unmatched closing
+% parenthesis.
% \begin{macrocode}
-\cs_new:Npn \bool_get_not_next:N #1
+\cs_new:Npn \@@_get_next:NN #1#2
{
\use:c
{
- bool_not_
- \if_meaning:w !#1 ! \else: \if_meaning:w (#1 ( \else: p \fi: \fi:
- :w
+ @@_
+ \if_meaning:w !#2 ! \else: \if_meaning:w (#2 ( \else: p \fi: \fi:
+ :Nw
}
- #1
- }
-% \end{macrocode}
-% We need these later on to nullify the unity operation |!!|.
-% \begin{macrocode}
-\cs_new:Npn \bool_get_next:NN #1#2 { \bool_get_next:N #2 }
-\cs_new:Npn \bool_get_not_next:NN #1#2 { \bool_get_not_next:N #2 }
-% \end{macrocode}
-% The Not operation. Discard the token read and reverse the truth
-% value of the next expression if there
-% are brackets; otherwise
-% if we're coming up to a |!| then we don't need to reverse anything
-% (but we then want to continue scanning ahead in case some fool has written
-% |!!(...)|);
-% otherwise we have a boolean that we can reverse here and now.
-% \begin{macrocode}
-\cs_new:cpn { bool_!:w } #1#2
- {
- \if_meaning:w ( #2
- \exp_after:wN \bool_Not:w
- \else:
- \if_meaning:w ! #2
- \exp_after:wN \exp_after:wN \exp_after:wN \bool_get_next:NN
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN \bool_Not:N
- \fi:
- \fi:
- #2
- }
-% \end{macrocode}
-% Variant called when already inside a Not.
-% Essentially the opposite of the above.
-% \begin{macrocode}
-\cs_new:cpn { bool_not_!:w } #1#2
- {
- \if_meaning:w ( #2
- \exp_after:wN \bool_not_Not:w
- \else:
- \if_meaning:w ! #2
- \exp_after:wN \exp_after:wN \exp_after:wN \bool_get_not_next:NN
- \else:
- \exp_after:wN \exp_after:wN \exp_after:wN \bool_not_Not:N
- \fi:
- \fi:
- #2
+ #1 #2
}
% \end{macrocode}
-% These occur when processing |!(...)|. The idea is to use a variant
-% of |\bool_get_next:N| that finishes its parsing with a logic reversal.
-% Of course, the double logic reversal gets us back to where we started.
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_!:Nw}
+% The Not operation reverses the logic: discard the |!| token and call
+% the GetNext operation with its first argument reversed.
% \begin{macrocode}
-\cs_new:Npn \bool_Not:w { \exp_after:wN \int_value:w \bool_get_not_next:N }
-\cs_new:Npn \bool_not_Not:w { \exp_after:wN \int_value:w \bool_get_next:N }
+\cs_new:cpn { @@_!:Nw } #1#2
+ { \exp_after:wN \@@_get_next:NN #1 \use_ii:nn \use_i:nn }
% \end{macrocode}
-% These occur when processing |!<bool>| and can be evaluated directly.
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_(:Nw}
+% The Open operation starts a sub-expression after discarding the
+% token. This is done by calling GetNext, with a post-processing step
+% which looks for And, Or or Close afterwards.
% \begin{macrocode}
-\cs_new:Npn \bool_Not:N #1
+\cs_new:cpn { @@_(:Nw } #1#2
{
- \exp_after:wN \bool_p:w
- \if_meaning:w #1 \c_true_bool
- \c_false_bool
- \else:
- \c_true_bool
- \fi:
+ \exp_after:wN \@@_choose:NNN \exp_after:wN #1
+ \__int_value:w \@@_get_next:NN \use_i:nn
}
-\cs_new:Npn \bool_not_Not:N #1
- {
- \exp_after:wN \bool_p:w
- \if_meaning:w #1 \c_true_bool
- \c_true_bool
- \else:
- \c_false_bool
- \fi:
- }
-% \end{macrocode}
-% The Open operation. Discard the token read and start a
-% sub-expression.
-% |\bool_get_next:N| continues building up the logical expressions as usual;
-% |\bool_not_cleanup:N| is what reverses the logic if we're inside |!(...)|.
-% \begin{macrocode}
-\cs_new:cpn { bool_(:w } #1
- { \exp_after:wN \bool_cleanup:N \int_value:w \bool_get_next:N }
-\cs_new:cpn { bool_not_(:w } #1
- { \exp_after:wN \bool_not_cleanup:N \int_value:w \bool_get_next:N }
% \end{macrocode}
-% Otherwise just evaluate the predicate and look for And, Or or Close
-% afterwards.
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_p:Nw}
+% If what follows GetNext is neither |!| nor |(|, evaluate the
+% predicate using the primitive \cs{__int_value:w}. The canonical
+% true and false values have numerical values $1$ and $0$
+% respectively. Look for And, Or or Close afterwards.
% \begin{macrocode}
-\cs_new:cpn { bool_p:w } { \exp_after:wN \bool_cleanup:N \int_value:w }
-\cs_new:cpn { bool_not_p:w } {\exp_after:wN \bool_not_cleanup:N \int_value:w }
+\cs_new:cpn { @@_p:Nw } #1
+ { \exp_after:wN \@@_choose:NNN \exp_after:wN #1 \__int_value:w }
% \end{macrocode}
-% This cleanup function can be omitted once predicates return their
-% true/false booleans outside the conditionals.
+% \end{macro}
+%
+% \begin{macro}[aux]{\@@_choose:NNN}
+% Branching the eight-way switch. The arguments are 1: \cs{use_i:nn}
+% or \cs{use_ii:nn}, 2: $0$ or $1$ encoding the current truth value,
+% 3: the next operation, And, Or, Close or Stop. If |#1| is
+% \cs{use_ii:nn}, the logic of |#2| must be reversed.
% \begin{macrocode}
-\cs_new:Npn \bool_cleanup:N #1
+\cs_new:Npn \@@_choose:NNN #1#2#3
{
- \exp_after:wN \bool_choose:NN \exp_after:wN #1
- \int_to_roman:w - `\q
- }
-\cs_new:Npn \bool_not_cleanup:N #1
- {
- \exp_after:wN \bool_not_choose:NN \exp_after:wN #1
- \int_to_roman:w - `\q
+ \use:c
+ {
+ @@_ #3 _
+ #1 #2 { \if_meaning:w 0 #2 1 \else: 0 \fi: }
+ :w
+ }
}
% \end{macrocode}
-% Branching the six way switch.
-% Reversals should be reasonably straightforward.
-% \begin{macrocode}
-\cs_new:Npn \bool_choose:NN #1#2 { \use:c { bool_ #2 _ #1 :w } }
-\cs_new:Npn \bool_not_choose:NN #1#2 { \use:c { bool_not_ #2 _ #1 :w } }
-% \end{macrocode}
-% Continues scanning. Must remove the second "&" or \verb"|".
-% \begin{macrocode}
-\cs_new_nopar:cpn { bool_&_1:w } & { \bool_get_next:N }
-\cs_new_nopar:cpn { bool_|_0:w } | { \bool_get_next:N }
-\cs_new_nopar:cpn { bool_not_&_0:w } & { \bool_get_next:N }
-\cs_new_nopar:cpn { bool_not_|_1:w } | { \bool_get_next:N }
-% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux]
+% {
+% \@@_)_0:w,
+% \@@_)_1:w,
+% \@@_S_0:w,
+% \@@_S_1:w,
+% }
% Closing a group is just about returning the result. The Stop
% operation is similar except it closes the special alignment group
% before returning the boolean.
% \begin{macrocode}
-\cs_new_nopar:cpn { bool_)_0:w } { \c_false_bool }
-\cs_new_nopar:cpn { bool_)_1:w } { \c_true_bool }
-\cs_new_nopar:cpn { bool_not_)_0:w } { \c_true_bool }
-\cs_new_nopar:cpn { bool_not_)_1:w } { \c_false_bool }
-\cs_new_nopar:cpn { bool_S_0:w } { \group_align_safe_end: \c_false_bool }
-\cs_new_nopar:cpn { bool_S_1:w } { \group_align_safe_end: \c_true_bool }
+\cs_new_nopar:cpn { @@_)_0:w } { \c_false_bool }
+\cs_new_nopar:cpn { @@_)_1:w } { \c_true_bool }
+\cs_new_nopar:cpn { @@_S_0:w } { \group_align_safe_end: \c_false_bool }
+\cs_new_nopar:cpn { @@_S_1:w } { \group_align_safe_end: \c_true_bool }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[aux]+\@@_&_1:w+
+% \begin{macro}[aux]+\@@_|_0:w+
+% Two cases where we simply continue scanning. We must remove the
+% second "&" or \verb"|".
+% \begin{macrocode}
+\cs_new_nopar:cpn { @@_&_1:w } & { \@@_get_next:NN \use_i:nn }
+\cs_new_nopar:cpn { @@_|_0:w } | { \@@_get_next:NN \use_i:nn }
% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[aux]+\@@_&_0:w+
+% \begin{macro}[aux]+\@@_|_1:w+
+% \begin{macro}[aux]
+% {
+% \@@_eval_skip_to_end:Nw,
+% \@@_eval_skip_to_end_ii:Nw,
+% \@@_eval_skip_to_end_iii:Nw
+% }
% When the truth value has already been decided, we have to throw away
% the remainder of the current group as we are doing minimal
% evaluation. This is slightly tricky as there are no braces so we
% have to play match the |()| manually.
% \begin{macrocode}
-\cs_new_nopar:cpn { bool_&_0:w } & { \bool_eval_skip_to_end:Nw \c_false_bool }
-\cs_new_nopar:cpn { bool_|_1:w } | { \bool_eval_skip_to_end:Nw \c_true_bool }
-\cs_new_nopar:cpn { bool_not_&_1:w } &
- { \bool_eval_skip_to_end:Nw \c_false_bool }
-\cs_new_nopar:cpn { bool_not_|_0:w } |
- { \bool_eval_skip_to_end:Nw \c_true_bool }
+\cs_new_nopar:cpn { @@_&_0:w } & { \@@_eval_skip_to_end:Nw \c_false_bool }
+\cs_new_nopar:cpn { @@_|_1:w } | { \@@_eval_skip_to_end:Nw \c_true_bool }
% \end{macrocode}
% There is always at least one |)| waiting, namely the outer
% one. However, we are facing the problem that there may be more than
@@ -1275,9 +1142,9 @@
% finally close the group nicely.
% \begin{macrocode}
%% (
-\cs_new:Npn \bool_eval_skip_to_end:Nw #1#2 )
+\cs_new:Npn \@@_eval_skip_to_end:Nw #1#2 )
{
- \bool_eval_skip_to_end_aux:Nw #1#2 ( % )
+ \@@_eval_skip_to_end_ii:Nw #1#2 ( % )
\q_no_value \q_stop
{#2}
}
@@ -1286,31 +1153,29 @@
% the boolean |#1|. If there is, we need to grab a |()| pair and then
% recurse
% \begin{macrocode}
-\cs_new:Npn \bool_eval_skip_to_end_aux:Nw #1#2 ( #3#4 \q_stop #5 % )
+\cs_new:Npn \@@_eval_skip_to_end_ii:Nw #1#2 ( #3#4 \q_stop #5 % )
{
\quark_if_no_value:NTF #3
{#1}
- { \bool_eval_skip_to_end_aux_ii:Nw #1 #5 }
+ { \@@_eval_skip_to_end_iii:Nw #1 #5 }
}
% \end{macrocode}
% Keep the boolean, throw away anything up to the |(| as it is
% irrelevant, remove a |()| pair but remember to reinsert |#3| as it may
% contain |(| tokens!
% \begin{macrocode}
-\cs_new:Npn \bool_eval_skip_to_end_aux_ii:Nw #1#2 ( #3 )
+\cs_new:Npn \@@_eval_skip_to_end_iii:Nw #1#2 ( #3 )
{ % (
- \bool_eval_skip_to_end:Nw #1#3 )
+ \@@_eval_skip_to_end:Nw #1#3 )
}
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
%
% \begin{macro}{\bool_not_p:n}
% \UnitTested
-% The Not variant just reverses the outcome of |\bool_if_p:n|. Can
+% The Not variant just reverses the outcome of \cs{bool_if_p:n}. Can
% be optimized but this is nice and simple and according to the
% implementation plan. Not even particularly useful to have it when
% the infix notation is easier to use.
@@ -1410,156 +1275,42 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{Switching by case}
-%
-% A family of functions to select one case of a number: the same ideas
-% are used for a number of different situations.
-%
-% \begin{macro}[aux]{\prg_case_end:nw}
-% In all cases the end statement is the same. Here, |#1| will be the
-% code needed, |#2| the other cases to throw away, including the
-% \enquote{else} case. The \cs{c_zero} marker stops the expansion of
-% \tn{romannumeral} which begins each \cs{prg_case_...} function.
-% \begin{macrocode}
-\cs_new:Npn \prg_case_end:nw #1 #2 \q_recursion_stop { \c_zero #1 }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\prg_case_int:nnn}
-% \UnitTested
-% \begin{macro}[aux]{\prg_case_int_aux:nnn,\prg_case_int_aux:nw}
-% For integer cases, the first task to fully expand the check
-% condition. After that, a loop is started to compare each possible
-% value and stop if the test is true. The tested value is put at the
-% end to ensure that there is necessarily a match, which will fire the
-% \enquote{else} pathway. The leading \tn{romannumeral} triggers an
-% expansion which is then stopped in \cs{prg_case_end:nw}.
-% \begin{macrocode}
-\cs_new:Npn \prg_case_int:nnn #1
- {
- \tex_romannumeral:D
- \exp_args:Nf \prg_case_int_aux:nnn { \int_eval:n {#1} }
- }
-\cs_new:Npn \prg_case_int_aux:nnn #1 #2 #3
- { \prg_case_int_aux:nw {#1} #2 {#1} {#3} \q_recursion_stop }
-\cs_new:Npn \prg_case_int_aux:nw #1#2#3
- {
- \int_compare:nNnTF {#1} = {#2}
- { \prg_case_end:nw {#3} }
- { \prg_case_int_aux:nw {#1} }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\prg_case_dim:nnn}
-% \UnitTested
-% \begin{macro}[aux]{\prg_case_dim_aux:nnn,\prg_case_dim_aux:nw}
-% The dimension function is the same, just a change of calculation
-% method.
-% \begin{macrocode}
-\cs_new:Npn \prg_case_dim:nnn #1
- {
- \tex_romannumeral:D
- \exp_args:Nf \prg_case_dim_aux:nnn { \dim_eval:n {#1} }
- }
-\cs_new:Npn \prg_case_dim_aux:nnn #1 #2 #3
- { \prg_case_dim_aux:nw {#1} #2 {#1} {#3} \q_recursion_stop }
-\cs_new:Npn \prg_case_dim_aux:nw #1#2#3
- {
- \dim_compare:nNnTF {#1} = {#2}
- { \prg_case_end:nw {#3} }
- { \prg_case_dim_aux:nw {#1} }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\prg_case_str:nnn, \prg_case_str:onn, \prg_case_str:xxn}
-% \UnitTested
-% \begin{macro}[aux]{\prg_case_str_aux:nw, \prg_case_str_x_aux:nw}
-% No calculations for strings, otherwise no surprises.
-% \begin{macrocode}
-\cs_new:Npn \prg_case_str:nnn #1#2#3
- {
- \tex_romannumeral:D
- \prg_case_str_aux:nw {#1} #2 {#1} {#3} \q_recursion_stop
- }
-\cs_new:Npn \prg_case_str_aux:nw #1#2#3
- {
- \str_if_eq:nnTF {#1} {#2}
- { \prg_case_end:nw {#3} }
- { \prg_case_str_aux:nw {#1} }
- }
-\cs_generate_variant:Nn \prg_case_str:nnn { o }
-\cs_new:Npn \prg_case_str:xxn #1#2#3
- {
- \tex_romannumeral:D
- \prg_case_str_x_aux:nw {#1} #2 {#1} {#3} \q_recursion_stop
- }
-\cs_new:Npn \prg_case_str_x_aux:nw #1#2#3
- {
- \str_if_eq:xxTF {#1} {#2}
- { \prg_case_end:nw {#3} }
- { \prg_case_str_x_aux:nw {#1} }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
+% \subsection{Producing $n$ copies}
%
-% \begin{macro}{\prg_case_tl:Nnn, \prg_case_tl:cnn}
-% \UnitTested
-% \begin{macro}[aux]{\prg_case_tl_aux:Nw}
-% Similar again, but this time with some variants.
% \begin{macrocode}
-\cs_new:Npn \prg_case_tl:Nnn #1#2#3
- {
- \tex_romannumeral:D
- \prg_case_tl_aux:Nw #1 #2 #1 {#3} \q_recursion_stop
- }
-\cs_new:Npn \prg_case_tl_aux:Nw #1#2#3
- {
- \tl_if_eq:NNTF #1 #2
- { \prg_case_end:nw {#3} }
- { \prg_case_tl_aux:Nw #1 }
- }
-\cs_generate_variant:Nn \prg_case_tl:Nnn { c }
+%<@@=prg>
% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \subsection{Producing $n$ copies}
%
% \begin{macro}{\prg_replicate:nn}
% \UnitTested
-% \begin{macro}[aux]{\prg_replicate_aux:N, \prg_replicate_first_aux:N}
-% \begin{macro}[aux]{\prg_replicate_}
+% \begin{macro}[aux]{\@@_replicate:N, \@@_replicate_first:N}
+% \begin{macro}[aux]{\@@_replicate_}
% \begin{macro}[aux]
% {
-% \prg_replicate_0:n,
-% \prg_replicate_1:n,
-% \prg_replicate_2:n,
-% \prg_replicate_3:n,
-% \prg_replicate_4:n,
-% \prg_replicate_5:n,
-% \prg_replicate_6:n,
-% \prg_replicate_7:n,
-% \prg_replicate_8:n,
-% \prg_replicate_9:n
+% \@@_replicate_0:n,
+% \@@_replicate_1:n,
+% \@@_replicate_2:n,
+% \@@_replicate_3:n,
+% \@@_replicate_4:n,
+% \@@_replicate_5:n,
+% \@@_replicate_6:n,
+% \@@_replicate_7:n,
+% \@@_replicate_8:n,
+% \@@_replicate_9:n
% }
% \begin{macro}[aux]
% {
-% \prg_replicate_first_-:n,
-% \prg_replicate_first_0:n,
-% \prg_replicate_first_1:n,
-% \prg_replicate_first_2:n,
-% \prg_replicate_first_3:n,
-% \prg_replicate_first_4:n,
-% \prg_replicate_first_5:n,
-% \prg_replicate_first_6:n,
-% \prg_replicate_first_7:n,
-% \prg_replicate_first_8:n,
-% \prg_replicate_first_9:n
+% \@@_replicate_first_-:n,
+% \@@_replicate_first_0:n,
+% \@@_replicate_first_1:n,
+% \@@_replicate_first_2:n,
+% \@@_replicate_first_3:n,
+% \@@_replicate_first_4:n,
+% \@@_replicate_first_5:n,
+% \@@_replicate_first_6:n,
+% \@@_replicate_first_7:n,
+% \@@_replicate_first_8:n,
+% \@@_replicate_first_9:n
% }
% This function uses a cascading csname technique by David Kastrup
% (who else :-)
@@ -1577,7 +1328,7 @@
% to avoid the last function to insert say, $100$ copies of the original
% argument just to gobble them again we define separate functions to
% be inserted first. These functions also close the expansion of
-% \cs{int_to_roman:w}, which ensures that \cs{prg_replicate:nn} only
+% \cs{__int_to_roman:w}, which ensures that \cs{prg_replicate:nn} only
% requires two steps of expansion.
%
% This function has one flaw though: Since it constantly passes down
@@ -1587,144 +1338,67 @@
% necessary, it is possible to write
% |\prg_replicate:nn{1000}{\prg_replicate:nn{1000}{|\meta{code}|}}|. An
% alternative approach is to create a string of |m|'s with
-% \cs{int_to_roman:w} which can be done with just four macros but that
+% \cs{__int_to_roman:w} which can be done with just four macros but that
% method has its own problems since it can exhaust the string
% pool. Also, it is considerably slower than what we use here so the
% few extra csnames are well spent I would say.
% \begin{macrocode}
\cs_new:Npn \prg_replicate:nn #1
{
- \int_to_roman:w
- \exp_after:wN \prg_replicate_first_aux:N
- \int_value:w \int_eval:w #1 \int_eval_end:
+ \__int_to_roman:w
+ \exp_after:wN \@@_replicate_first:N
+ \__int_value:w \__int_eval:w #1 \__int_eval_end:
\cs_end:
}
-\cs_new:Npn \prg_replicate_aux:N #1
- { \cs:w prg_replicate_#1 :n \prg_replicate_aux:N }
-\cs_new:Npn \prg_replicate_first_aux:N #1
- { \cs:w prg_replicate_first_ #1 :n \prg_replicate_aux:N }
+\cs_new:Npn \@@_replicate:N #1
+ { \cs:w @@_replicate_#1 :n \@@_replicate:N }
+\cs_new:Npn \@@_replicate_first:N #1
+ { \cs:w @@_replicate_first_ #1 :n \@@_replicate:N }
% \end{macrocode}
-% Then comes all the functions that do the hard work of inserting all
-% the copies.
+% Then comes all the functions that do the hard work of inserting all
+% the copies. The first function takes |:n| as a parameter.
% \begin{macrocode}
-\cs_new:Npn \prg_replicate_ :n #1 { \cs_end: }
-\cs_new:cpn { prg_replicate_0:n } #1 { \cs_end: {#1#1#1#1#1#1#1#1#1#1} }
-\cs_new:cpn { prg_replicate_1:n } #1 { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1 }
-\cs_new:cpn { prg_replicate_2:n } #1 { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1 }
-\cs_new:cpn { prg_replicate_3:n } #1
+\cs_new:Npn \@@_replicate_ :n #1 { \cs_end: }
+\cs_new:cpn { @@_replicate_0:n } #1 { \cs_end: {#1#1#1#1#1#1#1#1#1#1} }
+\cs_new:cpn { @@_replicate_1:n } #1 { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1 }
+\cs_new:cpn { @@_replicate_2:n } #1 { \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1 }
+\cs_new:cpn { @@_replicate_3:n } #1
{ \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1 }
-\cs_new:cpn { prg_replicate_4:n } #1
+\cs_new:cpn { @@_replicate_4:n } #1
{ \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1 }
-\cs_new:cpn { prg_replicate_5:n } #1
+\cs_new:cpn { @@_replicate_5:n } #1
{ \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1 }
-\cs_new:cpn { prg_replicate_6:n } #1
+\cs_new:cpn { @@_replicate_6:n } #1
{ \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1#1 }
-\cs_new:cpn { prg_replicate_7:n } #1
+\cs_new:cpn { @@_replicate_7:n } #1
{ \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1#1#1 }
-\cs_new:cpn { prg_replicate_8:n } #1
+\cs_new:cpn { @@_replicate_8:n } #1
{ \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1#1#1#1 }
-\cs_new:cpn { prg_replicate_9:n } #1
+\cs_new:cpn { @@_replicate_9:n } #1
{ \cs_end: {#1#1#1#1#1#1#1#1#1#1} #1#1#1#1#1#1#1#1#1 }
% \end{macrocode}
% Users shouldn't ask for something to be replicated once or even
% not at all but\dots
% \begin{macrocode}
-\cs_new:cpn { prg_replicate_first_-:n } #1
- { \c_zero \msg_expandable_kernel_error:nn { prg } { replicate-neg } }
-\cs_new:cpn { prg_replicate_first_0:n } #1 { \c_zero }
-\cs_new:cpn { prg_replicate_first_1:n } #1 { \c_zero #1 }
-\cs_new:cpn { prg_replicate_first_2:n } #1 { \c_zero #1#1 }
-\cs_new:cpn { prg_replicate_first_3:n } #1 { \c_zero #1#1#1 }
-\cs_new:cpn { prg_replicate_first_4:n } #1 { \c_zero #1#1#1#1 }
-\cs_new:cpn { prg_replicate_first_5:n } #1 { \c_zero #1#1#1#1#1 }
-\cs_new:cpn { prg_replicate_first_6:n } #1 { \c_zero #1#1#1#1#1#1 }
-\cs_new:cpn { prg_replicate_first_7:n } #1 { \c_zero #1#1#1#1#1#1#1 }
-\cs_new:cpn { prg_replicate_first_8:n } #1 { \c_zero #1#1#1#1#1#1#1#1 }
-\cs_new:cpn { prg_replicate_first_9:n } #1 { \c_zero #1#1#1#1#1#1#1#1#1 }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\prg_stepwise_function:nnnN}
-% \begin{macro}[aux]{\prg_stepwise_aux:nnnN}
-% \begin{macro}[aux]{\prg_stepwise_aux:NnnnN}
-% Repeating a function by steps first needs a check on the direction
-% of the steps. After that, do the function for the start value
-% then step and loop around. It would be more symmetrical to test
-% for a step size of zero before checking the sign, but we optimize
-% for the most frequent case (positive step).
-% \begin{macrocode}
-\cs_new:Npn \prg_stepwise_function:nnnN #1#2#3#4
+\cs_new:cpn { @@_replicate_first_-:n } #1
{
- \prg_stepwise_aux:nnnN {#1} {#2} {#3} #4
- \prg_break_point:n { }
- }
-\cs_new:Npn \prg_stepwise_aux:nnnN #1#2#3#4
- {
- \int_compare:nNnTF {#2} > \c_zero
- { \exp_args:NNf \prg_stepwise_aux:NnnnN > }
- {
- \int_compare:nNnTF {#2} = \c_zero
- {
- \msg_expandable_kernel_error:nnn { prg } { zero-step } {#4}
- \prg_map_break:
- }
- { \exp_args:NNf \prg_stepwise_aux:NnnnN < }
- }
- { \int_eval:n {#1} } {#2} {#3} #4
- }
-\cs_new:Npn \prg_stepwise_aux:NnnnN #1#2#3#4#5
- {
- \int_compare:nNnF {#2} #1 {#4}
- {
- #5 {#2}
- \exp_args:NNf \prg_stepwise_aux:NnnnN
- #1 { \int_eval:n { #2 + #3 } } {#3} {#4} #5
- }
+ \c_zero
+ \__msg_kernel_expandable_error:nn { kernel } { negative-replication }
}
+\cs_new:cpn { @@_replicate_first_0:n } #1 { \c_zero }
+\cs_new:cpn { @@_replicate_first_1:n } #1 { \c_zero #1 }
+\cs_new:cpn { @@_replicate_first_2:n } #1 { \c_zero #1#1 }
+\cs_new:cpn { @@_replicate_first_3:n } #1 { \c_zero #1#1#1 }
+\cs_new:cpn { @@_replicate_first_4:n } #1 { \c_zero #1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_5:n } #1 { \c_zero #1#1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_6:n } #1 { \c_zero #1#1#1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_7:n } #1 { \c_zero #1#1#1#1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_8:n } #1 { \c_zero #1#1#1#1#1#1#1#1 }
+\cs_new:cpn { @@_replicate_first_9:n } #1 { \c_zero #1#1#1#1#1#1#1#1#1 }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
-%
-% \begin{macro}{\prg_stepwise_inline:nnnn}
-% \begin{macro}{\prg_stepwise_variable:nnnNn}
-% \UnitTested
-% \begin{macro}[aux]{\prg_stepwise_aux:NNnnnn}
-% The approach here is to build a function, with a global integer required
-% to make the nesting safe (as seen in other in line functions),
-% and map that function using \cs{prg_stepwise_function:nnnN}.
-% \begin{macrocode}
-\cs_new_protected:Npn \prg_stepwise_inline:nnnn
- {
- \exp_args:NNc \prg_stepwise_aux:NNnnnn
- \cs_gset_nopar:Npn
- { g_prg_stepwise_ \int_use:N \g_prg_map_int :n }
- }
-\cs_new_protected:Npn \prg_stepwise_variable:nnnNn #1#2#3#4#5
- {
- \exp_args:NNc \prg_stepwise_aux:NNnnnn
- \cs_gset_nopar:Npx
- { g_prg_stepwise_ \int_use:N \g_prg_map_int :n }
- {#1}{#2}{#3}
- {
- \tl_set:Nn \exp_not:N #4 {##1}
- \exp_not:n {#5}
- }
- }
-\cs_new_protected:Npn \prg_stepwise_aux:NNnnnn #1#2#3#4#5#6
- {
- #1 #2 ##1 {#6}
- \int_gincr:N \g_prg_map_int
- \prg_stepwise_aux:nnnN {#3} {#4} {#5} #2
- \prg_break_point:n { \int_gdecr:N \g_prg_map_int }
- }
-% \end{macrocode}
-% \end{macro}
% \end{macro}
% \end{macro}
%
@@ -1735,7 +1409,7 @@
% For testing vertical mode. Strikes me here on the bus with David,
% that as long as we are just talking about returning true and
% false states, we can just use the primitive conditionals for this
-% and gobbling the |\c_zero| in the input stream. However this
+% and gobbling the \cs{c_zero} in the input stream. However this
% requires knowledge of the implementation so we keep things nice
% and clean and use the return statements.
% \begin{macrocode}
@@ -1779,13 +1453,13 @@
% \TeX{}'s alignment structures present many problems. As Knuth says
% himself in \emph{\TeX : The Program}: \enquote{It's sort of a miracle
% whenever \tn{halign} or \tn{valign} work, [\ldots]} One problem relates
-% to commands that internally issues a |\cr| but also peek ahead for
+% to commands that internally issues a \tn{cr} but also peek ahead for
% the next character for use in, say, an optional argument. If the
% next token happens to be a |&| with category code~4 we will get some
% sort of weird error message because the underlying
% \tn{futurelet} will store the token at the end of the alignment
% template. This could be a |&|$_4$ giving a message like
-% |! Misplaced \cr.| or even worse: it could be the |\endtemplate|
+% |! Misplaced \cr.| or even worse: it could be the \tn{endtemplate}
% token causing even more trouble! To solve this we have to open a
% special group so that \TeX{} still thinks it's on safe ground but at
% the same time we don't want to introduce any brace group that may
@@ -1805,11 +1479,11 @@
%
% \begin{macro}[int]{\scan_align_safe_stop:}
% When \TeX{} is in the beginning of an align cell (right after the
-% |\cr|) it is in a somewhat strange mode as it is looking ahead to
+% \tn{cr}) it is in a somewhat strange mode as it is looking ahead to
% find an \tn{omit} or \tn{noalign} and hasn't looked at the
% preamble yet. Thus an \tn{ifmmode} test will always fail unless
-% we insert |\scan_stop:| to stop \TeX{}'s scanning ahead. On the other
-% hand we don't want to insert a |\scan_stop:| every time as that will
+% we insert \cs{scan_stop:} to stop \TeX{}'s scanning ahead. On the other
+% hand we don't want to insert a \cs{scan_stop:} every time as that will
% destroy kerning between letters\footnote{Unless we enforce an extra
% pass with an appropriate value of \tn{pretolerance}.}
% Unfortunately there is no way to detect if we're in the beginning of
@@ -1817,7 +1491,7 @@
% on column number, \emph{etc.} However we \emph{can} detect if we're in an
% alignment cell by checking the current group type and we can also
% check if the previous node was a character or ligature. What is done
-% here is that |\scan_stop:| is only inserted if an only
+% here is that \cs{scan_stop:} is only inserted if an only
% if a)~we're in the outer part of an alignment cell and b)~the last node
% \emph{wasn't} a char node or a ligature node. Thus an older definition
% here was
@@ -1842,47 +1516,51 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[int]{\prg_variable_get_scope:N}
-% \begin{macro}[aux]{\prg_variable_get_scope_aux:w}
-% \begin{macro}[int]{\prg_variable_get_type:N}
-% \begin{macro}[aux]{\prg_variable_get_type:w}
+% \begin{macrocode}
+%<@@=prg>
+% \end{macrocode}
+%
+% \begin{macro}[int]{\@@_variable_get_scope:N}
+% \begin{macro}[aux]{\@@_variable_get_scope:w}
+% \begin{macro}[int]{\@@_variable_get_type:N}
+% \begin{macro}[aux]{\@@_variable_get_type:w}
% Expandable functions to find the type of a variable, and to
% return \texttt{g} if the variable is global. The trick for
-% \cs{prg_variable_get_scope:N} is the same as that in
-% \cs{cs_split_function:NN}, but it can be simplified as the
+% \cs{@@_variable_get_scope:N} is the same as that in
+% \cs{__cs_split_function:NN}, but it can be simplified as the
% requirements here are less complex.
% \begin{macrocode}
\group_begin:
- \tex_lccode:D `\& = `\g \scan_stop:
- \tex_catcode:D `\& = \c_twelve
+ \tex_lccode:D `* = `g \scan_stop:
+ \tex_catcode:D `* = \c_twelve
\tl_to_lowercase:n
{
\group_end:
- \cs_new:Npn \prg_variable_get_scope:N #1
+ \cs_new:Npn \@@_variable_get_scope:N #1
{
\exp_after:wN \exp_after:wN
- \exp_after:wN \prg_variable_get_scope_aux:w
+ \exp_after:wN \@@_variable_get_scope:w
\cs_to_str:N #1 \exp_stop_f: \q_stop
}
- \cs_new:Npn \prg_variable_get_scope_aux:w #1#2 \q_stop
- { \token_if_eq_meaning:NNT & #1 { g } }
+ \cs_new:Npn \@@_variable_get_scope:w #1#2 \q_stop
+ { \token_if_eq_meaning:NNT * #1 { g } }
}
\group_begin:
- \tex_lccode:D `\& = `\_ \scan_stop:
- \tex_catcode:D `\& = \c_twelve
+ \tex_lccode:D `* = `_ \scan_stop:
+ \tex_catcode:D `* = \c_twelve
\tl_to_lowercase:n
{
\group_end:
- \cs_new:Npn \prg_variable_get_type:N #1
+ \cs_new:Npn \@@_variable_get_type:N #1
{
- \exp_after:wN \prg_variable_get_type_aux:w
- \token_to_str:N #1 & a \q_stop
+ \exp_after:wN \@@_variable_get_type:w
+ \token_to_str:N #1 * a \q_stop
}
- \cs_new:Npn \prg_variable_get_type_aux:w #1 & #2#3 \q_stop
+ \cs_new:Npn \@@_variable_get_type:w #1 * #2#3 \q_stop
{
\token_if_eq_meaning:NNTF a #2
{#1}
- { \prg_variable_get_type_aux:w #2#3 \q_stop }
+ { \@@_variable_get_type:w #2#3 \q_stop }
}
}
% \end{macrocode}
@@ -1891,20 +1569,32 @@
% \end{macro}
% \end{macro}
%
-% \begin{variable}{\g_prg_map_int}
+% \begin{variable}{\g_@@_map_int}
% A nesting counter for mapping.
% \begin{macrocode}
-\int_new:N \g_prg_map_int
+\int_new:N \g_@@_map_int
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}{\prg_break_point:n}
-% \begin{macro}{\prg_map_break:}
-% \begin{macro}{\prg_map_break:n}
-% These are all defined in \pkg{l3basics}, as they are needed
+% \begin{macro}{\@@_break_point:Nn}
+% \begin{macro}{\@@_map_break:Nn}
+% These are defined in \pkg{l3basics}, as they are needed
% \enquote{early}. This is just a reminder that that is the case!
% \end{macro}
% \end{macro}
+%
+% \begin{macro}{\@@_break_point:}
+% \begin{macro}{\@@_break:, \@@_break:n}
+% Very simple analogs of \cs{@@_break_point:Nn} and
+% \cs{@@_map_break:Nn}, for use in fast short-term recursions which
+% are not mappings, do not need to support nesting, and in which
+% nothing has to be done at the end of the loop.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_break_point: \prg_do_nothing:
+\cs_new:Npn \@@_break: #1 \@@_break_point: { }
+\cs_new:Npn \@@_break:n #1#2 \@@_break_point: {#1}
+% \end{macrocode}
+% \end{macro}
% \end{macro}
%
% \subsection{Deprecated functions}
@@ -1939,6 +1629,7 @@
% by Bernd Raichle. Firstly we define the function for parsing the
% initial list and then the braced list afterwards.
% \begin{macrocode}
+%<*deprecated>
\cs_new_protected:Npn \prg_define_quicksort:nnn #1#2#3 {
\cs_set:cpx{#1_quicksort:n}##1{
\exp_not:c{#1_quicksort_start_partition:w} ##1
@@ -1956,9 +1647,11 @@
\exp_not:N \quark_if_nil:nT {##1}\exp_not:N \use_none_delimit_by_q_stop:w
\exp_not:c{#1_quicksort_do_partition_i_braced:nnnn} {##1}{}{}
}
+%</deprecated>
% \end{macrocode}
% Now for doing the partitions.
% \begin{macrocode}
+%<*deprecated>
\cs_set:cpx {#1_quicksort_do_partition_i:nnnw} ##1##2##3 #2 ##4 #3 {
\exp_not:N \quark_if_nil:nTF {##4} \exp_not:c {#1_do_quicksort_braced:nnnnw}
{
@@ -1995,10 +1688,12 @@
}
{##1}{##2}{##3}{##4}
}
+%</deprecated>
% \end{macrocode}
% This part of the code handles the two branches in each
% sorting. Again we will also have to do it braced.
% \begin{macrocode}
+%<*deprecated>
\cs_set:cpx {#1_quicksort_partition_less_i:nnnn} ##1##2##3##4{
\exp_not:c{#1_quicksort_do_partition_i:nnnw}{##1}{##2}{{##4}##3}}
\cs_set:cpx {#1_quicksort_partition_less_ii:nnnn} ##1##2##3##4{
@@ -2015,15 +1710,18 @@
\exp_not:c{#1_quicksort_do_partition_i_braced:nnnn}{##1}{{##4}##2}{##3}}
\cs_set:cpx {#1_quicksort_partition_greater_ii_braced:nnnn} ##1##2##3##4{
\exp_not:c{#1_quicksort_do_partition_ii_braced:nnnn}{##1}{##2{##4}}{##3}}
+%</deprecated>
% \end{macrocode}
% Finally, the big kahuna! This is where the sub-lists are sorted.
% \begin{macrocode}
+%<*deprecated>
\cs_set:cpx {#1_do_quicksort_braced:nnnnw} ##1##2##3##4\q_stop {
\exp_not:c{#1_quicksort_braced:n}{##2}
\exp_not:c{#1_quicksort_function:n}{##1}
\exp_not:c{#1_quicksort_braced:n}{##3}
}
}
+%</deprecated>
% \end{macrocode}
% \end{macro}
%
@@ -2032,15 +1730,19 @@
% |\prg_quicksort_compare:nnTF| to compare items, and places the
% function |\prg_quicksort_function:n| in front of each of them.
% \begin{macrocode}
+%<*deprecated>
\prg_define_quicksort:nnn {prg}{}{}
+%</deprecated>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\prg_quicksort_function:n}
% \begin{macro}{\prg_quicksort_compare:nnTF}
% \begin{macrocode}
+%<*deprecated>
\cs_set:Npn \prg_quicksort_function:n {\ERROR}
\cs_set:Npn \prg_quicksort_compare:nnTF {\ERROR}
+%</deprecated>
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -2061,6 +1763,38 @@
% \end{macro}
% \end{macro}
%
+% Deprecated 2012-06-03 for removal after 2012-12-31.
+%
+% \begin{macro}[EXP]
+% {
+% \prg_case_int:nnn, \prg_case_str:nnn, \prg_case_str:onn,
+% \prg_case_str:xxn, \prg_case_tl:Nnn, \prg_case_tl:cnn
+% }
+% Moved to more sensible modules.
+% \begin{macrocode}
+\cs_new_eq:NN \prg_case_int:nnn \int_case:nnn
+\cs_new_eq:NN \prg_case_str:nnn \str_case:nnn
+\cs_new_eq:NN \prg_case_str:onn \str_case:onn
+\cs_new_eq:NN \prg_case_str:xxn \str_case_x:nnn
+\cs_new_eq:NN \prg_case_tl:Nnn \tl_case:Nnn
+\cs_new_eq:NN \prg_case_tl:cnn \tl_case:cnn
+% \end{macrocode}
+% \end{macro}
+%
+% Deprecated 2012-06-04 for removal after 2012-12-31.
+%
+% \begin{macro}
+% {
+% \prg_stepwise_function:nnnN, \prg_stepwise_inline:nnnn,
+% \prg_stepwise_variable:nnnNn
+% }
+% \begin{macrocode}
+\cs_new_eq:NN \prg_stepwise_function:nnnN \int_step_function:nnnN
+\cs_new_eq:NN \prg_stepwise_inline:nnnn \int_step_inline:nnnn
+\cs_new_eq:NN \prg_stepwise_variable:nnnNn \int_step_variable:nnnNn
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
index b90ff41e63a..e20e2aa5d26 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3prop.dtx
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3prop.dtx 3490 2012-03-04 01:00:53Z bruno $
- {L3 Experimental property lists}
+\GetIdInfo$Id: l3prop.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Property lists}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -90,7 +90,7 @@
% \cs{prop_new:N} \meta{property list}
% \end{syntax}
% Creates a new \meta{property list} or raises an error if the name is
-% already taken. The declaration is global. The \meta{property lists} will
+% already taken. The declaration is global. The \meta{property list} will
% initially contain no entries.
% \end{function}
%
@@ -121,15 +121,15 @@
% \prop_gset_eq:NN, \prop_gset_eq:cN, \prop_gset_eq:Nc, \prop_gset_eq:cc
% }
% \begin{syntax}
-% \cs{prop_set_eq:NN} \meta{property list1} \meta{property list2}
+% \cs{prop_set_eq:NN} \meta{property list_1} \meta{property list_2}
% \end{syntax}
-% Sets the content of \meta{property list1} equal to that of
-% \meta{property list2}.
+% Sets the content of \meta{property list_1} equal to that of
+% \meta{property list_2}.
% \end{function}
%
% \section{Adding entries to property lists}
%
-% \begin{function}
+% \begin{function}[updated = 2012-07-09]
% {
% \prop_put:Nnn, \prop_put:NnV, \prop_put:Nno, \prop_put:Nnx,
% \prop_put:NVn, \prop_put:NVV, \prop_put:Non, \prop_put:Noo,
@@ -198,7 +198,7 @@
% \meta{property list} then the \meta{token list variable} will
% contain the special marker \cs{q_no_value}. The \meta{key} and
% \meta{value} are then deleted from the property list. Both
-% assignments are local.
+% assignments are local. See also \cs{prop_pop:NnNTF}.
% \end{function}
%
% \begin{function}[updated = 2011-08-18]
@@ -213,29 +213,29 @@
% contain the special marker \cs{q_no_value}. The \meta{key} and
% \meta{value} are then deleted from the property list.
% The \meta{property list} is modified globally, while the assignment of
-% the \meta{token list variable} is local.
+% the \meta{token list variable} is local. See also \cs{prop_gpop:NnNTF}.
% \end{function}
-%%
+%
% \section{Modifying property lists}
%
-% \begin{function}
+% \begin{function}[added = 2012-05-12]
% {
-% \prop_del:Nn, \prop_del:NV, \prop_del:cn, \prop_del:cV,
-% \prop_gdel:Nn, \prop_gdel:NV, \prop_gdel:cn, \prop_gdel:cV
+% \prop_remove:Nn, \prop_remove:NV, \prop_remove:cn, \prop_remove:cV,
+% \prop_gremove:Nn, \prop_gremove:NV, \prop_gremove:cn, \prop_gremove:cV
% }
% \begin{syntax}
-% \cs{prop_del:Nn} \meta{property list} \Arg{key}
+% \cs{prop_remove:Nn} \meta{property list} \Arg{key}
% \end{syntax}
-% Deletes the entry listed under \meta{key} from the
-% \meta{property list} which may be accessed. If the \meta{key} is
+% Removes the entry listed under \meta{key} from the
+% \meta{property list}. If the \meta{key} is
% not found in the \meta{property list} no change occurs,
% \emph{i.e}~there is no need to test for the existence of a key before
-% deleting it. The deletion is restricted to the current \TeX{} group.
+% deleting it.
% \end{function}
%
% \section{Property list conditionals}
%
-% \begin{function}[EXP, pTF, added=2012-03-03]
+% \begin{function}[EXP, pTF, added = 2012-03-03]
% {\prop_if_exist:N, \prop_if_exist:c}
% \begin{syntax}
% \cs{prop_if_exist_p:N} \meta{property list}
@@ -278,7 +278,7 @@
% or absence of a key in a property list. They offer increased readability
% and performance over separate testing and recovery phases.
%
-% \begin{function}[updated = 2011-08-28, TF]
+% \begin{function}[updated = 2012-05-19, TF]
% {
% \prop_get:NnN, \prop_get:NVN, \prop_get:NoN,
% \prop_get:cnN, \prop_get:cVN, \prop_get:coN
@@ -288,21 +288,24 @@
% ~~\Arg{true code} \Arg{false code}
% \end{syntax}
% If the \meta{key} is not present in the \meta{property list}, leaves
-% the \meta{false code} in the input stream and leaves the
-% \meta{token list variable} unchanged. If the \meta{key} is present in
-% the \meta{property list}, stores the corresponding \meta{value}
-% in the \meta{token list variable} without removing it from the
-% \meta{property list}. The \meta{token list variable} is assigned locally.
+% the \meta{false code} in the input stream. The value of the
+% \meta{token list variable} is not defined in this case and should
+% not be relied upon. If the \meta{key} is present in the
+% \meta{property list}, stores the corresponding \meta{value} in the
+% \meta{token list variable} without removing it from the
+% \meta{property list}, then leaves the \meta{true code} in the input
+% stream. The \meta{token list variable} is assigned locally.
% \end{function}
%
-% \begin{function}[added = 2011-08-18,TF]{\prop_pop:NnN, \prop_pop:cnN}
+% \begin{function}[TF, added = 2011-08-18, updated = 2012-05-19]
+% {\prop_pop:NnN, \prop_pop:cnN}
% \begin{syntax}
-% \cs{prop_pop:NnNTF} \meta{property list} \Arg{key} \meta{token list variable} \\
-% ~~\Arg{true code} \Arg{false code}
+% \cs{prop_pop:NnNTF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code} \Arg{false code}
% \end{syntax}
% If the \meta{key} is not present in the \meta{property list}, leaves
-% the \meta{false code} in the input stream and leaves the
-% \meta{token list variable} unchanged. If the \meta{key} is present in
+% the \meta{false code} in the input stream. The value of the
+% \meta{token list variable} is not defined in this case and should
+% not be relied upon. If the \meta{key} is present in
% the \meta{property list}, pops the corresponding \meta{value}
% in the \meta{token list variable}, \emph{i.e.}~removes the item from
% the \meta{property list}.
@@ -310,9 +313,26 @@
% are assigned locally.
% \end{function}
%
+% \begin{function}[TF, added = 2011-08-18, updated = 2012-05-19]
+% {\prop_gpop:NnN, \prop_gpop:cnN}
+% \begin{syntax}
+% \cs{prop_gpop:NnNTF} \meta{property list} \Arg{key} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{key} is not present in the \meta{property list}, leaves
+% the \meta{false code} in the input stream. The value of the
+% \meta{token list variable} is not defined in this case and should
+% not be relied upon. If the \meta{key} is present in
+% the \meta{property list}, pops the corresponding \meta{value}
+% in the \meta{token list variable}, \emph{i.e.}~removes the item from
+% the \meta{property list}.
+% The \meta{property list} is modified globally, while the
+% \meta{token list variable} is assigned locally.
+% \end{function}
+%
% \section{Mapping to property lists}
%
-% \begin{function}[rEXP]{\prop_map_function:NN, \prop_map_function:cN}
+% \begin{function}[updated = 2012-06-29, rEXP]
+% {\prop_map_function:NN, \prop_map_function:cN}
% \begin{syntax}
% \cs{prop_map_function:NN} \meta{property list} \meta{function}
% \end{syntax}
@@ -323,7 +343,8 @@
% should not be relied upon.
% \end{function}
%
-% \begin{function}{\prop_map_inline:Nn, \prop_map_inline:cn}
+% \begin{function}[updated = 2012-06-29]
+% {\prop_map_inline:Nn, \prop_map_inline:cn}
% \begin{syntax}
% \cs{prop_map_inline:Nn} \meta{property list} \Arg{inline function}
% \end{syntax}
@@ -335,7 +356,7 @@
% should not be relied upon.
% \end{function}
%
-% \begin{function}[rEXP]{\prop_map_break:}
+% \begin{function}[updated = 2012-06-29, rEXP]{\prop_map_break:}
% \begin{syntax}
% \cs{prop_map_break:}
% \end{syntax}
@@ -356,7 +377,7 @@
% level \TeX{} errors.
% \end{function}
%
-% \begin{function}[rEXP]{\prop_map_break:n}
+% \begin{function}[updated = 2012-06-29, rEXP]{\prop_map_break:n}
% \begin{syntax}
% \cs{prop_map_break:n} \Arg{tokens}
% \end{syntax}
@@ -387,103 +408,45 @@
% Displays the entries in the \meta{property list} in the terminal.
% \end{function}
%
-% \section{Experimental property list functions}
+% \section{Scratch property lists}
%
-% This section contains functions which may or may not be retained, depending
-% on how useful they are found to be.
+% \begin{variable}[added = 2012-06-23]{\l_tmpa_prop, \l_tmpb_prop}
+% Scratch property lists for local assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
%
-% \begin{function}[added = 2011-08-18,TF]{\prop_gpop:NnN, \prop_gpop:cnN}
-% \begin{syntax}
-% \cs{prop_gpop:NnNTF} \meta{property list} \Arg{key} \meta{token list variable} \\
-% ~~\Arg{true code} \Arg{false code}
-% \end{syntax}
-% If the \meta{key} is not present in the \meta{property list}, leaves
-% the \meta{false code} in the input stream and leaves the
-% \meta{token list variable} unchanged. If the \meta{key} is present in
-% the \meta{property list}, pops the corresponding \meta{value}
-% in the \meta{token list variable}, \emph{i.e.}~removes the item from
-% the \meta{property list}.
-% The \meta{property list} is modified globally, while the
-% \meta{token list variable} is assigned locally.
-% \end{function}
+% \begin{variable}[added = 2012-06-23]{\g_tmpa_prop, \g_tmpb_prop}
+% Scratch property lists for global assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
%
-% \begin{function}[added = 2011-08-18,rEXP]
-% {\prop_map_tokens:Nn, \prop_map_tokens:cn}
-% \begin{syntax}
-% \cs{prop_map_tokens:Nn} \meta{property list} \Arg{code}
-% \end{syntax}
-% Analogue of \cs{prop_map_function:NN} which maps several tokens
-% instead of a single function. The \meta{code} receives each
-% key--value pair in the \meta{property list} as two trailing brace
-% groups. For instance,
-% \begin{verbatim}
-% \prop_map_tokens:Nn \l_my_prop { \str_if_eq:nnT { mykey } }
-% \end{verbatim}
-% will expand to the value corresponding to \texttt{mykey}: for each
-% pair in \cs{l_my_prop} the function \cs{str_if_eq:nnT} receives
-% \texttt{mykey}, the \meta{key} and the \meta{value} as its three
-% arguments. For that specific task, \cs{prop_get:Nn} is faster.
-% \end{function}
+% \section{Constants}
%
-% \begin{function}[updated = 2012-01-08,EXP]{\prop_get:Nn, \prop_get:cn}
-% \begin{syntax}
-% \cs{prop_get:Nn} \meta{property list} \Arg{key}
-% \end{syntax}
-% Expands to the \meta{value} corresponding to the \meta{key} in
-% the \meta{property list}. If the \meta{key} is missing, this has
-% an empty expansion.
-% \begin{texnote}
-% This function is slower than the non-expandable analogue
-% \cs{prop_get:NnN}.
-% The result is returned within the \tn{unexpanded}
-% primitive (\cs{exp_not:n}), which means that the \meta{value}
-% will not expand further when appearing in an x-type
-% argument expansion.
-% \end{texnote}
-% \end{function}
+% \begin{variable}{\c_empty_prop}
+% A permanently-empty property list used for internal comparisons.
+% \end{variable}
%
% \section{Internal property list functions}
%
-% \begin{function}{\q_prop}
+% \begin{variable}{\q__prop}
% The internal token used to separate out property list entries, separating
% both the \meta{key} from the \meta{value} and also one entry from another.
-% \end{function}
-%
-% \begin{function}{\c_empty_prop}
-% A permanently-empty property list used for internal comparisons.
-% \end{function}
-%
-% \begin{function}{\prop_split:Nnn}
-% \begin{syntax}
-% \cs{prop_split:Nnn} \meta{property list} \Arg{key} \Arg{code}
-% \end{syntax}
-% Splits the \meta{property list} at the \meta{key}, giving three
-% groups: the \meta{extract} of \meta{property list} before the
-% \meta{key}, the \meta{value} associated with the \meta{key} and the
-% \meta{extract} of the \meta{property list} after the \meta{value}.
-% The first \meta{extract} retains the internal structure of a property
-% list. The second is only missing the leading separator \cs{q_prop}.
-% This ensures that the concatenation of the two \meta{extracts} is a
-% property list.
-% If the \meta{key} is not present in the \meta{property list} then
-% the second group will contain the marker \cs{q_no_value} and the third
-% is empty.
-% Once the split has occurred, the \meta{code} is inserted followed by the
-% three groups: thus the \meta{code} should properly absorb three
-% arguments.
-% The \meta{key} comparison takes place as described for \cs{str_if_eq:nn}.
-% \end{function}
+% \end{variable}
%
-% \begin{function}{\prop_split:NnTF}
+% \begin{function}{\__prop_split:NnTF}
% \begin{syntax}
-% \cs{prop_split:NnTF} \meta{property list} \Arg{key} \Arg{true code} \Arg{false code}
+% \cs{__prop_split:NnTF} \meta{property list} \Arg{key} \Arg{true code} \Arg{false code}
% \end{syntax}
% Splits the \meta{property list} at the \meta{key}, giving three
% groups: the \meta{extract} of \meta{property list} before the
% \meta{key}, the \meta{value} associated with the \meta{key} and the
% \meta{extract} of the \meta{property list} after the \meta{value}.
% The first \meta{extract} retains the internal structure of a property
-% list. The second is only missing the leading separator \cs{q_prop}.
+% list. The second is only missing the leading separator \cs{q__prop}.
% This ensures that the concatenation of the two \meta{extracts} is a
% property list.
% If the \meta{key} is present in the \meta{property list} then the
@@ -501,44 +464,51 @@
%
% \section{\pkg{l3prop} implementation}
%
-% \TestFiles{m3prop001}
+% \TestFiles{m3prop001, m3prop002, m3prop003, m3prop004, m3show001}
%
% \begin{macrocode}
%<*initex|package>
% \end{macrocode}
%
% \begin{macrocode}
+%<@@=prop>
+% \end{macrocode}
+%
+% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
% A property list is a macro whose top-level expansion is for the form
-% \enquote{\cs{q_prop} \meta{key$_0$} \cs{q_prop} \Arg{value$_0$} \cs{q_prop}
-% \ldots \cs{q_prop} \meta{key$_{n-1}$} \cs{q_prop} \Arg{value$_{n-1}$}
-% \cs{q_prop}}.
-% The trailing \cs{q_prop} is always present for performance reasons: this
-% means that empty property lists are not actually empty.
-%
-% \begin{macro}[int]{\q_prop}
+% \begin{quote}
+% \cs{q_@@} \meta{key_1} \cs{q_@@} \Arg{value_1} \\
+% \ldots{} \\
+% \cs{q_@@} \meta{key_n} \cs{q_@@} \Arg{value_n} \\
+% \cs{q_@@}
+% \end{quote}
+% where the trailing \cs{q_@@} is always present for performance
+% reasons: this means that empty property lists are not actually empty.
+%
+% \begin{macro}[int]{\q_@@}
% A private quark is used as a marker between entries.
% \begin{macrocode}
-\quark_new:N \q_prop
+\quark_new:N \q_@@
% \end{macrocode}
% \end{macro}
%
-% \begin{variable}{\c_empty_prop}
-% An empty prop contains exactly one \cs{q_prop}.
+% \begin{variable}[tested = m3prop004]{\c_empty_prop}
+% An empty prop contains exactly one \cs{q_@@}.
% \begin{macrocode}
-\tl_const:Nn \c_empty_prop { \q_prop }
+\tl_const:Nn \c_empty_prop { \q_@@ }
% \end{macrocode}
% \end{variable}
%
% \subsection{Allocation and initialisation}
%
-% \begin{macro}{\prop_new:N,\prop_new:c}
+% \begin{macro}[tested = m3prop001]{\prop_new:N,\prop_new:c}
% Internally, property lists are token lists, but an empty prop
% is not an empty tl, so we need to do things by hand.
% \begin{macrocode}
@@ -547,20 +517,20 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\prop_clear:N, \prop_clear:c}
-% \begin{macro}{\prop_gclear:N, \prop_gclear:c}
+% \begin{macro}[tested = m3prop001]{\prop_clear:N, \prop_clear:c}
+% \begin{macro}[tested = m3prop001]{\prop_gclear:N, \prop_gclear:c}
% The same idea for clearing
% \begin{macrocode}
\cs_new_protected:Npn \prop_clear:N #1 { \cs_set_eq:NN #1 \c_empty_prop }
-\cs_new_protected:Npn \prop_clear:c #1 { \cs_set_eq:cN {#1} \c_empty_prop }
+\cs_generate_variant:Nn \prop_clear:N { c }
\cs_new_protected:Npn \prop_gclear:N #1 { \cs_gset_eq:NN #1 \c_empty_prop }
-\cs_new_protected:Npn \prop_gclear:c #1 { \cs_gset_eq:cN {#1} \c_empty_prop }
+\cs_generate_variant:Nn \prop_gclear:N { c }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\prop_clear_new:N, \prop_clear_new:c}
-% \begin{macro}{\prop_gclear_new:N, \prop_gclear_new:c}
+% \begin{macro}[tested = m3prop001]{\prop_clear_new:N, \prop_clear_new:c}
+% \begin{macro}[tested = m3prop001]{\prop_gclear_new:N, \prop_gclear_new:c}
% Once again a simple copy from the token list functions.
% \begin{macrocode}
\cs_new_protected:Npn \prop_clear_new:N #1
@@ -573,9 +543,9 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}
+% \begin{macro}[tested = m3prop001]
% {\prop_set_eq:NN, \prop_set_eq:cN, \prop_set_eq:Nc, \prop_set_eq:cc}
-% \begin{macro}
+% \begin{macro}[tested = m3prop001]
% {\prop_gset_eq:NN, \prop_gset_eq:cN, \prop_gset_eq:Nc, \prop_gset_eq:cc}
% Once again, these are simply copies from the token list functions.
% \begin{macrocode}
@@ -591,116 +561,109 @@
% \end{macro}
% \end{macro}
%
+% \begin{variable}[tested = m3prop004]{\l_tmpa_prop, \l_tmpb_prop}
+% \begin{variable}[tested = m3prop004]{\g_tmpa_prop, \g_tmpb_prop}
+% We can now initialize the scratch variables.
+% \begin{macrocode}
+\prop_new:N \l_tmpa_prop
+\prop_new:N \l_tmpb_prop
+\prop_new:N \g_tmpa_prop
+\prop_new:N \g_tmpb_prop
+% \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
% \subsection{Accessing data in property lists}
%
-% \begin{macro}[int]{\prop_split:NnTF}
-% \begin{macro}[aux]{\prop_split_aux:NnTF}
-% \begin{macro}[aux]{\prop_split_aux:nnnn}
-% \begin{macro}[aux]{\prop_split_aux:w}
+% \begin{macro}[int]{\@@_split:NnTF}
+% \begin{macro}[aux]{\@@_split_aux:NnTF}
+% \begin{macro}[aux]{\@@_split_aux:nnnn}
+% \begin{macro}[aux]{\@@_split_aux:w}
% This function is used by most of the module, and hence must be fast.
% The aim here is to split a property list at a given key into the part
% before the key--value pair, the value associated with the key and the part
% after the key--value pair. To do this, the key is first detokenized (to
% avoid repeatedly doing this), then a delimited function is constructed to
-% match the key. It will match \cs{q_prop} \meta{detokenized key} \cs{q_prop}
-% \marg{value} \meta{extra argument}, effectively separating an
-% \meta{extract1} before the key in the property list and an \meta{extract2}
+% match the key. It will match \cs{q_@@} \meta{detokenized key} \cs{q_@@}
+% \Arg{value} \meta{extra argument}, effectively separating an
+% \meta{extract_1} before the key in the property list and an \meta{extract_2}
% after the key.
%
% If the key is present in the property list, then \meta{extra argument}
-% is simply \cs{q_prop}, and \cs{prop_split_aux:nnnn} will gobble this
+% is simply \cs{q_@@}, and \cs{@@_split_aux:nnnn} will gobble this
% and the false branch (|#4|), leaving the correct code on the input
% stream. More precisely, it leaves the user code (true branch), followed
% by three groups, \Arg{extract_1} \Arg{value} \Arg{extract_2}.
-% In order for \meta{extract1}\meta{extract2} to be a well-formed
-% property list, \meta{extract1} has a leading and trailing \cs{q_prop},
-% retaining exactly the structure of a property list, while \meta{extract2}
-% omits the leading \cs{q_prop}.
-%
-% If the key is not there, then \meta{extra argument} is
-% |? \use_ii:nn { }|, and |\prop_split_aux:nnnn ? \use_ii:nn { }| removes
-% the three brace groups that just follow. Then \cs{use_ii:nn} removes
-% the true branch, leaving the false branch, with no trailing material.
+% In order for \meta{extract_1}\meta{extract_2} to be a well-formed
+% property list, \meta{extract_1} has a leading and trailing \cs{q_@@},
+% retaining exactly the structure of a property list, while \meta{extract_2}
+% omits the leading \cs{q_@@}.
+%
+% If the key is not there, then \meta{extra argument} is |?|
+% \cs{use_ii:nn} |{ }|, and \cs{@@_split_aux:nnnn} |?| \cs{use_ii:nn}
+% |{ }| removes the three brace groups that just follow. Then
+% \cs{use_ii:nn} removes the true branch, leaving the false branch,
+% with no trailing material.
% \begin{macrocode}
-\cs_new_protected:Npn \prop_split:NnTF #1#2
- { \exp_args:NNo \prop_split_aux:NnTF #1 { \tl_to_str:n {#2} } }
-\cs_new_protected:Npn \prop_split_aux:NnTF #1#2
+\cs_new_protected:Npn \@@_split:NnTF #1#2
+ { \exp_args:NNo \@@_split_aux:NnTF #1 { \tl_to_str:n {#2} } }
+\cs_new_protected:Npn \@@_split_aux:NnTF #1#2
{
- \cs_set_protected:Npn \prop_split_aux:w
- ##1 \q_prop #2 \q_prop ##2 ##3 ##4 \q_mark ##5 \q_stop
- { \prop_split_aux:nnnn ##3 { {##1 \q_prop } {##2} {##4} } }
- \exp_after:wN \prop_split_aux:w #1 \q_mark
- \q_prop #2 \q_prop { } { ? \use_ii:nn { } } \q_mark \q_stop
+ \cs_set_protected:Npn \@@_split_aux:w
+ ##1 \q_@@ #2 \q_@@ ##2 ##3 ##4 \q_mark ##5 \q_stop
+ { \@@_split_aux:nnnn ##3 { {##1 \q_@@ } {##2} {##4} } }
+ \exp_after:wN \@@_split_aux:w #1 \q_mark
+ \q_@@ #2 \q_@@ { } { ? \use_ii:nn { } } \q_mark \q_stop
}
-\cs_new:Npn \prop_split_aux:nnnn #1#2#3#4 { #3 #2 }
-\cs_new_protected:Npn \prop_split_aux:w { }
+\cs_new:Npn \@@_split_aux:nnnn #1#2#3#4 { #3 #2 }
+\cs_new_protected:Npn \@@_split_aux:w { }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\prop_split:Nnn}
-% The goal here is to provide a common interface for both true and false
-% branches of \cs{prop_split:NnTF}. In both cases, the code given by the
-% user will be placed in front of three brace groups, \Arg{extract_1}
-% \Arg{value} \Arg{extract_2}.
-% If the key was missing from the property list, then \meta{extract1}
-% is the full property list, \meta{value} is \cs{q_no_value}, and
-% \meta{extract2} is empty.
-% Otherwise, \meta{extract1} is the part of the property list before the
-% \meta{key}, and has the structure of a property list, \meta{value} is
-% the value corresponding to the \meta{key}, and \meta{extract2} (the part
-% after the \meta{key}) is missing the leading \cs{q_prop}.
-% \begin{macrocode}
-\cs_new_protected:Npn \prop_split:Nnn #1#2#3
- {
- \prop_split:NnTF #1 {#2}
- {#3}
- { \exp_args:Nno \use:n {#3} {#1} { \q_no_value } { } }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}{\prop_del:Nn, \prop_del:NV, \prop_del:cn, \prop_del:cV}
-% \begin{macro}{\prop_gdel:Nn, \prop_gdel:NV, \prop_gdel:cn, \prop_gdel:cV}
-% \begin{macro}[aux]{\prop_del_aux:NNnnn}
+% \begin{macro}[tested = m3prop002]
+% {\prop_remove:Nn, \prop_remove:NV, \prop_remove:cn, \prop_remove:cV}
+% \begin{macro}[tested = m3prop002]
+% {\prop_gremove:Nn, \prop_gremove:NV, \prop_gremove:cn, \prop_gremove:cV}
+% \begin{macro}[aux]{\@@_remove:NNnnn}
% Deleting from a property starts by splitting the list.
% If the key is present in the property list, the returned value is ignored.
% If the key is missing, nothing happens.
% \begin{macrocode}
-\cs_new_protected:Npn \prop_del:Nn #1#2
- { \prop_split:NnTF #1 {#2} { \prop_del_aux:NNnnn \tl_set:Nn #1 } { } }
-\cs_new_protected:Npn \prop_gdel:Nn #1#2
- { \prop_split:NnTF #1 {#2} { \prop_del_aux:NNnnn \tl_gset:Nn #1 } { } }
-\cs_new_protected:Npn \prop_del_aux:NNnnn #1#2#3#4#5
+\cs_new_protected:Npn \prop_remove:Nn #1#2
+ { \@@_split:NnTF #1 {#2} { \@@_remove:NNnnn \tl_set:Nn #1 } { } }
+\cs_new_protected:Npn \prop_gremove:Nn #1#2
+ { \@@_split:NnTF #1 {#2} { \@@_remove:NNnnn \tl_gset:Nn #1 } { } }
+\cs_new_protected:Npn \@@_remove:NNnnn #1#2#3#4#5
{ #1 #2 { #3 #5 } }
-\cs_generate_variant:Nn \prop_del:Nn { NV }
-\cs_generate_variant:Nn \prop_del:Nn { c , cV }
-\cs_generate_variant:Nn \prop_gdel:Nn { NV }
-\cs_generate_variant:Nn \prop_gdel:Nn { c , cV }
+\cs_generate_variant:Nn \prop_remove:Nn { NV }
+\cs_generate_variant:Nn \prop_remove:Nn { c , cV }
+\cs_generate_variant:Nn \prop_gremove:Nn { NV }
+\cs_generate_variant:Nn \prop_gremove:Nn { c , cV }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
-% \begin{macro}
+% \begin{macro}[tested = m3prop002]
% {
% \prop_get:NnN, \prop_get:NVN, \prop_get:NoN,
-% \prop_get:cnN, \prop_get:cVN, \prop_get:NoN
+% \prop_get:cnN, \prop_get:cVN, \prop_get:coN
% }
-% \begin{macro}[aux]{\prop_get_aux:Nnnn}
+% \begin{macro}[aux]{\@@_get:Nnnn}
% Getting an item from a list is very easy: after splitting,
% if the key is in the property list, just set the token list variable
% to the return value, otherwise to \cs{q_no_value}.
% \begin{macrocode}
\cs_new_protected:Npn \prop_get:NnN #1#2#3
{
- \prop_split:NnTF #1 {#2}
- { \prop_get_aux:Nnnn #3 }
+ \@@_split:NnTF #1 {#2}
+ { \@@_get:Nnnn #3 }
{ \tl_set:Nn #3 { \q_no_value } }
}
-\cs_new_protected:Npn \prop_get_aux:Nnnn #1#2#3#4
+\cs_new_protected:Npn \@@_get:Nnnn #1#2#3#4
{ \tl_set:Nn #1 {#3} }
\cs_generate_variant:Nn \prop_get:NnN { NV , No }
\cs_generate_variant:Nn \prop_get:NnN { c , cV , co }
@@ -708,9 +671,11 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\prop_pop:NnN, \prop_pop:NoN, \prop_pop:cnN, \prop_pop:coN}
-% \begin{macro}{\prop_gpop:NnN, \prop_gpop:NoN, \prop_gpop:cnN, \prop_gpop:coN}
-% \begin{macro}[aux]{\prop_pop_aux:NNNnnn}
+% \begin{macro}[tested = m3prop002]
+% {\prop_pop:NnN, \prop_pop:NoN, \prop_pop:cnN, \prop_pop:coN}
+% \begin{macro}[tested = m3prop002]
+% {\prop_gpop:NnN, \prop_gpop:NoN, \prop_gpop:cnN, \prop_gpop:coN}
+% \begin{macro}[aux]{\@@_pop:NNNnnn}
% Popping a value also starts by doing the split.
% If the key is present, save the value in the token list and update the
% property list as when deleting.
@@ -718,17 +683,17 @@
% \begin{macrocode}
\cs_new_protected:Npn \prop_pop:NnN #1#2#3
{
- \prop_split:NnTF #1 {#2}
- { \prop_pop_aux:NNNnnn \tl_set:Nn #1 #3 }
+ \@@_split:NnTF #1 {#2}
+ { \@@_pop:NNNnnn \tl_set:Nn #1 #3 }
{ \tl_set:Nn #3 { \q_no_value } }
}
\cs_new_protected:Npn \prop_gpop:NnN #1#2#3
{
- \prop_split:NnTF #1 {#2}
- { \prop_pop_aux:NNNnnn \tl_gset:Nn #1 #3 }
+ \@@_split:NnTF #1 {#2}
+ { \@@_pop:NNNnnn \tl_gset:Nn #1 #3 }
{ \tl_set:Nn #3 { \q_no_value } }
}
-\cs_new_protected:Npn \prop_pop_aux:NNNnnn #1#2#3#4#5#6
+\cs_new_protected:Npn \@@_pop:NNNnnn #1#2#3#4#5#6
{
\tl_set:Nn #3 {#5}
#1 #2 { #4 #6 }
@@ -742,38 +707,82 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}
+% \begin{macro}[TF, tested = m3prop004]
+% {\prop_pop:NnN, \prop_pop:cnN, \prop_gpop:NnN, \prop_gpop:cnN}
+% \begin{macro}[aux]{\@@_pop_true:NNNnnn}
+% Popping an item from a property list, keeping track of whether
+% the key was present or not, is implemented as a conditional.
+% If the key was missing, neither the property list, nor the token
+% list are altered. Otherwise, \cs{prg_return_true:} is used after
+% the assignments.
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn \prop_pop:NnN #1#2#3 { T , F , TF }
+ {
+ \@@_split:NnTF #1 {#2}
+ { \@@_pop_true:NNNnnn \tl_set:Nn #1 #3 }
+ { \prg_return_false: }
+ }
+\prg_new_protected_conditional:Npnn \prop_gpop:NnN #1#2#3 { T , F , TF }
+ {
+ \@@_split:NnTF #1 {#2}
+ { \@@_pop_true:NNNnnn \tl_gset:Nn #1 #3 }
+ { \prg_return_false: }
+ }
+\cs_new_protected:Npn \@@_pop_true:NNNnnn #1#2#3#4#5#6
+ {
+ \tl_set:Nn #3 {#5}
+ #1 #2 { #4 #6 }
+ \prg_return_true:
+ }
+\cs_generate_variant:Nn \prop_pop:NnNT { c }
+\cs_generate_variant:Nn \prop_pop:NnNF { c }
+\cs_generate_variant:Nn \prop_pop:NnNTF { c }
+\cs_generate_variant:Nn \prop_gpop:NnNT { c }
+\cs_generate_variant:Nn \prop_gpop:NnNF { c }
+\cs_generate_variant:Nn \prop_gpop:NnNTF { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[tested = m3prop002]
% {
% \prop_put:Nnn, \prop_put:NnV, \prop_put:Nno, \prop_put:Nnx,
% \prop_put:NVn, \prop_put:NVV, \prop_put:Non, \prop_put:Noo,
% \prop_put:cnn, \prop_put:cnV, \prop_put:cno, \prop_put:cnx,
% \prop_put:cVn, \prop_put:cVV, \prop_put:con, \prop_put:coo
% }
-% \begin{macro}
+% \begin{macro}[tested = m3prop002]
% {
% \prop_gput:Nnn, \prop_gput:NnV, \prop_gput:Nno, \prop_gput:Nnx,
% \prop_gput:NVn, \prop_gput:NVV, \prop_gput:Non, \prop_gput:Noo,
% \prop_gput:cnn, \prop_gput:cnV, \prop_gput:cno, \prop_gput:cnx,
% \prop_gput:cVn, \prop_gput:cVV, \prop_gput:con, \prop_gput:coo
% }
-% \begin{macro}[aux]{\prop_put_aux:NNnnnnn}
-% Putting a key--value pair in a property list starts by splitting
-% to remove any existing value. The property list is then
-% reconstructed with the two remaining parts |#5| and |#7| first,
-% followed by the new or updated entry.
+% \begin{macro}[aux]{\@@_put:NNNnn, \@@_put:NNnnnnn}
+% Putting a key--value pair in a property list starts by splitting to
+% remove any existing value. If the \meta{key} was absent, append the
+% new key--value pair. Otherwise, the property list is reconstructed
+% from the two remaining parts |#5| and |#7|, and the updated entry.
+% The updated entry is placed at the same spot as the original
+% \meta{key} in the property list, preserving the order of entries.
% \begin{macrocode}
-\cs_new_protected:Npn \prop_put:Nnn { \prop_put_aux:NNnn \tl_set:Nx }
-\cs_new_protected:Npn \prop_gput:Nnn { \prop_put_aux:NNnn \tl_gset:Nx }
-\cs_new_protected:Npn \prop_put_aux:NNnn #1#2#3#4
+\cs_new_protected:Npn \prop_put:Nnn
+ { \@@_put:NNNnn \tl_set:Nx \tl_put_right:Nx }
+\cs_new_protected:Npn \prop_gput:Nnn
+ { \@@_put:NNNnn \tl_gset:Nx \tl_gput_right:Nx }
+\cs_new_protected:Npn \@@_put:NNNnn #1#2#3#4#5
{
- \prop_split:Nnn #2 {#3} { \prop_put_aux:NNnnnnn #1 #2 {#3} {#4} }
+ \@@_split:NnTF #3 {#4}
+ { \@@_put:NNnnnnn #1 #3 {#4} {#5} }
+ { #2 #3 { \tl_to_str:n {#4} \exp_not:n { \q_@@ {#5} \q_@@ } } }
}
-\cs_new_protected:Npn \prop_put_aux:NNnnnnn #1#2#3#4#5#6#7
+\cs_new_protected:Npn \@@_put:NNnnnnn #1#2#3#4#5#6#7
{
#1 #2
{
- \exp_not:n { #5 #7 }
- \tl_to_str:n {#3} \exp_not:n { \q_prop {#4} \q_prop }
+ \exp_not:n {#5}
+ \tl_to_str:n {#3} \exp_not:n { \q_@@ {#4} \q_@@ }
+ \exp_not:n {#7}
}
}
\cs_generate_variant:Nn \prop_put:Nnn
@@ -789,24 +798,27 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\prop_put_if_new:Nnn, \prop_put_if_new:cnn}
-% \begin{macro}{\prop_gput_if_new:Nnn, \prop_gput_if_new:cnn}
+% \begin{macro}[tested = m3prop002]
+% {\prop_put_if_new:Nnn, \prop_put_if_new:cnn}
+% \begin{macro}[tested = m3prop002]
+% {\prop_gput_if_new:Nnn, \prop_gput_if_new:cnn}
+% \begin{macro}[aux]{\@@_put_if_new:NNnn}
% Adding conditionally also splits. If the key is already present,
-% the three brace groups given by \cs{prop_split:NnTF} are removed.
+% the three brace groups given by \cs{@@_split:NnTF} are removed.
% If the key is new, then the value is added, being careful to
% convert the key to a string using \cs{tl_to_str:n}.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \prop_put_if_new:Nnn
- { \prop_put_if_new_aux:NNnn \tl_put_right:Nx }
+ { \@@_put_if_new:NNnn \tl_put_right:Nx }
\cs_new_protected_nopar:Npn \prop_gput_if_new:Nnn
- { \prop_put_if_new_aux:NNnn \tl_gput_right:Nx }
-\cs_new_protected:Npn \prop_put_if_new_aux:NNnn #1#2#3#4
+ { \@@_put_if_new:NNnn \tl_gput_right:Nx }
+\cs_new_protected:Npn \@@_put_if_new:NNnn #1#2#3#4
{
- \prop_split:NnTF #2 {#3}
+ \@@_split:NnTF #2 {#3}
{ \use_none:nnn }
{
#1 #2
- { \tl_to_str:n {#3} \exp_not:n { \q_prop {#4} \q_prop } }
+ { \tl_to_str:n {#3} \exp_not:n { \q_@@ {#4} \q_@@ } }
}
}
\cs_generate_variant:Nn \prop_put_if_new:Nnn { c }
@@ -814,10 +826,11 @@
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \subsection{Property list conditionals}
%
-% \begin{macro}[pTF]{\prop_if_exist:N, \prop_if_exist:c}
+% \begin{macro}[pTF, tested = m3prop004]{\prop_if_exist:N, \prop_if_exist:c}
% Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
% \begin{macrocode}
\cs_new_eq:NN \prop_if_exist:NTF \cs_if_exist:NTF
@@ -831,7 +844,7 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[pTF]{\prop_if_empty:N, \prop_if_empty:c}
+% \begin{macro}[pTF, tested = m3prop003]{\prop_if_empty:N, \prop_if_empty:c}
% The test here uses \cs{c_empty_prop} as it is not really empty!
% \begin{macrocode}
\prg_new_conditional:Npnn \prop_if_empty:N #1 { p, T , F , TF }
@@ -849,19 +862,19 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[pTF]
+% \begin{macro}[pTF, tested = m3prop003]
% {
% \prop_if_in:Nn, \prop_if_in:NV, \prop_if_in:No,
% \prop_if_in:cn, \prop_if_in:cV, \prop_if_in:co
% }
-% \begin{macro}[aux]{\prop_if_in_aux:nwn,\prop_if_in_aux:N}
+% \begin{macro}[aux]{\@@_if_in:nwn,\@@_if_in:N}
% Testing expandably if a key is in a property list
% requires to go through the key--value pairs one by one.
% This is rather slow, and a faster test would be
% \begin{verbatim}
% \prg_new_protected_conditional:Npnn \prop_if_in:Nn #1 #2
% {
-% \prop_split:NnTF #1 {#2}
+% \@@_split:NnTF #1 {#2}
% {
% \prg_return_true:
% \use_none:nnn
@@ -869,15 +882,15 @@
% { \prg_return_false: }
% }
% \end{verbatim}
-% but \cs{prop_split:NnTF} is non-expandable.
+% but \cs{@@_split:NnTF} is non-expandable.
%
-% Instead, the key is compared to each key in turn using \cs{str_if_eq:xx},
+% Instead, the key is compared to each key in turn using \cs{str_if_eq_x:nn},
% which is expandable. To terminate the mapping, we add the key that
% is search for at the end of the property list. This second
% \cs{tl_to_str:n} is not expanded at the start, but only when included
-% in the \cs{str_if_eq:xx}. It cannot make the breaking mechanism choke,
+% in the \cs{str_if_eq_x:nn}. It cannot make the breaking mechanism choke,
% because the arbitrary token list material is enclosed in braces.
-% When ending, we test the next token: it is either \cs{q_prop}
+% When ending, we test the next token: it is either \cs{q_@@}
% or \cs{q_recursion_tail} in the case of a missing key.
% Here, \cs{prop_map_function:NN} is not sufficient for the mapping,
% since it can only map a single token, and cannot carry the key that
@@ -885,26 +898,26 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \prop_if_in:Nn #1#2 { p , T , F , TF }
{
- \exp_last_unbraced:Noo \prop_if_in_aux:nwn
+ \exp_last_unbraced:Noo \@@_if_in:nwn
{ \tl_to_str:n {#2} } #1
- \tl_to_str:n {#2} \q_prop { }
- \q_recursion_tail
- \prg_break_point:n { }
+ \tl_to_str:n {#2} \q_@@ { }
+ \q_recursion_tail % could be any cs != \q_@@
+ \__prg_break_point:
}
-\cs_new:Npn \prop_if_in_aux:nwn #1 \q_prop #2 \q_prop #3
+\cs_new:Npn \@@_if_in:nwn #1 \q_@@ #2 \q_@@ #3
{
- \str_if_eq:xxTF {#1} {#2}
- { \prop_if_in_aux:N }
- { \prop_if_in_aux:nwn {#1} }
+ \str_if_eq_x:nnTF {#1} {#2}
+ { \@@_if_in:N }
+ { \@@_if_in:nwn {#1} }
}
-\cs_new:Npn \prop_if_in_aux:N #1
+\cs_new:Npn \@@_if_in:N #1
{
- \if_meaning:w \q_prop #1
+ \if_meaning:w \q_@@ #1
\prg_return_true:
\else:
\prg_return_false:
\fi:
- \prop_map_break:
+ \__prg_break:
}
\cs_generate_variant:Nn \prop_if_in_p:Nn { NV , No }
\cs_generate_variant:Nn \prop_if_in_p:Nn { c , cV , co }
@@ -920,23 +933,23 @@
%
% \subsection{Recovering values from property lists with branching}
%
-% \begin{macro}[TF]
+% \begin{macro}[TF, tested = m3prop004]
% {
% \prop_get:NnN, \prop_get:NVN, \prop_get:NoN,
% \prop_get:cnN, \prop_get:cVN, \prop_get:coN
% }
-% \begin{macro}[aux]{\prop_get_aux_true:Nnnn}
+% \begin{macro}[aux]{\@@_get_true:Nnnn}
% Getting the value corresponding to a key, keeping track of whether
% the key was present or not, is implemented as a conditional (with
% side effects). If the key was absent, the token list is not altered.
% \begin{macrocode}
\prg_new_protected_conditional:Npnn \prop_get:NnN #1#2#3 { T , F , TF }
{
- \prop_split:NnTF #1 {#2}
- { \prop_get_aux_true:Nnnn #3 }
+ \@@_split:NnTF #1 {#2}
+ { \@@_get_true:Nnnn #3 }
{ \prg_return_false: }
}
-\cs_new_protected:Npn \prop_get_aux_true:Nnnn #1#2#3#4
+\cs_new_protected:Npn \@@_get_true:Nnnn #1#2#3#4
{
\tl_set:Nn #1 {#3}
\prg_return_true:
@@ -953,29 +966,27 @@
%
% \subsection{Mapping to property lists}
%
-% \begin{macro}
+% \begin{macro}[tested = m3prop003]
% {
% \prop_map_function:NN, \prop_map_function:Nc,
% \prop_map_function:cN, \prop_map_function:cc
% }
-% \begin{macro}[aux]{\prop_map_function_aux:Nwn}
-% The fastest way to do a recursion here is to use an
+% \begin{macro}[aux]{\@@_map_function:Nwn}
+% The fastest way to do a recursion here would be to use an
% \cs{if_meaning:w} test: the keys are strings, and thus
% cannot match the marker \cs{q_recursion_tail}.
% \begin{macrocode}
\cs_new:Npn \prop_map_function:NN #1#2
{
- \exp_last_unbraced:NNo \prop_map_function_aux:Nwn #2
- #1 \q_recursion_tail \q_prop { }
- \prg_break_point:n { }
+ \exp_last_unbraced:NNo \@@_map_function:Nwn #2
+ #1 \q_recursion_tail \q_@@ { }
+ \__prg_break_point:Nn \prop_map_break: { }
}
-\cs_new:Npn \prop_map_function_aux:Nwn #1 \q_prop #2 \q_prop #3
+\cs_new:Npn \@@_map_function:Nwn #1 \q_@@ #2 \q_@@ #3
{
- \if_meaning:w \q_recursion_tail #2
- \exp_after:wN \prop_map_break:
- \fi:
+ \__quark_if_recursion_tail_break:nN {#2} \prop_map_break:
#1 {#2} {#3}
- \prop_map_function_aux:Nwn #1
+ \@@_map_function:Nwn #1
}
\cs_generate_variant:Nn \prop_map_function:NN { Nc }
\cs_generate_variant:Nn \prop_map_function:NN { c , cc }
@@ -983,145 +994,53 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\prop_map_inline:Nn, \prop_map_inline:cn}
+% \begin{macro}[tested = m3prop003]{\prop_map_inline:Nn, \prop_map_inline:cn}
% Mapping in line requires a nesting level counter.
% \begin{macrocode}
\cs_new_protected:Npn \prop_map_inline:Nn #1#2
{
- \int_gincr:N \g_prg_map_int
- \cs_gset:cpn { prop_map_inline_ \int_use:N \g_prg_map_int :nn }
- ##1##2 {#2}
- \exp_last_unbraced:Nco \prop_map_function_aux:Nwn
- { prop_map_inline_ \int_use:N \g_prg_map_int :nn }
+ \int_gincr:N \g__prg_map_int
+ \cs_gset:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } ##1##2 {#2}
+ \exp_last_unbraced:Nco \@@_map_function:Nwn
+ { __prg_map_ \int_use:N \g__prg_map_int :w }
#1
- \q_recursion_tail \q_prop { }
- \prg_break_point:n { \int_gdecr:N \g_prg_map_int }
+ \q_recursion_tail \q_@@ { }
+ \__prg_break_point:Nn \prop_map_break: { \int_gdecr:N \g__prg_map_int }
}
\cs_generate_variant:Nn \prop_map_inline:Nn { c }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\prop_map_break:}
-% \begin{macro}{\prop_map_break:n}
-% The break statements are simply copies.
+% \begin{macro}[tested = m3prop003]{\prop_map_break:}
+% \begin{macro}[tested = m3prop003]{\prop_map_break:n}
+% The break statements are based on the general \cs{__prg_map_break:Nn}.
% \begin{macrocode}
-\cs_new_eq:NN \prop_map_break: \prg_map_break:
-\cs_new_eq:NN \prop_map_break:n \prg_map_break:n
+\cs_new_nopar:Npn \prop_map_break:
+ { \__prg_map_break:Nn \prop_map_break: { } }
+\cs_new_nopar:Npn \prop_map_break:n
+ { \__prg_map_break:Nn \prop_map_break: }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Viewing property lists}
%
-% \begin{macro}{\prop_show:N, \prop_show:c}
-% Apply the general \cs{msg_aux_show:Nnx}. Contrarily
-% to sequences and comma lists, we use \cs{msg_aux_show:nn}
+% \begin{macro}[tested = m3show001]{\prop_show:N, \prop_show:c}
+% Apply the general \cs{__msg_show_variable:Nnn}. Contrarily
+% to sequences and comma lists, we use \cs{__msg_show_item:nn}
% to format both the key and the value for each pair.
% \begin{macrocode}
\cs_new_protected:Npn \prop_show:N #1
{
- \msg_aux_show:Nnx
+ \__msg_show_variable:Nnn
#1
{ prop }
- { \prop_map_function:NN #1 \msg_aux_show:nn }
+ { \prop_map_function:NN #1 \__msg_show_item:nn }
}
\cs_generate_variant:Nn \prop_show:N { c }
% \end{macrocode}
% \end{macro}
%
-% \subsection{Experimental functions}
-%
-% \begin{macro}[TF]
-% {\prop_pop:NnN, \prop_pop:cnN, \prop_gpop:cnN, \prop_gpop:cnN}
-% \begin{macro}[aux]{\prop_pop_aux_true:NNNnnn}
-% Popping an item from a property list, keeping track of whether
-% the key was present or not, is implemented as a conditional.
-% If the key was missing, neither the property list, nor the token
-% list are altered. Otherwise, \cs{prg_return_true:} is used after
-% the assignments.
-% \begin{macrocode}
-\prg_new_protected_conditional:Npnn \prop_pop:NnN #1#2#3 { T , F , TF }
- {
- \prop_split:NnTF #1 {#2}
- { \prop_pop_aux_true:NNNnnn \tl_set:Nn #1 #3 }
- { \prg_return_false: }
- }
-\prg_new_protected_conditional:Npnn \prop_gpop:NnN #1#2#3 { T , F , TF }
- {
- \prop_split:NnTF #1 {#2}
- { \prop_pop_aux_true:NNNnnn \tl_gset:Nn #1 #3 }
- { \prg_return_false: }
- }
-\cs_new_protected:Npn \prop_pop_aux_true:NNNnnn #1#2#3#4#5#6
- {
- \tl_set:Nn #3 {#5}
- #1 #2 { #4 #6 }
- \prg_return_true:
- }
-\cs_generate_variant:Nn \prop_pop:NnNT { c }
-\cs_generate_variant:Nn \prop_pop:NnNF { c }
-\cs_generate_variant:Nn \prop_pop:NnNTF { c }
-\cs_generate_variant:Nn \prop_gpop:NnNT { c }
-\cs_generate_variant:Nn \prop_gpop:NnNF { c }
-\cs_generate_variant:Nn \prop_gpop:NnNTF { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[rEXP]{\prop_map_tokens:Nn, \prop_map_tokens:cn}
-% \begin{macro}[aux]{\prop_map_tokens_aux:nwn}
-% The mapping grabs one key--value pair at a time, and stops when
-% reaching the marker key \cs{q_recursion_tail}, which
-% cannot appear in normal keys since those are strings. The odd
-% construction |\use:n {#1}| allows |#1| to contain any token.
-% \begin{macrocode}
-\cs_new:Npn \prop_map_tokens:Nn #1#2
- {
- \exp_last_unbraced:Nno \prop_map_tokens_aux:nwn {#2} #1
- \q_recursion_tail \q_prop { }
- \prg_break_point:n { }
- }
-\cs_new:Npn \prop_map_tokens_aux:nwn #1 \q_prop #2 \q_prop #3
- {
- \if_meaning:w \q_recursion_tail #2
- \exp_after:wN \prop_map_break:
- \fi:
- \use:n {#1} {#2} {#3}
- \prop_map_tokens_aux:nwn {#1}
- }
-\cs_generate_variant:Nn \prop_map_tokens:Nn { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\prop_get:Nn, \prop_get:cn}
-% \begin{macro}[aux]{\prop_get_Nn_aux:nwn}
-% Getting the value corresponding to a key in a property list in an
-% expandable fashion is a simple instance of mapping some tokens.
-% Map the function \cs{prop_get_aux:nnn} which takes as its three
-% arguments the \meta{key} that we are looking for, the current
-% \meta{key} and the current \meta{value}. If the \meta{keys} match,
-% the \meta{value} is returned. If none of the keys match, this expands
-% to nothing.
-% \begin{macrocode}
-\cs_new:Npn \prop_get:Nn #1#2
- {
- \exp_last_unbraced:Noo \prop_get_Nn_aux:nwn
- { \tl_to_str:n {#2} } #1
- \tl_to_str:n {#2} \q_prop { }
- \prg_break_point:n { }
- }
-\cs_new:Npn \prop_get_Nn_aux:nwn #1 \q_prop #2 \q_prop #3
- {
- \str_if_eq:xxTF {#1} {#2}
- { \prg_map_break:n { \exp_not:n {#3} } }
- { \prop_get_Nn_aux:nwn {#1} }
- }
-\cs_generate_variant:Nn \prop_get:Nn { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
% \subsection{Deprecated interfaces}
%
% Deprecated on 2011-05-27, for removal by 2011-08-31.
@@ -1142,10 +1061,12 @@
% the necessary code for the transition is provided directly.
% \begin{macrocode}
%<*deprecated>
+\tl_new:N \l_@@_internal_tl
\cs_new_protected:Npn \prop_gget:NnN #1#2#3
- { \prop_split:Nnn #1 {#2} { \prop_gget_aux:Nnnn #3 } }
-\cs_new_protected:Npn \prop_gget_aux:Nnnn #1#2#3#4
- { \tl_gset:Nn #1 {#3} }
+ {
+ \prop_get:NnN #1 {#2} \l_@@_internal_tl
+ \tl_gset_eq:NN #3 \l_@@_internal_tl
+ }
\cs_generate_variant:Nn \prop_gget:NnN { NV }
\cs_generate_variant:Nn \prop_gget:NnN { c , cV }
%</deprecated>
@@ -1195,6 +1116,23 @@
% \end{macrocode}
% \end{macro}
%
+% Deprecated on 2012-05-12, for removal by 2012-11-30.
+%
+% \begin{macro}{\prop_del:Nn, \prop_del:NV, \prop_del:cn, \prop_del:cV}
+% \begin{macro}{\prop_gdel:Nn, \prop_gdel:NV, \prop_gdel:cn, \prop_gdel:cV}
+% \begin{macrocode}
+\cs_new_eq:NN \prop_del:Nn \prop_remove:Nn
+\cs_new_eq:NN \prop_del:NV \prop_remove:NV
+\cs_new_eq:NN \prop_del:cn \prop_remove:cn
+\cs_new_eq:NN \prop_del:cV \prop_remove:cV
+\cs_new_eq:NN \prop_gdel:Nn \prop_gremove:Nn
+\cs_new_eq:NN \prop_gdel:NV \prop_gremove:NV
+\cs_new_eq:NN \prop_gdel:cn \prop_gremove:cn
+\cs_new_eq:NN \prop_gdel:cV \prop_gremove:cV
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
index 3cb65a59b33..b85b03440df 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3quark.dtx
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3quark.dtx 3384 2012-02-12 13:13:11Z will $
- {L3 Experimental quarks}
+\GetIdInfo$Id: l3quark.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Quarks}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -71,8 +71,9 @@
%
% Two special types of constants in \LaTeX3 are \enquote{quarks} and
% \enquote{scan marks}. By convention all constants of type quark
-% start out with |\q_|, and scan marks start with |\s_|.
-% \emph{Scan marks are an experimental feature.}
+% start out with |\q_|, and scan marks start with |\s_|. Scan marks are
+% for internal use by the kernel: they are not intended for more general
+% use.
%
% \subsection{Quarks}
%
@@ -114,22 +115,6 @@
% An example of the quark testing functions and their use in recursion
% can be seen in the implementation of \cs{clist_map_function:NN}.
%
-%
-% \subsection{Scan marks}
-%
-% Scan marks are control sequences set equal to \cs{scan_stop:},
-% hence will never expand in an expansion context and will be (largely)
-% invisible if they are encountered in a typesetting context.
-%
-% Like quarks, they can be used as delimiters in weird functions
-% and are often safer to use for this purpose.
-% Since they are harmless when executed by \TeX{} in non-expandable
-% contexts, they can be used to mark the end of a set of instructions.
-% This allows to skip to that point if the end of the instructions
-% should not be performed (see \pkg{l3regex}).
-%
-%^^A todo: talk about the use of scan marks in galley and fp.
-%
% \section{Defining quarks}
%
% \begin{function}{\quark_new:N}
@@ -279,63 +264,81 @@
% ended.
% \end{function}
%
+% \section{Clearing quarks away}
+%
+% \begin{function}{\use_none_delimit_by_q_recursion_stop:w}
+% \begin{syntax}
+% \cs{use_none_delimit_by_q_recursion_stop:w} \meta{tokens} \cs{q_recursion_stop}
+% \end{syntax}
+% Used to prematurely terminate a recursion using \cs{q_recursion_stop}
+% as the end marker, removing any remaining \meta{tokens} from the
+% input stream.
+% \end{function}
+%
+% \begin{function}{\use_i_delimit_by_q_recursion_stop:nw}
+% \begin{syntax}
+% \cs{use_i_delimit_by_q_recursion_stop:nw} \Arg{insertion}
+% ~~\meta{tokens} \cs{q_recursion_stop}
+% \end{syntax}
+% Used to prematurely terminate a recursion using \cs{q_recursion_stop}
+% as the end marker, removing any remaining \meta{tokens} from the
+% input stream. The \meta{insertion} is then made into the input
+% stream after the end of the recursion.
+% \end{function}
+%
+% \section{Internal quark functions}
+%
% \begin{function}
% {
-% \quark_if_recursion_tail_break:N,
-% \quark_if_recursion_tail_break:n
+% \__quark_if_recursion_tail_break:NN,
+% \__quark_if_recursion_tail_break:nN
% }
% \begin{syntax}
-% \cs{quark_if_recursion_tail_break:n} \Arg{token list}
+% \cs{__quark_if_recursion_tail_break:nN} \Arg{token list} \cs{\meta{type}_map_break:}
% \end{syntax}
-% Tests if \meta{token list} contains only \cs{q_recursion_tail},
-% and if so terminates the recursion using \cs{prg_map_break:}.
-% The recursion end should be marked by \cs{prg_break_point:n}.
+% Tests if \meta{token list} contains only \cs{q_recursion_tail}, and
+% if so terminates the recursion using \cs{\meta{type}_map_break:}.
+% The recursion end should be marked by \cs{prg_break_point:Nn}
+% \cs{\meta{type}_map_break:}.
% \end{function}
%
% \section{Scan marks}
%
-% \begin{function}{\scan_new:N}
+% Scan marks are control sequences set equal to \cs{scan_stop:},
+% hence will never expand in an expansion context and will be (largely)
+% invisible if they are encountered in a typesetting context.
+%
+% Like quarks, they can be used as delimiters in weird functions
+% and are often safer to use for this purpose.
+% Since they are harmless when executed by \TeX{} in non-expandable
+% contexts, they can be used to mark the end of a set of instructions.
+% This allows to skip to that point if the end of the instructions
+% should not be performed (see \pkg{l3regex}).
+%
+% The scan marks system is only for internal use by the kernel team in
+% a small number of very specific places. These functions should not be
+% used more generally.
+%
+% \begin{function}{\__scan_new:N}
% \begin{syntax}
-% \cs{scan_new:N} \meta{scan mark}
+% \cs{__scan_new:N} \meta{scan mark}
% \end{syntax}
% Creates a new \meta{scan mark} which is set equal to \cs{scan_stop:}.
% The \meta{scan mark} will be defined globally, and an error message
% will be raised if the name was already taken by another scan mark.
% \end{function}
%
-% \begin{variable}{\s_stop}
+% \begin{variable}{\s__stop}
% Used at the end of a set of instructions, as a marker
-% that can be jumped to using \cs{use_none_delimit_by_s_stop:w}.
+% that can be jumped to using \cs{__use_none_delimit_by_s__stop:w}.
% \end{variable}
%
-% \begin{function}{\use_none_delimit_by_s_stop:w}
+% \begin{function}{\__use_none_delimit_by_s__stop:w}
% \begin{syntax}
-% \cs{use_none_delimit_by_s_stop:w} \meta{tokens} \cs{s_stop}
+% \cs{__use_none_delimit_by_s__stop:w} \meta{tokens} \cs{s__stop}
% \end{syntax}
-% Removes the \meta{tokens} and \cs{s_stop} from the input stream.
-% This leads to a low-level \TeX{} error if \cs{s_stop} is absent.
-% \end{function}
-%
-% \section{Internal quark functions}
-%
-% \begin{function}{\use_none_delimit_by_q_recursion_stop:w}
-% \begin{syntax}
-% \cs{use_none_delimit_by_q_recursion_stop:w} \meta{tokens} \cs{q_recursion_stop}
-% \end{syntax}
-% Used to prematurely terminate a recursion using \cs{q_recursion_stop}
-% as the end marker, removing any remaining \meta{tokens} from the
-% input stream.
-% \end{function}
-%
-% \begin{function}{\use_i_delimit_by_q_recursion_stop:nw}
-% \begin{syntax}
-% \cs{use_i_delimit_by_q_recursion_stop:nw} \Arg{insertion}
-% ~~\meta{tokens} \cs{q_recursion_stop}
-% \end{syntax}
-% Used to prematurely terminate a recursion using \cs{q_recursion_stop}
-% as the end marker, removing any remaining \meta{tokens} from the
-% input stream. The \meta{insertion} is then made into the input
-% stream after the end of the recursion.
+% Removes the \meta{tokens} and \cs{s__stop} from the input stream.
+% This leads to a low-level \TeX{} error if \cs{s__stop} is absent.
% \end{function}
%
% \end{documentation}
@@ -354,7 +357,7 @@
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -453,22 +456,22 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\quark_if_recursion_tail_break:N}
-% \begin{macro}{\quark_if_recursion_tail_break:n}
+% \begin{macro}{\__quark_if_recursion_tail_break:NN}
+% \begin{macro}{\__quark_if_recursion_tail_break:nN}
% Analogs of the \cs{quark_if_recursion_tail_stop\ldots{}} functions.
-% Break the mapping using \cs{prg_map_break:}.
+% Break the mapping using |#2|.
% \begin{macrocode}
-\cs_new:Npn \quark_if_recursion_tail_break:N #1
+\cs_new:Npn \__quark_if_recursion_tail_break:NN #1#2
{
\if_meaning:w \q_recursion_tail #1
- \exp_after:wN \prg_map_break:
+ \exp_after:wN #2
\fi:
}
-\cs_new:Npn \quark_if_recursion_tail_break:n #1
+\cs_new:Npn \__quark_if_recursion_tail_break:nN #1#2
{
\if_int_compare:w \pdftex_strcmp:D
{ \exp_not:N \q_recursion_tail } { \exp_not:n {#1} } = \c_zero
- \exp_after:wN \prg_map_break:
+ \exp_after:wN #2
\fi:
}
% \end{macrocode}
@@ -477,7 +480,7 @@
%
% \begin{macro}[pTF]{\quark_if_nil:N}
% \UnitTested
-% \begin{macro}[pTF]{\quark_if_no_value:N., \quark_if_no_value:c}
+% \begin{macro}[pTF]{\quark_if_no_value:N, \quark_if_no_value:c}
% \UnitTested
% Here we test if we found a special quark as the first argument.
% We better start with \cs{q_no_value} as the first argument since
@@ -541,59 +544,77 @@
% \end{macro}
% \end{macro}
%
-% \begin{variable}{\q_tl_act_mark,\q_tl_act_stop}
+% \begin{variable}{\q__tl_act_mark, \q__tl_act_stop}
% These private quarks are needed by \pkg{l3tl}, but that is loaded
% before the quark module, hence their definition is deferred.
% \begin{macrocode}
-\quark_new:N \q_tl_act_mark
-\quark_new:N \q_tl_act_stop
+\quark_new:N \q__tl_act_mark
+\quark_new:N \q__tl_act_stop
% \end{macrocode}
% \end{variable}
%
% \subsection{Scan marks}
+%
+% \begin{macrocode}
+%<@@=scan>
+% \end{macrocode}
%
-% \begin{variable}{\g_scan_marks_tl}
+% \begin{variable}{\g_@@_marks_tl}
% \UnitTested
% The list of all scan marks currently declared.
% \begin{macrocode}
-\tl_new:N \g_scan_marks_tl
+\tl_new:N \g_@@_marks_tl
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}{\scan_new:N}
+% \begin{macro}[int]{\@@_new:N}
% \UnitTested
% Check whether the variable is already a scan mark,
% then declare it to be equal to \cs{scan_stop:} globally.
% \begin{macrocode}
-\cs_new_protected:Npn \scan_new:N #1
+\cs_new_protected:Npn \@@_new:N #1
{
- \tl_if_in:NnTF \g_scan_marks_tl { #1 }
+ \tl_if_in:NnTF \g_@@_marks_tl { #1 }
{
- \msg_kernel_error:nnx { scan } { already-defined }
+ \__msg_kernel_error:nnx { kernel } { scanmark-already-defined }
{ \token_to_str:N #1 }
}
{
- \tl_gput_right:Nn \g_scan_marks_tl {#1}
+ \tl_gput_right:Nn \g_@@_marks_tl {#1}
\cs_new_eq:NN #1 \scan_stop:
}
}
% \end{macrocode}
% \end{macro}
%
-% \begin{variable}{\s_stop}
+% \begin{variable}{\s__stop}
% \UnitTested
% We only declare one scan mark here, more can be defined
% by specific modules.
% \begin{macrocode}
-\scan_new:N \s_stop
+\@@_new:N \s__stop
% \end{macrocode}
% \end{variable}
%
-% \begin{macro}{\use_none_delimit_by_s_stop:w}
+% \begin{macro}[int]{\__use_none_delimit_by_s__stop:w}
% \UnitTested
% Similar to \cs{use_none_delimit_by_q_stop:w}.
% \begin{macrocode}
-\cs_new:Npn \use_none_delimit_by_s_stop:w #1 \s_stop { }
+\cs_new:Npn \__use_none_delimit_by_s__stop:w #1 \s__stop { }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Deprecated quark functions}
+%
+% \begin{macro}
+% {\quark_if_recursion_tail_break:N, \quark_if_recursion_tail_break:n}
+% It's not clear what breaking function we should be using here, so
+% I'm picking one somewhat arbitrarily.
+% \begin{macrocode}
+\cs_new:Npn \quark_if_recursion_tail_break:N #1
+ { \__quark_if_recursion_tail_break:NN #1 \prg_break: }
+\cs_new:Npn \quark_if_recursion_tail_break:n #1
+ { \__quark_if_recursion_tail_break:nN {#1} \prg_break: }
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
index d8dd80c75ed..d4a3688a068 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3seq.dtx
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3seq.dtx 3490 2012-03-04 01:00:53Z bruno $
- {L3 Experimental sequences and stacks}
+\GetIdInfo$Id: l3seq.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Sequences and stacks}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -109,14 +109,17 @@
% \seq_gset_eq:NN, \seq_gset_eq:cN, \seq_gset_eq:Nc, \seq_gset_eq:cc
% }
% \begin{syntax}
-% \cs{seq_set_eq:NN} \meta{sequence1} \meta{sequence2}
+% \cs{seq_set_eq:NN} \meta{sequence_1} \meta{sequence_2}
% \end{syntax}
-% Sets the content of \meta{sequence1} equal to that of
-% \meta{sequence2}.
+% Sets the content of \meta{sequence_1} equal to that of
+% \meta{sequence_2}.
% \end{function}
%
-% \begin{function}[added = 2011-08-15, updated = 2011-12-07]
-% {\seq_set_split:Nnn, \seq_gset_split:Nnn}
+% \begin{function}[added = 2011-08-15, updated = 2012-07-02]
+% {
+% \seq_set_split:Nnn , \seq_set_split:NnV ,
+% \seq_gset_split:Nnn, \seq_gset_split:NnV
+% }
% \begin{syntax}
% \cs{seq_set_split:Nnn} \meta{sequence} \Arg{delimiter} \Arg{token list}
% \end{syntax}
@@ -137,11 +140,11 @@
% \begin{function}
% {\seq_concat:NNN, \seq_concat:ccc, \seq_gconcat:NNN, \seq_gconcat:ccc}
% \begin{syntax}
-% \cs{seq_concat:NNN} \meta{sequence1} \meta{sequence2} \meta{sequence3}
+% \cs{seq_concat:NNN} \meta{sequence_1} \meta{sequence_2} \meta{sequence_3}
% \end{syntax}
-% Concatenates the content of \meta{sequence2} and \meta{sequence3}
-% together and saves the result in \meta{sequence1}. The items in
-% \meta{sequence2} will be placed at the left side of the new sequence.
+% Concatenates the content of \meta{sequence_2} and \meta{sequence_3}
+% together and saves the result in \meta{sequence_1}. The items in
+% \meta{sequence_2} will be placed at the left side of the new sequence.
% \end{function}
%
% \begin{function}[EXP, pTF, added=2012-03-03]
@@ -197,27 +200,29 @@
% \meta{token list variable} used with \cs{tl_set:Nn} and \emph{never}
% \cs{tl_gset:Nn}.
%
-% \begin{function}{\seq_get_left:NN, \seq_get_left:cN}
+% \begin{function}[updated = 2012-05-14]{\seq_get_left:NN, \seq_get_left:cN}
% \begin{syntax}
% \cs{seq_get_left:NN} \meta{sequence} \meta{token list variable}
% \end{syntax}
% Stores the left-most item from a \meta{sequence} in the
% \meta{token list variable} without removing it from the
% \meta{sequence}. The \meta{token list variable} is assigned locally.
-% If \meta{sequence} is empty an error will be raised.
+% If \meta{sequence} is empty the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}.
% \end{function}
%
-% \begin{function}{\seq_get_right:NN, \seq_get_right:cN}
+% \begin{function}[updated = 2012-05-19]{\seq_get_right:NN, \seq_get_right:cN}
% \begin{syntax}
% \cs{seq_get_right:NN} \meta{sequence} \meta{token list variable}
% \end{syntax}
% Stores the right-most item from a \meta{sequence} in the
% \meta{token list variable} without removing it from the
% \meta{sequence}. The \meta{token list variable} is assigned locally.
-% If \meta{sequence} is empty an error will be raised.
+% If \meta{sequence} is empty the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}.
% \end{function}
%
-% \begin{function}{\seq_pop_left:NN, \seq_pop_left:cN}
+% \begin{function}[updated = 2012-05-14]{\seq_pop_left:NN, \seq_pop_left:cN}
% \begin{syntax}
% \cs{seq_pop_left:NN} \meta{sequence} \meta{token list variable}
% \end{syntax}
@@ -225,10 +230,11 @@
% \meta{token list variable}, \emph{i.e.}~removes the item from the
% sequence and stores it in the \meta{token list variable}.
% Both of the variables are assigned locally. If \meta{sequence} is
-% empty an error will be raised.
+% empty the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}.
% \end{function}
%
-% \begin{function}{\seq_gpop_left:NN, \seq_gpop_left:cN}
+% \begin{function}[updated = 2012-05-14]{\seq_gpop_left:NN, \seq_gpop_left:cN}
% \begin{syntax}
% \cs{seq_gpop_left:NN} \meta{sequence} \meta{token list variable}
% \end{syntax}
@@ -237,10 +243,11 @@
% sequence and stores it in the \meta{token list variable}.
% The \meta{sequence} is modified globally, while the assignment of
% the \meta{token list variable} is local.
-% If \meta{sequence} is empty an error will be raised.
+% If \meta{sequence} is empty the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}.
% \end{function}
%
-% \begin{function}{\seq_pop_right:NN, \seq_pop_right:cN}
+% \begin{function}[updated = 2012-05-19]{\seq_pop_right:NN, \seq_pop_right:cN}
% \begin{syntax}
% \cs{seq_pop_right:NN} \meta{sequence} \meta{token list variable}
% \end{syntax}
@@ -248,10 +255,11 @@
% \meta{token list variable}, \emph{i.e.}~removes the item from the
% sequence and stores it in in the \meta{token list variable}.
% Both of the variables are assigned locally. If \meta{sequence} is
-% empty an error will be raised.
+% empty the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}.
% \end{function}
%
-% \begin{function}{\seq_gpop_right:NN, \seq_gpop_right:cN}
+% \begin{function}[updated = 2012-05-19]{\seq_gpop_right:NN, \seq_gpop_right:cN}
% \begin{syntax}
% \cs{seq_gpop_right:NN} \meta{sequence} \meta{token list variable}
% \end{syntax}
@@ -260,7 +268,104 @@
% sequence and stores it in the \meta{token list variable}.
% The \meta{sequence} is modified globally, while the assignment of
% the \meta{token list variable} is local.
-% If \meta{sequence} is empty an error will be raised.
+% If \meta{sequence} is empty the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}.
+% \end{function}
+%
+% \section{Recovering values from sequences with branching}
+%
+% The functions in this section combine tests for non-empty sequences
+% with recovery of an item from the sequence. They offer increased readability
+% and performance over separate testing and recovery phases.
+%
+% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19]
+% {\seq_get_left:NN, \seq_get_left:cN}
+% \begin{syntax}
+% \cs{seq_get_left:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{sequence} is empty, leaves the \meta{false code} in the
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{sequence} is non-empty, stores the left-most item from a
+% \meta{sequence}
+% in the \meta{token list variable} without removing it from a
+% \meta{sequence}.
+% The \meta{token list variable} is assigned locally.
+% \end{function}
+%
+% \begin{function}[TF, added = 2012-05-19]
+% {\seq_get_right:NN, \seq_get_right:cN}
+% \begin{syntax}
+% \cs{seq_get_right:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{sequence} is empty, leaves the \meta{false code} in the
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{sequence} is non-empty, stores the right-most item from a
+% \meta{sequence}
+% in the \meta{token list variable} without removing it from a
+% \meta{sequence}.
+% The \meta{token list variable} is assigned locally.
+% \end{function}
+%
+% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19]
+% {\seq_pop_left:NN, \seq_pop_left:cN}
+% \begin{syntax}
+% \cs{seq_pop_left:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{sequence} is empty, leaves the \meta{false code} in the
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{sequence} is non-empty, pops the left-most item from a
+% \meta{sequence}
+% in the \meta{token list variable}, \emph{i.e.}~removes the item from a
+% \meta{sequence}.
+% Both the \meta{sequence} and the \meta{token list variable} are assigned
+% locally.
+% \end{function}
+%
+% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19]
+% {\seq_gpop_left:NN, \seq_gpop_left:cN}
+% \begin{syntax}
+% \cs{seq_gpop_left:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{sequence} is empty, leaves the \meta{false code} in the
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{sequence} is non-empty, pops the left-most item from a \meta{sequence}
+% in the \meta{token list variable}, \emph{i.e.}~removes the item from a
+% \meta{sequence}.
+% The \meta{sequence} is modified globally, while the \meta{token list variable}
+% is assigned locally.
+% \end{function}
+%
+% \begin{function}[TF, added = 2012-05-19]
+% {\seq_pop_right:NN, \seq_pop_right:cN}
+% \begin{syntax}
+% \cs{seq_pop_right:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{sequence} is empty, leaves the \meta{false code} in the
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{sequence} is non-empty, pops the right-most item from a \meta{sequence}
+% in the \meta{token list variable}, \emph{i.e.}~removes the item from a
+% \meta{sequence}.
+% Both the \meta{sequence} and the \meta{token list variable} are assigned
+% locally.
+% \end{function}
+%
+% \begin{function}[TF, added = 2012-05-19]
+% {\seq_gpop_right:NN, \seq_gpop_right:cN}
+% \begin{syntax}
+% \cs{seq_gpop_right:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% If the \meta{sequence} is empty, leaves the \meta{false code} in the
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{sequence} is non-empty, pops the right-most item from a \meta{sequence}
+% in the \meta{token list variable}, \emph{i.e.}~removes the item from a
+% \meta{sequence}. The \meta{sequence} is modified globally, while the
+% \meta{token list variable} is assigned locally.
% \end{function}
%
% \section{Modifying sequences}
@@ -324,7 +429,8 @@
%
% \section{Mapping to sequences}
%
-% \begin{function}[rEXP]{\seq_map_function:NN, \seq_map_function:cN}
+% \begin{function}[rEXP, updated = 2012-06-29]
+% {\seq_map_function:NN, \seq_map_function:cN}
% \begin{syntax}
% \cs{seq_map_function:NN} \meta{sequence} \meta{function}
% \end{syntax}
@@ -336,7 +442,8 @@
% One mapping may be nested inside another.
% \end{function}
%
-% \begin{function}{\seq_map_inline:Nn, \seq_map_inline:cn}
+% \begin{function}[updated = 2012-06-29]
+% {\seq_map_inline:Nn, \seq_map_inline:cn}
% \begin{syntax}
% \cs{seq_map_inline:Nn} \meta{sequence} \Arg{inline function}
% \end{syntax}
@@ -347,10 +454,11 @@
% are returned from left to right.
% \end{function}
%
-% \begin{function}{
-% \seq_map_variable:NNn, \seq_map_variable:Ncn,
-% \seq_map_variable:cNn, \seq_map_variable:ccn
-% }
+% \begin{function}[updated = 2012-06-29]
+% {
+% \seq_map_variable:NNn, \seq_map_variable:Ncn,
+% \seq_map_variable:cNn, \seq_map_variable:ccn
+% }
% \begin{syntax}
% \cs{seq_map_variable:NNn} \meta{sequence} \meta{tl~var.} \Arg{function using tl~var.}
% \end{syntax}
@@ -362,7 +470,7 @@
% are returned from left to right.
% \end{function}
%
-% \begin{function}[rEXP]{\seq_map_break:}
+% \begin{function}[rEXP, updated = 2012-06-29]{\seq_map_break:}
% \begin{syntax}
% \cs{seq_map_break:}
% \end{syntax}
@@ -383,13 +491,13 @@
% level \TeX{} errors.
% \begin{texnote}
% When the mapping is broken, additional tokens may be inserted by the
-% internal macro \cs{prg_break_point:n} before further items are taken
+% internal macro \cs{__prg_break_point:Nn} before further items are taken
% from the input stream. This will depend on the design of the mapping
% function.
% \end{texnote}
% \end{function}
%
-% \begin{function}[rEXP]{\seq_map_break:n}
+% \begin{function}[rEXP, updated = 2012-06-29]{\seq_map_break:n}
% \begin{syntax}
% \cs{seq_map_break:n} \Arg{tokens}
% \end{syntax}
@@ -411,12 +519,22 @@
% level \TeX{} errors.
% \begin{texnote}
% When the mapping is broken, additional tokens may be inserted by the
-% internal macro \cs{prg_break_point:n} before the \meta{tokens} are
+% internal macro \cs{__prg_break_point:Nn} before the \meta{tokens} are
% inserted into the input stream.
% This will depend on the design of the mapping function.
% \end{texnote}
% \end{function}
%
+% \begin{function}[EXP, added = 2012-07-13]{\seq_count:N, \seq_count:c}
+% \begin{syntax}
+% \cs{seq_count:N} \meta{sequence}
+% \end{syntax}
+% Leaves the number of items in the \meta{sequence} in the input
+% stream as an \meta{integer denotation}. The total number of items
+% in a \meta{sequence} will include those which are empty and duplicates,
+% \emph{i.e.}~every item in a \meta{sequence} is unique.
+% \end{function}
+%
% \section{Sequences as stacks}
%
% Sequences can be used as stacks, where data is pushed to and popped
@@ -426,322 +544,147 @@
% in the previous section: a sequence should either be used as an
% ordered data type or as a stack, but not in both ways.
%
-% \begin{function}{\seq_get:NN, \seq_get:cN}
+% \begin{function}[updated = 2012-05-14]{\seq_get:NN, \seq_get:cN}
% \begin{syntax}
% \cs{seq_get:NN} \meta{sequence} \meta{token list variable}
% \end{syntax}
% Reads the top item from a \meta{sequence} into the
% \meta{token list variable} without removing it from the
% \meta{sequence}. The \meta{token list variable} is assigned locally.
-% If \meta{sequence} is empty an error will be raised.
+% If \meta{sequence} is empty the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}.
% \end{function}
%
-% \begin{function}{\seq_pop:NN, \seq_pop:cN}
+% \begin{function}[updated = 2012-05-14]{\seq_pop:NN, \seq_pop:cN}
% \begin{syntax}
% \cs{seq_pop:NN} \meta{sequence} \meta{token list variable}
% \end{syntax}
% Pops the top item from a \meta{sequence} into the
% \meta{token list variable}. Both of the variables are assigned
-% locally. If \meta{sequence} is empty an error will be raised.
+% locally. If \meta{sequence} is empty the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}.
% \end{function}
%
-% \begin{function}{\seq_gpop:NN, \seq_gpop:cN}
+% \begin{function}[updated = 2012-05-14]{\seq_gpop:NN, \seq_gpop:cN}
% \begin{syntax}
% \cs{seq_gpop:NN} \meta{sequence} \meta{token list variable}
% \end{syntax}
% Pops the top item from a \meta{sequence} into the
% \meta{token list variable}. The \meta{sequence} is modified globally,
% while the \meta{token list variable} is assigned locally. If
-% \meta{sequence} is empty an error will be raised.
-% \end{function}
-%
-% \begin{function}
-% {
-% \seq_push:Nn, \seq_push:NV, \seq_push:Nv, \seq_push:No, \seq_push:Nx,
-% \seq_push:cn, \seq_push:cV, \seq_push:cv, \seq_push:co, \seq_push:cx,
-% \seq_gpush:Nn, \seq_gpush:NV, \seq_gpush:Nv,
-% \seq_gpush:No, \seq_gpush:Nx,
-% \seq_gpush:cn, \seq_gpush:cV, \seq_gpush:cv,
-% \seq_gpush:co, \seq_gpush:cx
-% }
-% \begin{syntax}
-% \cs{seq_push:Nn} \meta{sequence} \Arg{item}
-% \end{syntax}
-% Adds the \Arg{item} to the top of the \meta{sequence}.
-% \end{function}
-%
-% \section{Viewing sequences}
-%
-% \begin{function}{\seq_show:N, \seq_show:c}
-% \begin{syntax}
-% \cs{seq_show:N} \meta{sequence}
-% \end{syntax}
-% Displays the entries in the \meta{sequence} in the terminal.
-% \end{function}
-%
-% \section{Experimental sequence functions}
-%
-% This section contains functions which may or may not be retained, depending
-% on how useful they are found to be.
-%
-% \begin{function}[TF]{\seq_get_left:NN, \seq_get_left:cN}
-% \begin{syntax}
-% \cs{seq_get_left:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% If the \meta{sequence} is empty, leaves the \meta{false code} in the
-% input stream and leaves the \meta{token list variable} unchanged. If the
-% \meta{sequence} is non-empty, stores the left-most item from a
-% \meta{sequence}
-% in the \meta{token list variable} without removing it from a
-% \meta{sequence}.
-% The \meta{token list variable} is assigned locally.
-% \end{function}
-%
-% \begin{function}[TF]{\seq_get_right:NN, \seq_get_right:cN}
-% \begin{syntax}
-% \cs{seq_get_right:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% If the \meta{sequence} is empty, leaves the \meta{false code} in the
-% input stream and leaves the \meta{token list variable} unchanged. If the
-% \meta{sequence} is non-empty, stores the right-most item from a
-% \meta{sequence}
-% in the \meta{token list variable} without removing it from a
-% \meta{sequence}.
-% The \meta{token list variable} is assigned locally.
-% \end{function}
-%
-% \begin{function}[TF]{\seq_pop_left:NN, \seq_pop_left:cN}
-% \begin{syntax}
-% \cs{seq_pop_left:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% If the \meta{sequence} is empty, leaves the \meta{false code} in the
-% input stream and leaves the \meta{token list variable} unchanged. If the
-% \meta{sequence} is non-empty, pops the left-most item from a
-% \meta{sequence}
-% in the \meta{token list variable}, \emph{i.e.}~removes the item from a
-% \meta{sequence}.
-% Both the \meta{sequence} and the \meta{token list variable} are assigned
-% locally.
+% \meta{sequence} is empty the \meta{token list variable} will
+% contain the special marker \cs{q_no_value}.
% \end{function}
%
-% \begin{function}[TF]{\seq_gpop_left:NN, \seq_gpop_left:cN}
+% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19]{\seq_get:NN, \seq_get:cN}
% \begin{syntax}
-% \cs{seq_gpop_left:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \cs{seq_get:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
% \end{syntax}
% If the \meta{sequence} is empty, leaves the \meta{false code} in the
-% input stream and leaves the \meta{token list variable} unchanged. If the
-% \meta{sequence} is non-empty, pops the left-most item from a \meta{sequence}
-% in the \meta{token list variable}, \emph{i.e.}~removes the item from a
-% \meta{sequence}.
-% The \meta{sequence} is modified globally, while the \meta{token list variable}
-% is assigned locally.
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{sequence} is non-empty, stores the top item from a
+% \meta{sequence} in the \meta{token list variable} without removing it from
+% the \meta{sequence}. The \meta{token list variable} is assigned locally.
% \end{function}
%
-% \begin{function}[TF]{\seq_pop_right:NN, \seq_pop_right:cN}
+% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19]{\seq_pop:NN, \seq_pop:cN}
% \begin{syntax}
-% \cs{seq_pop_right:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
+% \cs{seq_pop:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
% \end{syntax}
% If the \meta{sequence} is empty, leaves the \meta{false code} in the
-% input stream and leaves the \meta{token list variable} unchanged. If the
-% \meta{sequence} is non-empty, pops the right-most item from a \meta{sequence}
-% in the \meta{token list variable}, \emph{i.e.}~removes the item from a
-% \meta{sequence}.
-% Both the \meta{sequence} and the \meta{token list variable} are assigned
-% locally.
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{sequence} is non-empty, pops the top item from the
+% \meta{sequence} in the \meta{token list variable}, \emph{i.e.}~removes the
+% item from the \meta{sequence}. Both the \meta{sequence} and the
+% \meta{token list variable} are assigned locally.
% \end{function}
%
-% \begin{function}[TF]{\seq_gpop_right:NN, \seq_gpop_right:cN}
+% \begin{function}[TF, added = 2012-05-14, updated = 2012-05-19]{\seq_gpop:NN, \seq_gpop:cN}
% \begin{syntax}
-% \cs{seq_gpop_right:NNTF} \meta{sequence} \meta{token list variable}
-% ~~\Arg{true code} \Arg{false code}
+% \cs{seq_gpop:NNTF} \meta{sequence} \meta{token list variable} \Arg{true code} \Arg{false code}
% \end{syntax}
% If the \meta{sequence} is empty, leaves the \meta{false code} in the
-% input stream and leaves the \meta{token list variable} unchanged. If the
-% \meta{sequence} is non-empty, pops the right-most item from a \meta{sequence}
-% in the \meta{token list variable}, \emph{i.e.}~removes the item from a
-% \meta{sequence}.
-% The \meta{sequence} is modified globally, while the \meta{token list variable}
-% is assigned locally.
-% \end{function}
-%
-% \begin{function}[EXP]{\seq_length:N, \seq_length:c}
-% \begin{syntax}
-% \cs{seq_length:N} \meta{sequence}
-% \end{syntax}
-% Leaves the number of items in the \meta{sequence} in the input
-% stream as an \meta{integer denotation}. The total number of items
-% in a \meta{sequence} will include those which are empty and duplicates,
-% \emph{i.e.}~every item in a \meta{sequence} is unique.
-% \end{function}
-%
-% \begin{function}[EXP, updated = 2012-01-08]{\seq_item:Nn, \seq_item:cn}
-% \begin{syntax}
-% \cs{seq_item:Nn} \meta{sequence} \Arg{integer expression}
-% \end{syntax}
-% Indexing items in the \meta{sequence} from $0$ at the top (left), this
-% function will evaluate the \meta{integer expression} and leave the
-% appropriate item from the sequence in the input stream. If the
-% \meta{integer expression} is negative, indexing occurs from the
-% bottom (right) of the sequence. When the \meta{integer expression}
-% is larger than the number of items in the \meta{sequence} (as
-% calculated by \cs{seq_length:N}) then the function will expand to
-% nothing.
-% \begin{texnote}
-% The result is returned within the \tn{unexpanded}
-% primitive (\cs{exp_not:n}), which means that the \meta{item}
-% will not expand further when appearing in an x-type
-% argument expansion.
-% \end{texnote}
-% \end{function}
-%
-% \begin{function}[rEXP]{\seq_use:N, \seq_use:c}
-% \begin{syntax}
-% \cs{seq_use:N} \meta{sequence}
-% \end{syntax}
-% Places each \meta{item} in the \meta{sequence} in turn in the input stream.
-% This occurs in an expandable fashion, and is implemented as a mapping.
-% This means that the process may be prematurely terminated using
-% \cs{seq_map_break:} or \cs{seq_map_break:n}. The \meta{items} in the
-% \meta{sequence} will be used from left (top) to right (bottom).
-% \end{function}
-%
-% \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{seq1} \meta{seq2} \meta{function}
-% \end{syntax}
-% Applies \meta{function} to every pair of items
-% \meta{seq1-item}--\meta{seq2-item} from the two sequences, returning
-% items from both sequences from left to right. The \meta{function} will
-% receive two \texttt{n}-type arguments for each iteration. The mapping
-% will terminate when
-% the end of either sequence is reached (\emph{i.e.}~whichever sequence has
-% fewer items determines how many iterations
-% occur).
+% input stream. The value of the \meta{token list variable} is
+% not defined in this case and should not be relied upon. If the
+% \meta{sequence} is non-empty, pops the top item from the \meta{sequence}
+% in the \meta{token list variable}, \emph{i.e.}~removes the item from the
+% \meta{sequence}. The \meta{sequence} is modified globally, while the
+% \meta{token list variable} is assigned locally.
% \end{function}
%
% \begin{function}
% {
-% \seq_set_from_clist:NN, \seq_set_from_clist:cN,
-% \seq_set_from_clist:Nc, \seq_set_from_clist:cc,
-% \seq_set_from_clist:Nn, \seq_set_from_clist:cn,
-% \seq_gset_from_clist:NN, \seq_gset_from_clist:cN,
-% \seq_gset_from_clist:Nc, \seq_gset_from_clist:cc,
-% \seq_gset_from_clist:Nn, \seq_gset_from_clist:cn
+% \seq_push:Nn, \seq_push:NV, \seq_push:Nv, \seq_push:No, \seq_push:Nx,
+% \seq_push:cn, \seq_push:cV, \seq_push:cv, \seq_push:co, \seq_push:cx,
+% \seq_gpush:Nn, \seq_gpush:NV, \seq_gpush:Nv,
+% \seq_gpush:No, \seq_gpush:Nx,
+% \seq_gpush:cn, \seq_gpush:cV, \seq_gpush:cv,
+% \seq_gpush:co, \seq_gpush:cx
% }
% \begin{syntax}
-% \cs{seq_set_from_clist:NN} \meta{sequence} \meta{comma-list}
+% \cs{seq_push:Nn} \meta{sequence} \Arg{item}
% \end{syntax}
-% Sets the \meta{sequence} within the current \TeX{} group to be equal
-% to the content of the \meta{comma-list}.
+% Adds the \Arg{item} to the top of the \meta{sequence}.
% \end{function}
%
-% \begin{function}[added = 2011-11-22, updated = 2011-11-24]
-% {\seq_reverse:N, \seq_greverse:N}
-% \begin{syntax}
-% \cs{seq_reverse:N} \meta{sequence}
-% \end{syntax}
-% Reverses the order of items in the \meta{sequence}, and
-% assigns the result to \meta{sequence}, locally or globally
-% according to the variant chosen.
-% \end{function}
+% \section{Constant and scratch sequences}
%
-% \begin{function}[added = 2011-12-22]
-% {\seq_set_filter:NNn, \seq_gset_filter:NNn}
-% \begin{syntax}
-% \cs{seq_set_filter:NNn} \meta{sequence1} \meta{sequence2} \Arg{inline boolexpr}
-% \end{syntax}
-% Evaluates the \meta{inline boolexpr} for every \meta{item} stored
-% within the \meta{sequence2}. The \meta{inline boolexpr} will
-% receive 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{sequence1}.
-% \begin{texnote}
-% Contrarily to other mapping functions, \cs{seq_map_break:} cannot
-% be used in this function, and will lead to low-level \TeX{} errors.
-% \end{texnote}
-% \end{function}
+% \begin{variable}[added = 2012-07-02]{\c_empty_seq}
+% Constant that is always empty.
+% \end{variable}
%
-% \begin{function}[added = 2011-12-22]
-% {\seq_set_map:NNn, \seq_gset_map:NNn}
-% \begin{syntax}
-% \cs{seq_set_map:NNn} \meta{sequence1} \meta{sequence2} \Arg{inline function}
-% \end{syntax}
-% Applies \meta{inline function} to every \meta{item} stored
-% within the \meta{sequence2}. The \meta{inline function} should
-% consist of code which will receive the \meta{item} as |#1|.
-% The sequence resulting from \texttt{x}-expanding
-% \meta{inline function} applied to each \meta{item}
-% is assigned to \meta{sequence1}. As such, the code
-% in \meta{inline function} should be expandable.
-% \begin{texnote}
-% Contrarily to other mapping functions, \cs{seq_map_break:} cannot
-% be used in this function, and will lead to low-level \TeX{} errors.
-% \end{texnote}
-% \end{function}
+% \begin{variable}[added = 2012-04-26]{\l_tmpa_seq, \l_tmpb_seq}
+% Scratch sequences for local assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
%
-% \section{Internal sequence functions}
+% \begin{variable}[added = 2012-04-26]{\g_tmpa_seq, \g_tmpb_seq}
+% Scratch sequences for global assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \section{Viewing sequences}
%
-% \begin{function}{\seq_if_empty_err_break:N}
+% \begin{function}{\seq_show:N, \seq_show:c}
% \begin{syntax}
-% \cs{seq_if_empty_err_break:N} \meta{sequence}
+% \cs{seq_show:N} \meta{sequence}
% \end{syntax}
-% Tests if the \meta{sequence} is empty, and if so issues an error
-% message before skipping over any tokens up to \cs{prg_break_point:n}.
-% This function is used to avoid more serious errors which would
-% otherwise occur if some internal functions were applied to an
-% empty \meta{sequence}.
+% Displays the entries in the \meta{sequence} in the terminal.
% \end{function}
%
-% \begin{function}[EXP]{\seq_item:n}
+% \section{Internal sequence functions}
+%
+% \begin{function}[EXP]{\__seq_item:n}
% \begin{syntax}
-% \cs{seq_item:n} \meta{item}
+% \cs{__seq_item:n} \meta{item}
% \end{syntax}
% The internal token used to begin each sequence entry. If expanded
% outside of a mapping or manipulation function, an error will be
% raised. The definition should always be set globally.
% \end{function}
%
-% \begin{function}{\seq_push_item_def:n, \seq_push_item_def:x}
+% \begin{function}{\__seq_push_item_def:n, \__seq_push_item_def:x}
% \begin{syntax}
-% \cs{seq_push_item_def:n} \Arg{code}
+% \cs{__seq_push_item_def:n} \Arg{code}
% \end{syntax}
-% Saves the definition of \cs{seq_item:n} and redefines it to
+% Saves the definition of \cs{__seq_item:n} and redefines it to
% accept one parameter and expand to \meta{code}. This function
-% should always be balanced by use of \cs{seq_pop_item_def:}.
-% \end{function}
-%
-% \begin{function}{\seq_pop_item_def:}
-% \begin{syntax}
-% \cs{seq_pop_item_def:}
-% \end{syntax}
-% Restores the definition of \cs{seq_item:n} most recently saved by
-% \cs{seq_push_item_def:n}. This function should always be used in
-% a balanced pair with \cs{seq_push_item_def:n}.
+% should always be balanced by use of \cs{__seq_pop_item_def:}.
% \end{function}
%
-% \begin{function}[EXP]{\seq_break:}
+% \begin{function}{\__seq_pop_item_def:}
% \begin{syntax}
-% \cs{seq_break:}
+% \cs{__seq_pop_item_def:}
% \end{syntax}
-% Used to terminate sequence functions by gobbling all tokens
-% up to \cs{prg_break_point:n}. This function is a copy of
-% \cs{seq_map_break:}, but is used in situations which are
-% not mappings.
-% \end{function}
-%
-% \begin{function}[EXP]{\seq_break:n}
-% \begin{syntax}
-% \cs{seq_break:n} \Arg{tokens}
-% \end{syntax}
-% Used to terminate sequence functions by gobbling all tokens
-% up to \cs{prg_break_point:n}, then inserting the \meta{tokens}
-% before continuing reading the input stream. This function is a copy
-% of \cs{seq_map_break:n}, but is used in situations which are
-% not mappings.
+% Restores the definition of \cs{__seq_item:n} most recently saved by
+% \cs{__seq_push_item_def:n}. This function should always be used in
+% a balanced pair with \cs{__seq_push_item_def:n}.
% \end{function}
%
% \end{documentation}
@@ -757,41 +700,52 @@
% \end{macrocode}
%
% \begin{macrocode}
+%<@@=seq>
+% \end{macrocode}
+%
+% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
% A sequence is a control sequence whose top-level expansion is of
-% the form \enquote{\cs{seq_item:n} \marg{item$_0$}
-% \ldots \cs{seq_item:n} \marg{item$_{n-1}$}}. An earlier implementation
-% used the structure \enquote{\cs{seq_elt:w} \meta{item$_1$}
-% \cs{seq_elt_end:} \ldots \cs{seq_elt:w} \meta{item$_n$}
+% the form \enquote{\cs{@@_item:n} \marg{item_1}
+% \ldots \cs{@@_item:n} \marg{item_n}}. An earlier implementation
+% used the structure \enquote{\cs{seq_elt:w} \meta{item_1}
+% \cs{seq_elt_end:} \ldots \cs{seq_elt:w} \meta{item_n}
% \cs{seq_elt_end:}}. This allows rapid searching using a delimited
% function, but is not suitable for items containing |{|, |}| and |#|
% tokens, and also leads to the loss of surrounding braces
% around items.
%
-% \begin{macro}[int]{\seq_item:n}
+% \begin{macro}[int]{\@@_item:n}
% The delimiter is always defined, but when used incorrectly simply
% removes its argument and hits an undefined control sequence to
% raise an error.
% \begin{macrocode}
-\cs_new:Npn \seq_item:n
+\cs_new:Npn \@@_item:n
{
- \msg_expandable_kernel_error:nn { seq } { misused }
+ \__msg_kernel_expandable_error:nn { kernel } { misused-sequence }
\use_none:n
}
% \end{macrocode}
% \end{macro}
%
-% \begin{variable}{\l_seq_internal_a_tl, \l_seq_internal_b_tl}
+% \begin{variable}{\l_@@_internal_a_tl, \l_@@_internal_b_tl}
% Scratch space for various internal uses.
% \begin{macrocode}
-\tl_new:N \l_seq_internal_a_tl
-\tl_new:N \l_seq_internal_b_tl
+\tl_new:N \l_@@_internal_a_tl
+\tl_new:N \l_@@_internal_b_tl
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_empty_seq}
+% Simply copy the empty token list.
+% \begin{macrocode}
+\cs_new_eq:NN \c_empty_seq \c_empty_tl
% \end{macrocode}
% \end{variable}
%
@@ -853,25 +807,29 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\seq_set_split:Nnn,\seq_gset_split:Nnn}
-% \begin{macro}[aux]{\seq_set_split_aux:NNnn}
+% \begin{macro}
+% {
+% \seq_set_split:Nnn , \seq_set_split:NnV ,
+% \seq_gset_split:Nnn, \seq_gset_split:NnV
+% }
+% \begin{macro}[aux]{\@@_set_split:NNnn}
% \begin{macro}[aux]
% {
-% \seq_set_split_aux_i:w, \seq_set_split_aux_ii:w,
-% \seq_set_split_aux_end:
+% \@@_set_split_i:w, \@@_set_split_ii:w,
+% \@@_set_split_end:
% }
% The goal is to split a given token list at a marker,
% strip spaces from each item, and remove one set of
% outer braces if after removing leading and trailing
% spaces the item is enclosed within braces. After
-% \cs{tl_replace_all:Nnn}, the token list \cs{l_seq_internal_a_tl}
+% \cs{tl_replace_all:Nnn}, the token list \cs{l_@@_internal_a_tl}
% is a repetition of the pattern
-% \cs{seq_set_split_aux_i:w} \cs{prg_do_nothing:}
-% \meta{item with spaces} \cs{seq_set_split_aux_end:}.
-% Then, \texttt{x}-expansion causes \cs{seq_set_split_aux_i:w}
+% \cs{@@_set_split_i:w} \cs{prg_do_nothing:}
+% \meta{item with spaces} \cs{@@_set_split_end:}.
+% Then, \texttt{x}-expansion causes \cs{@@_set_split_i:w}
% to trim spaces, and leaves its result as
-% \cs{seq_set_split_aux_ii:w} \meta{trimmed item}
-% \cs{seq_set_split_aux_end:}. This is then converted
+% \cs{@@_set_split_ii:w} \meta{trimmed item}
+% \cs{@@_set_split_end:}. This is then converted
% to the \pkg{l3seq} internal structure by another
% \texttt{x}-expansion. In the first step, we insert
% \cs{prg_do_nothing:} to avoid losing braces too early:
@@ -880,37 +838,39 @@
% braces which are outermost after space trimming.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_set_split:Nnn
- { \seq_set_split_aux:NNnn \tl_set:Nx }
+ { \@@_set_split:NNnn \tl_set:Nx }
\cs_new_protected_nopar:Npn \seq_gset_split:Nnn
- { \seq_set_split_aux:NNnn \tl_gset:Nx }
-\cs_new_protected:Npn \seq_set_split_aux:NNnn #1 #2 #3 #4
+ { \@@_set_split:NNnn \tl_gset:Nx }
+\cs_new_protected:Npn \@@_set_split:NNnn #1 #2 #3 #4
{
\tl_if_empty:nTF {#3}
- { #1 #2 { \tl_map_function:nN {#4} \seq_wrap_item:n } }
+ { #1 #2 { \tl_map_function:nN {#4} \@@_wrap_item:n } }
{
- \tl_set:Nn \l_seq_internal_a_tl
+ \tl_set:Nn \l_@@_internal_a_tl
{
- \seq_set_split_aux_i:w \prg_do_nothing:
+ \@@_set_split_i:w \prg_do_nothing:
#4
- \seq_set_split_aux_end:
+ \@@_set_split_end:
}
- \tl_replace_all:Nnn \l_seq_internal_a_tl { #3 }
+ \tl_replace_all:Nnn \l_@@_internal_a_tl { #3 }
{
- \seq_set_split_aux_end:
- \seq_set_split_aux_i:w \prg_do_nothing:
+ \@@_set_split_end:
+ \@@_set_split_i:w \prg_do_nothing:
}
- \tl_set:Nx \l_seq_internal_a_tl { \l_seq_internal_a_tl }
- #1 #2 { \l_seq_internal_a_tl }
+ \tl_set:Nx \l_@@_internal_a_tl { \l_@@_internal_a_tl }
+ #1 #2 { \l_@@_internal_a_tl }
}
}
-\cs_new:Npn \seq_set_split_aux_i:w #1 \seq_set_split_aux_end:
+\cs_new:Npn \@@_set_split_i:w #1 \@@_set_split_end:
{
- \exp_not:N \seq_set_split_aux_ii:w
+ \exp_not:N \@@_set_split_ii:w
\exp_args:No \tl_trim_spaces:n {#1}
- \exp_not:N \seq_set_split_aux_end:
+ \exp_not:N \@@_set_split_end:
}
-\cs_new:Npn \seq_set_split_aux_ii:w #1 \seq_set_split_aux_end:
- { \seq_wrap_item:n {#1} }
+\cs_new:Npn \@@_set_split_ii:w #1 \@@_set_split_end:
+ { \@@_wrap_item:n {#1} }
+\cs_generate_variant:Nn \seq_set_split:Nnn { NnV }
+\cs_generate_variant:Nn \seq_gset_split:Nnn { NnV }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -965,9 +925,9 @@
% The code here is just a wrapper for adding to token lists.
% \begin{macrocode}
\cs_new_protected:Npn \seq_put_left:Nn #1#2
- { \tl_put_left:Nn #1 { \seq_item:n {#2} } }
+ { \tl_put_left:Nn #1 { \@@_item:n {#2} } }
\cs_new_protected:Npn \seq_put_right:Nn #1#2
- { \tl_put_right:Nn #1 { \seq_item:n {#2} } }
+ { \tl_put_right:Nn #1 { \@@_item:n {#2} } }
\cs_generate_variant:Nn \seq_put_left:Nn { NV , Nv , No , Nx }
\cs_generate_variant:Nn \seq_put_left:Nn { c , cV , cv , co , cx }
\cs_generate_variant:Nn \seq_put_right:Nn { NV , Nv , No , Nx }
@@ -991,9 +951,9 @@
% The same for global addition.
% \begin{macrocode}
\cs_new_protected:Npn \seq_gput_left:Nn #1#2
- { \tl_gput_left:Nn #1 { \seq_item:n {#2} } }
+ { \tl_gput_left:Nn #1 { \@@_item:n {#2} } }
\cs_new_protected:Npn \seq_gput_right:Nn #1#2
- { \tl_gput_right:Nn #1 { \seq_item:n {#2} } }
+ { \tl_gput_right:Nn #1 { \@@_item:n {#2} } }
\cs_generate_variant:Nn \seq_gput_left:Nn { NV , Nv , No , Nx }
\cs_generate_variant:Nn \seq_gput_left:Nn { c , cV , cv , co , cx }
\cs_generate_variant:Nn \seq_gput_right:Nn { NV , Nv , No , Nx }
@@ -1004,18 +964,18 @@
%
% \subsection{Modifying sequences}
%
-% \begin{macro}[aux]{\seq_wrap_item:n}
+% \begin{macro}[aux]{\@@_wrap_item:n}
% This function converts its argument to a proper sequence item
% in an \texttt{x}-expansion context.
% \begin{macrocode}
-\cs_new:Npn \seq_wrap_item:n #1 { \exp_not:n { \seq_item:n {#1} } }
+\cs_new:Npn \@@_wrap_item:n #1 { \exp_not:n { \@@_item:n {#1} } }
% \end{macrocode}
% \end{macro}
%
-% \begin{variable}{\l_seq_internal_remove_seq}
+% \begin{variable}{\l_@@_remove_seq}
% An internal sequence for the removal routines.
% \begin{macrocode}
-\seq_new:N \l_seq_internal_remove_seq
+\seq_new:N \l_@@_remove_seq
% \end{macrocode}
% \end{variable}
%
@@ -1023,22 +983,22 @@
% \UnitTested
% \begin{macro}{\seq_gremove_duplicates:N, \seq_gremove_duplicates:c}
% \UnitTested
-% \begin{macro}[aux]{\seq_remove_duplicates_aux:NN}
+% \begin{macro}[aux]{\@@_remove_duplicates:NN}
% Removing duplicates means making a new list then copying it.
% \begin{macrocode}
\cs_new_protected:Npn \seq_remove_duplicates:N
- { \seq_remove_duplicates_aux:NN \seq_set_eq:NN }
+ { \@@_remove_duplicates:NN \seq_set_eq:NN }
\cs_new_protected:Npn \seq_gremove_duplicates:N
- { \seq_remove_duplicates_aux:NN \seq_gset_eq:NN }
-\cs_new_protected:Npn \seq_remove_duplicates_aux:NN #1#2
+ { \@@_remove_duplicates:NN \seq_gset_eq:NN }
+\cs_new_protected:Npn \@@_remove_duplicates:NN #1#2
{
- \seq_clear:N \l_seq_internal_remove_seq
+ \seq_clear:N \l_@@_remove_seq
\seq_map_inline:Nn #2
{
- \seq_if_in:NnF \l_seq_internal_remove_seq {##1}
- { \seq_put_right:Nn \l_seq_internal_remove_seq {##1} }
+ \seq_if_in:NnF \l_@@_remove_seq {##1}
+ { \seq_put_right:Nn \l_@@_remove_seq {##1} }
}
- #1 #2 \l_seq_internal_remove_seq
+ #1 #2 \l_@@_remove_seq
}
\cs_generate_variant:Nn \seq_remove_duplicates:N { c }
\cs_generate_variant:Nn \seq_gremove_duplicates:N { c }
@@ -1051,11 +1011,11 @@
% \UnitTested
% \begin{macro}{\seq_gremove_all:Nn, \seq_gremove_all:cn}
% \UnitTested
-% \begin{macro}[aux]{\seq_remove_all_aux:NNn}
+% \begin{macro}[aux]{\@@_remove_all_aux:NNn}
% The idea of the code here is to avoid a relatively expensive addition of
% items one at a time to an intermediate sequence.
% The approach taken is therefore similar to
-% that in \cs{seq_pop_right_aux_ii:NNN}, using a \enquote{flexible}
+% that in \cs{@@_pop_right_aux_ii:NNN}, using a \enquote{flexible}
% \texttt{x}-type expansion to do most of the work. As \cs{tl_if_eq:nnT}
% is not expandable, a two-part strategy is needed. First, the
% \texttt{x}-type expansion uses \cs{str_if_eq:nnT} to find potential
@@ -1068,28 +1028,28 @@
% lost.
% \begin{macrocode}
\cs_new_protected:Npn \seq_remove_all:Nn
- { \seq_remove_all_aux:NNn \tl_set:Nx }
+ { \@@_remove_all_aux:NNn \tl_set:Nx }
\cs_new_protected:Npn \seq_gremove_all:Nn
- { \seq_remove_all_aux:NNn \tl_gset:Nx }
-\cs_new_protected:Npn \seq_remove_all_aux:NNn #1#2#3
+ { \@@_remove_all_aux:NNn \tl_gset:Nx }
+\cs_new_protected:Npn \@@_remove_all_aux:NNn #1#2#3
{
- \seq_push_item_def:n
+ \@@_push_item_def:n
{
\str_if_eq:nnT {##1} {#3}
{
\if_false: { \fi: }
- \tl_set:Nn \l_seq_internal_b_tl {##1}
+ \tl_set:Nn \l_@@_internal_b_tl {##1}
#1 #2
{ \if_false: } \fi:
\exp_not:o {#2}
- \tl_if_eq:NNT \l_seq_internal_a_tl \l_seq_internal_b_tl
+ \tl_if_eq:NNT \l_@@_internal_a_tl \l_@@_internal_b_tl
{ \use_none:nn }
}
- \seq_wrap_item:n {##1}
+ \@@_wrap_item:n {##1}
}
- \tl_set:Nn \l_seq_internal_a_tl {#3}
+ \tl_set:Nn \l_@@_internal_a_tl {#3}
#1 #2 {#2}
- \seq_pop_item_def:
+ \@@_pop_item_def:
}
\cs_generate_variant:Nn \seq_remove_all:Nn { c }
\cs_generate_variant:Nn \seq_gremove_all:Nn { c }
@@ -1117,33 +1077,35 @@
% \seq_if_in:cn, \seq_if_in:cV, \seq_if_in:cv, \seq_if_in:co, \seq_if_in:cx
% }
% \UnitTested
-% \begin{macro}[aux]{\seq_if_in_aux:}
-% The approach here is to define \cs{seq_item:n} to compare its
+% \begin{macro}[aux]{\@@_if_in:}
+% The approach here is to define \cs{@@_item:n} to compare its
% argument with the test sequence. If the two items are equal, the
-% mapping is terminated and \cs{prg_return_true:} is inserted. On the
+% mapping is terminated and \cs{group_end:} \cs{prg_return_true:}
+% is inserted after skipping over the rest of the recursion. On the
% other hand, if there is no match then the loop will break returning
-% \cs{prg_return_false:}. In either case, \cs{prg_break_point:n}
-% ensures that the group ends before the logical value is returned.
-% Everything is inside a group so that \cs{seq_item:n} is preserved
+% \cs{prg_return_false:}.
+% Everything is inside a group so that \cs{@@_item:n} is preserved
% in nested situations.
% \begin{macrocode}
\prg_new_protected_conditional:Npnn \seq_if_in:Nn #1#2
{ T , F , TF }
{
\group_begin:
- \tl_set:Nn \l_seq_internal_a_tl {#2}
- \cs_set_protected:Npn \seq_item:n ##1
+ \tl_set:Nn \l_@@_internal_a_tl {#2}
+ \cs_set_protected:Npn \@@_item:n ##1
{
- \tl_set:Nn \l_seq_internal_b_tl {##1}
- \if_meaning:w \l_seq_internal_a_tl \l_seq_internal_b_tl
- \exp_after:wN \seq_if_in_aux:
+ \tl_set:Nn \l_@@_internal_b_tl {##1}
+ \if_meaning:w \l_@@_internal_a_tl \l_@@_internal_b_tl
+ \exp_after:wN \@@_if_in:
\fi:
}
#1
- \seq_break:n { \prg_return_false: }
- \prg_break_point:n { \group_end: }
+ \group_end:
+ \prg_return_false:
+ \__prg_break_point:
}
-\cs_new_nopar:Npn \seq_if_in_aux: { \seq_break:n { \prg_return_true: } }
+\cs_new_nopar:Npn \@@_if_in:
+ { \__prg_break:n { \group_end: \prg_return_true: } }
\cs_generate_variant:Nn \seq_if_in:NnT { NV , Nv , No , Nx }
\cs_generate_variant:Nn \seq_if_in:NnT { c , cV , cv , co , cx }
\cs_generate_variant:Nn \seq_if_in:NnF { NV , Nv , No , Nx }
@@ -1156,21 +1118,50 @@
%
% \subsection{Recovering data from sequences}
%
+% \begin{macro}[int]{\@@_pop:NNNN, \@@_pop_TF:NNNN}
+% The two \texttt{pop} functions share their emptiness tests. We also
+% use a common emptiness test for all branching \texttt{get} and
+% \texttt{pop} functions.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_pop:NNNN #1#2#3#4
+ {
+ \if_meaning:w #3 \c_empty_seq
+ \tl_set:Nn #4 { \q_no_value }
+ \else:
+ #1#2#3#4
+ \fi:
+ }
+\cs_new_protected:Npn \@@_pop_TF:NNNN #1#2#3#4
+ {
+ \if_meaning:w #3 \c_empty_seq
+ % \tl_set:Nn #4 { \q_no_value }
+ \prg_return_false:
+ \else:
+ #1#2#3#4
+ \prg_return_true:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\seq_get_left:NN, \seq_get_left:cN}
% \UnitTested
-% \begin{macro}[aux]{\seq_get_left_aux:NnwN}
+% \begin{macro}[aux]{\@@_get_left:NnwN}
% Getting an item from the left of a sequence is pretty easy: just
-% trim off the first item after removing the \cs{seq_item:n} at
-% the start.
+% trim off the first item after removing the \cs{@@_item:n} at
+% the start. We first append a \cs{q_no_value} item to cover the case
+% of an empty sequence
% \begin{macrocode}
\cs_new_protected:Npn \seq_get_left:NN #1#2
{
- \seq_if_empty_err_break:N #1
- \exp_after:wN \seq_get_left_aux:NnwN #1 \q_stop #2
- \prg_break_point:n { }
+ \tl_set:Nx #2
+ {
+ \exp_after:wN \@@_get_left:Nnw
+ #1 \@@_item:n { \q_no_value } \q_stop
+ }
}
-\cs_new_protected:Npn \seq_get_left_aux:NnwN \seq_item:n #1#2 \q_stop #3
- { \tl_set:Nn #3 {#1} }
+\cs_new:Npn \@@_get_left:Nnw \@@_item:n #1#2 \q_stop
+ { \exp_not:n {#1} }
\cs_generate_variant:Nn \seq_get_left:NN { c }
% \end{macrocode}
% \end{macro}
@@ -1180,24 +1171,19 @@
% \UnitTested
% \begin{macro}{\seq_gpop_left:NN, \seq_gpop_left:cN}
% \UnitTested
-% \begin{macro}[aux]{\seq_pop_left_aux:NNN}
-% \begin{macro}[aux]{\seq_pop_left_aux:NnwNNN}
+% \begin{macro}[aux]{\@@_pop_left:NNN, \@@_pop_left:NnwNNN}
% The approach to popping an item is pretty similar to that to get
% an item, with the only difference being that the sequence itself has
% to be redefined. This makes it more sensible to use an auxiliary
% function for the local and global cases.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_pop_left:NN
- { \seq_pop_left_aux:NNN \tl_set:Nn }
+ { \@@_pop:NNNN \@@_pop_left:NNN \tl_set:Nn }
\cs_new_protected_nopar:Npn \seq_gpop_left:NN
- { \seq_pop_left_aux:NNN \tl_gset:Nn }
-\cs_new_protected:Npn \seq_pop_left_aux:NNN #1#2#3
- {
- \seq_if_empty_err_break:N #2
- \exp_after:wN \seq_pop_left_aux:NnwNNN #2 \q_stop #1#2#3
- \prg_break_point:n { }
- }
-\cs_new_protected:Npn \seq_pop_left_aux:NnwNNN \seq_item:n #1#2 \q_stop #3#4#5
+ { \@@_pop:NNNN \@@_pop_left:NNN \tl_gset:Nn }
+\cs_new_protected:Npn \@@_pop_left:NNN #1#2#3
+ { \exp_after:wN \@@_pop_left:NnwNNN #2 \q_stop #1#2#3 }
+\cs_new_protected:Npn \@@_pop_left:NnwNNN \@@_item:n #1#2 \q_stop #3#4#5
{
#3 #4 {#2}
\tl_set:Nn #5 {#1}
@@ -1208,94 +1194,84 @@
% \end{macro}
% \end{macro}
% \end{macro}
-% \end{macro}
%
% \begin{macro}{\seq_get_right:NN, \seq_get_right:cN}
% \UnitTested
-% \begin{macro}[aux]{\seq_get_right_aux:NN}
-% \begin{macro}[aux]{\seq_get_right_loop:nn}
-% The idea here is to remove the very first \cs{seq_item:n} from the
-% sequence, leaving a token list starting with the first braced entry.
-% Two arguments at a time are then grabbed: apart from the right-hand end of
-% the sequence, this will be a brace group followed by \cs{seq_item:n}. The
-% set up code means that these all disappear. At the end of the sequence,
-% the assignment is placed in front of the very last entry in the sequence,
-% before a tidying-up step takes place to remove the loop and reset the
-% meaning of \cs{seq_item:n}.
+% \begin{macro}[aux]{\@@_get_right_loop:nn}
+% First prepend \cs{q_no_value}, then take two arguments at a time.
+% Apart from the right-hand end of the sequence, this be a brace group
+% followed by \cs{@@_item:n}. The \cs{use_none:nn} removes both of
+% those. At the end of the sequence, the two question marks are taken
+% by \cs{use_none:nn}, and the assignment is placed before the
+% right-most item. The \tn{afterassignment} primitive places
+% \cs{use_none:n} to get rid of a trailing \cs{@@_get_right_loop:nn}.
% \begin{macrocode}
\cs_new_protected:Npn \seq_get_right:NN #1#2
{
- \seq_if_empty_err_break:N #1
- \seq_get_right_aux:NN #1#2
- \prg_break_point:n { }
+ \exp_after:wN \@@_get_right_loop:nn
+ \exp_after:wN \q_no_value
+ #1
+ {
+ ??
+ \tex_afterassignment:D \use_none:n
+ \tl_set:Nn #2
+ }
}
-\cs_new_protected:Npn \seq_get_right_aux:NN #1#2
- {
- \seq_push_item_def:n { }
- \exp_after:wN \exp_after:wN \exp_after:wN \seq_get_right_loop:nn
- \exp_after:wN \use_none:n #1
- { \tl_set:Nn #2 }
- { }
- {
- \seq_pop_item_def:
- \seq_break:
- }
-}
-\cs_new:Npn \seq_get_right_loop:nn #1#2
+\cs_new_protected:Npn \@@_get_right_loop:nn #1#2
{
- #2 {#1}
- \seq_get_right_loop:nn
+ \use_none:nn #2 {#1}
+ \@@_get_right_loop:nn
}
\cs_generate_variant:Nn \seq_get_right:NN { c }
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
%
% \begin{macro}{\seq_pop_right:NN, \seq_pop_right:cN}
% \UnitTested
% \begin{macro}{\seq_gpop_right:NN, \seq_gpop_right:cN}
% \UnitTested
-% \begin{macro}[aux]{\seq_pop_right_aux:NNN, \seq_pop_right_aux_ii:NNN}
+% \begin{macro}[aux]{\@@_pop_right_aux:NNN, \@@_pop_right_loop:nn}
% The approach to popping from the right is a bit more involved, but does
% use some of the same ideas as getting from the right. What is needed is a
% \enquote{flexible length} way to set a token list variable. This is
-% supplied by the |{ \if_false:} \fi:| \ldots
+% supplied by the |{ \if_false: } \fi:| \ldots
% |\if_false: { \fi: }| construct. Using an \texttt{x}-type
-% expansion and a \enquote{non-expanding} definition for \cs{seq_item:n},
+% expansion and a \enquote{non-expanding} definition for \cs{@@_item:n},
% the left-most $n - 1$ entries in a sequence of $n$ items will be stored
% back in the sequence. That needs a loop of unknown length, hence using the
% strange \cs{if_false:} way of including brackets. When the last item
% of the sequence is reached, the closing bracket for the assignment is
-% inserted, and |\tl_set:Nn #3| is inserted in front of the final entry.
-% This therefore does the pop assignment, then a final loop clears up the
-% code.
+% inserted, and |\tl_set:Nn #3| is inserted in front of the final
+% entry. This therefore does the pop assignment. The trailing
+% looping macro is removed by placing a \cs{use_none:n} using the
+% \tn{afterassignment} primitive.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \seq_pop_right:NN
- { \seq_pop_right_aux:NNN \tl_set:Nx }
+ { \@@_pop:NNNN \@@_pop_right_aux:NNN \tl_set:Nx }
\cs_new_protected_nopar:Npn \seq_gpop_right:NN
- { \seq_pop_right_aux:NNN \tl_gset:Nx }
-\cs_new_protected:Npn \seq_pop_right_aux:NNN #1#2#3
- {
- \seq_if_empty_err_break:N #2
- \seq_pop_right_aux_ii:NNN #1 #2 #3
- \prg_break_point:n { }
- }
-\cs_new_protected:Npn \seq_pop_right_aux_ii:NNN #1#2#3
+ { \@@_pop:NNNN \@@_pop_right_aux:NNN \tl_gset:Nx }
+\cs_new_protected:Npn \@@_pop_right_aux:NNN #1#2#3
{
- \seq_push_item_def:n { \seq_wrap_item:n {##1} }
- #1 #2 { \if_false: } \fi:
- \exp_after:wN \exp_after:wN \exp_after:wN \seq_get_right_loop:nn
- \exp_after:wN \use_none:n #2
+ \cs_set_eq:NN \seq_tmp:w \@@_item:n
+ \cs_set_eq:NN \@@_item:n \scan_stop:
+ #1 #2
+ { \if_false: } \fi:
+ \exp_after:wN \exp_after:wN
+ \exp_after:wN \@@_pop_right_loop:nn
+ \exp_after:wN \use_none:n
+ #2
{
\if_false: { \fi: }
- \tl_set:Nn #3
- }
- { }
- {
- \seq_pop_item_def:
- \seq_break:
+ \tex_afterassignment:D \use_none:n
+ \tl_set:Nx #3
}
+ \cs_set_eq:NN \@@_item:n \seq_tmp:w
+ }
+\cs_new:Npn \@@_pop_right_loop:nn #1#2
+ {
+ #2 { \exp_not:n {#1} }
+ \@@_pop_right_loop:nn
}
\cs_generate_variant:Nn \seq_pop_right:NN { c }
\cs_generate_variant:Nn \seq_gpop_right:NN { c }
@@ -1304,99 +1280,130 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}[TF]{\seq_get_left:NN, \seq_get_left:cN}
+% \begin{macro}[TF]{\seq_get_right:NN, \seq_get_right:cN}
+% Getting from the left or right with a check on the results. The
+% first argument to \cs{@@_pop_TF:NNNN} is left unused.
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn \seq_get_left:NN #1#2 { T , F , TF }
+ { \@@_pop_TF:NNNN \prg_do_nothing: \seq_get_left:NN #1#2 }
+\prg_new_protected_conditional:Npnn \seq_get_right:NN #1#2 { T , F , TF }
+ { \@@_pop_TF:NNNN \prg_do_nothing: \seq_get_right:NN #1#2 }
+\cs_generate_variant:Nn \seq_get_left:NNT { c }
+\cs_generate_variant:Nn \seq_get_left:NNF { c }
+\cs_generate_variant:Nn \seq_get_left:NNTF { c }
+\cs_generate_variant:Nn \seq_get_right:NNT { c }
+\cs_generate_variant:Nn \seq_get_right:NNF { c }
+\cs_generate_variant:Nn \seq_get_right:NNTF { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[TF]{\seq_pop_left:NN, \seq_pop_left:cN}
+% \begin{macro}[TF]{\seq_gpop_left:NN, \seq_gpop_left:cN}
+% \begin{macro}[TF]{\seq_pop_right:NN, \seq_pop_right:cN}
+% \begin{macro}[TF]{\seq_gpop_right:NN, \seq_gpop_right:cN}
+% More or less the same for popping.
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn \seq_pop_left:NN #1#2 { T , F , TF }
+ { \@@_pop_TF:NNNN \@@_pop_left:NNN \tl_set:Nn #1 #2 }
+\prg_new_protected_conditional:Npnn \seq_gpop_left:NN #1#2 { T , F , TF }
+ { \@@_pop_TF:NNNN \@@_pop_left:NNN \tl_gset:Nn #1 #2 }
+\prg_new_protected_conditional:Npnn \seq_pop_right:NN #1#2 { T , F , TF }
+ { \@@_pop_TF:NNNN \@@_pop_right_aux:NNN \tl_set:Nx #1 #2 }
+\prg_new_protected_conditional:Npnn \seq_gpop_right:NN #1#2 { T , F , TF }
+ { \@@_pop_TF:NNNN \@@_pop_right_aux:NNN \tl_gset:Nx #1 #2 }
+\cs_generate_variant:Nn \seq_pop_left:NNT { c }
+\cs_generate_variant:Nn \seq_pop_left:NNF { c }
+\cs_generate_variant:Nn \seq_pop_left:NNTF { c }
+\cs_generate_variant:Nn \seq_gpop_left:NNT { c }
+\cs_generate_variant:Nn \seq_gpop_left:NNF { c }
+\cs_generate_variant:Nn \seq_gpop_left:NNTF { c }
+\cs_generate_variant:Nn \seq_pop_right:NNT { c }
+\cs_generate_variant:Nn \seq_pop_right:NNF { c }
+\cs_generate_variant:Nn \seq_pop_right:NNTF { c }
+\cs_generate_variant:Nn \seq_gpop_right:NNT { c }
+\cs_generate_variant:Nn \seq_gpop_right:NNF { c }
+\cs_generate_variant:Nn \seq_gpop_right:NNTF { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Mapping to sequences}
%
% \begin{macro}{\seq_map_break:}
% \UnitTested
% \begin{macro}{\seq_map_break:n}
% \UnitTested
-% \begin{macro}[int]{\seq_break:}
-% \begin{macro}[int]{\seq_break:n}
-% To break a function, the special token \cs{prg_break_point:n} is
+% To break a function, the special token \cs{__prg_break_point:Nn} is
% used to find the end of the code. Any ending code is then inserted
% before the return value of \cs{seq_map_break:n} is inserted.
-% Semantically-logical copies of the break functions for use inside
-% mappings.
% \begin{macrocode}
-\cs_new_eq:NN \seq_break: \prg_map_break:
-\cs_new_eq:NN \seq_break:n \prg_map_break:n
-\cs_new_eq:NN \seq_map_break: \prg_map_break:
-\cs_new_eq:NN \seq_map_break:n \prg_map_break:n
+\cs_new_nopar:Npn \seq_map_break:
+ { \__prg_map_break:Nn \seq_map_break: { } }
+\cs_new_nopar:Npn \seq_map_break:n
+ { \__prg_map_break:Nn \seq_map_break: }
% \end{macrocode}
% \end{macro}
% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[int]{\seq_if_empty_err_break:N}
-% A function to check that sequences really have some content. This
-% is optimised for speed, hence the direct primitive use.
-% \begin{macrocode}
-\cs_new_protected:Npn \seq_if_empty_err_break:N #1
- {
- \if_meaning:w #1 \c_empty_tl
- \msg_kernel_error:nnx { seq } { empty-sequence } { \token_to_str:N #1 }
- \exp_after:wN \seq_break:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
%
% \begin{macro}{\seq_map_function:NN, \seq_map_function:cN}
% \UnitTested
-% \begin{macro}[aux]{\seq_map_function_aux:NNn}
+% \begin{macro}[aux]{\@@_map_function:NNn}
% The idea here is to apply the code of |#2| to each item in the
-% sequence without altering the definition of \cs{seq_item:n}. This
+% sequence without altering the definition of \cs{@@_item:n}. This
% is done as by noting that every odd token in the sequence must be
-% \cs{seq_item:n}, which can be gobbled by \cs{use_none:n}. At the end of
+% \cs{@@_item:n}, which can be gobbled by \cs{use_none:n}. At the end of
% the loop, |#2| is instead |? \seq_map_break:|, which therefore breaks the
% loop without needing to do a (relatively-expensive) quark test.
% \begin{macrocode}
\cs_new:Npn \seq_map_function:NN #1#2
{
- \exp_after:wN \seq_map_function_aux:NNn \exp_after:wN #2 #1
+ \exp_after:wN \@@_map_function:NNn \exp_after:wN #2 #1
{ ? \seq_map_break: } { }
- \prg_break_point:n { }
+ \__prg_break_point:Nn \seq_map_break: { }
}
-\cs_new:Npn \seq_map_function_aux:NNn #1#2#3
+\cs_new:Npn \@@_map_function:NNn #1#2#3
{
\use_none:n #2
#1 {#3}
- \seq_map_function_aux:NNn #1
+ \@@_map_function:NNn #1
}
\cs_generate_variant:Nn \seq_map_function:NN { c }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[int]{\seq_push_item_def:n, \seq_push_item_def:x}
-% \begin{macro}[aux]{\seq_push_item_def_aux:}
-% \begin{macro}[int]{\seq_pop_item_def:}
-% The definition of \cs{seq_item:n} needs to be saved and restored at
+% \begin{macro}[int]{\@@_push_item_def:n, \@@_push_item_def:x}
+% \begin{macro}[aux]{\@@_push_item_def:}
+% \begin{macro}[int]{\@@_pop_item_def:}
+% The definition of \cs{@@_item:n} needs to be saved and restored at
% various points within the mapping and manipulation code. That is handled
% here: as always, this approach uses global assignments.
% \begin{macrocode}
-\cs_new_protected:Npn \seq_push_item_def:n
+\cs_new_protected:Npn \@@_push_item_def:n
{
- \seq_push_item_def_aux:
- \cs_gset:Npn \seq_item:n ##1
+ \@@_push_item_def:
+ \cs_gset:Npn \@@_item:n ##1
}
-\cs_new_protected:Npn \seq_push_item_def:x
+\cs_new_protected:Npn \@@_push_item_def:x
{
- \seq_push_item_def_aux:
- \cs_gset:Npx \seq_item:n ##1
+ \@@_push_item_def:
+ \cs_gset:Npx \@@_item:n ##1
}
-\cs_new_protected:Npn \seq_push_item_def_aux:
+\cs_new_protected:Npn \@@_push_item_def:
{
- \cs_gset_eq:cN { seq_item_ \int_use:N \g_prg_map_int :n }
- \seq_item:n
- \int_gincr:N \g_prg_map_int
+ \int_gincr:N \g__prg_map_int
+ \cs_gset_eq:cN { __prg_map_ \int_use:N \g__prg_map_int :w }
+ \@@_item:n
}
-\cs_new_protected_nopar:Npn \seq_pop_item_def:
+\cs_new_protected_nopar:Npn \@@_pop_item_def:
{
- \int_gdecr:N \g_prg_map_int
- \cs_gset_eq:Nc \seq_item:n
- { seq_item_ \int_use:N \g_prg_map_int :n }
+ \cs_gset_eq:Nc \@@_item:n
+ { __prg_map_ \int_use:N \g__prg_map_int :w }
+ \int_gdecr:N \g__prg_map_int
}
% \end{macrocode}
% \end{macro}
@@ -1405,15 +1412,15 @@
%
% \begin{macro}{\seq_map_inline:Nn, \seq_map_inline:cn}
% \UnitTested
-% The idea here is that \cs{seq_item:n} is already \enquote{applied} to
+% The idea here is that \cs{@@_item:n} is already \enquote{applied} to
% each item in a sequence, and so an in-line mapping is just a case of
-% redefining \cs{seq_item:n}.
+% redefining \cs{@@_item:n}.
% \begin{macrocode}
\cs_new_protected:Npn \seq_map_inline:Nn #1#2
{
- \seq_push_item_def:n {#2}
+ \@@_push_item_def:n {#2}
#1
- \prg_break_point:n { \seq_pop_item_def: }
+ \__prg_break_point:Nn \seq_map_break: { \@@_pop_item_def: }
}
\cs_generate_variant:Nn \seq_map_inline:Nn { c }
% \end{macrocode}
@@ -1431,18 +1438,38 @@
% \begin{macrocode}
\cs_new_protected:Npn \seq_map_variable:NNn #1#2#3
{
- \seq_push_item_def:x
+ \@@_push_item_def:x
{
\tl_set:Nn \exp_not:N #2 {##1}
\exp_not:n {#3}
}
#1
- \prg_break_point:n { \seq_pop_item_def: }
+ \__prg_break_point:Nn \seq_map_break: { \@@_pop_item_def: }
}
\cs_generate_variant:Nn \seq_map_variable:NNn { Nc }
\cs_generate_variant:Nn \seq_map_variable:NNn { c , cc }
% \end{macrocode}
% \end{macro}
+%
+% \begin{macro}{\seq_count:N, \seq_count:c}
+% \begin{macro}[aux]{\@@_count:n}
+% Counting the items in a sequence is done using the same approach as for
+% other count functions: turn each entry into a \texttt{+1} then use
+% integer evaluation to actually do the mathematics.
+% \begin{macrocode}
+\cs_new:Npn \seq_count:N #1
+ {
+ \int_eval:n
+ {
+ 0
+ \seq_map_function:NN #1 \@@_count:n
+ }
+ }
+\cs_new:Npn \@@_count:n #1 { + \c_one }
+\cs_generate_variant:Nn \seq_count:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
%
% \subsection{Sequence stacks}
%
@@ -1504,379 +1531,50 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}[TF]{\seq_get:NN, \seq_get:cN}
+% \begin{macro}[TF]{\seq_pop:NN, \seq_pop:cN}
+% \begin{macro}[TF]{\seq_gpop:NN, \seq_gpop:cN}
+% More copies.
+% \begin{macrocode}
+\prg_new_eq_conditional:NNn \seq_get:NN \seq_get_left:NN { T , F , TF }
+\prg_new_eq_conditional:NNn \seq_get:cN \seq_get_left:cN { T , F , TF }
+\prg_new_eq_conditional:NNn \seq_pop:NN \seq_pop_left:NN { T , F , TF }
+\prg_new_eq_conditional:NNn \seq_pop:cN \seq_pop_left:cN { T , F , TF }
+\prg_new_eq_conditional:NNn \seq_gpop:NN \seq_gpop_left:NN { T , F , TF }
+\prg_new_eq_conditional:NNn \seq_gpop:cN \seq_gpop_left:cN { T , F , TF }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Viewing sequences}
%
% \begin{macro}{\seq_show:N, \seq_show:c}
% \UnitTested
-% Apply the general \cs{msg_aux_show:Nnx}.
+% Apply the general \cs{__msg_show_variable:Nnn}.
% \begin{macrocode}
\cs_new_protected:Npn \seq_show:N #1
{
- \msg_aux_show:Nnx
+ \__msg_show_variable:Nnn
#1
{ seq }
- { \seq_map_function:NN #1 \msg_aux_show:n }
+ { \seq_map_function:NN #1 \__msg_show_item:n }
}
\cs_generate_variant:Nn \seq_show:N { c }
% \end{macrocode}
% \end{macro}
%
-% \subsection{Experimental functions}
+% \subsection{Scratch sequences}
%
-% \begin{macro}[aux]{\seq_if_empty_break_return_false:N}
-% The name says it all: of the sequence is empty, returns logical
-% \texttt{false}.
+% \begin{variable}{\l_tmpa_seq, \l_tmpb_seq, \g_tmpa_seq, \g_tmpb_seq}
+% Temporary comma list variables.
% \begin{macrocode}
-\cs_new:Npn \seq_if_empty_break_return_false:N #1
- {
- \if_meaning:w #1 \c_empty_tl
- \prg_return_false:
- \exp_after:wN \seq_break:
- \fi:
- }
+\seq_new:N \l_tmpa_seq
+\seq_new:N \l_tmpb_seq
+\seq_new:N \g_tmpa_seq
+\seq_new:N \g_tmpb_seq
% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[TF]{\seq_get_left:NN, \seq_get_left:cN}
-% \begin{macro}[TF]{\seq_get_right:NN, \seq_get_right:cN}
-% Getting from the left or right with a check on the results.
-% \begin{macrocode}
-\prg_new_protected_conditional:Npnn \seq_get_left:NN #1 #2 { T , F , TF }
- {
- \seq_if_empty_break_return_false:N #1
- \exp_after:wN \seq_get_left_aux:Nw #1 \q_stop #2
- \prg_return_true:
- \seq_break:
- \prg_break_point:n { }
- }
-\prg_new_protected_conditional:Npnn \seq_get_right:NN #1#2 { T , F , TF }
- {
- \seq_if_empty_break_return_false:N #1
- \seq_get_right_aux:NN #1#2
- \prg_return_true: \seq_break:
- \prg_break_point:n { }
- }
-\cs_generate_variant:Nn \seq_get_left:NNT { c }
-\cs_generate_variant:Nn \seq_get_left:NNF { c }
-\cs_generate_variant:Nn \seq_get_left:NNTF { c }
-\cs_generate_variant:Nn \seq_get_right:NNT { c }
-\cs_generate_variant:Nn \seq_get_right:NNF { c }
-\cs_generate_variant:Nn \seq_get_right:NNTF { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[TF]{\seq_pop_left:NN, \seq_pop_left:cN}
-% \begin{macro}[TF]{\seq_gpop_left:NN, \seq_gpop_left:cN}
-% \begin{macro}[TF]{\seq_pop_right:NN, \seq_pop_right:cN}
-% \begin{macro}[TF]{\seq_gpop_right:NN, \seq_gpop_right:cN}
-% More or less the same for popping.
-% \begin{macrocode}
-\prg_new_protected_conditional:Npnn \seq_pop_left:NN #1#2 { T , F , TF }
- {
- \seq_if_empty_break_return_false:N #1
- \exp_after:wN \seq_pop_left_aux:NnwNNN #1 \q_stop \tl_set:Nn #1#2
- \prg_return_true: \seq_break:
- \prg_break_point:n { }
- }
-\prg_new_protected_conditional:Npnn \seq_gpop_left:NN #1#2 { T , F , TF }
- {
- \seq_if_empty_break_return_false:N #1
- \exp_after:wN \seq_pop_left_aux:NnwNNN #1 \q_stop \tl_gset:Nn #1#2
- \prg_return_true: \seq_break:
- \prg_break_point:n { }
- }
-\prg_new_protected_conditional:Npnn \seq_pop_right:NN #1#2 { T , F , TF }
- {
- \seq_if_empty_break_return_false:N #1
- \seq_pop_right_aux_ii:NNN \tl_set:Nx #1 #2
- \prg_return_true: \seq_break:
- \prg_break_point:n { }
- }
-\prg_new_protected_conditional:Npnn \seq_gpop_right:NN #1#2 { T , F , TF }
- {
- \seq_if_empty_break_return_false:N #1
- \seq_pop_right_aux_ii:NNN \tl_gset:Nx #1 #2
- \prg_return_true: \seq_break:
- \prg_break_point:n { }
- }
-\cs_generate_variant:Nn \seq_pop_left:NNT { c }
-\cs_generate_variant:Nn \seq_pop_left:NNF { c }
-\cs_generate_variant:Nn \seq_pop_left:NNTF { c }
-\cs_generate_variant:Nn \seq_gpop_left:NNT { c }
-\cs_generate_variant:Nn \seq_gpop_left:NNF { c }
-\cs_generate_variant:Nn \seq_gpop_left:NNTF { c }
-\cs_generate_variant:Nn \seq_pop_right:NNT { c }
-\cs_generate_variant:Nn \seq_pop_right:NNF { c }
-\cs_generate_variant:Nn \seq_pop_right:NNTF { c }
-\cs_generate_variant:Nn \seq_gpop_right:NNT { c }
-\cs_generate_variant:Nn \seq_gpop_right:NNF { c }
-\cs_generate_variant:Nn \seq_gpop_right:NNTF { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\seq_length:N, \seq_length:c}
-% \begin{macro}[aux]{\seq_length_aux:n}
-% Counting the items in a sequence is done using the same approach as for
-% other length functions: turn each entry into a \texttt{+1} then use
-% integer evaluation to actually do the mathematics.
-% \begin{macrocode}
-\cs_new:Npn \seq_length:N #1
- {
- \int_eval:n
- {
- 0
- \seq_map_function:NN #1 \seq_length_aux:n
- }
- }
-\cs_new:Npn \seq_length_aux:n #1 { +1 }
-\cs_generate_variant:Nn \seq_length:N { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\seq_item:Nn, \seq_item:cn}
-% \begin{macro}[aux]{\seq_item_aux:nnn}
-% The idea here is to find the offset of the item from the left, then use
-% a loop to grab the correct item. If the resulting offset is too large,
-% then the stop code |{ ? \seq_break: } { }| will be used by the auxiliary,
-% terminating the loop and returning nothing at all.
-% \begin{macrocode}
-\cs_new:Npn \seq_item:Nn #1#2
- {
- \exp_last_unbraced:Nfo \seq_item_aux:nnn
- {
- \int_eval:n
- {
- \int_compare:nNnT {#2} < \c_zero
- { \seq_length:N #1 + }
- #2
- }
- }
- #1
- { ? \seq_break: }
- { }
- \prg_break_point:n { }
- }
-\cs_new:Npn \seq_item_aux:nnn #1#2#3
- {
- \use_none:n #2
- \int_compare:nNnTF {#1} = \c_zero
- { \seq_break:n { \exp_not:n {#3} } }
- { \exp_args:Nf \seq_item_aux:nnn { \int_eval:n { #1 - 1 } } }
- }
-\cs_generate_variant:Nn \seq_item:Nn { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\seq_use:N, \seq_use:c}
-% A simple short cut for a mapping.
-% \begin{macrocode}
-\cs_new:Npn \seq_use:N #1 { \seq_map_function:NN #1 \use:n }
-\cs_generate_variant:Nn \seq_use:N { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}
-% {
-% \seq_mapthread_function:NNN, \seq_mapthread_function:NcN,
-% \seq_mapthread_function:cNN, \seq_mapthread_function:ccN
-% }
-% \begin{macro}[aux]{\seq_mapthread_function_aux:NN}
-% \begin{macro}[aux]{\seq_mapthread_function_aux:Nnnwnn}
-% The idea here is to first expand both of the sequences, adding the usual
-% |{ ? \seq_break: } { }| to the end of each on. This is most conveniently
-% done in two steps using an auxiliary function. The mapping then throws
-% away the first token of |#2| and |#5|, which for items in the sequences
-% will both be \cs{seq_item:n}. The function to be mapped will then be
-% applied to the two entries. When the code hits the end of one of the
-% sequences, the break material will stop the entire loop and tidy up. This
-% avoids needing to find the length 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 \seq_mapthread_function_aux:NN
- \exp_after:wN #3
- \exp_after:wN #1
- #2
- { ? \seq_break: } { }
- \prg_break_point:n { }
- }
-\cs_new:Npn \seq_mapthread_function_aux:NN #1#2
- {
- \exp_after:wN \seq_mapthread_function_aux:Nnnwnn
- \exp_after:wN #1
- #2
- { ? \seq_break: } { }
- \q_stop
- }
-\cs_new:Npn \seq_mapthread_function_aux:Nnnwnn #1#2#3#4 \q_stop #5#6
- {
- \use_none:n #2
- \use_none:n #5
- #1 {#3} {#6}
- \seq_mapthread_function_aux:Nnnwnn #1 #4 \q_stop
- }
-\cs_generate_variant:Nn \seq_mapthread_function:NNN { Nc }
-\cs_generate_variant:Nn \seq_mapthread_function:NNN { c , cc }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}
-% {
-% \seq_set_from_clist:NN, \seq_set_from_clist:cN,
-% \seq_set_from_clist:Nc, \seq_set_from_clist:cc,
-% \seq_set_from_clist:Nn, \seq_set_from_clist:cn
-% }
-% \begin{macro}
-% {
-% \seq_gset_from_clist:NN, \seq_gset_from_clist:cN,
-% \seq_gset_from_clist:Nc, \seq_gset_from_clist:cc,
-% \seq_gset_from_clist:Nn, \seq_gset_from_clist:cn
-% }
-% Setting a sequence from a comma-separated list is done using a simple
-% mapping.
-% \begin{macrocode}
-\cs_new_protected:Npn \seq_set_from_clist:NN #1#2
- {
- \tl_set:Nx #1
- { \clist_map_function:NN #2 \seq_wrap_item:n }
- }
-\cs_new_protected:Npn \seq_set_from_clist:Nn #1#2
- {
- \tl_set:Nx #1
- { \clist_map_function:nN {#2} \seq_wrap_item:n }
- }
-\cs_new_protected:Npn \seq_gset_from_clist:NN #1#2
- {
- \tl_gset:Nx #1
- { \clist_map_function:NN #2 \seq_wrap_item:n }
- }
-\cs_new_protected:Npn \seq_gset_from_clist:Nn #1#2
- {
- \tl_gset:Nx #1
- { \clist_map_function:nN {#2} \seq_wrap_item:n }
- }
-\cs_generate_variant:Nn \seq_set_from_clist:NN { Nc }
-\cs_generate_variant:Nn \seq_set_from_clist:NN { c , cc }
-\cs_generate_variant:Nn \seq_set_from_clist:Nn { c }
-\cs_generate_variant:Nn \seq_gset_from_clist:NN { Nc }
-\cs_generate_variant:Nn \seq_gset_from_clist:NN { c , cc }
-\cs_generate_variant:Nn \seq_gset_from_clist:Nn { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}
-% {\seq_reverse:N, \seq_reverse:c, \seq_greverse:N, \seq_greverse:c}
-% \begin{macro}[aux]{\seq_reverse_aux:NN}
-% \begin{macro}[aux]{\seq_reverse_aux_item:nwn}
-% Previously, \cs{seq_reverse:N} was coded by collecting the items
-% in reverse order after an \cs{exp_stop_f:} marker.
-% \begin{verbatim}
-% \cs_new_protected:Npn \seq_reverse:N #1
-% {
-% \cs_set_eq:NN \seq_item:n \seq_reverse_aux_item:nw
-% \tl_set:Nf #2 { #2 \exp_stop_f: }
-% }
-% \cs_new:Npn \seq_reverse_aux_item:nw #1 #2 \exp_stop_f:
-% {
-% #2 \exp_stop_f:
-% \seq_item:n {#1}
-% }
-% \end{verbatim}
-% At first, this seems optimal, since we can forget about each item
-% as soon as it is placed after \cs{exp_stop_f:}. Unfortunately,
-% \TeX{}'s usual tail recursion does not take place in this case:
-% since the following \cs{seq_reverse_aux_item:nw} only reads
-% tokens until \cs{exp_stop_f:}, and never reads the
-% |\seq_item:n {#1}| left by the previous call, \TeX{} cannot
-% remove that previous call from the stack, and in particular
-% must retain the various macro paramters in memory, until the
-% end of the replacement text is reached. The stack is thus
-% only flushed after all the \cs{seq_reverse_aux_item:nw} are
-% expanded. Keeping track of the arguments of all those calls
-% uses up a memory quadratic in the length of the sequence.
-% \TeX{} can then not cope with more than a few thousand items.
-%
-% Instead, we collect the items in the argument
-% of \cs{exp_not:n}. The previous calls are cleanly removed
-% from the stack, and the memory consumption becomes linear.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \seq_tmp:w { }
-\cs_new_protected_nopar:Npn \seq_reverse:N
- { \seq_reverse_aux:NN \tl_set:Nx }
-\cs_new_protected_nopar:Npn \seq_greverse:N
- { \seq_reverse_aux:NN \tl_gset:Nx }
-\cs_new_protected:Npn \seq_reverse_aux:NN #1 #2
- {
- \cs_set_eq:NN \seq_tmp:w \seq_item:n
- \cs_set_eq:NN \seq_item:n \seq_reverse_aux_item:nwn
- #1 #2 { #2 \exp_not:n { } }
- \cs_set_eq:NN \seq_item:n \seq_tmp:w
- }
-\cs_new:Npn \seq_reverse_aux_item:nwn #1 #2 \exp_not:n #3
- {
- #2
- \exp_not:n { \seq_item:n {#1} #3 }
- }
-\cs_generate_variant:Nn \seq_reverse:N { c }
-\cs_generate_variant:Nn \seq_greverse:N { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\seq_set_filter:NNn, \seq_gset_filter:NNn}
-% \begin{macro}[aux]{\seq_set_filter_aux:NNNn}
-% Similar to \cs{seq_map_inline:Nn}, without a
-% \cs{prg_break_point:n} because the user's code
-% is performed within the evaluation of a boolean expression,
-% and skipping out of that would break horribly.
-% The \cs{seq_wrap_item:n} function inserts the relevant
-% \cs{seq_item:n} without expansion in the input stream,
-% hence in the \texttt{x}-expanding assignment.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \seq_set_filter:NNn
- { \seq_set_filter_aux:NNNn \tl_set:Nx }
-\cs_new_protected_nopar:Npn \seq_gset_filter:NNn
- { \seq_set_filter_aux:NNNn \tl_gset:Nx }
-\cs_new_protected:Npn \seq_set_filter_aux:NNNn #1#2#3#4
- {
- \seq_push_item_def:n { \bool_if:nT {#4} { \seq_wrap_item:n {##1} } }
- #1 #2 { #3 \prg_break_point:n { } }
- \seq_pop_item_def:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\seq_set_map:NNn,\seq_gset_map:NNn}
-% \begin{macro}[aux]{\seq_set_map_aux:NNNn}
-% Very similar to \cs{seq_set_filter:NNn}. We could actually
-% merge the two within a single function, but it would have weird
-% semantics.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \seq_set_map:NNn
- { \seq_set_map_aux:NNNn \tl_set:Nx }
-\cs_new_protected_nopar:Npn \seq_gset_map:NNn
- { \seq_set_map_aux:NNNn \tl_gset:Nx }
-\cs_new_protected:Npn \seq_set_map_aux:NNNn #1#2#3#4
- {
- \seq_push_item_def:n { \exp_not:N \seq_item:n {#4} }
- #1 #2 { #3 }
- \seq_pop_item_def:
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
+% \end{variable}
%
% \subsection{Deprecated interfaces}
%
@@ -1904,6 +1602,25 @@
% \end{macrocode}
% \end{macro}
%
+% Deprecated 2012-05-13 for removal by 2012-11-30.
+%
+% \begin{macro}{\seq_length:N, \seq_length:c}
+% \begin{macrocode}
+\cs_new_eq:NN \seq_length:N \seq_count:N
+\cs_new_eq:NN \seq_length:c \seq_count:c
+% \end{macrocode}
+% \end{macro}
+%
+% Deprecated 2012-05-23 for removal by 2012-08-30.
+%
+% \begin{macro}{\seq_use:N, \seq_use:c}
+% A simple short cut for a mapping.
+% \begin{macrocode}
+\cs_new:Npn \seq_use:N #1 { \seq_map_function:NN #1 \use:n }
+\cs_generate_variant:Nn \seq_use:N { c }
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
index 9bb1fa1eadc..b83319e74b3 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
@@ -36,8 +36,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3skip.dtx 3499 2012-03-05 16:08:55Z bruno $
- {L3 Experimental dimensions and skips}
+\GetIdInfo$Id: l3skip.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Dimensions and skips}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -150,10 +150,10 @@
% \dim_gset_eq:NN, \dim_gset_eq:cN, \dim_gset_eq:Nc, \dim_gset_eq:cc
% }
% \begin{syntax}
-% \cs{dim_set_eq:NN} \meta{dimension1} \meta{dimension2}
+% \cs{dim_set_eq:NN} \meta{dimension_1} \meta{dimension_2}
% \end{syntax}
-% Sets the content of \meta{dimension1} equal to that of
-% \meta{dimension2}.
+% Sets the content of \meta{dimension_1} equal to that of
+% \meta{dimension_2}.
% \end{function}
%
% \begin{function}[updated = 2012-02-06]
@@ -220,7 +220,7 @@
%
% \begin{function}[EXP,pTF]{\dim_compare:nNn}
% \begin{syntax}
-% \cs{dim_compare_p:nNn} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \\
+% \cs{@@_compare_p:nNn} \Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2} \\
% \cs{dim_compare:nNnTF}
% ~~\Arg{dimexpr_1} \meta{relation} \Arg{dimexpr_2}
% ~~\Arg{true code} \Arg{false code}
@@ -239,9 +239,9 @@
%
% \begin{function}[EXP,pTF]{\dim_compare:n}
% \begin{syntax}
-% \cs{dim_compare_p:n} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \\
+% \cs{@@_compare_p:n} \{ \meta{dimexpr_1} \meta{relation} \meta{dimexpr_2} \} \\
% \cs{dim_compare:nTF}
-% ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \}
+% ~~\{ \meta{dimexpr_1} \meta{relation} \meta{dimexpr_2} \}
% ~~\Arg{true code} \Arg{false code}
% \end{syntax}
% This function first evaluates each of the \meta{dimension expressions}
@@ -259,6 +259,37 @@
% \end{center}
% \end{function}
%
+% \begin{function}[added = 2012-06-03, EXP]{\dim_case:nnn}
+% \begin{syntax}
+% \cs{dim_case:nnn} \Arg{test dimension expression} \\
+% ~~|{| \\
+% ~~~~\Arg{dimexpr case_1} \Arg{code case_1} \\
+% ~~~~\Arg{dimexpr case_2} \Arg{code case_2} \\
+% ~~~~\ldots \\
+% ~~~~\Arg{dimexpr case_n} \Arg{code case_n} \\
+% ~~|}| \\
+% ~~\Arg{else code}
+% \end{syntax}
+% This function evaluates the \meta{test dimension expression} and
+% compares this in turn to each of the
+% \meta{dimension expression cases}. If the two are equal then the
+% associated \meta{code} is left in the input stream. If none of
+% the tests are \texttt{true} then the \texttt{else code} will be
+% left in the input stream. For example
+% \begin{verbatim}
+% \dim_set:Nn \l_tmpa_dim { 5 pt }
+% \dim_case:nnn
+% { 2 \l_tmpa_dim }
+% {
+% { 5 pt } { Small }
+% { 4 pt + 6 pt } { Medium }
+% { - 10 pt } { Negative }
+% }
+% { No idea! }
+% \end{verbatim}
+% will leave \enquote{\texttt{Medium}} in the input stream.
+% \end{function}
+%
% \section{Dimension expression loops}
%
% \begin{function}[rEXP]{\dim_do_while:nNnn}
@@ -311,7 +342,7 @@
%
% \begin{function}[rEXP]{\dim_do_while:nn}
% \begin{syntax}
-% \cs{dim_do_while:nn} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
+% \cs{dim_do_while:nn} \{ \meta{dimexpr_1} \meta{relation} \meta{dimexpr_2} \} \Arg{code}
% \end{syntax}
% Evaluates the relationship between the two \meta{dimension expressions}
% as described for \cs{dim_compare:nTF}, and then places the
@@ -323,7 +354,7 @@
%
% \begin{function}[rEXP]{\dim_do_until:nn}
% \begin{syntax}
-% \cs{dim_do_until:nn} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
+% \cs{dim_do_until:nn} \{ \meta{dimexpr_1} \meta{relation} \meta{dimexpr_2} \} \Arg{code}
% \end{syntax}
% Evaluates the relationship between the two \meta{dimension expressions}
% as described for \cs{dim_compare:nTF}, and then places the
@@ -335,7 +366,7 @@
%
% \begin{function}[rEXP]{\dim_until_do:nn}
% \begin{syntax}
-% \cs{dim_until_do:nn} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
+% \cs{dim_until_do:nn} \{ \meta{dimexpr_1} \meta{relation} \meta{dimexpr_2} \} \Arg{code}
% \end{syntax}
% Places the \meta{code} in the input stream for \TeX{} to process, and
% then evaluates the relationship between the two
@@ -347,7 +378,7 @@
%
% \begin{function}[rEXP]{\dim_while_do:nn}
% \begin{syntax}
-% \cs{dim_while_do:nn} \{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
+% \cs{dim_while_do:nn} \{ \meta{dimexpr_1} \meta{relation} \meta{dimexpr_2} \} \Arg{code}
% \end{syntax}
% Places the \meta{code} in the input stream for \TeX{} to process, and
% then evaluates the relationship between the two
@@ -398,7 +429,7 @@
% Displays the value of the \meta{dimension} on the terminal.
% \end{function}
%
-% \begin{function}[added = 2011-11-22]{\dim_show:n}
+% \begin{function}[added = 2011-11-22, updated = 2012-05-27]{\dim_show:n}
% \begin{syntax}
% \cs{dim_show:n} \meta{dimension expression}
% \end{syntax}
@@ -419,7 +450,7 @@
%
% \section{Scratch dimensions}
%
-% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim, \l_tmpc_dim}
+% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim}
% Scratch dimension for local assignment. These are never used by
% the kernel code, and so are safe for use with any \LaTeX3-defined
% function. However, they may be overwritten by other non-kernel
@@ -507,9 +538,9 @@
% \skip_gset_eq:NN, \skip_gset_eq:cN, \skip_gset_eq:Nc, \skip_gset_eq:cc
% }
% \begin{syntax}
-% \cs{skip_set_eq:NN} \meta{skip1} \meta{skip2}
+% \cs{skip_set_eq:NN} \meta{skip_1} \meta{skip_2}
% \end{syntax}
-% Sets the content of \meta{skip1} equal to that of \meta{skip2}.
+% Sets the content of \meta{skip_1} equal to that of \meta{skip_2}.
% \end{function}
%
% \begin{function}[updated = 2011-10-22]
@@ -527,7 +558,7 @@
% \begin{syntax}
% \cs{skip_if_eq_p:nn} \Arg{skipexpr_1} \Arg{skipexpr_2}
% \cs{dim_compare:nTF}
-% ~~\Arg{skip expr1} \Arg{skip expr2}
+% ~~\Arg{skipexpr_1} \Arg{skipexpr_2}
% ~~\Arg{true code} \Arg{false code}
% \end{syntax}
% This function first evaluates each of the
@@ -537,16 +568,6 @@
% for the test to be true.
% \end{function}
%
-% \begin{function}[EXP, pTF, updated = 2012-03-05]{\skip_if_infinite_glue:n}
-% \begin{syntax}
-% \cs{skip_if_infinite_glue_p:n} \Arg{skipexpr}
-% \cs{skip_if_infinite_glue:nTF} \Arg{skipexpr} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Evaluates the \meta{skip expression} as described for \cs{skip_eval:n},
-% and then tests if this contains an infinite stretch or shrink
-% component (or both).
-% \end{function}
-%
% \begin{function}[EXP, pTF, added = 2012-03-05]{\skip_if_finite:n}
% \begin{syntax}
% \cs{skip_if_finite_p:n} \Arg{skipexpr}
@@ -596,7 +617,7 @@
% Displays the value of the \meta{skip} on the terminal.
% \end{function}
%
-% \begin{function}[added = 2011-11-22]{\skip_show:n}
+% \begin{function}[added = 2011-11-22, updated = 2012-05-27]{\skip_show:n}
% \begin{syntax}
% \cs{skip_show:n} \meta{skip expression}
% \end{syntax}
@@ -617,7 +638,7 @@
%
% \section{Scratch skips}
%
-% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip, \l_tmpc_skip}
+% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip}
% Scratch skip for local assignment. These are never used by
% the kernel code, and so are safe for use with any \LaTeX3-defined
% function. However, they may be overwritten by other non-kernel
@@ -631,6 +652,32 @@
% code and so should only be used for short-term storage.
% \end{variable}
%
+% \section{Inserting skips into the output}
+%
+% \begin{function}[updated = 2011-10-22]
+% {\skip_horizontal:N, \skip_horizontal:c, \skip_horizontal:n}
+% \begin{syntax}
+% \cs{skip_horizontal:N} \meta{skip}
+% \cs{skip_horizontal:n} \Arg{skipexpr}
+% \end{syntax}
+% Inserts a horizontal \meta{skip} into the current list.
+% \begin{texnote}
+% \cs{skip_horizontal:N} is the \TeX{} primitive \tn{hskip} renamed.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}[updated = 2011-10-22]
+% {\skip_vertical:N, \skip_vertical:c, \skip_vertical:n}
+% \begin{syntax}
+% \cs{skip_vertical:N} \meta{skip}
+% \cs{skip_vertical:n} \Arg{skipexpr}
+% \end{syntax}
+% Inserts a vertical \meta{skip} into the current list.
+% \begin{texnote}
+% \cs{skip_vertical:N} is the \TeX{} primitive \tn{vskip} renamed.
+% \end{texnote}
+% \end{function}
+%
% \section{Creating and initialising \texttt{muskip} variables}
%
% \begin{function}{\muskip_new:N, \muskip_new:c}
@@ -711,10 +758,10 @@
% \muskip_gset_eq:Nc, \muskip_gset_eq:cc
% }
% \begin{syntax}
-% \cs{muskip_set_eq:NN} \meta{muskip1} \meta{muskip2}
+% \cs{muskip_set_eq:NN} \meta{muskip_1} \meta{muskip_2}
% \end{syntax}
-% Sets the content of \meta{muskip1} equal to that of
-% \meta{muskip2}.
+% Sets the content of \meta{muskip_1} equal to that of
+% \meta{muskip_2}.
% \end{function}
%
% \begin{function}[updated = 2011-10-22]
@@ -757,32 +804,6 @@
% \end{texnote}
% \end{function}
%
-% \section{Inserting skips into the output}
-%
-% \begin{function}[updated = 2011-10-22]
-% {\skip_horizontal:N, \skip_horizontal:c, \skip_horizontal:n}
-% \begin{syntax}
-% \cs{skip_horizontal:N} \meta{skip}
-% \cs{skip_horizontal:n} \Arg{skipexpr}
-% \end{syntax}
-% Inserts a horizontal \meta{skip} into the current list.
-% \begin{texnote}
-% \cs{skip_horizontal:N} is the \TeX{} primitive \tn{hskip} renamed.
-% \end{texnote}
-% \end{function}
-%
-% \begin{function}[updated = 2011-10-22]
-% {\skip_vertical:N, \skip_vertical:c, \skip_vertical:n}
-% \begin{syntax}
-% \cs{skip_vertical:N} \meta{skip}
-% \cs{skip_vertical:n} \Arg{skipexpr}
-% \end{syntax}
-% Inserts a vertical \meta{skip} into the current list.
-% \begin{texnote}
-% \cs{skip_vertical:N} is the \TeX{} primitive \tn{vskip} renamed.
-% \end{texnote}
-% \end{function}
-%
% \section{Viewing \texttt{muskip} variables}
%
% \begin{function}{\muskip_show:N, \muskip_show:c}
@@ -792,7 +813,7 @@
% Displays the value of the \meta{muskip} on the terminal.
% \end{function}
%
-% \begin{function}[added = 2011-11-22]{\muskip_show:n}
+% \begin{function}[added = 2011-11-22, updated = 2012-05-27]{\muskip_show:n}
% \begin{syntax}
% \cs{muskip_show:n} \meta{muskip expression}
% \end{syntax}
@@ -800,11 +821,37 @@
% on the terminal.
% \end{function}
%
-% \section{Internal functions}
+% \section{Constant muskips}
+%
+% \begin{variable}{\c_max_muskip}
+% The maximum value that can be stored as a muskip.
+% \end{variable}
+%
+% \begin{variable}{\c_zero_muskip}
+% A zero length as a muskip.
+% \end{variable}
+%
+% \section{Scratch muskips}
+%
+% \begin{variable}{\l_tmpa_muskip, \l_tmpb_muskip}
+% Scratch muskip for local assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \begin{variable}{\g_tmpa_muskip, \g_tmpb_muskip}
+% Scratch muskip for global assignment. These are never used by
+% the kernel code, and so are safe for use with any \LaTeX3-defined
+% function. However, they may be overwritten by other non-kernel
+% code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \section{Primitive conditional}
%
% \begin{function}{\if_dim:w}
% \begin{syntax}
-% \cs{if_dim:w} \meta{dimen1} \meta{relation} \meta{dimen1}
+% \cs{if_dim:w} \meta{dimen_1} \meta{relation} \meta{dimen_2}
% ~~\meta{true code}
% \cs{else:}
% ~~\meta{false}
@@ -817,44 +864,28 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}[EXP]{\dim_eval:w, \dim_eval_end:}
+% \section{Internal functions}
+%
+% \begin{function}[EXP]{\__dim_eval:w, \__dim_eval_end:}
% \begin{syntax}
-% \cs{dim_eval:w} \meta{dimexpr} \cs{dim_eval_end:}
+% \cs{__dim_eval:w} \meta{dimexpr} \cs{__dim_eval_end:}
% \end{syntax}
% Evaluates \meta{dimension expression} as described for \cs{dim_eval:n}.
% The evaluation stops when an unexpandable token which is not a valid
-% part of a dimension is read or when \cs{dim_eval_end:} is
+% part of a dimension is read or when \cs{__dim_eval_end:} is
% reached. The latter is gobbled by the scanner mechanism:
-% \cs{dim_eval_end:} itself is unexpandable but used correctly
+% \cs{__dim_eval_end:} itself is unexpandable but used correctly
% the entire construct is expandable.
% \begin{texnote}
% This is the \eTeX{} primitive \tn{dimexpr}.
% \end{texnote}
% \end{function}
%
-% \section{Experimental skip functions}
-%
-% \begin{function}[updated = 2011-10-22]{\skip_split_finite_else_action:nnNN}
-% \begin{syntax}
-% \cs{skip_split_finite_else_action:nnNN} \Arg{skipexpr} \Arg{action}
-% ~~\meta{dimen1} \meta{dimen2}
-% \end{syntax}
-% Checks if the \meta{skipexpr} contains finite glue. If it does then it
-% assigns
-% \meta{dimen1} the stretch component and \meta{dimen2} the shrink
-% component. If
-% it contains infinite glue set \meta{dimen1} and \meta{dimen2} to $0$\,pt
-% and place |#2| into the input stream: this is usually an error or
-% warning message of some sort.
-% \end{function}
-%
-% \section{Internal functions}
-%
% \begin{function}[added = 2011-11-11, EXP]
-% {\dim_strip_bp:n, \dim_strip_pt:n}
+% {\__dim_strip_bp:n, \__dim_strip_pt:n}
% \begin{syntax}
-% \cs{dim_strip_bp:n} \Arg{dimension expression}
-% \cs{dim_strip_pt:n} \Arg{dimension expression}
+% \cs{__dim_strip_bp:n} \Arg{dimension expression}
+% \cs{__dim_strip_pt:n} \Arg{dimension expression}
% \end{syntax}
% Evaluates the \meta{dimension expression}, expanding any
% dimensions and token list variables within the \meta{expression}
@@ -867,7 +898,7 @@
% If the \Arg{dimension expression} contains additional units, these will
% be ignored, so for example
% \begin{verbatim}
-% \dim_strip_pt:n { 1 bp pt }
+% \__dim_strip_pt:n { 1 bp pt }
% \end{verbatim}
% will leave |1.00374| in the input stream (\emph{i.e.}~the magnitude of
% one \enquote{big point} when converted to points).
@@ -884,23 +915,27 @@
% \end{macrocode}
%
% \begin{macrocode}
+%<@@=dim>
+% \end{macrocode}
+%
+% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
% \subsection{Length primitives renamed}
%
% \begin{macro}{\if_dim:w}
-% \begin{macro}{\dim_eval:w}
-% \begin{macro}{\dim_eval_end:}
+% \begin{macro}{\@@_eval:w}
+% \begin{macro}{\@@_eval_end:}
% Primitives renamed.
% \begin{macrocode}
\cs_new_eq:NN \if_dim:w \tex_ifdim:D
-\cs_new_eq:NN \dim_eval:w \etex_dimexpr:D
-\cs_new_eq:NN \dim_eval_end: \tex_relax:D
+\cs_new_eq:NN \@@_eval:w \etex_dimexpr:D
+\cs_new_eq:NN \@@_eval_end: \tex_relax:D
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -914,7 +949,7 @@
%<*package>
\cs_new_protected:Npn \dim_new:N #1
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\newdimen #1
}
%</package>
@@ -981,7 +1016,7 @@
% Setting dimensions is easy enough.
% \begin{macrocode}
\cs_new_protected:Npn \dim_set:Nn #1#2
- { #1 ~ \dim_eval:w #2 \dim_eval_end: }
+ { #1 ~ \@@_eval:w #2 \@@_eval_end: }
\cs_new_protected:Npn \dim_gset:Nn { \tex_global:D \dim_set:Nn }
\cs_generate_variant:Nn \dim_set:Nn { c }
\cs_generate_variant:Nn \dim_gset:Nn { c }
@@ -1008,19 +1043,19 @@
% \begin{macro}{\dim_set_min:Nn, \dim_set_min:cn}
% \begin{macro}{\dim_gset_max:Nn, \dim_gset_max:cn}
% \begin{macro}{\dim_gset_min:Nn, \dim_gset_min:cn}
-% \begin{macro}[aux]{\dim_set_max_aux:NNNn}
+% \begin{macro}[aux]{\@@_set_max:NNNn}
% Setting maximum and minimum values is simply a case of so build-in
% comparison. This only applies to dimensions as skips are not ordered.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \dim_set_max:Nn
- { \dim_set_max_aux:NNNn < \dim_set:Nn }
+ { \@@_set_max:NNNn < \dim_set:Nn }
\cs_new_protected_nopar:Npn \dim_gset_max:Nn
- { \dim_set_max_aux:NNNn < \dim_gset:Nn }
+ { \@@_set_max:NNNn < \dim_gset:Nn }
\cs_new_protected_nopar:Npn \dim_set_min:Nn
- { \dim_set_max_aux:NNNn > \dim_set:Nn }
+ { \@@_set_max:NNNn > \dim_set:Nn }
\cs_new_protected_nopar:Npn \dim_gset_min:Nn
- { \dim_set_max_aux:NNNn > \dim_gset:Nn }
-\cs_new_protected:Npn \dim_set_max_aux:NNNn #1#2#3#4
+ { \@@_set_max:NNNn > \dim_gset:Nn }
+\cs_new_protected:Npn \@@_set_max:NNNn #1#2#3#4
{ \dim_compare:nNnT {#3} #1 {#4} { #2 #3 {#4} } }
\cs_generate_variant:Nn \dim_set_max:Nn { c }
\cs_generate_variant:Nn \dim_gset_max:Nn { c }
@@ -1040,12 +1075,12 @@
% Using |by| here deals with the (incorrect) case |\dimen123|.
% \begin{macrocode}
\cs_new_protected:Npn \dim_add:Nn #1#2
- { \tex_advance:D #1 by \dim_eval:w #2 \dim_eval_end: }
+ { \tex_advance:D #1 by \@@_eval:w #2 \@@_eval_end: }
\cs_new_protected:Npn \dim_gadd:Nn { \tex_global:D \dim_add:Nn }
\cs_generate_variant:Nn \dim_add:Nn { c }
\cs_generate_variant:Nn \dim_gadd:Nn { c }
\cs_new_protected:Npn \dim_sub:Nn #1#2
- { \tex_advance:D #1 by - \dim_eval:w #2 \dim_eval_end: }
+ { \tex_advance:D #1 by - \@@_eval:w #2 \@@_eval_end: }
\cs_new_protected:Npn \dim_gsub:Nn { \tex_global:D \dim_sub:Nn }
\cs_generate_variant:Nn \dim_sub:Nn { c }
\cs_generate_variant:Nn \dim_gsub:Nn { c }
@@ -1065,57 +1100,55 @@
\cs_new:Npn \dim_abs:n #1
{
\dim_use:N
- \dim_eval:w
- \if_dim:w \dim_eval:w #1 < \c_zero_dim
+ \@@_eval:w
+ \if_dim:w \@@_eval:w #1 < \c_zero_dim
-
\fi:
- \dim_eval:w #1 \dim_eval_end:
- \dim_eval_end:
+ \@@_eval:w #1 \@@_eval_end:
+ \@@_eval_end:
}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\dim_ratio:nn}
-% \begin{macro}[aux]{\dim_ratio_aux:n}
+% \begin{macro}[aux]{\@@_ratio:n}
% With dimension expressions, something like |10 pt * ( 5 pt / 10 pt )| will
% not work. Instead, the ratio part needs to be converted to an integer
-% expression. Using \cs{int_value:w} forces everything into |sp|, avoiding
+% expression. Using \cs{__int_value:w} forces everything into |sp|, avoiding
% any decimal parts.
% \begin{macrocode}
\cs_new:Npn \dim_ratio:nn #1#2
- { \dim_ratio_aux:n {#1} / \dim_ratio_aux:n {#2} }
-\cs_new:Npn \dim_ratio_aux:n #1
- { \int_value:w \dim_eval:w #1 \dim_eval_end: }
+ { \@@_ratio:n {#1} / \@@_ratio:n {#2} }
+\cs_new:Npn \@@_ratio:n #1
+ { \__int_value:w \@@_eval:w #1 \@@_eval_end: }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Dimension expression conditionals}
%
-% \begin{macro}{\dim_compare_p:nNn}
-% \begin{macro}[TF]{\dim_compare:nNn}
+% \begin{macro}[pTF, EXP]{\dim_compare:nNn}
% Simple comparison.
% \begin{macrocode}
\prg_new_conditional:Npnn \dim_compare:nNn #1#2#3 { p , T , F , TF }
{
- \if_dim:w \dim_eval:w #1 #2 \dim_eval:w #3 \dim_eval_end:
+ \if_dim:w \@@_eval:w #1 #2 \@@_eval:w #3 \@@_eval_end:
\prg_return_true: \else: \prg_return_false: \fi:
}
% \end{macrocode}
% \end{macro}
-% \end{macro}
%
% \begin{macro}[pTF, EXP]{\dim_compare:n}
-% \begin{macro}[aux, EXP]{\dim_compare_aux:w, \dim_compare_aux:NNw}
+% \begin{macro}[aux, EXP]{\@@_compare_aux:w, \@@_compare_aux:NNw}
% \begin{macro}[aux, EXP]
% {
-% \dim_compare_=:NNw,
-% \dim_compare_<:NNw,
-% \dim_compare_>:NNw,
-% \dim_compare_==:NNw,
-% \dim_compare_!=:NNw,
-% \dim_compare_<=:NNw,
-% \dim_compare_>=:NNw
+% \@@_compare_=:NNw,
+% \@@_compare_<:NNw,
+% \@@_compare_>:NNw,
+% \@@_compare_==:NNw,
+% \@@_compare_!=:NNw,
+% \@@_compare_<=:NNw,
+% \@@_compare_>=:NNw
% }
% This code is adapted from the \cs{int_compare:nTF} function. First
% evaluate the left-hand side. Then access the relation symbol by
@@ -1124,40 +1157,65 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \dim_compare:n #1 { p , T , F , TF }
{
- \exp_after:wN \dim_compare_aux:w \dim_use:N \dim_eval:w #1
- \kernel_compare_error: \dim_eval_end:
+ \exp_after:wN \@@_compare_aux:w \dim_use:N \@@_eval:w #1
+ \__prg_compare_error: \@@_eval_end:
\prg_return_true:
\else:
\prg_return_false:
\fi:
}
\exp_args:Nno \use:nn
- { \cs_new:Npn \dim_compare_aux:w #1 }
+ { \cs_new:Npn \@@_compare_aux:w #1 }
{ \tl_to_str:n { pt } }
- #2 \kernel_compare_error:
+ #2 \__prg_compare_error:
{
- \exp_after:wN \dim_compare_aux:NNw #2 ?? \q_mark
+ \exp_after:wN \@@_compare_aux:NNw #2 ?? \q_mark
#1 pt #2
}
-\cs_new:Npn \dim_compare_aux:NNw #1#2#3 \q_mark
+\cs_new:Npn \@@_compare_aux:NNw #1#2#3 \q_mark
{
- \use:c { dim_compare_ #1 \if_meaning:w = #2 = \fi: :NNw }
- \kernel_compare_error:Nw #1
+ \use:c { @@_compare_ #1 \if_meaning:w = #2 = \fi: :NNw }
+ \__prg_compare_error:Nw #1
}
-\cs_new:cpn { dim_compare_=:NNw } #1#2#3 =
- { \if_dim:w #3 = \dim_eval:w }
-\cs_new:cpn { dim_compare_<:NNw } #1#2#3 <
- { \if_dim:w #3 < \dim_eval:w }
-\cs_new:cpn { dim_compare_>:NNw } #1#2#3 >
- { \if_dim:w #3 > \dim_eval:w }
-\cs_new:cpn { dim_compare_==:NNw } #1#2#3 ==
- { \if_dim:w #3 = \dim_eval:w }
-\cs_new:cpn { dim_compare_!=:NNw } #1#2#3 !=
- { \reverse_if:N \if_dim:w #3 = \dim_eval:w }
-\cs_new:cpn { dim_compare_<=:NNw } #1#2#3 <=
- { \reverse_if:N \if_dim:w #3 > \dim_eval:w }
-\cs_new:cpn { dim_compare_>=:NNw } #1#2#3 >=
- { \reverse_if:N \if_dim:w #3 < \dim_eval:w }
+\cs_new:cpn { @@_compare_=:NNw } #1#2#3 =
+ { \if_dim:w #3 = \@@_eval:w }
+\cs_new:cpn { @@_compare_<:NNw } #1#2#3 <
+ { \if_dim:w #3 < \@@_eval:w }
+\cs_new:cpn { @@_compare_>:NNw } #1#2#3 >
+ { \if_dim:w #3 > \@@_eval:w }
+\cs_new:cpn { @@_compare_==:NNw } #1#2#3 ==
+ { \if_dim:w #3 = \@@_eval:w }
+\cs_new:cpn { @@_compare_!=:NNw } #1#2#3 !=
+ { \reverse_if:N \if_dim:w #3 = \@@_eval:w }
+\cs_new:cpn { @@_compare_<=:NNw } #1#2#3 <=
+ { \reverse_if:N \if_dim:w #3 > \@@_eval:w }
+\cs_new:cpn { @@_compare_>=:NNw } #1#2#3 >=
+ { \reverse_if:N \if_dim:w #3 < \@@_eval:w }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\dim_case:nnn}
+% \begin{macro}[aux, EXP]{\@@_case_aux:nnn}
+% \begin{macro}[aux, EXP]{\@@_case_aux:nw,\@@_case_end:nw}
+% The dimension function is the same as the \texttt{int} version, so there
+% is not much to say here.
+% \begin{macrocode}
+\cs_new:Npn \dim_case:nnn #1
+ {
+ \tex_romannumeral:D
+ \exp_args:Nf \@@_case_aux:nnn { \dim_eval:n {#1} }
+ }
+\cs_new:Npn \@@_case_aux:nnn #1#2#3
+ { \@@_case_aux:nw {#1} #2 {#1} {#3} \q_recursion_stop }
+\cs_new:Npn \@@_case_aux:nw #1#2#3
+ {
+ \dim_compare:nNnTF {#1} = {#2}
+ { \@@_case_end:nw {#3} }
+ { \@@_case_aux:nw {#1} }
+ }
+\cs_new_eq:NN \@@_case_end:nw \__prg_case_end:nw
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1253,33 +1311,33 @@
% Evaluating a dimension expression expandably.
% \begin{macrocode}
\cs_new:Npn \dim_eval:n #1
- { \dim_use:N \dim_eval:w #1 \dim_eval_end: }
+ { \dim_use:N \@@_eval:w #1 \@@_eval_end: }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[EXP]{\dim_strip_bp:n}
+% \begin{macro}[EXP, int]{\@@_strip_bp:n}
% \begin{macrocode}
-\cs_new:Npn \dim_strip_bp:n #1
- { \dim_strip_pt:n { 0.996 26 \dim_eval:w #1 \dim_eval_end: } }
+\cs_new:Npn \@@_strip_bp:n #1
+ { \@@_strip_pt:n { 0.996 26 \@@_eval:w #1 \@@_eval_end: } }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[EXP]{\dim_strip_pt:n}
-% \begin{macro}[EXP, aux]{\dim_strip_pt:w}
+% \begin{macro}[EXP]{\@@_strip_pt:n}
+% \begin{macro}[EXP, aux]{\@@_strip_pt:w}
% A function which comes up often enough to deserve a place in the kernel.
% The idea here is that the input is assumed to be in \texttt{pt}, but can
% be given in other units, while the output is the value of the dimension
% in \texttt{pt} but with no units given. This is used a lot by low-level
% manipulations.
% \begin{macrocode}
-\cs_new:Npn \dim_strip_pt:n #1
+\cs_new:Npn \@@_strip_pt:n #1
{
\exp_after:wN
- \dim_strip_pt:w \dim_use:N \dim_eval:w #1 \dim_eval_end: \q_stop
+ \@@_strip_pt:w \dim_use:N \@@_eval:w #1 \@@_eval_end: \q_stop
}
\use:x
{
- \cs_new:Npn \exp_not:N \dim_strip_pt:w
+ \cs_new:Npn \exp_not:N \@@_strip_pt:w
##1 . ##2 \tl_to_str:n { pt } ##3 \exp_not:N \q_stop
{
##1
@@ -1304,16 +1362,18 @@
% \begin{macro}{\dim_show:N, \dim_show:c}
% Diagnostics.
% \begin{macrocode}
-\cs_new_eq:NN \dim_show:N \kernel_register_show:N
+\cs_new_eq:NN \dim_show:N \__kernel_register_show:N
\cs_generate_variant:Nn \dim_show:N { c }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\dim_show:n}
-% Diagnostics.
+% Diagnostics. We don't use the \TeX{} primitive \tn{showthe} to show
+% dimension expressions: this gives a more unified output, since the
+% closing brace is read by the dimension expression in all cases.
% \begin{macrocode}
\cs_new_protected:Npn \dim_show:n #1
- { \tex_showthe:D \dim_eval:w #1 \dim_eval_end: }
+ { \etex_showtokens:D \exp_after:wN { \dim_use:N \@@_eval:w #1 } }
% \end{macrocode}
% \end{macro}
%
@@ -1338,14 +1398,13 @@
%
% \subsection{Scratch dimensions}
%
-% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim, \l_tmpc_dim}
+% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim}
% \begin{variable}{\g_tmpa_dim, \g_tmpb_dim}
-% We provide three local and two global scratch registers, maybe we
+% We provide two local and two global scratch registers, maybe we
% need more or less.
% \begin{macrocode}
\dim_new:N \l_tmpa_dim
\dim_new:N \l_tmpb_dim
-\dim_new:N \l_tmpc_dim
\dim_new:N \g_tmpa_dim
\dim_new:N \g_tmpb_dim
% \end{macrocode}
@@ -1360,7 +1419,7 @@
%<*package>
\cs_new_protected:Npn \skip_new:N #1
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\newskip #1
}
%</package>
@@ -1493,7 +1552,7 @@
% \end{macro}
%
% \begin{macro}[EXP,pTF]{\skip_if_finite:n}
-% \begin{macro}[EXP,aux]{\skip_if_finite_aux:wwNw}
+% \begin{macro}[EXP,aux]{\__skip_if_finite:wwNw}
% With \eTeX{}, we have an easy access to the order of infinities of
% the stretch and shrink components of a skip. However, to access
% both, we either need to evaluate the expression twice, or evaluate
@@ -1502,29 +1561,21 @@
% it is quicker to make it search for the string \texttt{fil} which
% characterizes infinite glue.
% \begin{macrocode}
-\cs_set_protected:Npn \cs_tmp:w #1
+\cs_set_protected:Npn \__cs_tmp:w #1
{
\prg_new_conditional:Npnn \skip_if_finite:n ##1 { p , T , F , TF }
{
- \exp_after:wN \skip_if_finite_aux:wwNw
+ \exp_after:wN \__skip_if_finite:wwNw
\skip_use:N \etex_glueexpr:D ##1 ; \prg_return_false:
#1 ; \prg_return_true: \q_stop
}
- \cs_new:Npn \skip_if_finite_aux:wwNw ##1 #1 ##2 ; ##3 ##4 \q_stop {##3}
+ \cs_new:Npn \__skip_if_finite:wwNw ##1 #1 ##2 ; ##3 ##4 \q_stop {##3}
}
-\exp_args:No \cs_tmp:w { \tl_to_str:n { fil } }
+\exp_args:No \__cs_tmp:w { \tl_to_str:n { fil } }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[EXP, pTF]{\skip_if_infinite_glue:n}
-% Reverse of \cs{skip_if_finite:nTF}.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \skip_if_infinite_glue:n #1 { p , T , F , TF }
- { \skip_if_finite:nTF {#1} \prg_return_false: \prg_return_true: }
-% \end{macrocode}
-% \end{macro}
-%
% \subsection{Using \texttt{skip} expressions and variables}
%
% \begin{macro}{\skip_eval:n}
@@ -1566,16 +1617,18 @@
% \begin{macro}{\skip_show:N, \skip_show:c}
% Diagnostics.
% \begin{macrocode}
-\cs_new_eq:NN \skip_show:N \kernel_register_show:N
+\cs_new_eq:NN \skip_show:N \__kernel_register_show:N
\cs_generate_variant:Nn \skip_show:N { c }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\skip_show:n}
-% Diagnostics.
+% Diagnostics. We don't use the \TeX{} primitive \tn{showthe} to show
+% skip expressions: this gives a more unified output, since the
+% closing brace is read by the skip expression in all cases.
% \begin{macrocode}
\cs_new_protected:Npn \skip_show:n #1
- { \tex_showthe:D \etex_glueexpr:D #1 \scan_stop: }
+ { \etex_showtokens:D \exp_after:wN { \tex_the:D \etex_glueexpr:D #1 } }
% \end{macrocode}
% \end{macro}
%
@@ -1593,14 +1646,13 @@
%
% \subsection{Scratch skips}
%
-% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip, \l_tmpc_skip}
+% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip}
% \begin{variable}{\g_tmpa_skip, \g_tmpb_skip}
-% We provide three local and two global scratch registers, maybe we
+% We provide two local and two global scratch registers, maybe we
% need more or less.
% \begin{macrocode}
\skip_new:N \l_tmpa_skip
\skip_new:N \l_tmpb_skip
-\skip_new:N \l_tmpc_skip
\skip_new:N \g_tmpa_skip
\skip_new:N \g_tmpb_skip
% \end{macrocode}
@@ -1615,7 +1667,7 @@
%<*package>
\cs_new_protected:Npn \muskip_new:N #1
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\newmuskip #1
}
%</package>
@@ -1761,44 +1813,76 @@
% \begin{macro}{\muskip_show:N, \muskip_show:c}
% Diagnostics.
% \begin{macrocode}
-\cs_new_eq:NN \muskip_show:N \kernel_register_show:N
+\cs_new_eq:NN \muskip_show:N \__kernel_register_show:N
\cs_generate_variant:Nn \muskip_show:N { c }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\muskip_show:n}
-% Diagnostics.
+% Diagnostics. We don't use the \TeX{} primitive \tn{showthe} to show
+% muskip expressions: this gives a more unified output, since the
+% closing brace is read by the muskip expression in all cases.
% \begin{macrocode}
\cs_new_protected:Npn \muskip_show:n #1
- { \tex_showthe:D \etex_muexpr:D #1 \scan_stop: }
+ { \etex_showtokens:D \exp_after:wN { \tex_the:D \etex_muexpr:D #1 } }
% \end{macrocode}
% \end{macro}
%
-% \subsection{Experimental skip functions}
+% \subsection{Constant muskips}
%
-% \begin{macro}{\skip_split_finite_else_action:nnNN}
-% This macro is useful when performing error checking in certain
-% circumstances. If the \meta{skip} register holds finite glue it sets
-% |#3| and |#4| to the stretch and shrink component, resp. If it holds
-% infinite glue set |#3| and |#4| to zero and issue the special action
-% |#2| which is probably an error message.
-% Assignments are local.
+% \begin{macro}{\c_zero_muskip}
+% \begin{macro}{\c_max_muskip}
+% Constant muskips given by their value.
% \begin{macrocode}
-\cs_new:Npn \skip_split_finite_else_action:nnNN #1#2#3#4
- {
- \skip_if_finite:nTF {#1}
- {
- #3 = \etex_gluestretch:D #1 \scan_stop:
- #4 = \etex_glueshrink:D #1 \scan_stop:
- }
- {
- #3 = \c_zero_skip
- #4 = \c_zero_skip
- #2
- }
- }
+\muskip_const:Nn \c_zero_muskip { 0 mu }
+\muskip_const:Nn \c_max_muskip { 16383.99999 mu }
% \end{macrocode}
-% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Scratch muskips}
+%
+% \begin{variable}{\l_tmpa_muskip, \l_tmpb_muskip}
+% \begin{variable}{\g_tmpa_muskip, \g_tmpb_muskip}
+% We provide two local and two global scratch registers, maybe we
+% need more or less.
+% \begin{macrocode}
+\muskip_new:N \l_tmpa_muskip
+\muskip_new:N \l_tmpb_muskip
+\muskip_new:N \g_tmpa_muskip
+\muskip_new:N \g_tmpb_muskip
+% \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \subsection{Deprecated functions}
+%
+% Deprecated on 2012-05-10, for removal by 2012-08-31.
+%
+% \begin{macro}[EXP, pTF]{\skip_if_infinite_glue:n}
+% Reverse of \cs{skip_if_finite:nTF}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \skip_if_infinite_glue:n #1 { p , T , F , TF }
+ { \skip_if_finite:nTF {#1} \prg_return_false: \prg_return_true: }
+% \end{macrocode}
+% \end{macro}
+%
+% Deprecated 2012-06-03 for removal after 2012-12-31.
+%
+% \begin{macro}[EXP]{\prg_case_dim:nnn}
+% Moved here, was in \pkg{l3prg} but load order means we define it here
+% now.
+% \begin{macrocode}
+\cs_new_eq:NN \prg_case_dim:nnn \dim_case:nnn
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\dim_eval:w, \dim_eval_end:}
+% \begin{macrocode}
+\cs_new_eq:NN \dim_eval:w \__dim_eval:w
+\cs_new_eq:NN \dim_eval_end: \__dim_eval_end:
+% \end{macrocode}
+% \end{macro}
%
% \begin{macrocode}
%</initex|package>
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
index 51fcddc242e..08d2630523d 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx
@@ -35,8 +35,8 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3tl.dtx 3490 2012-03-04 01:00:53Z bruno $
- {L3 Experimental token lists}
+\GetIdInfo$Id: l3tl.dtx 3986 2012-07-15 19:23:51Z joseph $
+ {L3 Token lists}
%</driver|package>
%<*driver>
\documentclass[full]{l3doc}
@@ -148,10 +148,23 @@
% \tl_gset_eq:NN, \tl_gset_eq:cN, \tl_gset_eq:Nc, \tl_gset_eq:cc
% }
% \begin{syntax}
-% \cs{tl_set_eq:NN} \meta{tl~var1} \meta{tl~var2}
+% \cs{tl_set_eq:NN} \meta{tl~var_1} \meta{tl~var_2}
% \end{syntax}
-% Sets the content of \meta{tl~var1} equal to that of
-% \meta{tl~var2}.
+% Sets the content of \meta{tl~var_1} equal to that of
+% \meta{tl~var_2}.
+% \end{function}
+%
+% \begin{function}[added = 2012-05-18]
+% {
+% \tl_concat:NNN, \tl_concat:ccc,
+% \tl_gconcat:NNN, \tl_gconcat:ccc
+% }
+% \begin{syntax}
+% \cs{tl_concat:NNN} \meta{tl~var_1} \meta{tl~var_2} \meta{tl~var_3}
+% \end{syntax}
+% Concatenates the content of \meta{tl~var_2} and \meta{tl~var_3}
+% together and saves the result in \meta{tl~var_1}. The \meta{tl~var_2}
+% will be placed at the left side of the new token list.
% \end{function}
%
% \begin{function}[EXP, pTF, added=2012-03-03]{\tl_if_exist:N, \tl_if_exist:c}
@@ -363,23 +376,21 @@
% (\emph{i.e.}~contains no tokens at all).
% \end{function}
%
-% \begin{function}[EXP,pTF]
-% {\tl_if_empty:n, \tl_if_empty:V, \tl_if_empty:o, \tl_if_empty:x}
+% \begin{function}[added = 2012-05-24, updated = 2012-06-05, EXP,pTF]
+% {\tl_if_empty:n, \tl_if_empty:V, \tl_if_empty:o}
% \begin{syntax}
% \cs{tl_if_empty_p:n} \Arg{token list}
% \cs{tl_if_empty:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the \meta{token list} is entirely empty
% (\emph{i.e.}~contains no tokens at all).
-% All versions of these functions are fully expandable
-% (including those involving an \texttt{x}-type expansion).
% \end{function}
%
% \begin{function}[EXP,pTF]
% {\tl_if_eq:NN, \tl_if_eq:Nc, \tl_if_eq:cN, \tl_if_eq:cc}
% \begin{syntax}
-% \cs{tl_if_eq_p:NN} \Arg{tl var1} \Arg{tl var2}
-% \cs{tl_if_eq:NNTF} \Arg{tl var1} \Arg{tl var2} \Arg{true code} \Arg{false code}
+% \cs{tl_if_eq_p:NN} \Arg{tl var_1} \Arg{tl var_2}
+% \cs{tl_if_eq:NNTF} \Arg{tl var_1} \Arg{tl var_2} \Arg{true code} \Arg{false code}
% \end{syntax}
% Compares the content of two \meta{token list variables} and
% is logically \texttt{true} if the two contain the same list of
@@ -395,9 +406,9 @@
%
% \begin{function}[TF]{\tl_if_eq:nn}
% \begin{syntax}
-% \cs{tl_if_eq:nnTF} \meta{token list1} \Arg{token list2} \Arg{true code} \Arg{false code}
+% \cs{tl_if_eq:nnTF} \meta{token list_1} \Arg{token list_2} \Arg{true code} \Arg{false code}
% \end{syntax}
-% Tests if \meta{token list1} and \meta{token list2} are equal, both in
+% Tests if \meta{token list_1} and \meta{token list_2} are equal, both in
% respect of character codes and category codes.
% \end{function}
%
@@ -414,9 +425,9 @@
% \begin{function}[TF]
% {\tl_if_in:nn, \tl_if_in:Vn, \tl_if_in:on, \tl_if_in:no}
% \begin{syntax}
-% \cs{tl_if_in:nnTF} \Arg{token list1} \Arg{token list2} \Arg{true code} \Arg{false code}
+% \cs{tl_if_in:nnTF} \Arg{token list_1} \Arg{token list_2} \Arg{true code} \Arg{false code}
% \end{syntax}
-% Tests if <token list2> is found inside <token list1>.
+% Tests if <token list_2> is found inside <token list_1>.
% The \meta{token list} cannot contain the tokens |{|, |}| or |#|
% (assuming the usual \TeX{} category codes apply).
% \end{function}
@@ -430,8 +441,8 @@
% Tests if the content of the \meta{tl~var} consists of a single item,
% \emph{i.e.}~is either a single normal token (excluding spaces,
% and brace tokens) or a single brace group, surrounded by optional
-% spaces on both sides. In other words, such a token list has length
-% $1$ according to \cs{tl_length:N}.
+% spaces on both sides. In other words, such a token list has token count
+% $1$ according to \cs{tl_count:N}.
% \end{function}
%
% \begin{function}[updated = 2011-08-13, EXP,pTF]{\tl_if_single:n}
@@ -442,22 +453,33 @@
% Tests if the token list has exactly one item, \emph{i.e.}~is either
% a single normal token or a single brace group, surrounded by
% optional spaces on both sides. In other words, such a token list
-% has length $1$ according to \cs{tl_length:n}.
+% has token count $1$ according to \cs{tl_count:n}.
% \end{function}
%
-% \begin{function}[added = 2011-08-11,EXP,pTF]{\tl_if_single_token:n}
+% \begin{function}[added = 2012-06-03, EXP]{\tl_case:Nnn, \tl_case:cnn}
% \begin{syntax}
-% \cs{tl_if_single_token_p:n} \Arg{token list}
-% \cs{tl_if_single_token:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
+% \cs{tl_case:Nnn} \meta{test token list variable} \\
+% ~~"{" \\
+% ~~~~\meta{token list variable case_1} \Arg{code case_1} \\
+% ~~~~\meta{token list variable case_2} \Arg{code case_2} \\
+% ~~~~\ldots \\
+% ~~~~\meta{token list variable case_n} \Arg{code case_n} \\
+% ~~"}" \\
+% ~~\Arg{else code}
% \end{syntax}
-% Tests if the token list consists of exactly one token, \emph{i.e.}~is
-% either a single space character or a single \enquote{normal} token.
-% Token groups (|{|\ldots|}|) are not single tokens.
+% This function compares the \meta{test token list variable} in turn
+% with each of the \meta{token list variable cases}. If the two
+% are equal (as described for
+% \cs{tl_if_eq:nnTF}
+% then the associated \meta{code} is left in the input
+% stream. If none of the tests are \texttt{true} then the
+% \texttt{else code} will be left in the input stream.
% \end{function}
%
% \section{Mapping to token lists}
%
-% \begin{function}[rEXP]{\tl_map_function:NN, \tl_map_function:cN}
+% \begin{function}[updated = 2012-06-29, rEXP]
+% {\tl_map_function:NN, \tl_map_function:cN}
% \begin{syntax}
% \cs{tl_map_function:NN} \meta{tl~var} \meta{function}
% \end{syntax}
@@ -468,7 +490,7 @@
% \texttt{n}-type arguments. See also \cs{tl_map_function:nN}.
% \end{function}
%
-% \begin{function}[rEXP]{\tl_map_function:nN}
+% \begin{function}[updated = 2012-06-29, rEXP]{\tl_map_function:nN}
% \begin{syntax}
% \cs{tl_map_function:nN} \meta{token list} \meta{function}
% \end{syntax}
@@ -479,7 +501,8 @@
% \texttt{n}-type arguments. See also \cs{tl_map_function:NN}.
% \end{function}
%
-% \begin{function}{\tl_map_inline:Nn, \tl_map_inline:cn}
+% \begin{function}[updated = 2012-06-29]
+% {\tl_map_inline:Nn, \tl_map_inline:cn}
% \begin{syntax}
% \cs{tl_map_inline:Nn} \meta{tl~var} \Arg{inline function}
% \end{syntax}
@@ -489,7 +512,7 @@
% inside another. See also \cs{tl_map_function:Nn}.
% \end{function}
%
-% \begin{function}{\tl_map_inline:nn}
+% \begin{function}[updated = 2012-06-29]{\tl_map_inline:nn}
% \begin{syntax}
% \cs{tl_map_inline:nn} \meta{token list} \Arg{inline function}
% \end{syntax}
@@ -499,7 +522,8 @@
% inside another. See also \cs{tl_map_function:nn}.
% \end{function}
%
-% \begin{function}{\tl_map_variable:NNn, \tl_map_variable:cNn}
+% \begin{function}[updated = 2012-06-29]
+% {\tl_map_variable:NNn, \tl_map_variable:cNn}
% \begin{syntax}
% \cs{tl_map_variable:NNn} \meta{tl~var} \meta{variable} \Arg{function}
% \end{syntax}
@@ -510,7 +534,7 @@
% \cs{tl_map_inline:Nn}.
% \end{function}
%
-% \begin{function}{\tl_map_variable:nNn}
+% \begin{function}[updated = 2012-06-29]{\tl_map_variable:nNn}
% \begin{syntax}
% \cs{tl_map_variable:nNn} \meta{token list} \meta{variable} \Arg{function}
% \end{syntax}
@@ -521,7 +545,7 @@
% \cs{tl_map_inline:nn}.
% \end{function}
%
-% \begin{function}[rEXP]{\tl_map_break:}
+% \begin{function}[updated = 2012-06-29, rEXP]{\tl_map_break:}
% \begin{syntax}
% \cs{tl_map_break:}
% \end{syntax}
@@ -540,6 +564,40 @@
% \end{verbatim}
% Use outside of a \cs{tl_map_\ldots} scenario will lead low
% level \TeX{} errors.
+% \begin{texnote}
+% When the mapping is broken, additional tokens may be inserted by the
+% internal macro \cs{__prg_break_point:Nn} before the \meta{tokens} are
+% inserted into the input stream.
+% This will depend on the design of the mapping function.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}[updated = 2012-06-29, rEXP]{\tl_map_break:n}
+% \begin{syntax}
+% \cs{tl_map_break:n} \Arg{tokens}
+% \end{syntax}
+% Used to terminate a \cs{tl_map_\ldots} function before all
+% entries in the \meta{token list variable} have been processed, inserting
+% the \meta{tokens} after the mapping has ended. This will
+% normally take place within a conditional statement, for example
+% \begin{verbatim}
+% \tl_map_inline:Nn \l_my_tl
+% {
+% \str_if_eq:nnTF { #1 } { bingo }
+% { \tl_map_break:n { <tokens> } }
+% {
+% % Do something useful
+% }
+% }
+% \end{verbatim}
+% Use outside of a \cs{tl_map_\ldots} scenario will lead to low
+% level \TeX{} errors.
+% \begin{texnote}
+% When the mapping is broken, additional tokens may be inserted by the
+% internal macro \cs{__prg_break_point:Nn} before the \meta{tokens} are
+% inserted into the input stream.
+% This will depend on the design of the mapping function.
+% \end{texnote}
% \end{function}
%
% \section{Using token lists}
@@ -564,7 +622,8 @@
% in the input stream. Note that this function requires only a single
% expansion.
% \begin{texnote}
-% This is the \eTeX{} primitive \tn{detokenize}.
+% This is the \eTeX{} primitive \tn{detokenize}. Hence its argument
+% \emph{must} be given within braces.
% \end{texnote}
% \end{function}
%
@@ -580,28 +639,28 @@
%
% \section{Working with the content of token lists}
%
-% \begin{function}[updated = 2011-08-13, EXP]
-% {\tl_length:n, \tl_length:V, \tl_length:o}
+% \begin{function}[added = 2012-05-13, EXP]
+% {\tl_count:n, \tl_count:V, \tl_count:o}
% \begin{syntax}
-% \cs{tl_length:n} \Arg{tokens}
+% \cs{tl_count:n} \Arg{tokens}
% \end{syntax}
% Counts the number of \meta{items} in \meta{tokens} and leaves this
% information in the input stream. Unbraced tokens count as one
% element as do each token group (|{|\ldots|}|). This process will
% ignore any unprotected spaces within \meta{tokens}. See also
-% \cs{tl_length:N}. This function requires three expansions,
+% \cs{tl_count:N}. This function requires three expansions,
% giving an \meta{integer denotation}.
% \end{function}
%
-% \begin{function}[updated = 2011-08-13, EXP]{\tl_length:N, \tl_length:c}
+% \begin{function}[added = 2012-05-13, EXP]{\tl_count:N, \tl_count:c}
% \begin{syntax}
-% \cs{tl_length:N} \Arg{tl~var}
+% \cs{tl_count:N} \Arg{tl~var}
% \end{syntax}
% Counts the number of token groups in the \meta{tl~var}
% and leaves this information in the input stream. Unbraced tokens
% count as one element as do each token group (|{|\ldots|}|). This
% process will ignore any unprotected spaces within \meta{tokens}.
-% See also \cs{tl_length:n}. This function requires three expansions,
+% See also \cs{tl_count:n}. This function requires three expansions,
% giving an \meta{integer denotation}.
% \end{function}
%
@@ -611,8 +670,8 @@
% \cs{tl_reverse:n} \Arg{token list}
% \end{syntax}
% Reverses the order of the \meta{items} in the \meta{token list},
-% so that \meta{item1}\meta{item2}\meta{item3} \ldots \meta{item$_n$}
-% becomes \meta{item$_n$}\ldots \meta{item3}\meta{item2}\meta{item1}.
+% so that \meta{item_1}\meta{item_2}\meta{item_3} \ldots \meta{item_n}
+% becomes \meta{item_n}\ldots \meta{item_3}\meta{item_2}\meta{item_1}.
% This process will preserve unprotected space within the
% \meta{token list}. Tokens are not reversed within braced token
% groups, which keep their outer set of braces.
@@ -633,8 +692,8 @@
% \cs{tl_reverse:N} \Arg{tl~var}
% \end{syntax}
% Reverses the order of the \meta{items} stored in \meta{tl~var}, so
-% that \meta{item1}\meta{item2}\meta{item3} \ldots \meta{item$_n$}
-% becomes \meta{item$_n$}\ldots \meta{item3}\meta{item2}\meta{item1}.
+% that \meta{item_1}\meta{item_2}\meta{item_3} \ldots \meta{item_n}
+% becomes \meta{item_n}\ldots \meta{item_3}\meta{item_2}\meta{item_1}.
% This process will preserve unprotected spaces within the
% \meta{token list variable}. Braced token groups are copied without
% reversing the order of tokens, but keep the outer set of braces.
@@ -646,8 +705,8 @@
% \cs{tl_reverse_items:n} \Arg{token list}
% \end{syntax}
% Reverses the order of the \meta{items} stored in \meta{tl~var},
-% so that \Arg{item_1}\Arg{item_2}\Arg{item_3} \ldots \Arg{item$_n$}
-% becomes \Arg{item$_n$} \ldots{} \Arg{item_3}\Arg{item_2}\Arg{item_1}.
+% so that \Arg{item_1}\Arg{item_2}\Arg{item_3} \ldots \Arg{item_n}
+% becomes \Arg{item_n} \ldots{} \Arg{item_3}\Arg{item_2}\Arg{item_1}.
% This process will remove any unprotected space within the
% \meta{token list}. Braced token groups are copied without
% reversing the order of tokens, and keep the outer set of braces.
@@ -662,14 +721,14 @@
% \end{texnote}
% \end{function}
%
-% \begin{function}[added = 2011-07-09, updated = 2011-08-13, EXP]
+% \begin{function}[added = 2011-07-09, updated = 2012-06-25, EXP]
% {\tl_trim_spaces:n}
% \begin{syntax}
% \cs{tl_trim_spaces:n} \meta{token list}
% \end{syntax}
% Removes any leading and trailing explicit space characters
% from the \meta{token list} and leaves the result in the input
-% stream. This process requires two expansions.
+% stream.
% \begin{texnote}
% The result is returned within the \tn{unexpanded}
% primitive (\cs{exp_not:n}), which means that the token
@@ -793,78 +852,75 @@
% nothing is left in the input stream.
% \end{function}
%
-% \begin{function}[updated = 2011-08-10, EXP,pTF]{\tl_if_head_eq_catcode:nN}
+% \begin{function}[updated = 2012-07-09, EXP, pTF]{\tl_if_head_eq_catcode:nN}
% \begin{syntax}
% \cs{tl_if_head_eq_catcode_p:nN} \Arg{token list} \meta{test token}
% \cs{tl_if_head_eq_catcode:nNTF} \Arg{token list} \meta{test token}
% ~~\Arg{true code} \Arg{false code}
% \end{syntax}
-% Tests if the first \meta{token} in the \meta{token list} has the same
-% category code as the \meta{test token}. In the case where
-% \meta{token list} is empty, its head is considered to be \cs{q_nil},
-% and the test will be true if \meta{test token} is a control sequence.
+% Tests if the first \meta{token} in the \meta{token list} has the
+% same category code as the \meta{test token}. In the case where the
+% \meta{token list} is empty, the test will always be \texttt{false}.
% \end{function}
%
-% \begin{function}[updated = 2011-08-10, EXP,pTF]
+% \begin{function}[updated = 2012-07-09, EXP, pTF]
% {\tl_if_head_eq_charcode:nN, \tl_if_head_eq_charcode:fN}
% \begin{syntax}
% \cs{tl_if_head_eq_charcode_p:nN} \Arg{token list} \meta{test token}
% \cs{tl_if_head_eq_charcode:nNTF} \Arg{token list} \meta{test token}
% ~~\Arg{true code} \Arg{false code}
% \end{syntax}
-% Tests if the first \meta{token} in the \meta{token list} has the same
-% character code as the \meta{test token}. In the case where
-% \meta{token list} is empty, its head is considered to be \cs{q_nil},
-% and the test will be true if \meta{test token} is a control sequence.
+% Tests if the first \meta{token} in the \meta{token list} has the
+% same character code as the \meta{test token}. In the case where the
+% \meta{token list} is empty, the test will always be \texttt{false}.
% \end{function}
%
-% \begin{function}[updated = 2011-08-10, EXP,pTF]{\tl_if_head_eq_meaning:nN}
+% \begin{function}[updated = 2012-07-09, EXP, pTF]{\tl_if_head_eq_meaning:nN}
% \begin{syntax}
% \cs{tl_if_head_eq_meaning_p:nN} \Arg{token list} \meta{test token}
% \cs{tl_if_head_eq_meaning:nNTF} \Arg{token list} \meta{test token}
% ~~\Arg{true code} \Arg{false code}
% \end{syntax}
-% Tests if the first \meta{token} in the \meta{token list} has the same
-% meaning as the \meta{test token}. In the case where \meta{token list}
-% is empty, its head is considered to be \cs{q_nil}, and the test will
-% be true if \meta{test token} has the same meaning as \cs{q_nil}.
+% Tests if the first \meta{token} in the \meta{token list} has the
+% same meaning as the \meta{test token}. In the case where
+% \meta{token list} is empty, the test will always be \texttt{false}.
% \end{function}
%
-% \begin{function}[updated = 2011-08-11, EXP,pTF]{\tl_if_head_group:n}
+% \begin{function}[added = 2012-07-08, EXP, pTF]{\tl_if_head_is_group:n}
% \begin{syntax}
-% \cs{tl_if_head_group_p:n} \Arg{token list}
-% \cs{tl_if_head_group:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
+% \cs{tl_if_head_is_group_p:n} \Arg{token list}
+% \cs{tl_if_head_is_group:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the first \meta{token} in the \meta{token list}
% is an explicit begin-group character (with category code~1
% and any character code), in other words, if the \meta{token list}
-% starts with a brace group. In particular, the test is false
+% starts with a brace group. In particular, the test is \texttt{false}
% if the \meta{token list} starts with an implicit token such as
% \cs{c_group_begin_token}, or if it empty.
% This function is useful to implement actions on token lists on
% a token by token basis.
% \end{function}
%
-% \begin{function}[added = 2011-08-11,EXP,pTF]{\tl_if_head_N_type:n}
+% \begin{function}[added = 2012-07-08, EXP, pTF]{\tl_if_head_is_N_type:n}
% \begin{syntax}
-% \cs{tl_if_head_N_type_p:n} \Arg{token list}
-% \cs{tl_if_head_N_type:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
+% \cs{tl_if_head_is_N_type_p:n} \Arg{token list}
+% \cs{tl_if_head_is_N_type:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the first \meta{token} in the \meta{token list}
% is a normal \texttt{N}-type argument. In other words,
% it is neither an explicit space character (with category code~10
% and character code~32) nor an explicit begin-group character
% (with category code~1 and any character code). An empty
-% argument yields false, as it does not have a \enquote{normal}
+% argument yields \texttt{false}, as it does not have a \enquote{normal}
% first token.
% This function is useful to implement actions on token lists on
% a token by token basis.
% \end{function}
%
-% \begin{function}[updated = 2011-08-11,EXP,pTF]{\tl_if_head_space:n}
+% \begin{function}[updated = 2012-07-08, EXP, pTF]{\tl_if_head_is_space:n}
% \begin{syntax}
-% \cs{tl_if_head_space_p:n} \Arg{token list}
-% \cs{tl_if_head_space:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
+% \cs{tl_if_head_is_space_p:n} \Arg{token list}
+% \cs{tl_if_head_is_space:nTF} \Arg{token list} \Arg{true code} \Arg{false code}
% \end{syntax}
%^^A We need to add a discussion of
%^^A explicit vs implicit tokens somewhere in the doc.
@@ -872,7 +928,7 @@
% is an explicit space character (with category code~$10$
% and character code~$32$). If \meta{token list} starts with
% an implicit token such as \cs{c_space_token}, the test
-% will yield false, as well as if the argument is empty.
+% will yield \texttt{false}, as well as if the argument is empty.
% This function is useful to implement actions on token lists on
% a token by token basis.
% \begin{texnote}
@@ -942,89 +998,22 @@
% code and so should only be used for short-term storage.
% \end{variable}
%
-% \section{Experimental token list functions}
-%
-% \begin{function}[added = 2012-01-08, EXP]{\tl_reverse_tokens:n}
-% \begin{syntax}
-% \cs{tl_reverse_tokens:n} \Arg{tokens}
-% \end{syntax}
-% This function, which works directly on \TeX{} tokens, reverses
-% the order of the \meta{tokens}: the first will be the last and
-% the last will become first. Spaces are preserved. The reversal
-% also operates within brace groups, but the braces themselves
-% are not exchanged, as this would lead to an unbalanced token
-% list. For instance, \cs{tl_reverse_tokens:n} |{a~{b()}}|
-% leaves |{)(b}~a| in the input stream. This function requires
-% two steps of expansion.
-% \begin{texnote}
-% The result is returned within the \tn{unexpanded}
-% primitive (\cs{exp_not:n}), which means that the token
-% list will not expand further when appearing in an x-type
-% argument expansion.
-% \end{texnote}
-% \end{function}
-%
-% \begin{function}[added = 2011-08-11, EXP]{\tl_length_tokens:n}
-% \begin{syntax}
-% \cs{tl_length_tokens:n} \Arg{tokens}
-% \end{syntax}
-% Counts the number of \TeX{} tokens in the \meta{tokens} and leaves
-% this information in the input stream. Every token, including spaces and
-% braces, contributes one to the total; thus for instance, the length of
-% |a~{bc}| is $6$.
-% This function requires three expansions,
-% giving an \meta{integer denotation}.
-% \end{function}
-%
-% \begin{function}[added = 2012-01-08, EXP]
-% {\tl_expandable_uppercase:n,\tl_expandable_lowercase:n}
-% \begin{syntax}
-% \cs{tl_expandable_uppercase:n} \Arg{tokens}
-% \cs{tl_expandable_lowercase:n} \Arg{tokens}
-% \end{syntax}
-% The \cs{tl_expandable_uppercase:n} function works through all of
-% the \meta{tokens}, replacing characters in the range |a|--|z|
-% (with arbitrary category code) by the corresponding letter
-% in the range |A|--|Z|, with category code $11$ (letter). Similarly,
-% \cs{tl_expandable_lowercase:n} replaces characters in the range
-% |A|--|Z| by letters in the range |a|--|z|, and leaves other tokens
-% unchanged. This function requires two steps of expansion.
-% \begin{texnote}
-% Begin-group and end-group characters are normalized and become
-% |{| and |}|, respectively.
-% The result is returned within the \tn{unexpanded}
-% primitive (\cs{exp_not:n}), which means that the token
-% list will not expand further when appearing in an x-type
-% argument expansion.
-% \end{texnote}
-% \end{function}
+% \section{Internal functions}
%
-% \begin{function}[added = 2011-11-21, updated = 2012-01-08, EXP]
-% {\tl_item:nn, \tl_item:Nn, \tl_item:cn}
+% \begin{function}{\__tl_trim_spaces:nn}
% \begin{syntax}
-% \cs{tl_item:nn} \Arg{token list} \Arg{integer expression}
+% \cs{__tl_trim_spaces:nn} |{ \q_mark| \meta{token list} |}| \Arg{continuation}
% \end{syntax}
-% Indexing items in the \meta{token list} from $0$ on the left, this
-% function will evaluate the \meta{integer expression} and leave the
-% appropriate item from the \meta{token list} in the input stream.
-% If the \meta{integer expression} is negative, indexing occurs from
-% the right of the token list, starting at $-1$ for the right-most item.
-% If the index is out of bounds, then thr function expands to nothing.
-% \begin{texnote}
-% The result is returned within the \tn{unexpanded}
-% primitive (\cs{exp_not:n}), which means that the \meta{item}
-% will not expand further when appearing in an x-type
-% argument expansion.
-% \end{texnote}
+% This function removes all leading and trailing explicit space
+% characters from the \meta{token list}, and expands to the
+% \meta{continuation}, followed by a brace group containing
+% \cs{use_none:n} \cs{q_mark} \meta{trimmed token list}. For
+% instance, \cs{tl_trim_spaces:n} is implemented by taking the
+% \meta{continuation} to be \cs{exp_not:o}, and the \texttt{o}-type
+% expansion removes the \cs{q_mark}. This function is also used in
+% \pkg{l3clist}.
% \end{function}
%
-% \section{Internal functions}
-%
-% \begin{variable}{\q_tl_act_mark,\q_tl_act_stop}
-% Quarks which are only used for the particular purposes of
-% \cs{tl_act_...} functions.
-% \end{variable}
-%
% \end{documentation}
%
% \begin{implementation}
@@ -1036,10 +1025,14 @@
% \end{macrocode}
%
% \begin{macrocode}
+%<@@=tl>
+% \end{macrocode}
+%
+% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -1055,7 +1048,7 @@
% \begin{macrocode}
\cs_new_protected:Npn \tl_new:N #1
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\cs_gset_eq:NN #1 \c_empty_tl
}
\cs_generate_variant:Nn \tl_new:N { c }
@@ -1067,12 +1060,12 @@
% \begin{macrocode}
\cs_new_protected:Npn \tl_const:Nn #1#2
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\cs_gset_nopar:Npx #1 { \exp_not:n {#2} }
}
\cs_new_protected:Npn \tl_const:Nx #1#2
{
- \chk_if_free_cs:N #1
+ \__chk_if_free_cs:N #1
\cs_gset_nopar:Npx #1 {#2}
}
\cs_generate_variant:Nn \tl_const:Nn { c }
@@ -1134,6 +1127,20 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\tl_concat:NNN, \tl_concat:ccc}
+% \begin{macro}{\tl_gconcat:NNN, \tl_gconcat:ccc}
+% Concatenating token lists is easy.
+% \begin{macrocode}
+\cs_new_protected:Npn \tl_concat:NNN #1#2#3
+ { \tl_set:Nx #1 { \exp_not:o {#2} \exp_not:o {#3} } }
+\cs_new_protected:Npn \tl_gconcat:NNN #1#2#3
+ { \tl_gset:Nx #1 { \exp_not:o {#2} \exp_not:o {#3} } }
+\cs_generate_variant:Nn \tl_concat:NNN { ccc }
+\cs_generate_variant:Nn \tl_gconcat:NNN { ccc }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
% \begin{macro}[pTF]{\tl_if_exist:N, \tl_if_exist:c}
% Copies of the \texttt{cs} functions defined in \pkg{l3basics}.
% \begin{macrocode}
@@ -1148,6 +1155,37 @@
% \end{macrocode}
% \end{macro}
%
+% \subsection{Constant token lists}
+%
+% \begin{variable}{\c_job_name_tl}
+% Inherited from the \LaTeX3 name for the primitive: this needs to
+% actually contain the text of the job name rather than the name of
+% the primitive, of course. \LuaTeX{} does not quote file names containing
+% spaces, whereas \pdfTeX{} and \XeTeX{} do. So there may be a correction to
+% make in the \LuaTeX{} case.
+% \begin{macrocode}
+%<*initex>
+\tex_everyjob:D \exp_after:wN
+ {
+ \tex_the:D \tex_everyjob:D
+ \luatex_if_engine:T
+ {
+ \lua_now:x
+ { dofile ( assert ( kpse.find_file ("lualatexquotejobname.lua" ) ) ) }
+ }
+ }
+%</initex>
+\tl_const:Nx \c_job_name_tl { \tex_jobname:D }
+% \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\c_space_tl}
+% A space as a token list (as opposed to as a character).
+% \begin{macrocode}
+\tl_const:Nn \c_space_tl { ~ }
+% \end{macrocode}
+% \end{variable}
+%
% \subsection{Adding to token list variables}
%
% \begin{macro}
@@ -1273,7 +1311,7 @@
%
% \subsection{Reassigning token list category codes}
%
-% \begin{variable}{\c_tl_rescan_marker_tl}
+% \begin{variable}{\c_@@_rescan_marker_tl}
% The rescanning code needs a special token list containing the same
% character with two different category codes. This is set up here,
% while the detail is described below.
@@ -1286,7 +1324,7 @@
\tex_lowercase:D
{
\group_end:
- \tl_const:Nn \c_tl_rescan_marker_tl { A B }
+ \tl_const:Nn \c_@@_rescan_marker_tl { A B }
}
% \end{macrocode}
% \end{variable}
@@ -1302,8 +1340,8 @@
% \tl_gset_rescan:cnn, \tl_gset_rescan:cno, \tl_gset_rescan:cnx
% }
% \begin{macro}{\tl_rescan:nn}
-% \begin{macro}[aux]{\tl_set_rescan_aux:NNnn}
-% \begin{macro}[aux]{\tl_rescan_aux:w}
+% \begin{macro}[aux]{\@@_set_rescan:NNnn}
+% \begin{macro}[aux]{\@@_rescan:w}
% The idea here is to deal cleanly with the problem that
% \tn{scantokens} treats the argument as a file, and without
% the correct settings a \TeX{} error occurs:
@@ -1322,15 +1360,15 @@
% \enquote{unprintable}.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \tl_set_rescan:Nnn
- { \tl_set_rescan_aux:NNnn \tl_set:Nn }
+ { \@@_set_rescan:NNnn \tl_set:Nn }
\cs_new_protected_nopar:Npn \tl_gset_rescan:Nnn
- { \tl_set_rescan_aux:NNnn \tl_gset:Nn }
+ { \@@_set_rescan:NNnn \tl_gset:Nn }
\cs_new_protected_nopar:Npn \tl_rescan:nn
- { \tl_set_rescan_aux:NNnn \prg_do_nothing: \use:n }
-\cs_new_protected:Npn \tl_set_rescan_aux:NNnn #1#2#3#4
+ { \@@_set_rescan:NNnn \prg_do_nothing: \use:n }
+\cs_new_protected:Npn \@@_set_rescan:NNnn #1#2#3#4
{
\group_begin:
- \exp_args:No \etex_everyeof:D { \c_tl_rescan_marker_tl \exp_not:N }
+ \exp_args:No \etex_everyeof:D { \c_@@_rescan_marker_tl \exp_not:N }
\tex_endlinechar:D \c_minus_one
\tex_newlinechar:D \c_minus_one
#3
@@ -1339,7 +1377,7 @@
\group_end:
#1 \exp_not:N #2
{
- \exp_after:wN \tl_rescan_aux:w
+ \exp_after:wN \@@_rescan:w
\exp_after:wN \prg_do_nothing:
\etex_scantokens:D {#4}
}
@@ -1347,8 +1385,8 @@
}
\use:x
{
- \cs_new:Npn \exp_not:N \tl_rescan_aux:w ##1
- \c_tl_rescan_marker_tl
+ \cs_new:Npn \exp_not:N \@@_rescan:w ##1
+ \c_@@_rescan_marker_tl
{ \exp_not:N \exp_not:o { ##1 } }
}
\cs_generate_variant:Nn \tl_set_rescan:Nnn { Nno , Nnx }
@@ -1380,21 +1418,21 @@
% \begin{macro}{\tl_greplace_all:Nnn, \tl_greplace_all:cnn}
% \begin{macro}{\tl_replace_once:Nnn, \tl_replace_once:cnn}
% \begin{macro}{\tl_greplace_once:Nnn, \tl_greplace_once:cnn}
-% \begin{macro}[aux]{\tl_replace_aux:NNNnn, \tl_replace_aux_ii:w}
-% \begin{macro}[aux]{\tl_replace_all_aux:, \tl_replace_once_aux:}
-% \begin{macro}[aux]{\tl_replace_once_aux_end:w}
-% All of the replace functions are based on \cs{tl_replace_aux:NNNnn},
+% \begin{macro}[aux]{\@@_replace:NNNnn, \@@_replace:w}
+% \begin{macro}[aux]{\@@_replace_all:, \@@_replace_once:}
+% \begin{macro}[aux]{\@@_replace_once_end:w}
+% All of the replace functions are based on \cs{@@_replace:NNNnn},
% whose arguments are: \meta{function}, \cs{tl_(g)set:Nx}, \meta{tl~var},
% \meta{search tokens}, \meta{replacement tokens}.
% \begin{macrocode}
\cs_new_protected_nopar:Npn \tl_replace_once:Nnn
- { \tl_replace_aux:NNNnn \tl_replace_once_aux: \tl_set:Nx }
+ { \@@_replace:NNNnn \@@_replace_once: \tl_set:Nx }
\cs_new_protected_nopar:Npn \tl_greplace_once:Nnn
- { \tl_replace_aux:NNNnn \tl_replace_once_aux: \tl_gset:Nx }
+ { \@@_replace:NNNnn \@@_replace_once: \tl_gset:Nx }
\cs_new_protected_nopar:Npn \tl_replace_all:Nnn
- { \tl_replace_aux:NNNnn \tl_replace_all_aux: \tl_set:Nx }
+ { \@@_replace:NNNnn \@@_replace_all: \tl_set:Nx }
\cs_new_protected_nopar:Npn \tl_greplace_all:Nnn
- { \tl_replace_aux:NNNnn \tl_replace_all_aux: \tl_gset:Nx }
+ { \@@_replace:NNNnn \@@_replace_all: \tl_gset:Nx }
\cs_generate_variant:Nn \tl_replace_once:Nnn { c }
\cs_generate_variant:Nn \tl_greplace_once:Nnn { c }
\cs_generate_variant:Nn \tl_replace_all:Nnn { c }
@@ -1402,34 +1440,34 @@
% \end{macrocode}
% The idea is easier to understand by considering the case of
% \cs{tl_replace_all:Nnn}. The replacement happens within an
-% \texttt{x}-type expansion. We use an auxiliary function \cs{tl_tmp:w},
+% \texttt{x}-type expansion. We use an auxiliary function \cs{@@_tmp:w},
% which essentially replaces the next \meta{search tokens} by
% \meta{replacement tokens}. To avoid runaway arguments,
-% we expand something like \cs{tl_tmp:w} \meta{token list} \cs{q_mark}
+% we expand something like \cs{@@_tmp:w} \meta{token list} \cs{q_mark}
% \meta{search tokens} \cs{q_stop}, repeating until the end. How do we
% detect that we have reached the last occurrence of \meta{search tokens}?
% The last replacement is characterized by the fact that the argument of
-% \cs{tl_tmp:w} contains \cs{q_mark}. In the code below,
-% \cs{tl_replace_aux_ii:w} takes an argument delimited by \cs{q_mark},
+% \cs{@@_tmp:w} contains \cs{q_mark}. In the code below,
+% \cs{@@_replace:w} takes an argument delimited by \cs{q_mark},
% and removes the following token. Before we reach the end, this gobbles
% \cs{q_mark} \cs{use_none_delimit_by_q_stop:w} which appear in the
-% definition of \cs{tl_tmp:w}, and leaves the \meta{replacement tokens},
+% definition of \cs{@@_tmp:w}, and leaves the \meta{replacement tokens},
% passed to \cs{exp_not:n}, to be included in the \texttt{x}-expanding
% definition. At the end, the first \cs{q_mark} is within the argument
-% of \cs{tl_tmp:w}, and \cs{tl_replace_aux_ii:w} gobbles the second
+% of \cs{@@_tmp:w}, and \cs{@@_replace:w} gobbles the second
% \cs{q_mark} as well, leaving \cs{use_none_delimit_by_q_stop:w},
% which ends the recursion cleanly.
% \begin{macrocode}
-\cs_new_protected:Npn \tl_replace_aux:NNNnn #1#2#3#4#5
+\cs_new_protected:Npn \@@_replace:NNNnn #1#2#3#4#5
{
\tl_if_empty:nTF {#4}
{
- \msg_kernel_error:nnx { tl } { empty-search-pattern }
+ \__msg_kernel_error:nnx { kernel } { empty-search-pattern }
{ \tl_to_str:n {#5} }
}
{
\group_align_safe_begin:
- \cs_set:Npx \tl_tmp:w ##1##2 #4
+ \cs_set:Npx \@@_tmp:w ##1##2 #4
{
##2
\exp_not:N \q_mark
@@ -1445,12 +1483,12 @@
}
}
}
-\cs_new:Npn \tl_replace_aux_ii:w #1 \q_mark #2 { \exp_not:o {#1} }
+\cs_new:Npn \@@_replace:w #1 \q_mark #2 { \exp_not:o {#1} }
% \end{macrocode}
-% The first argument of \cs{tl_tmp:w} is responsible for repeating
+% The first argument of \cs{@@_tmp:w} is responsible for repeating
% the replacement in the case of \texttt{replace_all}, and stopping
% it early for \texttt{replace_once}. Note also that we build
-% \cs{tl_tmp:w} within an \texttt{x}-expansion so that the
+% \cs{@@_tmp:w} within an \texttt{x}-expansion so that the
% \meta{replacement tokens} can contain |#|. The second
% \cs{exp_not:n} ensures that the \meta{replacement tokens}
% are not expanded by \cs{tl_(g)set:Nx}.
@@ -1460,17 +1498,17 @@
% ensure that we don't lose braces in case the tokens between two
% occurrences of the \meta{search tokens} form a brace group.
% \begin{macrocode}
-\cs_new:Npn \tl_replace_all_aux:
+\cs_new_nopar:Npn \@@_replace_all:
{
- \exp_after:wN \tl_replace_aux_ii:w
- \tl_tmp:w \tl_replace_all_aux: \prg_do_nothing:
+ \exp_after:wN \@@_replace:w
+ \@@_tmp:w \@@_replace_all: \prg_do_nothing:
}
-\cs_new_nopar:Npn \tl_replace_once_aux:
+\cs_new_nopar:Npn \@@_replace_once:
{
- \exp_after:wN \tl_replace_aux_ii:w
- \tl_tmp:w { \tl_replace_once_aux_end:w \prg_do_nothing: } \prg_do_nothing:
+ \exp_after:wN \@@_replace:w
+ \@@_tmp:w { \@@_replace_once_end:w \prg_do_nothing: } \prg_do_nothing:
}
-\cs_new:Npn \tl_replace_once_aux_end:w #1 \q_mark #2 \q_stop
+\cs_new:Npn \@@_replace_once_end:w #1 \q_mark #2 \q_stop
{ \exp_not:o {#1} }
% \end{macrocode}
% \end{macro}
@@ -1511,7 +1549,7 @@
% \subsection{Token list conditionals}
%
% \begin{macro}[pTF]{\tl_if_blank:n,\tl_if_blank:V,\tl_if_blank:o}
-% \begin{macro}[aux]{\tl_if_blank_p_aux:NNw}
+% \begin{macro}[aux]{\@@_if_blank_p:NNw}
% \TeX{} skips spaces when reading a non-delimited arguments. Thus,
% a \meta{token list} is blank if and only if \cs{use_none:n}
% \meta{token list} |?| is empty. For performance reasons, we hard-code
@@ -1525,7 +1563,7 @@
% while \tn{escapechar} is a space or is unprintable.
% \begin{macrocode}
\prg_new_conditional:Npnn \tl_if_blank:n #1 { p , T , F , TF }
- { \tl_if_empty_return:o { \use_none:n #1 ? } }
+ { \@@_if_empty_return:o { \use_none:n #1 ? } }
\cs_generate_variant:Nn \tl_if_blank_p:n { V }
\cs_generate_variant:Nn \tl_if_blank:nT { V }
\cs_generate_variant:Nn \tl_if_blank:nF { V }
@@ -1561,14 +1599,15 @@
% \begin{macro}[pTF]{\tl_if_empty:n,\tl_if_empty:V}
% It would be tempting to just use |\if_meaning:w \q_nil #1 \q_nil| as
% a test since this works really well. However, it fails on a token
-% list starting with |\q_nil| of course but more troubling is the
-% case where argument is a complete conditional such as |\if_true:|
-% a |\else:| b |\fi:| because then |\if_true:| is used by
-% |\if_meaning:w|, the test turns out false, the |\else:| executes
-% the false branch, the |\fi:| ends it and the |\q_nil| at the end
+% list starting with \cs{q_nil} of course but more troubling is the
+% case where argument is a complete conditional such as \cs{if_true:}
+% a \cs{else:} b \cs{fi:} because then \cs{if_true:} is used by
+% \cs{if_meaning:w}, the test turns out \texttt{false}, the \cs{else:}
+% executes the \texttt{false} branch, the \cs{fi:} ends it and the
+% \cs{q_nil} at the end
% starts executing\dots{} A safer route is to convert the entire
% token list into harmless characters first and then compare
-% that. This way the test will even accept |\q_nil| as the first
+% that. This way the test will even accept \cs{q_nil} as the first
% token.
% \begin{macrocode}
\prg_new_conditional:Npnn \tl_if_empty:n #1 { p , TF , T , F }
@@ -1587,8 +1626,8 @@
% \end{macro}
%
% \begin{macro}[pTF]{\tl_if_empty:o}
-% \begin{macro}[EXP,aux]{\tl_if_empty_return:o}
-% The auxiliary function \cs{tl_if_empty_return:o} is for use
+% \begin{macro}[EXP,aux]{\@@_if_empty_return:o}
+% The auxiliary function \cs{@@_if_empty_return:o} is for use
% in conditionals on token lists, which mostly reduce to testing
% if a given token list is empty after applying a simple function
% to it.
@@ -1598,7 +1637,7 @@
% Note that this works because \cs{tl_to_str:n} expands tokens
% that follow until reading a catcode $1$ (begin-group) token.
% \begin{macrocode}
-\cs_new:Npn \tl_if_empty_return:o #1
+\cs_new:Npn \@@_if_empty_return:o #1
{
\exp_after:wN \if_meaning:w \exp_after:wN \q_nil
\tl_to_str:n \exp_after:wN {#1} \q_nil
@@ -1608,7 +1647,7 @@
\fi:
}
\prg_new_conditional:Npnn \tl_if_empty:o #1 { p , TF , T , F }
- { \tl_if_empty_return:o {#1} }
+ { \@@_if_empty_return:o {#1} }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1670,10 +1709,10 @@
%
% \begin{macro}[TF]{\tl_if_in:nn, \tl_if_in:Vn, \tl_if_in:on, \tl_if_in:no}
% Once more, the test relies on \cs{tl_to_str:n} for robustness.
-% The function \cs{tl_tmp:w} removes tokens until the first occurrence
+% The function \cs{@@_tmp:w} removes tokens until the first occurrence
% of |#2|. If this does not appear in |#1|, then the final |#2| is removed,
% leaving an empty token list. Otherwise some tokens remain, and the
-% test is false. See \cs{tl_if_empty:n(TF)} for details on
+% test is \texttt{false}. See \cs{tl_if_empty:n(TF)} for details on
% the emptyness test.
%
% Special care is needed to treat correctly cases like
@@ -1685,8 +1724,8 @@
% \begin{macrocode}
\prg_new_protected_conditional:Npnn \tl_if_in:nn #1#2 { T , F , TF }
{
- \cs_set:Npn \tl_tmp:w ##1 #2 { }
- \tl_if_empty:oTF { \tl_tmp:w #1 {} {} #2 }
+ \cs_set:Npn \@@_tmp:w ##1 #2 { }
+ \tl_if_empty:oTF { \@@_tmp:w #1 {} {} #2 }
{ \prg_return_false: } { \prg_return_true: }
}
\cs_generate_variant:Nn \tl_if_in:nnT { V , o , no }
@@ -1695,27 +1734,73 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}[EXP,pTF]{\tl_if_single:N}
+% Expand the token list and feed it to \cs{tl_if_single:n}.
+% \begin{macrocode}
+\cs_new:Npn \tl_if_single_p:N { \exp_args:No \tl_if_single_p:n }
+\cs_new:Npn \tl_if_single:NT { \exp_args:No \tl_if_single:nT }
+\cs_new:Npn \tl_if_single:NF { \exp_args:No \tl_if_single:nF }
+\cs_new:Npn \tl_if_single:NTF { \exp_args:No \tl_if_single:nTF }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP,pTF]{\tl_if_single:n}
+% A token list has exactly one item if it is either a single
+% token surrounded by optional explicit spaces, or a single brace
+% group surrounded by optional explicit spaces. The naive
+% version of this test would do \cs{use_none:n} |#1|, and
+% test if the result is empty. However, this will fail when
+% the token list is empty. Furthermore, it does not allow optional
+% trailing spaces.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \tl_if_single:n #1 { p , T , F , TF }
+ { \__str_if_eq_x_return:nn { \exp_not:o { \use_none:nn #1 ?? } } {?} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\tl_case:Nnn, \tl_case:cnn}
+% \begin{macro}[aux, EXP]{\@@_case:Nw}
+% \begin{macro}[aux, EXP]{\@@_case_end:nw}
+% \begin{macrocode}
+\cs_new:Npn \tl_case:Nnn #1#2#3
+ {
+ \tex_romannumeral:D
+ \@@_case:Nw #1 #2 #1 {#3} \q_recursion_stop
+ }
+\cs_new:Npn \@@_case:Nw #1#2#3
+ {
+ \tl_if_eq:NNTF #1 #2
+ { \@@_case_end:nw {#3} }
+ { \@@_case:Nw #1 }
+ }
+\cs_generate_variant:Nn \tl_case:Nnn { c }
+\cs_new_eq:NN \@@_case_end:nw \__prg_case_end:nw
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Mapping to token lists}
%
% \begin{macro}{\tl_map_function:nN}
% \begin{macro}{\tl_map_function:NN, \tl_map_function:cN}
-% \begin{macro}[aux]{\tl_map_function_aux:Nn}
+% \begin{macro}[aux]{\@@_map_function:Nn}
% Expandable loop macro for token lists. These have the advantage of not
% needing to test if the argument is empty, because if it is, the stop
% marker will be read immediately and the loop terminated.
% \begin{macrocode}
\cs_new:Npn \tl_map_function:nN #1#2
{
- \tl_map_function_aux:Nn #2 #1
+ \@@_map_function:Nn #2 #1
\q_recursion_tail
- \prg_break_point:n { }
+ \__prg_break_point:Nn \tl_map_break: { }
}
\cs_new_nopar:Npn \tl_map_function:NN
{ \exp_args:No \tl_map_function:nN }
-\cs_new:Npn \tl_map_function_aux:Nn #1#2
+\cs_new:Npn \@@_map_function:Nn #1#2
{
- \quark_if_recursion_tail_break:n {#2}
- #1 {#2} \tl_map_function_aux:Nn #1
+ \__quark_if_recursion_tail_break:nN {#2} \tl_map_break:
+ #1 {#2} \@@_map_function:Nn #1
}
\cs_generate_variant:Nn \tl_map_function:NN { c }
% \end{macrocode}
@@ -1726,19 +1811,18 @@
% \begin{macro}{\tl_map_inline:nn}
% \begin{macro}{\tl_map_inline:Nn, \tl_map_inline:cn}
% The inline functions are straight forward by now. We use a little
-% trick with the counter \cs{g_prg_map_int} to make
-% them nestable. We can also make use of \cs{tl_map_function_aux:Nn}
+% trick with the counter \cs{g__prg_map_int} to make
+% them nestable. We can also make use of \cs{@@_map_function:Nn}
% from before.
% \begin{macrocode}
\cs_new_protected:Npn \tl_map_inline:nn #1#2
{
- \int_gincr:N \g_prg_map_int
- \cs_gset:cpn { tl_map_inline_ \int_use:N \g_prg_map_int :n }
- ##1 {#2}
- \exp_args:Nc \tl_map_function_aux:Nn
- { tl_map_inline_ \int_use:N \g_prg_map_int :n }
+ \int_gincr:N \g__prg_map_int
+ \cs_gset:cpn { __prg_map_ \int_use:N \g__prg_map_int :w } ##1 {#2}
+ \exp_args:Nc \@@_map_function:Nn
+ { __prg_map_ \int_use:N \g__prg_map_int :w }
#1 \q_recursion_tail
- \prg_break_point:n { \int_gdecr:N \g_prg_map_int }
+ \__prg_break_point:Nn \tl_map_break: { \int_gdecr:N \g__prg_map_int }
}
\cs_new_protected:Npn \tl_map_inline:Nn
{ \exp_args:No \tl_map_inline:nn }
@@ -1749,25 +1833,25 @@
%
% \begin{macro}{\tl_map_variable:nNn}
% \begin{macro}{\tl_map_variable:NNn, \tl_map_variable:cNn}
-% \begin{macro}[aux]{\tl_map_variable_aux:Nnn}
+% \begin{macro}[aux]{\@@_map_variable:Nnn}
% \cs{tl_map_variable:nNn} \meta{token list} \meta{temp} \meta{action}
% assigns
% \meta{temp} to each element and executes \meta{action}.
% \begin{macrocode}
\cs_new_protected:Npn \tl_map_variable:nNn #1#2#3
{
- \tl_map_variable_aux:Nnn #2 {#3} #1
+ \@@_map_variable:Nnn #2 {#3} #1
\q_recursion_tail
- \prg_break_point:n { }
+ \__prg_break_point:Nn \tl_map_break: { }
}
\cs_new_protected_nopar:Npn \tl_map_variable:NNn
{ \exp_args:No \tl_map_variable:nNn }
-\cs_new_protected:Npn \tl_map_variable_aux:Nnn #1#2#3
+\cs_new_protected:Npn \@@_map_variable:Nnn #1#2#3
{
\tl_set:Nn #1 {#3}
- \quark_if_recursion_tail_break:N #1
+ \__quark_if_recursion_tail_break:NN #1 \tl_map_break:
\use:n {#2}
- \tl_map_variable_aux:Nnn #1 {#2}
+ \@@_map_variable:Nnn #1 {#2}
}
\cs_generate_variant:Nn \tl_map_variable:NNn { c }
% \end{macrocode}
@@ -1777,10 +1861,12 @@
%
% \begin{macro}{\tl_map_break:}
% \begin{macro}{\tl_map_break:n}
-% The break statements are simply copies.
+% The break statements use the general \cs{__prg_map_break:Nn}.
% \begin{macrocode}
-\cs_new_eq:NN \tl_map_break: \prg_map_break:
-\cs_new_eq:NN \tl_map_break:n \prg_map_break:n
+\cs_new_nopar:Npn \tl_map_break:
+ { \__prg_map_break:Nn \tl_map_break: { } }
+\cs_new_nopar:Npn \tl_map_break:n
+ { \__prg_map_break:Nn \tl_map_break: }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1811,7 +1897,7 @@
\cs_new:Npn \tl_use:N #1
{
\tl_if_exist:NTF #1 {#1}
- { \msg_expandable_kernel_error:nnn { kernel } { bad-var } {#1} }
+ { \__msg_kernel_expandable_error:nnn { kernel } { bad-variable } {#1} }
}
\cs_generate_variant:Nn \tl_use:N { c }
% \end{macrocode}
@@ -1819,54 +1905,54 @@
%
% \subsection{Working with the contents of token lists}
%
-% \begin{macro}{\tl_length:n, \tl_length:V, \tl_length:o}
-% \begin{macro}{\tl_length:N, \tl_length:c}
-% \begin{macro}[aux]{\tl_length_aux:n}
+% \begin{macro}{\tl_count:n, \tl_count:V, \tl_count:o}
+% \begin{macro}{\tl_count:N, \tl_count:c}
+% \begin{macro}[aux]{\@@_count:n}
% Count number of elements within a token list or token list
% variable. Brace groups within the list are read as a single
% element. Spaces are ignored.
-% \cs{tl_length_aux:n} grabs the element and replaces it by |+1|.
+% \cs{@@_count:n} grabs the element and replaces it by |+1|.
% The |0| to ensure it works on an empty list.
% \begin{macrocode}
-\cs_new:Npn \tl_length:n #1
+\cs_new:Npn \tl_count:n #1
{
\int_eval:n
- { 0 \tl_map_function:nN {#1} \tl_length_aux:n }
+ { 0 \tl_map_function:nN {#1} \@@_count:n }
}
-\cs_new:Npn \tl_length:N #1
+\cs_new:Npn \tl_count:N #1
{
\int_eval:n
- { 0 \tl_map_function:NN #1 \tl_length_aux:n }
+ { 0 \tl_map_function:NN #1 \@@_count:n }
}
-\cs_new:Npn \tl_length_aux:n #1 { + \c_one }
-\cs_generate_variant:Nn \tl_length:n { V , o }
-\cs_generate_variant:Nn \tl_length:N { c }
+\cs_new:Npn \@@_count:n #1 { + \c_one }
+\cs_generate_variant:Nn \tl_count:n { V , o }
+\cs_generate_variant:Nn \tl_count:N { c }
% \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\tl_reverse_items:n}
-% \begin{macro}[aux]{\tl_reverse_items_aux:nwNwn}
-% \begin{macro}[aux]{\tl_reverse_items_aux:wn}
+% \begin{macro}[aux]{\@@_reverse_items:nwNwn}
+% \begin{macro}[aux]{\@@_reverse_items:wn}
% Reversal of a token list is done by taking one item at a time
% and putting it after \cs{q_stop}.
% \begin{macrocode}
\cs_new:Npn \tl_reverse_items:n #1
{
- \tl_reverse_items_aux:nwNwn #1 ?
- \q_mark \tl_reverse_items_aux:nwNwn
- \q_mark \tl_reverse_items_aux:wn
+ \@@_reverse_items:nwNwn #1 ?
+ \q_mark \@@_reverse_items:nwNwn
+ \q_mark \@@_reverse_items:wn
\q_stop { }
}
-\cs_new:Npn \tl_reverse_items_aux:nwNwn #1 #2 \q_mark #3 #4 \q_stop #5
+\cs_new:Npn \@@_reverse_items:nwNwn #1 #2 \q_mark #3 #4 \q_stop #5
{
#3 #2
- \q_mark \tl_reverse_items_aux:nwNwn
- \q_mark \tl_reverse_items_aux:wn
+ \q_mark \@@_reverse_items:nwNwn
+ \q_mark \@@_reverse_items:wn
\q_stop { {#1} #5 }
}
-\cs_new:Npn \tl_reverse_items_aux:wn #1 \q_stop #2
+\cs_new:Npn \@@_reverse_items:wn #1 \q_stop #2
{ \exp_not:o { \use_none:nn #2 } }
% \end{macrocode}
% \end{macro}
@@ -1879,78 +1965,237 @@
% \tl_trim_spaces:N, \tl_trim_spaces:c,
% \tl_gtrim_spaces:N, \tl_gtrim_spaces:c
% }
+% Trimming spaces from around the input is deferred to an internal
+% function whose first argument is the token list to trim, augmented
+% by an initial \cs{q_mark}, and whose second argument is a
+% \meta{continuation}, which will receive as a braced argument
+% \cs{use_none:n} \cs{q_mark} \meta{trimmed token list}. In the case
+% at hand, we take \cs{exp_not:o} as our continuation, so that space
+% trimming will behave correctly within an \texttt{x}-type expansion.
+% \begin{macrocode}
+\cs_new:Npn \tl_trim_spaces:n #1
+ { \@@_trim_spaces:nn { \q_mark #1 } \exp_not:o }
+\cs_new_protected:Npn \tl_trim_spaces:N #1
+ { \tl_set:Nx #1 { \exp_args:No \tl_trim_spaces:n {#1} } }
+\cs_new_protected:Npn \tl_gtrim_spaces:N #1
+ { \tl_gset:Nx #1 { \exp_args:No \tl_trim_spaces:n {#1} } }
+\cs_generate_variant:Nn \tl_trim_spaces:N { c }
+\cs_generate_variant:Nn \tl_gtrim_spaces:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[int]{\@@_trim_spaces:nn}
% \begin{macro}[aux]
% {
-% \tl_trim_spaces_aux_i:w, \tl_trim_spaces_aux_ii:w
-% \tl_trim_spaces_aux_iii:w, \tl_trim_spaces_aux_iv:w
+% \@@_trim_spaces_i:w, \@@_trim_spaces_ii:w
+% \@@_trim_spaces_iii:w, \@@_trim_spaces_iv:w
% }
% Trimming spaces from around the input is done using delimited
% arguments and quarks, and to get spaces at odd places in the
-% definitions, we nest those in \cs{tl_tmp:w}, which then receives
+% definitions, we nest those in \cs{@@_tmp:w}, which then receives
% a single space as its argument: |#1| is \verb*+ +.
-% Removing leading spaces is done with \cs{tl_trim_spaces_aux_i:w},
+% Removing leading spaces is done with \cs{@@_trim_spaces_i:w},
% which loops until \cs{q_mark}\verb*+ + matches the end of the token
% list: then |##1| is the token list and |##3| is
-% \cs{tl_trim_spaces_aux_ii:w}. This hands the relevant tokens to the
-% loop \cs{tl_trim_spaces_aux_iii:w}, responsible for trimming
+% \cs{@@_trim_spaces_ii:w}. This hands the relevant tokens to the
+% loop \cs{@@_trim_spaces_iii:w}, responsible for trimming
% trailing spaces. The end is reached when \verb*+ + \cs{q_nil}
% matches the one present in the definition of \cs{tl_trim_spacs:n}.
-% Then \cs{tl_trim_spaces_aux_iv:w} puts the token list into a group,
-% as the argument of the initial \tn{unexpanded}.
-% The \tn{unexpanded} here is used so that space trimming will
-% behave correctly within an \texttt{x}-type expansion.
-%
-% Some of the auxiliaries used in this code are also used
-% in the \pkg{l3clist} module. Change with care.
+% Then \cs{@@_trim_spaces_iv:w} puts the token list into a group,
+% with \cs{use_none:n} placed there to gobble a lingering \cs{q_mark},
+% and feeds this to the \meta{continuation}.
% \begin{macrocode}
-\cs_set:Npn \tl_tmp:w #1
+\cs_set:Npn \@@_tmp:w #1
{
- \cs_new:Npn \tl_trim_spaces:n ##1
+ \cs_new:Npn \@@_trim_spaces:nn ##1
{
- \etex_unexpanded:D
- \tl_trim_spaces_aux_i:w
- \q_mark
+ \@@_trim_spaces_i:w
##1
\q_nil
\q_mark #1 { }
- \q_mark \tl_trim_spaces_aux_ii:w
- \tl_trim_spaces_aux_iii:w
+ \q_mark \@@_trim_spaces_ii:w
+ \@@_trim_spaces_iii:w
#1 \q_nil
- \tl_trim_spaces_aux_iv:w
- \q_stop
+ \@@_trim_spaces_iv:w
+ \q_stop
}
- \cs_new:Npn \tl_trim_spaces_aux_i:w ##1 \q_mark #1 ##2 \q_mark ##3
+ \cs_new:Npn \@@_trim_spaces_i:w ##1 \q_mark #1 ##2 \q_mark ##3
{
##3
- \tl_trim_spaces_aux_i:w
+ \@@_trim_spaces_i:w
\q_mark
##2
\q_mark #1 {##1}
}
- \cs_new:Npn \tl_trim_spaces_aux_ii:w ##1 \q_mark \q_mark ##2
+ \cs_new:Npn \@@_trim_spaces_ii:w
+ \@@_trim_spaces_i:w \q_mark \q_mark ##1
{
- \tl_trim_spaces_aux_iii:w
- ##2
+ \@@_trim_spaces_iii:w
+ ##1
}
- \cs_new:Npn \tl_trim_spaces_aux_iii:w ##1 #1 \q_nil ##2
+ \cs_new:Npn \@@_trim_spaces_iii:w ##1 #1 \q_nil ##2
{
##2
##1 \q_nil
- \tl_trim_spaces_aux_iii:w
+ \@@_trim_spaces_iii:w
}
- \cs_new:Npn \tl_trim_spaces_aux_iv:w ##1 \q_nil ##2 \q_stop
- { \exp_after:wN { \use_none:n ##1 } }
+ \cs_new:Npn \@@_trim_spaces_iv:w ##1 \q_nil ##2 \q_stop ##3
+ { ##3 { \use_none:n ##1 } }
}
-\tl_tmp:w { ~ }
-\cs_new_protected:Npn \tl_trim_spaces:N #1
- { \tl_set:Nx #1 { \exp_after:wN \tl_trim_spaces:n \exp_after:wN {#1} } }
-\cs_new_protected:Npn \tl_gtrim_spaces:N #1
- { \tl_gset:Nx #1 { \exp_after:wN \tl_trim_spaces:n \exp_after:wN {#1} } }
-\cs_generate_variant:Nn \tl_trim_spaces:N { c }
-\cs_generate_variant:Nn \tl_gtrim_spaces:N { c }
+\@@_tmp:w { ~ }
% \end{macrocode}
% \end{macro}
% \end{macro}
+%
+% \subsection{Token by token changes}
+%
+% \begin{variable}{\q__@@_act_mark,\q__@@_act_stop}
+% The \cs{tl_act} functions may be applied to any token list.
+% Hence, we use two private quarks, to allow any token, even quarks,
+% in the token list.^^A in particular critical for future \::e.
+% Only \cs{q__@@_act_mark} and \cs{q__@@_act_stop} may not appear
+% in the token lists manipulated by \cs{@@_act:NNNnn} functions. The quarks
+% are effectively defined in \pkg{l3quark}.
+% \end{variable}
+%
+% \begin{macro}[EXP,int]{\@@_act:NNNnn}
+% \begin{macro}[EXP,aux]{\@@_act_output:n, \@@_act_reverse_output:n}
+% \begin{macro}[EXP,aux]{\@@_act_loop:w}
+% \begin{macro}[EXP,aux]{\@@_act_normal:NwnNNN}
+% \begin{macro}[EXP,aux]{\@@_act_group:nwnNNN}
+% \begin{macro}[EXP,aux]{\@@_act_space:wwnNNN}
+% \begin{macro}[EXP,aux]{\@@_act_end:w}
+% To help control the expansion, \cs{@@_act:NNNnn} should always
+% be proceeded by \tn{romannumeral} and ends by producing \cs{c_zero}
+% once the result has been obtained. Then loop over tokens,
+% groups, and spaces in |#5|. The marker \cs{q__@@_act_mark}
+% is used both to avoid losing outer braces and to detect the
+% end of the token list more easily. The result is stored
+% as an argument for the dummy function \cs{@@_act_result:n}.
+% \begin{macrocode}
+\cs_new:Npn \@@_act:NNNnn #1#2#3#4#5
+ {
+ \group_align_safe_begin:
+ \@@_act_loop:w #5 \q__@@_act_mark \q__@@_act_stop
+ {#4} #1 #2 #3
+ \@@_act_result:n { }
+ }
+% \end{macrocode}
+% In the loop, we check how the token list begins and act
+% accordingly. In the \enquote{normal} case, we may have
+% reached \cs{q__@@_act_mark}, the end of the list. Then
+% leave \cs{c_zero} and the result in the input stream,
+% to terminate the expansion of \tn{romannumeral}.
+% Otherwise, apply the relevant function to the
+% \enquote{arguments}, |#3|
+% and to the head of the token list. Then repeat the loop.
+% The scheme is the same if the token list starts with a
+% group or with a space. Some extra work is needed to
+% make \cs{@@_act_space:wwnNNN} gobble the space.
+% \begin{macrocode}
+\cs_new:Npn \@@_act_loop:w #1 \q__@@_act_stop
+ {
+ \tl_if_head_is_N_type:nTF {#1}
+ { \@@_act_normal:NwnNNN }
+ {
+ \tl_if_head_is_group:nTF {#1}
+ { \@@_act_group:nwnNNN }
+ { \@@_act_space:wwnNNN }
+ }
+ #1 \q__@@_act_stop
+ }
+\cs_new:Npn \@@_act_normal:NwnNNN #1 #2 \q__@@_act_stop #3#4
+ {
+ \if_meaning:w \q__@@_act_mark #1
+ \exp_after:wN \@@_act_end:wn
+ \fi:
+ #4 {#3} #1
+ \@@_act_loop:w #2 \q__@@_act_stop
+ {#3} #4
+ }
+\cs_new:Npn \@@_act_end:wn #1 \@@_act_result:n #2
+ { \group_align_safe_end: \c_zero #2 }
+\cs_new:Npn \@@_act_group:nwnNNN #1 #2 \q__@@_act_stop #3#4#5
+ {
+ #5 {#3} {#1}
+ \@@_act_loop:w #2 \q__@@_act_stop
+ {#3} #4 #5
+ }
+\exp_last_unbraced:NNo
+ \cs_new:Npn \@@_act_space:wwnNNN \c_space_tl #1 \q__@@_act_stop #2#3#4#5
+ {
+ #5 {#2}
+ \@@_act_loop:w #1 \q__@@_act_stop
+ {#2} #3 #4 #5
+ }
+% \end{macrocode}
+% Typically, the output is done to the right of what was already output,
+% using \cs{@@_act_output:n}, but for the \cs{@@_act_reverse} functions,
+% it should be done to the left.
+% \begin{macrocode}
+\cs_new:Npn \@@_act_output:n #1 #2 \@@_act_result:n #3
+ { #2 \@@_act_result:n { #3 #1 } }
+\cs_new:Npn \@@_act_reverse_output:n #1 #2 \@@_act_result:n #3
+ { #2 \@@_act_result:n { #1 #3 } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\tl_reverse:n, \tl_reverse:o, \tl_reverse:V}
+% \begin{macro}[EXP,aux]{\@@_reverse_normal:nN}
+% \begin{macro}[EXP,aux]{\@@_reverse_group_preserve:nn}
+% \begin{macro}[EXP,aux]{\@@_reverse_space:n}
+% The goal here is to reverse without losing spaces nor braces.
+% This is done using the general internal function \cs{@@_act:NNNnn}.
+% Spaces and \enquote{normal} tokens are output on the left of the current
+% output. Grouped tokens are output to the left but without any reversal
+% within the group. All of the internal functions here drop one argument:
+% this is needed by \cs{@@_act:NNNnn} when changing case (to record
+% which direction the change is in), but not when reversing the tokens.
+% \begin{macrocode}
+\cs_new:Npn \tl_reverse:n #1
+ {
+ \etex_unexpanded:D \exp_after:wN
+ {
+ \tex_romannumeral:D
+ \@@_act:NNNnn
+ \@@_reverse_normal:nN
+ \@@_reverse_group_preserve:nn
+ \@@_reverse_space:n
+ { }
+ {#1}
+ }
+ }
+\cs_generate_variant:Nn \tl_reverse:n { o , V }
+\cs_new:Npn \@@_reverse_normal:nN #1#2
+ { \@@_act_reverse_output:n {#2} }
+\cs_new:Npn \@@_reverse_group_preserve:nn #1#2
+ { \@@_act_reverse_output:n { {#2} } }
+\cs_new:Npn \@@_reverse_space:n #1
+ { \@@_act_reverse_output:n { ~ } }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\tl_reverse:N, \tl_reverse:c, \tl_greverse:N, \tl_greverse:c}
+% This reverses the list, leaving \cs{exp_stop_f:} in front,
+% which stops the \texttt{f}-expansion.
+% \begin{macrocode}
+\cs_new_protected:Npn \tl_reverse:N #1
+ { \tl_set:Nx #1 { \exp_args:No \tl_reverse:n { #1 } } }
+\cs_new_protected:Npn \tl_greverse:N #1
+ { \tl_gset:Nx #1 { \exp_args:No \tl_reverse:n { #1 } } }
+\cs_generate_variant:Nn \tl_reverse:N { c }
+\cs_generate_variant:Nn \tl_greverse:N { c }
+% \end{macrocode}
% \end{macro}
%
% \subsection{The first token from a token list}
@@ -1959,6 +2204,7 @@
% \begin{macro}{\tl_head:w}
% \begin{macro}{\tl_tail:N, \tl_tail:n, \tl_tail:V, \tl_tail:v, \tl_tail:f}
% \begin{macro}{\tl_tail:w}
+% \begin{macro}[aux]{\@@_tail:w}
% These functions pick up either the head or the tail of a list. The
% empty brace groups in \cs{tl_head:n} and \cs{tl_tail:n} ensure that
% a blank argument gives an empty result. The result is returned within
@@ -1969,8 +2215,8 @@
\cs_new:Npn \tl_head:n #1
{ \etex_unexpanded:D \exp_after:wN { \tl_head:w #1 { } \q_stop } }
\cs_new:Npn \tl_tail:n #1
- { \etex_unexpanded:D \tl_tail_aux:w #1 \q_mark { } \q_mark \q_stop }
-\cs_new:Npn \tl_tail_aux:w #1 #2 \q_mark #3 \q_stop { {#2} }
+ { \etex_unexpanded:D \@@_tail:w #1 \q_mark { } \q_mark \q_stop }
+\cs_new:Npn \@@_tail:w #1 #2 \q_mark #3 \q_stop { {#2} }
\cs_new_nopar:Npn \tl_head:N { \exp_args:No \tl_head:n }
\cs_generate_variant:Nn \tl_head:n { V , v , f }
\cs_new_nopar:Npn \tl_tail:N { \exp_args:No \tl_tail:n }
@@ -1980,46 +2226,47 @@
% \end{macro}
% \end{macro}
% \end{macro}
+% \end{macro}
%
% \begin{macro}{\str_head:n, \str_tail:n}
-% \begin{macro}[aux]{\str_head_aux:w}
-% \begin{macro}[aux]{\str_tail_aux:w}
+% \begin{macro}[aux]{\__str_head:w}
+% \begin{macro}[aux]{\__str_tail:w}
% After \cs{tl_to_str:n}, we have a list of character tokens,
% all with category code 12, except the space, which has category
% code 10. Directly using \cs{tl_head:w} would thus lose leading spaces.
% Instead, we take an argument delimited by an explicit space, and
% then only use \cs{tl_head:w}. If the string started with a
-% space, then the argument of \cs{str_head_aux:w} is empty, and
+% space, then the argument of \cs{__str_head:w} is empty, and
% the function correctly returns a space character. Otherwise,
% it returns the first token of |#1|, which is the first token
% of the string. If the string is empty, we return an empty result.
%
% To remove the first character of \cs{tl_to_str:n} |{#1}|,
% we test it using \cs{if_charcode:w} \cs{scan_stop:},
-% always false for characters. If the argument was non-empty,
-% then \cs{str_tail_aux:w} returns everything until the first
+% always \texttt{false} for characters. If the argument was non-empty,
+% then \cs{__str_tail:w} returns everything until the first
% \texttt{X} (with category code letter, no risk of confusing
% with the user input). If the argument was empty, the first
% \texttt{X} is taken by \cs{if_charcode:w}, and nothing
% is returned. We use \texttt{X} as a \meta{marker}, rather than
% a quark because the test \cs{if_charcode:w} \cs{scan_stop:}
-% \meta{marker} has to be false.
+% \meta{marker} has to be \texttt{false}.
% \begin{macrocode}
\cs_new:Npn \str_head:n #1
{
- \exp_after:wN \str_head_aux:w
+ \exp_after:wN \__str_head:w
\tl_to_str:n {#1}
{ { } } ~ \q_stop
}
-\cs_new:Npn \str_head_aux:w #1 ~ %
+\cs_new:Npn \__str_head:w #1 ~ %
{ \tl_head:w #1 { ~ } }
\cs_new:Npn \str_tail:n #1
{
- \exp_after:wN \str_tail_aux:w
+ \exp_after:wN \__str_tail:w
\reverse_if:N \if_charcode:w
\scan_stop: \tl_to_str:n {#1} X X \q_stop
}
-\cs_new:Npn \str_tail_aux:w #1 X #2 \q_stop { \fi: #1 }
+\cs_new:Npn \__str_tail:w #1 X #2 \q_stop { \fi: #1 }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -2029,32 +2276,39 @@
% \begin{macro}[pTF]{\tl_if_head_eq_charcode:nN}
% \begin{macro}[pTF]{\tl_if_head_eq_charcode:fN}
% \begin{macro}[pTF]{\tl_if_head_eq_catcode:nN}
-% Accessing the first token of a token list is tricky in two cases:
-% when it has category code $1$ (begin-group token), or when it is
-% an explicit space, with category code $10$ and character code $32$.
-%
-% Forgetting temporarily about this issue we would use the
-% following test in \cs{tl_if_head_eq_charcode:nN}. Here,
-% an empty |#1| argument yields \cs{q_nil}, otherwise the
-% first token of the token list.
+% Accessing the first token of a token list is tricky in three cases:
+% when it has category code $1$ (begin-group token), when it is an
+% explicit space, with category code $10$ and character code $32$, or
+% when the token list is empty (obviously).
+%
+% Forgetting temporarily about this issue we would use the following
+% test in \cs{tl_if_head_eq_charcode:nN}. Here, \cs{tl_head:w} yields
+% the first token of the token list, then passed to \cs{exp_not:N}.
% \begin{verbatim}
% \if_charcode:w
% \exp_after:wN \exp_not:N \tl_head:w #1 \q_nil \q_stop
% \exp_not:N #2
% \end{verbatim}
-% The special cases are detected using \cs{tl_if_head_N_type:n}
-% (the extra |?| takes care of empty arguments).
-% In those cases, the first token is a character, and
-% since we only care about its character code, we can
-% use \cs{str_head:n} to access it (this works even if
-% it is a space character).
+% The two first special cases are detected by testing if the token
+% list starts with an \texttt{N}-type token (the extra |?| sends empty
+% token lists to the \texttt{true} branch of this test). In those
+% cases, the first token is a character, and since we only care about
+% its character code, we can use \cs{str_head:n} to access it (this
+% works even if it is a space character). An empty argument will
+% result in \cs{tl_head:w} leaving two tokens: |?| which is taken in
+% the \cs{if_charcode:w} test, and \cs{use_none:nn}, which ensures
+% that \cs{prg_return_false:} is returned regardless of whether the
+% charcode test was \texttt{true} or \texttt{false}.
% \begin{macrocode}
\prg_new_conditional:Npnn \tl_if_head_eq_charcode:nN #1#2 { p , T , F , TF }
{
\if_charcode:w
\exp_not:N #2
- \tl_if_head_N_type:nTF { #1 ? }
- { \exp_after:wN \exp_not:N \tl_head:w #1 \q_nil \q_stop }
+ \tl_if_head_is_N_type:nTF { #1 ? }
+ {
+ \exp_after:wN \exp_not:N
+ \tl_head:w #1 { ? \use_none:nn } \q_stop
+ }
{ \str_head:n {#1} }
\prg_return_true:
\else:
@@ -2066,20 +2320,26 @@
\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNT { f }
\cs_generate_variant:Nn \tl_if_head_eq_charcode:nNF { f }
% \end{macrocode}
-% For \cs{tl_if_head_eq_catcode:nN}, again we detect special
-% cases with a \cs{tl_if_head_N_type}. Then we need to test
-% if the first token is a begin-group token or an explicit
-% space token, and produce the relevant token, either
-% \cs{c_group_begin_token} or \cs{c_space_token}.
+% For \cs{tl_if_head_eq_catcode:nN}, again we detect special cases
+% with a \cs{tl_if_head_is_N_type:n}. Then we need to test if the
+% first token is a begin-group token or an explicit space token, and
+% produce the relevant token, either \cs{c_group_begin_token} or
+% \cs{c_space_token}. Again, for an empty argument, a hack is used,
+% removing \cs{prg_return_true:} and \cs{else:} with \cs{use_none:nn}
+% in case the catcode test with the (arbitrarily chosen) |?| is
+% \texttt{true}.
% \begin{macrocode}
\prg_new_conditional:Npnn \tl_if_head_eq_catcode:nN #1 #2 { p , T , F , TF }
{
\if_catcode:w
\exp_not:N #2
- \tl_if_head_N_type:nTF { #1 ? }
- { \exp_after:wN \exp_not:N \tl_head:w #1 \q_nil \q_stop }
+ \tl_if_head_is_N_type:nTF { #1 ? }
{
- \tl_if_head_group:nTF {#1}
+ \exp_after:wN \exp_not:N
+ \tl_head:w #1 { ? \use_none:nn } \q_stop
+ }
+ {
+ \tl_if_head_is_group:nTF {#1}
{ \c_group_begin_token }
{ \c_space_token }
}
@@ -2089,29 +2349,34 @@
\fi:
}
% \end{macrocode}
-% For \cs{tl_if_head_eq_meaning:nN}, again, detect special cases.
-% In the normal case, use \cs{tl_head:w}, with no \cs{exp_not:N}
-% this time, since \cs{if_meaning:w} causes no expansion.
+% For \cs{tl_if_head_eq_meaning:nN}, again, detect special cases. In
+% the normal case, use \cs{tl_head:w}, with no \cs{exp_not:N} this
+% time, since \cs{if_meaning:w} causes no expansion. With an empty
+% argument, the test is \texttt{true}, and \cs{use_none:nnn} removes
+% |#2| and the usual \cs{prg_return_true:} and \cs{else:}.
% In the special cases, we know that the first token is a character,
% hence \cs{if_charcode:w} and \cs{if_catcode:w} together are enough.
% We combine them in some order, hopefully faster than the reverse.
+% Tests are not nested because the arguments may contain unmatched
+% primitive conditionals.
% \begin{macrocode}
\prg_new_conditional:Npnn \tl_if_head_eq_meaning:nN #1#2 { p , T , F , TF }
{
- \tl_if_head_N_type:nTF { #1 ? }
- { \tl_if_head_eq_meaning_aux_normal:nN }
- { \tl_if_head_eq_meaning_aux_special:nN }
+ \tl_if_head_is_N_type:nTF { #1 ? }
+ { \@@_if_head_eq_meaning_normal:nN }
+ { \@@_if_head_eq_meaning_special:nN }
{#1} #2
}
-\cs_new:Npn \tl_if_head_eq_meaning_aux_normal:nN #1 #2
+\cs_new:Npn \@@_if_head_eq_meaning_normal:nN #1 #2
{
- \exp_after:wN \if_meaning:w \tl_head:w #1 \q_nil \q_stop #2
+ \exp_after:wN \if_meaning:w
+ \tl_head:w #1 { ?? \use_none:nnn } \q_stop #2
\prg_return_true:
\else:
\prg_return_false:
\fi:
}
-\cs_new:Npn \tl_if_head_eq_meaning_aux_special:nN #1 #2
+\cs_new:Npn \@@_if_head_eq_meaning_special:nN #1 #2
{
\if_charcode:w \str_head:n {#1} \exp_not:N #2
\exp_after:wN \use:n
@@ -2121,7 +2386,7 @@
\fi:
{
\if_catcode:w \exp_not:N #2
- \tl_if_head_group:nTF {#1}
+ \tl_if_head_is_group:nTF {#1}
{ \c_group_begin_token }
{ \c_space_token }
\prg_return_true:
@@ -2136,7 +2401,7 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[pTF]{\tl_if_head_N_type:n}
+% \begin{macro}[pTF]{\tl_if_head_is_N_type:n}
% The first token of a token list can be either an N-type argument,
% a begin-group token (catcode 1), or an explicit space token
% (catcode 10 and charcode 32). These two cases are characterized
@@ -2145,16 +2410,16 @@
% string representation). The extra brace group covers the case of
% an empty argument, whose head is not \enquote{normal}.
% \begin{macrocode}
-\prg_new_conditional:Npnn \tl_if_head_N_type:n #1 { p , T , F , TF }
+\prg_new_conditional:Npnn \tl_if_head_is_N_type:n #1 { p , T , F , TF }
{
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{ \exp_not:o { \use:n #1 { } } }
{ \exp_not:n { #1 { } } }
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[EXP,pTF]{\tl_if_head_group:n}
+% \begin{macro}[EXP,pTF]{\tl_if_head_is_group:n}
% Pass the first token of |#1| through \cs{token_to_str:N},
% then check for the brace balance. The extra \texttt{?}
% caters for an empty argument.\footnote{Bruno: this could
@@ -2163,7 +2428,7 @@
% to happen in one step of expansion, keeping the token
% list brace balanced at all times.}
% \begin{macrocode}
-\prg_new_conditional:Npnn \tl_if_head_group:n #1 { p , T , F , TF }
+\prg_new_conditional:Npnn \tl_if_head_is_group:n #1 { p , T , F , TF }
{
\if_catcode:w *
\exp_after:wN \use_none:n
@@ -2181,22 +2446,22 @@
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[EXP,pTF]{\tl_if_head_space:n}
-% \begin{macro}[EXP,aux]{\tl_if_head_space_aux:w}
+% \begin{macro}[EXP,pTF]{\tl_if_head_is_space:n}
+% \begin{macro}[EXP,aux]{\@@_if_head_is_space:w}
% If the first token of the token list is an explicit space, i.e.,
% a character token with character code $32$ and category code $10$,
-% then this test will be \meta{true}. It is \meta{false} if the token
+% then this test will be \texttt{true}. It is \texttt{false} if the token
% list is empty, if the first token is an implicit space token,
% such as \cs{c_space_token}, or any token other than an explicit space.
% The slightly convoluted approach with \tn{romannumeral} ensures that
% each expansion step gives a balanced token list.
% \begin{macrocode}
-\prg_new_conditional:Npnn \tl_if_head_space:n #1 { p , T , F , TF }
+\prg_new_conditional:Npnn \tl_if_head_is_space:n #1 { p , T , F , TF }
{
\tex_romannumeral:D \if_false: { \fi:
- \tl_if_head_space_aux:w ? #1 ? ~ }
+ \@@_if_head_is_space:w ? #1 ? ~ }
}
-\cs_new:Npn \tl_if_head_space_aux:w #1 ~
+\cs_new:Npn \@@_if_head_is_space:w #1 ~
{
\tl_if_empty:oTF { \use_none:n #1 }
{ \exp_after:wN \c_zero \exp_after:wN \prg_return_true: }
@@ -2225,37 +2490,6 @@
% \end{macrocode}
%\end{macro}
%
-% \subsection{Constant token lists}
-%
-% \begin{variable}{\c_job_name_tl}
-% Inherited from the \LaTeX3 name for the primitive: this needs to
-% actually contain the text of the job name rather than the name of
-% the primitive, of course. \LuaTeX{} does not quote file names containing
-% spaces, whereas \pdfTeX{} and \XeTeX{} do. So there may be a correction to
-% make in the \LuaTeX{} case.
-% \begin{macrocode}
-%<*initex>
-\tex_everyjob:D \exp_after:wN
- {
- \tex_the:D \tex_everyjob:D
- \luatex_if_engine:T
- {
- \lua_now:x
- { dofile ( assert ( kpse.find_file ("lualatexquotejobname.lua" ) ) ) }
- }
- }
-%</initex>
-\tl_const:Nx \c_job_name_tl { \tex_jobname:D }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{variable}{\c_space_tl}
-% A space as a token list (as opposed to as a character).
-% \begin{macrocode}
-\tl_const:Nn \c_space_tl { ~ }
-% \end{macrocode}
-% \end{variable}
-%
% \subsection{Scratch token lists}
%
% \begin{variable}{\g_tmpa_tl, \g_tmpb_tl}
@@ -2279,398 +2513,6 @@
% \end{macrocode}
% \end{variable}
%
-% \subsection{Experimental functions}
-%
-% \begin{macro}[EXP]{\str_if_eq_return:xx}
-% It turns out that we often need to compare a token list
-% with the result of applying some function to it, and
-% return with \cs{prg_return_true/false:}. This test is
-% similar to \cs{str_if_eq:nnTF}, but hard-coded for speed.
-% \begin{macrocode}
-\cs_new:Npn \str_if_eq_return:xx #1 #2
- {
- \if_int_compare:w \pdftex_strcmp:D {#1} {#2} = \c_zero
- \prg_return_true:
- \else:
- \prg_return_false:
- \fi:
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP,pTF]{\tl_if_single:N}
-% Expand the token list and feed it to \cs{tl_if_single:n}.
-% \begin{macrocode}
-\cs_new:Npn \tl_if_single_p:N { \exp_args:No \tl_if_single_p:n }
-\cs_new:Npn \tl_if_single:NT { \exp_args:No \tl_if_single:nT }
-\cs_new:Npn \tl_if_single:NF { \exp_args:No \tl_if_single:nF }
-\cs_new:Npn \tl_if_single:NTF { \exp_args:No \tl_if_single:nTF }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP,pTF]{\tl_if_single:n}
-% A token list has exactly one item if it is either a single
-% token surrounded by optional explicit spaces, or a single brace
-% group surrounded by optional explicit spaces. The naive
-% version of this test would do \cs{use_none:n} |#1|, and
-% test if the result is empty. However, this will fail when
-% the token list is empty. Furthermore, it does not allow optional
-% trailing spaces.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \tl_if_single:n #1 { p , T , F , TF }
- { \str_if_eq_return:xx { \exp_not:o { \use_none:nn #1 ?? } } {?} }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP,pTF]{\tl_if_single_token:n}
-% There are four cases: empty token list, token list starting with
-% a normal token, with a brace group, or with a space token.
-% If the token list starts with a normal token, remove it
-% and check for emptyness. Otherwise, compare with a single
-% space, only case where we have a single token.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \tl_if_single_token:n #1 { p , T , F , TF }
- {
- \tl_if_head_N_type:nTF {#1}
- { \str_if_eq_return:xx { \exp_not:o { \use_none:n #1 } } { } }
- { \str_if_eq_return:xx { \exp_not:n {#1} } { ~ } }
- }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{variable}{\q_tl_act_mark,\q_tl_act_stop}
-% The \cs{tl_act} functions may be applied to any token list.
-% Hence, we use two private quarks, to allow any token, even quarks,
-% in the token list.^^A in particular critical for future \::e.
-% Only \cs{q_tl_act_mark} and \cs{q_tl_act_stop} may not appear
-% in the token lists manipulated by \cs{tl_act} functions. The quarks
-% are effectively defined in \pkg{l3quark}.
-% \end{variable}
-%
-% \begin{macro}[EXP]{\tl_act:NNNnn,\tl_act_aux:NNNnn}
-% \begin{macro}[EXP]{\tl_act_output:n,\tl_act_reverse_output:n,
-% \tl_act_group_recurse:Nnn}
-% \begin{macro}[EXP,aux]{\tl_act_loop:w,\tl_act_normal:NwnNNN,
-% \tl_act_group:nwnNNN,\tl_act_space:wwnNNN,\tl_act_end:w}
-% To help control the expansion, \cs{tl_act:NNNnn} starts with
-% \tn{romannumeral} and ends by producing \cs{c_zero}
-% once the result has been obtained. Then loop over tokens,
-% groups, and spaces in |#5|. The marker \cs{q_tl_act_mark}
-% is used both to avoid losing outer braces and to detect the
-% end of the token list more easily. The result is stored
-% as an argument for the dummy function \cs{tl_act_result:n}.
-% \begin{macrocode}
-\cs_new:Npn \tl_act:NNNnn { \tex_romannumeral:D \tl_act_aux:NNNnn }
-\cs_new:Npn \tl_act_aux:NNNnn #1 #2 #3 #4 #5
- {
- \group_align_safe_begin:
- \tl_act_loop:w #5 \q_tl_act_mark \q_tl_act_stop
- {#4} #1 #2 #3
- \tl_act_result:n { }
- }
-% \end{macrocode}
-% In the loop, we check how the token list begins and act
-% accordingly. In the \enquote{normal} case, we may have
-% reached \cs{q_tl_act_mark}, the end of the list. Then
-% leave \cs{c_zero} and the result in the input stream,
-% to terminate the expansion of \tn{romannumeral}.
-% Otherwise, apply the relevant function to the
-% \enquote{arguments}, |#3|
-% and to the head of the token list. Then repeat the loop.
-% The scheme is the same if the token list starts with a
-% group or with a space. Some extra work is needed to
-% make \cs{tl_act_space:wwnNNN} gobble the space.
-% \begin{macrocode}
-\cs_new:Npn \tl_act_loop:w #1 \q_tl_act_stop
- {
- \tl_if_head_N_type:nTF {#1}
- { \tl_act_normal:NwnNNN }
- {
- \tl_if_head_group:nTF {#1}
- { \tl_act_group:nwnNNN }
- { \tl_act_space:wwnNNN }
- }
- #1 \q_tl_act_stop
- }
-\cs_new:Npn \tl_act_normal:NwnNNN #1 #2 \q_tl_act_stop #3#4
- {
- \if_meaning:w \q_tl_act_mark #1
- \exp_after:wN \tl_act_end:wn
- \fi:
- #4 {#3} #1
- \tl_act_loop:w #2 \q_tl_act_stop
- {#3} #4
- }
-\cs_new:Npn \tl_act_end:wn #1 \tl_act_result:n #2
- { \group_align_safe_end: \c_zero #2 }
-\cs_new:Npn \tl_act_group:nwnNNN #1 #2 \q_tl_act_stop #3#4#5
- {
- #5 {#3} {#1}
- \tl_act_loop:w #2 \q_tl_act_stop
- {#3} #4 #5
- }
-\exp_last_unbraced:NNo
- \cs_new:Npn \tl_act_space:wwnNNN \c_space_tl #1 \q_tl_act_stop #2#3#4#5
- {
- #5 {#2}
- \tl_act_loop:w #1 \q_tl_act_stop
- {#2} #3 #4 #5
- }
-% \end{macrocode}
-% Typically, the output is done to the right of what was already output,
-% using \cs{tl_act_output:n}, but for the \cs{tl_act_reverse} functions,
-% it should be done to the left.
-% \begin{macrocode}
-\cs_new:Npn \tl_act_output:n #1 #2 \tl_act_result:n #3
- { #2 \tl_act_result:n { #3 #1 } }
-\cs_new:Npn \tl_act_reverse_output:n #1 #2 \tl_act_result:n #3
- { #2 \tl_act_result:n { #1 #3 } }
-% \end{macrocode}
-% In many applications of \cs{tl_act:NNNnn}, we need to recursively
-% apply some transformation within brace groups, then output. In this
-% code, |#1| is the output function, |#2| is the transformation,
-% which should expand in two steps, and |#3| is the group.
-% \begin{macrocode}
-\cs_new:Npn \tl_act_group_recurse:Nnn #1#2#3
- {
- \exp_args:Nf #1
- { \exp_after:wN \exp_after:wN \exp_after:wN { #2 {#3} } }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\tl_reverse_tokens:n}
-% \begin{macro}[EXP,aux]{\tl_act_reverse_normal:nN,
-% \tl_act_reverse_group:nn, \tl_act_reverse_space:n}
-% The goal is to reverse a token list. This is done by feeding
-% \cs{tl_act_aux:NNNnn} three functions, an empty fourth argument
-% (we don't use it for \cs{tl_act_reverse_tokens:n}), and as
-% a fifth argument the token list to be reversed.
-% Spaces and normal tokens are output to the left of the current
-% output. For groups, we must recursively apply
-% \cs{tl_act_reverse_tokens:n} to the group, and output, still
-% on the left. Note that in all three cases, we throw one argument
-% away: this \meta{parameter} is where for instance the
-% upper/lowercasing action stores the information of whether it
-% is uppercasing or lowercasing.
-% \begin{macrocode}
-\cs_new:Npn \tl_reverse_tokens:n #1
- {
- \etex_unexpanded:D \exp_after:wN
- {
- \tex_romannumeral:D
- \tl_act_aux:NNNnn
- \tl_act_reverse_normal:nN
- \tl_act_reverse_group:nn
- \tl_act_reverse_space:n
- { }
- {#1}
- }
- }
-\cs_new:Npn \tl_act_reverse_space:n #1
- { \tl_act_reverse_output:n {~} }
-\cs_new:Npn \tl_act_reverse_normal:nN #1 #2
- { \tl_act_reverse_output:n {#2} }
-\cs_new:Npn \tl_act_reverse_group:nn #1
- {
- \tl_act_group_recurse:Nnn
- \tl_act_reverse_output:n
- { \tl_reverse_tokens:n }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\tl_reverse:n,\tl_reverse:o,\tl_reverse:V}
-% \begin{macro}[EXP,aux]{\tl_reverse_group_preserve:nn}
-% The goal here is to reverse without losing spaces nor braces.
-% The only difference with \cs{tl_reverse_tokens:n} is that
-% we now simply output groups without entering them.
-% \begin{macrocode}
-\cs_new:Npn \tl_reverse:n #1
- {
- \etex_unexpanded:D \exp_after:wN
- {
- \tex_romannumeral:D
- \tl_act_aux:NNNnn
- \tl_act_reverse_normal:nN
- \tl_act_reverse_group_preserve:nn
- \tl_act_reverse_space:n
- { }
- {#1}
- }
- }
-\cs_new:Npn \tl_act_reverse_group_preserve:nn #1 #2
- { \tl_act_reverse_output:n { {#2} } }
-\cs_generate_variant:Nn \tl_reverse:n { o , V }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\tl_reverse:N, \tl_reverse:c, \tl_greverse:N, \tl_greverse:c}
-% This reverses the list, leaving \cs{exp_stop_f:} in front,
-% which stops the \texttt{f}-expansion.
-% \begin{macrocode}
-\cs_new_protected:Npn \tl_reverse:N #1
- { \tl_set:Nx #1 { \exp_args:No \tl_reverse:n { #1 } } }
-\cs_new_protected:Npn \tl_greverse:N #1
- { \tl_gset:Nx #1 { \exp_args:No \tl_reverse:n { #1 } } }
-\cs_generate_variant:Nn \tl_reverse:N { c }
-\cs_generate_variant:Nn \tl_greverse:N { c }
-% \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[EXP]{\tl_length_tokens:n}
-% \begin{macro}[EXP,aux]{\tl_act_length_normal:nN,
-% \tl_act_length_group:nn,\tl_act_length_space:n}
-% The length is computed through an \cs{int_eval:n} construction.
-% Each \texttt{1+} is output to the \emph{left}, into the integer
-% expression, and the sum is ended by the \cs{c_zero} inserted by
-% \cs{tl_act_end:wn}. Somewhat a hack.
-% \begin{macrocode}
-\cs_new:Npn \tl_length_tokens:n #1
- {
- \int_eval:n
- {
- \tl_act_aux:NNNnn
- \tl_act_length_normal:nN
- \tl_act_length_group:nn
- \tl_act_length_space:n
- { }
- {#1}
- }
- }
-\cs_new:Npn \tl_act_length_normal:nN #1 #2 { 1 + }
-\cs_new:Npn \tl_act_length_space:n #1 { 1 + }
-\cs_new:Npn \tl_act_length_group:nn #1 #2
- { 2 + \tl_length_tokens:n {#2} + }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{variable}{\c_tl_act_uppercase_tl, \c_tl_act_lowercase_tl}
-% These constants contain the correspondance between lowercase
-% and uppercase letters, in the form |aAbBcC...| and |AaBbCc...|
-% respectively.
-% \begin{macrocode}
-\tl_const:Nn \c_tl_act_uppercase_tl
- {
- aA bB cC dD eE fF gG hH iI jJ kK lL mM
- nN oO pP qQ rR sS tT uU vV wW xX yY zZ
- }
-\tl_const:Nn \c_tl_act_lowercase_tl
- {
- Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm
- Nn Oo Pp Qq Rr Ss Tt Uu Vv Ww Xx Yy Zz
- }
-% \end{macrocode}
-% \end{variable}
-%
-% \begin{macro}[EXP]{\tl_expandable_uppercase:n,\tl_expandable_lowercase:n}
-% \begin{macro}[EXP,aux]{\tl_act_case_normal:nN,
-% \tl_act_case_group:nn,\tl_act_case_space:n}
-% The only difference between uppercasing and lowercasing is
-% the table of correspondance that is used. As for other
-% token list actions, we feed \cs{tl_act_aux:NNNnn} three
-% functions, and this time, we use the \meta{parameters}
-% argument to carry which case-changing we are applying.
-% A space is simply output. A normal token is compared
-% to each letter in the alphabet using \cs{str_if_eq:nn}
-% tests, and converted if necessary to upper/lowercase,
-% before being output. For a group, we must perform the
-% conversion within the group (the \cs{exp_after:wN} trigger
-% \tn{romannumeral}, which expands fully to give the
-% converted group), then output.
-% \begin{macrocode}
-\cs_new:Npn \tl_expandable_uppercase:n #1
- {
- \etex_unexpanded:D \exp_after:wN
- {
- \tex_romannumeral:D
- \tl_act_case_aux:nn { \c_tl_act_uppercase_tl } {#1}
- }
- }
-\cs_new:Npn \tl_expandable_lowercase:n #1
- {
- \etex_unexpanded:D \exp_after:wN
- {
- \tex_romannumeral:D
- \tl_act_case_aux:nn { \c_tl_act_lowercase_tl } {#1}
- }
- }
-\cs_new:Npn \tl_act_case_aux:nn
- {
- \tl_act_aux:NNNnn
- \tl_act_case_normal:nN
- \tl_act_case_group:nn
- \tl_act_case_space:n
- }
-\cs_new:Npn \tl_act_case_space:n #1 { \tl_act_output:n {~} }
-\cs_new:Npn \tl_act_case_normal:nN #1 #2
- {
- \exp_args:Nf \tl_act_output:n
- {
- \exp_args:NNo \prg_case_str:nnn #2 {#1}
- { \exp_stop_f: #2 }
- }
- }
-\cs_new:Npn \tl_act_case_group:nn #1 #2
- {
- \exp_after:wN \tl_act_output:n \exp_after:wN
- { \exp_after:wN { \tex_romannumeral:D \tl_act_case_aux:nn {#1} {#2} } }
- }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}{\tl_item:nn, \tl_item:Nn, \tl_item:cn}
-% \begin{macro}[aux]{\tl_item_aux:nn}
-% The idea here is to find the offset of the item from the left, then use
-% a loop to grab the correct item. If the resulting offset is too large,
-% then \cs{quark_if_recursion_tail_stop:n} terminates the loop, and returns
-% nothing at all.
-% \begin{macrocode}
-\cs_new:Npn \tl_item:nn #1#2
- {
- \exp_args:Nf \tl_item_aux:nn
- {
- \int_eval:n
- {
- \int_compare:nNnT {#2} < \c_zero
- { \tl_length:n {#1} + }
- #2
- }
- }
- #1
- \q_recursion_tail
- \prg_break_point:n { }
- }
-\cs_new:Npn \tl_item_aux:nn #1#2
- {
- \quark_if_recursion_tail_break:n {#2}
- \int_compare:nNnTF {#1} = \c_zero
- { \tl_map_break:n { \exp_not:n {#2} } }
- { \exp_args:Nf \tl_item_aux:nn { \int_eval:n { #1 - 1 } } }
- }
-\cs_new_nopar:Npn \tl_item:Nn { \exp_args:No \tl_item:nn }
-\cs_generate_variant:Nn \tl_item:Nn { c }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[pTF]{\tl_if_empty:x}
-% We can test expandably the emptyness of an expanded token list
-% thanks to the primitive \tn{pdfstrcmp} which expands its argument:
-% a token list is empty if and only if its string representation is
-% empty.
-% \begin{macrocode}
-\prg_new_conditional:Npnn \tl_if_empty:x #1 { p , T , F , TF }
- { \str_if_eq_return:xx { } {#1} }
-% \end{macrocode}
-% \end{macro}
-%
% \subsection{Deprecated functions}
%
% \begin{macro}{\tl_new:Nn, \tl_new:cn, \tl_new:Nx}
@@ -2751,11 +2593,11 @@
% Another renaming job.
% \begin{macrocode}
%<*deprecated>
-\cs_new_eq:NN \tl_elt_count:n \tl_length:n
-\cs_new_eq:NN \tl_elt_count:V \tl_length:V
-\cs_new_eq:NN \tl_elt_count:o \tl_length:o
-\cs_new_eq:NN \tl_elt_count:N \tl_length:N
-\cs_new_eq:NN \tl_elt_count:c \tl_length:c
+\cs_new_eq:NN \tl_elt_count:n \tl_count:n
+\cs_new_eq:NN \tl_elt_count:V \tl_count:V
+\cs_new_eq:NN \tl_elt_count:o \tl_count:o
+\cs_new_eq:NN \tl_elt_count:N \tl_count:N
+\cs_new_eq:NN \tl_elt_count:c \tl_count:c
%</deprecated>
% \end{macrocode}
% \end{macro}
@@ -2782,6 +2624,58 @@
% \end{macro}
% \end{macro}
%
+% Deprecated on 2012-05-13 for removal by 2012-08-31.
+%
+% \begin{macro}{\tl_length_tokens:n}
+% \begin{macrocode}
+\cs_new_eq:NN \tl_length_tokens:n \tl_count_tokens:n
+% \end{macrocode}
+% \end{macro}
+%
+% Deprecated 2012-05-13 for removal by 2012-11-31.
+%
+% \begin{macro}
+% {\tl_length:N, \tl_length:c, \tl_length:n, \tl_length:V, \tl_length:o}
+% Renames.
+% \begin{macrocode}
+\cs_new_eq:NN \tl_length:N \tl_count:N
+\cs_new_eq:NN \tl_length:c \tl_count:c
+\cs_new_eq:NN \tl_length:n \tl_count:n
+\cs_new_eq:NN \tl_length:V \tl_count:V
+\cs_new_eq:NN \tl_length:o \tl_count:o
+% \end{macrocode}
+% \end{macro}
+%
+% Deprecated 2012-06-05 for removal after 2012-12-31.
+%
+% \begin{macro}[pTF]{\tl_if_empty:x}
+% We can test expandably the emptiness of an expanded token list
+% thanks to the primitive \tn{pdfstrcmp} which expands its argument:
+% a token list is empty if and only if its string representation is
+% empty.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \tl_if_empty:x #1 { p , T , F , TF }
+ { \__str_if_eq_x_return:nn { } {#1} }
+% \end{macrocode}
+% \end{macro}
+%
+% Deprecated 2012-07-08 for removal after 2012-10-31.
+%
+% \begin{macro}[EXP, pTF]{\tl_if_head_group:n}
+% \begin{macro}[EXP, pTF]{\tl_if_head_N_type:n}
+% \begin{macro}[EXP, pTF]{\tl_if_head_space:n}
+% \begin{macrocode}
+\prg_new_eq_conditional:NNn \tl_if_head_group:n \tl_if_head_is_group:n
+ { p , T , F , TF }
+\prg_new_eq_conditional:NNn \tl_if_head_N_type:n \tl_if_head_is_N_type:n
+ { p , T , F , TF }
+\prg_new_eq_conditional:NNn \tl_if_head_space:n \tl_if_head_is_space:n
+ { p , T , F , TF }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \begin{macrocode}
%</initex|package>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
index b811e4a168a..6b1af27ca33 100644
--- a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
+++ b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx
@@ -35,7 +35,7 @@
%
%<*driver|package>
\RequirePackage{l3names}
-\GetIdInfo$Id: l3token.dtx 3491 2012-03-04 06:13:18Z bruno $
+\GetIdInfo$Id: l3token.dtx 3986 2012-07-15 19:23:51Z joseph $
{L3 Experimental token manipulation}
%</driver|package>
%<*driver>
@@ -78,8 +78,8 @@
% see if a certain character is present and maybe even remove it or
% disregard other tokens while scanning. This module provides
% functions for both and as such will have two primary function
-% categories: |\token| for anything that deals with tokens and
-% |\peek| for looking ahead in the token stream.
+% categories: |\token_| for anything that deals with tokens and
+% |\peek_| for looking ahead in the token stream.
%
% Most of the time we will be using the term \enquote{token} but most of the
% time the function we're describing can equally well by used on a
@@ -206,8 +206,8 @@
% \cs{char_set_lcode:nn} \Arg{intexpr_1} \Arg{intexpr_2}
% \end{syntax}
% This function set up the behaviour of \meta{character} when
-% found inside \cs{tl_to_lowercase:n}, such that \meta{character1}
-% will be converted into \meta{character2}. The two \meta{characters}
+% found inside \cs{tl_to_lowercase:n}, such that \meta{character_1}
+% will be converted into \meta{character_2}. The two \meta{characters}
% may be specified using an \meta{integer expression} for the character code
% concerned. This may include the \TeX{} |`|\meta{character}
% method for converting a single character into its character
@@ -243,8 +243,8 @@
% \cs{char_set_uccode:nn} \Arg{intexpr_1} \Arg{intexpr_2}
% \end{syntax}
% This function set up the behaviour of \meta{character} when
-% found inside \cs{tl_to_uppercase:n}, such that \meta{character1}
-% will be converted into \meta{character2}. The two \meta{characters}
+% found inside \cs{tl_to_uppercase:n}, such that \meta{character_1}
+% will be converted into \meta{character_2}. The two \meta{characters}
% may be specified using an \meta{integer expression} for the character code
% concerned. This may include the \TeX{} |`|\meta{character}
% method for converting a single character into its character
@@ -354,10 +354,10 @@
%
% \begin{function}{\token_new:Nn}
% \begin{syntax}
-% \cs{token_new:Nn} \meta{token1} \Arg{token_2}
+% \cs{token_new:Nn} \meta{token_1} \Arg{token_2}
% \end{syntax}
-% Defines \meta{token1} to globally be a snapshot of \meta{token2}.
-% This will be an implicit representation of \meta{token2}.
+% Defines \meta{token_1} to globally be a snapshot of \meta{token_2}.
+% This will be an implicit representation of \meta{token_2}.
% \end{function}
%
% ^^A Because it's late I can't figure out a better way to handle this:
@@ -540,24 +540,24 @@
%
% \begin{function}[EXP,pTF]{\token_if_eq_catcode:NN}
% \begin{syntax}
-% \cs{token_if_eq_catcode_p:NN} \meta{token1} \meta{token2} \\
-% \cs{token_if_eq_catcode:NNTF} \meta{token1} \meta{token2} \Arg{true code} \Arg{false code}
+% \cs{token_if_eq_catcode_p:NN} \meta{token_1} \meta{token_2} \\
+% \cs{token_if_eq_catcode:NNTF} \meta{token_1} \meta{token_2} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the two \meta{tokens} have the same category code.
% \end{function}
%
% \begin{function}[EXP,pTF]{\token_if_eq_charcode:NN}
% \begin{syntax}
-% \cs{token_if_eq_charcode_p:NN} \meta{token1} \meta{token2} \\
-% \cs{token_if_eq_charcode:NNTF} \meta{token1} \meta{token2} \Arg{true code} \Arg{false code}
+% \cs{token_if_eq_charcode_p:NN} \meta{token_1} \meta{token_2} \\
+% \cs{token_if_eq_charcode:NNTF} \meta{token_1} \meta{token_2} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the two \meta{tokens} have the same character code.
% \end{function}
%
% \begin{function}[EXP,pTF]{\token_if_eq_meaning:NN}
% \begin{syntax}
-% \cs{token_if_eq_meaning_p:NN} \meta{token1} \meta{token2} \\
-% \cs{token_if_eq_meaning:NNTF} \meta{token1} \meta{token2} \Arg{true code} \Arg{false code}
+% \cs{token_if_eq_meaning_p:NN} \meta{token_1} \meta{token_2} \\
+% \cs{token_if_eq_meaning:NNTF} \meta{token_1} \meta{token_2} \Arg{true code} \Arg{false code}
% \end{syntax}
% Tests if the two \meta{tokens} have the same meaning when expanded.
% \end{function}
@@ -941,79 +941,6 @@
% not a macro then \cs{scan_stop:} will be left in the input stream
% \end{function}
%
-% \section{Experimental token functions}
-%
-% \begin{function}[added = 2011-12-27]
-% {\char_set_active:Npn, \char_set_active:Npx}
-% \begin{syntax}
-% \cs{char_set_active:Npn} \meta{char} \meta{parameters} \Arg{code}
-% \end{syntax}
-% Makes \meta{char} an active character to expand to \meta{code} as
-% replacement text.
-% Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
-% \emph{etc.}) will be replaced by those absorbed. The \meta{char} is
-% made active within the current \TeX{} group level, and the definition
-% is also local.
-% \end{function}
-%
-% \begin{function}[added = 2011-12-27]
-% {\char_gset_active:Npn, \char_gset_active:Npx}
-% \begin{syntax}
-% \cs{char_gset_active:Npn} \meta{char} \meta{parameters} \Arg{code}
-% \end{syntax}
-% Makes \meta{char} an active character to expand to \meta{code} as
-% replacement text.
-% Within the \meta{code}, the \meta{parameters} (|#1|, |#2|,
-% \emph{etc.}) will be replaced by those absorbed. The \meta{char} is
-% made active within the current \TeX{} group level, but the definition
-% is global. This function is therefore suited to cases where an active
-% character definition should be applied only in some context (where the
-% \meta{char} is again made active).
-% \end{function}
-%
-% \begin{function}[added = 2011-12-27]
-% {\char_set_active_eq:NN}
-% \begin{syntax}
-% \cs{char_set_active_eq:NN} \meta{char} \meta{function}
-% \end{syntax}
-% Makes \meta{char} an active character equivalent in meaning to the
-% \meta{function} (which may itself be an active character). The \meta{char}
-% is made active within the current \TeX{} group level, and the definition
-% is also local.
-% \end{function}
-%
-% \begin{function}[added = 2011-12-27]
-% {\char_gset_active_eq:NN}
-% \begin{syntax}
-% \cs{char_gset_active_eq:NN} \meta{char} \meta{function}
-% \end{syntax}
-% Makes \meta{char} an active character equivalent in meaning to the
-% \meta{function} (which may itself be an active character). The \meta{char}
-% is made active within the current \TeX{} group level, but the definition
-% is global. This function is therefore suited to cases where an active
-% character definition should be applied only in some context (where the
-% \meta{char} is again made active).
-% \end{function}
-%
-% \begin{function}[added = 2011-08-14,TF]{\peek_N_type:}
-% \begin{syntax}
-% \cs{peek_N_type:TF} \Arg{true code} \Arg{false code}
-% \end{syntax}
-% Tests if the next \meta{token} in the input stream can be safely
-% grabbed as an \texttt{N}-type argument. The test will be \meta{false}
-% if the next \meta{token} is either an explicit or implicit
-% begin-group or end-group token (with any character code), or
-% an explicit or implicit space character (with character code $32$
-% and category code $10$), and \meta{true} in all other cases.
-% Note that a \meta{true} result ensures that the next \meta{token} is
-% a valid \texttt{N}-type argument. However, if the next \meta{token}
-% is for instance \cs{c_space_token}, the test will take the
-% \meta{false} branch, even though the next \meta{token} is in fact
-% a valid \texttt{N}-type argument. The \meta{token} will be left
-% in the input stream after the \meta{true code} or \meta{false code}
-% (as appropriate to the result of the test).
-% \end{function}
-%
% \end{documentation}
%
% \begin{implementation}
@@ -1023,12 +950,16 @@
% \begin{macrocode}
%<*initex|package>
% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=token>
+% \end{macrocode}
%
% \begin{macrocode}
%<*package>
\ProvidesExplPackage
{\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
-\package_check_loaded_expl:
+\__expl_package_check:
%</package>
% \end{macrocode}
%
@@ -1040,11 +971,11 @@
% Category code changes.
% \begin{macrocode}
\cs_new_protected:Npn \char_set_catcode:nn #1#2
- { \tex_catcode:D #1 = \int_eval:w #2 \int_eval_end: }
+ { \tex_catcode:D #1 = \__int_eval:w #2 \__int_eval_end: }
\cs_new:Npn \char_value_catcode:n #1
- { \tex_the:D \tex_catcode:D \int_eval:w #1\int_eval_end: }
+ { \tex_the:D \tex_catcode:D \__int_eval:w #1\__int_eval_end: }
\cs_new_protected:Npn \char_show_value_catcode:n #1
- { \tex_showthe:D \tex_catcode:D \int_eval:w #1 \int_eval_end: }
+ { \tex_showthe:D \tex_catcode:D \__int_eval:w #1 \__int_eval_end: }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1175,29 +1106,29 @@
% Pretty repetitive, but necessary!
% \begin{macrocode}
\cs_new_protected:Npn \char_set_mathcode:nn #1#2
- { \tex_mathcode:D #1 = \int_eval:w #2 \int_eval_end: }
+ { \tex_mathcode:D #1 = \__int_eval:w #2 \__int_eval_end: }
\cs_new:Npn \char_value_mathcode:n #1
- { \tex_the:D \tex_mathcode:D \int_eval:w #1\int_eval_end: }
+ { \tex_the:D \tex_mathcode:D \__int_eval:w #1\__int_eval_end: }
\cs_new_protected:Npn \char_show_value_mathcode:n #1
- { \tex_showthe:D \tex_mathcode:D \int_eval:w #1 \int_eval_end: }
+ { \tex_showthe:D \tex_mathcode:D \__int_eval:w #1 \__int_eval_end: }
\cs_new_protected:Npn \char_set_lccode:nn #1#2
- { \tex_lccode:D #1 = \int_eval:w #2 \int_eval_end: }
+ { \tex_lccode:D #1 = \__int_eval:w #2 \__int_eval_end: }
\cs_new:Npn \char_value_lccode:n #1
- { \tex_the:D \tex_lccode:D \int_eval:w #1\int_eval_end: }
+ { \tex_the:D \tex_lccode:D \__int_eval:w #1\__int_eval_end: }
\cs_new_protected:Npn \char_show_value_lccode:n #1
- { \tex_showthe:D \tex_lccode:D \int_eval:w #1 \int_eval_end: }
+ { \tex_showthe:D \tex_lccode:D \__int_eval:w #1 \__int_eval_end: }
\cs_new_protected:Npn \char_set_uccode:nn #1#2
- { \tex_uccode:D #1 = \int_eval:w #2 \int_eval_end: }
+ { \tex_uccode:D #1 = \__int_eval:w #2 \__int_eval_end: }
\cs_new:Npn \char_value_uccode:n #1
- { \tex_the:D \tex_uccode:D \int_eval:w #1\int_eval_end: }
+ { \tex_the:D \tex_uccode:D \__int_eval:w #1\__int_eval_end: }
\cs_new_protected:Npn \char_show_value_uccode:n #1
- { \tex_showthe:D \tex_uccode:D \int_eval:w #1 \int_eval_end: }
+ { \tex_showthe:D \tex_uccode:D \__int_eval:w #1 \__int_eval_end: }
\cs_new_protected:Npn \char_set_sfcode:nn #1#2
- { \tex_sfcode:D #1 = \int_eval:w #2 \int_eval_end: }
+ { \tex_sfcode:D #1 = \__int_eval:w #2 \__int_eval_end: }
\cs_new:Npn \char_value_sfcode:n #1
- { \tex_the:D \tex_sfcode:D \int_eval:w #1\int_eval_end: }
+ { \tex_the:D \tex_sfcode:D \__int_eval:w #1\__int_eval_end: }
\cs_new_protected:Npn \char_show_value_sfcode:n #1
- { \tex_showthe:D \tex_sfcode:D \int_eval:w #1 \int_eval_end: }
+ { \tex_showthe:D \tex_sfcode:D \__int_eval:w #1 \__int_eval_end: }
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1288,13 +1219,13 @@
\use:nn
{
\group_end:
- \seq_set_from_clist:Nn \l_char_active_seq
+ \seq_set_split:Nnn \l_char_active_seq { }
}
}
- { { " , $ , & , ^ , _ , ~ } } %$
+ { { " $ & ^ _ ~ } } %$
\seq_new:N \l_char_special_seq
-\seq_set_from_clist:Nn \l_char_special_seq
- { \ , \" , \# , \$ , \% , \& , \\ , \^ , \_ , \{ , \} , \~ }
+\seq_set_split:Nnn \l_char_special_seq { }
+ { \ \" \# \$ \% \& \\ \^ \_ \{ \} \~ }
% \end{macrocode}
% \end{variable}
%
@@ -1302,7 +1233,7 @@
%
% \begin{macro}[pTF]{\token_if_group_begin:N}
% Check if token is a begin group token. We use the constant
-% |\c_group_begin_token| for this.
+% \cs{c_group_begin_token} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_group_begin:N #1 { p , T , F , TF }
{
@@ -1314,7 +1245,7 @@
%
% \begin{macro}[pTF]{\token_if_group_end:N}
% Check if token is a end group token. We use the constant
-% |\c_group_end_token| for this.
+% \cs{c_group_end_token} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_group_end:N #1 { p , T , F , TF }
{
@@ -1326,7 +1257,7 @@
%
% \begin{macro}[pTF]{\token_if_math_toggle:N}
% Check if token is a math shift token. We use the constant
-% |\c_math_toggle_token| for this.
+% \cs{c_math_toggle_token} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_math_toggle:N #1 { p , T , F , TF }
{
@@ -1338,7 +1269,7 @@
%
% \begin{macro}[pTF]{\token_if_alignment:N}
% Check if token is an alignment tab token. We use the constant
-% |\c_alignment_tab_token| for this.
+% \cs{c_alignment_token} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_alignment:N #1 { p , T , F , TF }
{
@@ -1350,7 +1281,7 @@
%
% \begin{macro}[pTF]{\token_if_parameter:N}
% Check if token is a parameter token. We use the constant
-% |\c_parameter_token| for this. We have to trick \TeX{} a bit to
+% \cs{c_parameter_token} for this. We have to trick \TeX{} a bit to
% avoid an error message: within a group we prevent
% \cs{c_parameter_token} from behaving like a macro parameter character.
% The definitions of \cs{prg_new_conditional:Npnn} are global, so they
@@ -1369,7 +1300,7 @@
%
% \begin{macro}[pTF]{\token_if_math_superscript:N}
% Check if token is a math superscript token. We use the constant
-% |\c_superscript_token| for this.
+% \cs{c_math_superscript_token} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_math_superscript:N #1 { p , T , F , TF }
{
@@ -1381,7 +1312,7 @@
%
% \begin{macro}[pTF]{\token_if_math_subscript:N}
% Check if token is a math subscript token. We use the constant
-% |\c_subscript_token| for this.
+% \cs{c_math_subscript_token} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_math_subscript:N #1 { p , T , F , TF }
{
@@ -1393,7 +1324,7 @@
%
% \begin{macro}[pTF]{\token_if_space:N}
% Check if token is a space token. We use the constant
-% |\c_space_token| for this.
+% \cs{c_space_token} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_space:N #1 { p , T , F , TF }
{
@@ -1405,7 +1336,7 @@
%
% \begin{macro}[pTF]{\token_if_letter:N}
% Check if token is a letter token. We use the constant
-% |\c_letter_token| for this.
+% \cs{c_catcode_letter_token} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_letter:N #1 { p , T , F , TF }
{
@@ -1417,7 +1348,7 @@
%
% \begin{macro}[pTF]{\token_if_other:N}
% Check if token is an other char token. We use the constant
-% |\c_other_char_token| for this.
+% \cs{c_catcode_other_token} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_other:N #1 { p , T , F , TF }
{
@@ -1429,8 +1360,8 @@
%
% \begin{macro}[pTF]{\token_if_active:N}
% Check if token is an active char token. We use the constant
-% |\c_active_char_tl| for this. A technical point is that
-% \cs{c_active_char_tl} is in fact a macro expanding to
+% \cs{c_catcode_active_tl} for this. A technical point is that
+% \cs{c_catcode_active_tl} is in fact a macro expanding to
% |\exp_not:N *|, where |*| is active.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_active:N #1 { p , T , F , TF }
@@ -1475,8 +1406,8 @@
% \end{macro}
%
% \begin{macro}[pTF]{\token_if_macro:N}
-% \begin{macro}[aux]{\token_if_macro_p_aux:w}
-% When a token is a macro, |\token_to_meaning:N| will always output
+% \begin{macro}[aux]{\@@_if_macro_p:w}
+% When a token is a macro, \cs{token_to_meaning:N} will always output
% something like |\long macro:#1->#1| so we could naively check to
% see if the meaning contains |->|. However, this can fail the five
% \tn{...mark} primitives, whose meaning has the form
@@ -1513,10 +1444,10 @@
\group_end:
\prg_new_conditional:Npnn \token_if_macro:N #1 { p , T , F , TF }
{
- \exp_after:wN \token_if_macro_p_aux:w
+ \exp_after:wN \@@_if_macro_p:w
\token_to_meaning:N #1 MA; \q_stop
}
- \cs_new:Npn \token_if_macro_p_aux:w #1 MA #2 ; #3 \q_stop
+ \cs_new:Npn \@@_if_macro_p:w #1 MA #2 ; #3 \q_stop
{
\if_int_compare:w \pdftex_strcmp:D { #2 } { cro } = \c_zero
\prg_return_true:
@@ -1532,7 +1463,7 @@
% \begin{macro}[pTF]{\token_if_cs:N}
% Check if token has same catcode as a control sequence. This
% follows the same pattern as for \cs{token_if_letter:N} \emph{etc.}
-% We use |\scan_stop:| for this.
+% We use \cs{scan_stop:} for this.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_cs:N #1 { p , T , F , TF }
{
@@ -1544,17 +1475,23 @@
%
% \begin{macro}[pTF]{\token_if_expandable:N}
% Check if token is expandable. We use the fact that \TeX{} will
-% temporarily convert |\exp_not:N| \meta{token} into |\scan_stop:| if
-% \meta{token} is expandable.
+% temporarily convert \cs{exp_not:N} \meta{token} into \cs{scan_stop:}
+% if \meta{token} is expandable. An \texttt{undefined} token is not
+% considered as expandable. No problem nesting the conditionals,
+% since the third |#1| is only skipped if it is non-expandable (hence
+% not part of \TeX{}'s conditional apparatus).
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_expandable:N #1 { p , T , F , TF }
{
- \cs_if_exist:NTF #1
- {
- \exp_after:wN \if_meaning:w \exp_not:N #1 #1
- \prg_return_false: \else: \prg_return_true: \fi:
- }
- { \prg_return_false: }
+ \exp_after:wN \if_meaning:w \exp_not:N #1 #1
+ \prg_return_false:
+ \else:
+ \if_cs_exist:N #1
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ \fi:
}
% \end{macrocode}
% \end{macro}
@@ -1570,18 +1507,18 @@
% }
% \begin{macro}[aux]
% {
-% \token_if_chardef_aux:w,
-% \token_if_dim_register_aux:w,
-% \token_if_int_register_aux:w,
-% \token_if_muskip_register_aux:w,
-% \token_if_skip_register_aux:w,
-% \token_if_toks_register_aux:w,
-% \token_if_protected_macro_aux:w,
-% \token_if_long_macro_aux:w,
+% \@@_if_chardef:w,
+% \@@_if_dim_register:w,
+% \@@_if_int_register:w,
+% \@@_if_muskip_register:w,
+% \@@_if_skip_register:w,
+% \@@_if_toks_register:w,
+% \@@_if_protected_macro:w,
+% \@@_if_long_macro:w,
% }
% Most of these functions have to check the meaning of the token in
% question so we need to do some checkups on which characters are
-% output by |\token_to_meaning:N|. As usual, these characters have
+% output by \cs{token_to_meaning:N}. As usual, these characters have
% catcode 12 so we must do some serious substitutions in the code
% below\dots
% \begin{macrocode}
@@ -1613,23 +1550,23 @@
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_chardef:N #1 { p , T , F , TF }
{
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_chardef_aux:w
+ \exp_after:wN \@@_if_chardef:w
\token_to_meaning:N #1 CHAR" \q_stop
}
{ \token_to_str:N \char }
}
\prg_new_conditional:Npnn \token_if_mathchardef:N #1 { p , T , F , TF }
{
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_chardef_aux:w
+ \exp_after:wN \@@_if_chardef:w
\token_to_meaning:N #1 CHAR" \q_stop
}
{ \token_to_str:N \mathchar }
}
- \cs_new:Npn \token_if_chardef_aux:w #1 CHAR" #2 \q_stop { #1 CHAR }
+ \cs_new:Npn \@@_if_chardef:w #1 CHAR" #2 \q_stop { #1 CHAR }
% \end{macrocode}
%
% Dim registers are a little more difficult since their \tn{meaning}
@@ -1644,16 +1581,16 @@
\if_meaning:w \tex_dimendef:D #1
\prg_return_false:
\else:
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_dim_register_aux:w
+ \exp_after:wN \@@_if_dim_register:w
\token_to_meaning:N #1 ZIMEX \q_stop
}
{ \token_to_str:N \ }
\fi:
\fi:
}
- \cs_new:Npn \token_if_dim_register_aux:w #1 ZIMEX #2 \q_stop { #1 ~ }
+ \cs_new:Npn \@@_if_dim_register:w #1 ZIMEX #2 \q_stop { #1 ~ }
% \end{macrocode}
% Integer registers are one step harder since constants are implemented
% differently from variables, and we also have to take care of the
@@ -1671,9 +1608,9 @@
\if_meaning:w \tex_countdef:D #1
\prg_return_false:
\else:
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_int_register_aux:w
+ \exp_after:wN \@@_if_int_register:w
\token_to_meaning:N #1 COUXY \q_stop
}
{ \token_to_str:N \ }
@@ -1682,7 +1619,7 @@
% }
% }
}
- \cs_new:Npn \token_if_int_register_aux:w #1 COUXY #2 \q_stop { #1 ~ }
+ \cs_new:Npn \@@_if_int_register:w #1 COUXY #2 \q_stop { #1 ~ }
% \end{macrocode}
% Muskip registers are done the same way as the dimension registers.
% \begin{macrocode}
@@ -1694,16 +1631,16 @@
\if_meaning:w \tex_muskipdef:D #1
\prg_return_false:
\else:
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_muskip_register_aux:w
+ \exp_after:wN \@@_if_muskip_register:w
\token_to_meaning:N #1 MUSKIP \q_stop
}
{ \token_to_str:N \ }
\fi:
\fi:
}
- \cs_new:Npn \token_if_muskip_register_aux:w #1 MUSKIP #2 \q_stop { #1 ~ }
+ \cs_new:Npn \@@_if_muskip_register:w #1 MUSKIP #2 \q_stop { #1 ~ }
% \end{macrocode}
% Skip registers.
% \begin{macrocode}
@@ -1715,16 +1652,16 @@
\if_meaning:w \tex_skipdef:D #1
\prg_return_false:
\else:
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_skip_register_aux:w
+ \exp_after:wN \@@_if_skip_register:w
\token_to_meaning:N #1 SKIP \q_stop
}
{ \token_to_str:N \ }
\fi:
\fi:
}
- \cs_new:Npn \token_if_skip_register_aux:w #1 SKIP #2 \q_stop { #1 ~ }
+ \cs_new:Npn \@@_if_skip_register:w #1 SKIP #2 \q_stop { #1 ~ }
% \end{macrocode}
% Toks registers.
% \begin{macrocode}
@@ -1736,39 +1673,39 @@
\if_meaning:w \tex_toksdef:D #1
\prg_return_false:
\else:
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_toks_register_aux:w
+ \exp_after:wN \@@_if_toks_register:w
\token_to_meaning:N #1 YOKS \q_stop
}
{ \token_to_str:N \ }
\fi:
\fi:
}
- \cs_new:Npn \token_if_toks_register_aux:w #1 YOKS #2 \q_stop { #1 ~ }
+ \cs_new:Npn \@@_if_toks_register:w #1 YOKS #2 \q_stop { #1 ~ }
% \end{macrocode}
% Protected macros.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_protected_macro:N #1
{ p , T , F , TF }
{
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_protected_macro_aux:w
+ \exp_after:wN \@@_if_protected_macro:w
\token_to_meaning:N #1 PROYECYEZ~MACRO \q_stop
}
{ \token_to_str:N \ }
}
- \cs_new:Npn \token_if_protected_macro_aux:w
+ \cs_new:Npn \@@_if_protected_macro:w
#1 PROYECYEZ~MACRO #2 \q_stop { #1 ~ }
% \end{macrocode}
% Long macros and protected long macros share an auxiliary.
% \begin{macrocode}
\prg_new_conditional:Npnn \token_if_long_macro:N #1 { p , T , F , TF }
{
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_long_macro_aux:w
+ \exp_after:wN \@@_if_long_macro:w
\token_to_meaning:N #1 LOXG~MACRO \q_stop
}
{ \token_to_str:N \ }
@@ -1776,16 +1713,16 @@
\prg_new_conditional:Npnn \token_if_protected_long_macro:N #1
{ p , T , F , TF }
{
- \str_if_eq_return:xx
+ \__str_if_eq_x_return:nn
{
- \exp_after:wN \token_if_long_macro_aux:w
+ \exp_after:wN \@@_if_long_macro:w
\token_to_meaning:N #1 LOXG~MACRO \q_stop
}
{ \token_to_str:N \protected \token_to_str:N \ }
}
- \cs_new:Npn \token_if_long_macro_aux:w #1 LOXG~MACRO #2 \q_stop { #1 ~ }
+ \cs_new:Npn \@@_if_long_macro:w #1 LOXG~MACRO #2 \q_stop { #1 ~ }
% \end{macrocode}
-% Finally the |\tl_to_lowercase:n| ends!
+% Finally the \cs{tl_to_lowercase:n} ends!
% \begin{macrocode}
}
% \end{macrocode}
@@ -1793,12 +1730,12 @@
% \end{macro}
%
% \begin{macro}[pTF]{\token_if_primitive:N}
-% \begin{macro}[aux]{\token_if_primitive_aux:NNw,
-% \token_if_primitive_aux_space:w,
-% \token_if_primitive_aux_nullfont:N,
-% \token_if_primitive_aux_loop:N,
-% \token_if_primitive_auxii:Nw,
-% \token_if_primitive_aux_undefined:N}
+% \begin{macro}[aux]{\@@_if_primitive:NNw,
+% \@@_if_primitive_space:w,
+% \@@_if_primitive_nullfont:N,
+% \@@_if_primitive_loop:N,
+% \@@_if_primitive:Nw,
+% \@@_if_primitive_undefined:N}
%^^A See http://groups.google.com/group/comp.text.tex/browse_thread/thread/0a72666873f8753d#
%
% We filter out macros first, because they cause endless trouble later
@@ -1857,19 +1794,19 @@
\token_if_macro:NTF #1
\prg_return_false:
{
- \exp_after:wN \token_if_primitive_aux:NNw
+ \exp_after:wN \@@_if_primitive:NNw
\token_to_meaning:N #1 ; ; ; \q_stop #1
}
}
- \cs_new:Npn \token_if_primitive_aux:NNw #1#2 #3 ; #4 \q_stop
+ \cs_new:Npn \@@_if_primitive:NNw #1#2 #3 ; #4 \q_stop
{
- \tl_if_empty:oTF { \token_if_primitive_aux_space:w #3 ~ }
- { \token_if_primitive_aux_loop:N #3 ; \q_stop }
- { \token_if_primitive_aux_nullfont:N }
+ \tl_if_empty:oTF { \@@_if_primitive_space:w #3 ~ }
+ { \@@_if_primitive_loop:N #3 ; \q_stop }
+ { \@@_if_primitive_nullfont:N }
}
}
-\cs_new:Npn \token_if_primitive_aux_space:w #1 ~ { }
-\cs_new:Npn \token_if_primitive_aux_nullfont:N #1
+\cs_new:Npn \@@_if_primitive_space:w #1 ~ { }
+\cs_new:Npn \@@_if_primitive_nullfont:N #1
{
\if_meaning:w \tex_nullfont:D #1
\prg_return_true:
@@ -1877,25 +1814,25 @@
\prg_return_false:
\fi:
}
-\cs_new:Npn \token_if_primitive_aux_loop:N #1
+\cs_new:Npn \@@_if_primitive_loop:N #1
{
- \if_num:w `#1 < \c_token_A_int %
- \exp_after:wN \token_if_primitive_auxii:Nw
+ \if_int_compare:w `#1 < \c_token_A_int %
+ \exp_after:wN \@@_if_primitive:Nw
\exp_after:wN #1
\else:
- \exp_after:wN \token_if_primitive_aux_loop:N
+ \exp_after:wN \@@_if_primitive_loop:N
\fi:
}
-\cs_new:Npn \token_if_primitive_auxii:Nw #1 #2 \q_stop
+\cs_new:Npn \@@_if_primitive:Nw #1 #2 \q_stop
{
\if:w : #1
- \exp_after:wN \token_if_primitive_aux_undefined:N
+ \exp_after:wN \@@_if_primitive_undefined:N
\else:
\prg_return_false:
\exp_after:wN \use_none:n
\fi:
}
-\cs_new:Npn \token_if_primitive_aux_undefined:N #1
+\cs_new:Npn \@@_if_primitive_undefined:N #1
{
\if_cs_exist:N #1
\prg_return_true:
@@ -1908,6 +1845,10 @@
% \end{macro}
%
% \subsection{Peeking ahead at the next token}
+%
+% \begin{macrocode}
+%<@@=peek>
+% \end{macrocode}
%
% Peeking ahead is implemented using a two part mechanism. The
% outer level provides a defined interface to the lower level material.
@@ -1930,35 +1871,35 @@
% \end{variable}
% \end{variable}
%
-% \begin{variable}{\l_peek_search_token}
+% \begin{variable}{\l_@@_search_token}
% The token to search for as an implicit token:
-% \emph{cf.}~\cs{l_peek_search_tl}.
+% \emph{cf.}~\cs{l_@@_search_tl}.
% \begin{macrocode}
-\cs_new_eq:NN \l_peek_search_token ?
+\cs_new_eq:NN \l_@@_search_token ?
% \end{macrocode}
% \end{variable}
%
-% \begin{variable}{\l_peek_search_tl}
+% \begin{variable}{\l_@@_search_tl}
% The token to search for as an explicit token:
-% \emph{cf.}~\cs{l_peek_search_token}.
+% \emph{cf.}~\cs{l_@@_search_token}.
% \begin{macrocode}
-\tl_new:N \l_peek_search_tl
+\tl_new:N \l_@@_search_tl
% \end{macrocode}
% \end{variable}
%
% \begin{macro}[aux]
-% {\peek_true:w, \peek_true_aux:w, \peek_false:w, \peek_tmp:w}
+% {\@@_true:w, \@@_true_aux:w, \@@_false:w, \@@_tmp:w}
% Functions used by the branching and space-stripping code.
% \begin{macrocode}
-\cs_new_nopar:Npn \peek_true:w { }
-\cs_new_nopar:Npn \peek_true_aux:w { }
-\cs_new_nopar:Npn \peek_false:w { }
-\cs_new:Npn \peek_tmp:w { }
+\cs_new_nopar:Npn \@@_true:w { }
+\cs_new_nopar:Npn \@@_true_aux:w { }
+\cs_new_nopar:Npn \@@_false:w { }
+\cs_new:Npn \@@_tmp:w { }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\peek_after:Nw}
-% \begin{macro}{\peek_after:Nw}
+% \begin{macro}{\peek_gafter:Nw}
% Simple wrappers for \tn{futurelet}: no arguments absorbed
% here.
% \begin{macrocode}
@@ -1970,34 +1911,34 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux]{\peek_true_remove:w}
+% \begin{macro}[aux]{\@@_true_remove:w}
% A function to remove the next token and then regain control.
% \begin{macrocode}
-\cs_new_protected:Npn \peek_true_remove:w
+\cs_new_protected:Npn \@@_true_remove:w
{
\group_align_safe_end:
- \tex_afterassignment:D \peek_true_aux:w
- \cs_set_eq:NN \peek_tmp:w
+ \tex_afterassignment:D \@@_true_aux:w
+ \cs_set_eq:NN \@@_tmp:w
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[TF]{\peek_token_generic:NN}
+% \begin{macro}[TF]{\@@_token_generic:NN}
% The generic function stores the test token in both implicit and
% explicit modes, and the \texttt{true} and \texttt{false} code as
% token lists, more or less. The two branches have to be absorbed here
% as the input stream needs to be cleared for the peek function itself.
% \begin{macrocode}
-\cs_new_protected:Npn \peek_token_generic:NNTF #1#2#3#4
+\cs_new_protected:Npn \@@_token_generic:NNTF #1#2#3#4
{
- \cs_set_eq:NN \l_peek_search_token #2
- \tl_set:Nn \l_peek_search_tl {#2}
- \cs_set_nopar:Npx \peek_true:w
+ \cs_set_eq:NN \l_@@_search_token #2
+ \tl_set:Nn \l_@@_search_tl {#2}
+ \cs_set_nopar:Npx \@@_true:w
{
\exp_not:N \group_align_safe_end:
\exp_not:n {#3}
}
- \cs_set_nopar:Npx \peek_false:w
+ \cs_set_nopar:Npx \@@_false:w
{
\exp_not:N \group_align_safe_end:
\exp_not:n {#4}
@@ -2005,24 +1946,24 @@
\group_align_safe_begin:
\peek_after:Nw #1
}
-\cs_new_protected:Npn \peek_token_generic:NNT #1#2#3
- { \peek_token_generic:NNTF #1 #2 {#3} { } }
-\cs_new_protected:Npn \peek_token_generic:NNF #1#2#3
- { \peek_token_generic:NNTF #1 #2 { } {#3} }
+\cs_new_protected:Npn \@@_token_generic:NNT #1#2#3
+ { \@@_token_generic:NNTF #1 #2 {#3} { } }
+\cs_new_protected:Npn \@@_token_generic:NNF #1#2#3
+ { \@@_token_generic:NNTF #1 #2 { } {#3} }
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}[TF]{\peek_token_remove_generic:NN}
+% \begin{macro}[TF]{\@@_token_remove_generic:NN}
% For token removal there needs to be a call to the auxiliary
% function which does the work.
% \begin{macrocode}
-\cs_new_protected:Npn \peek_token_remove_generic:NNTF #1#2#3#4
+\cs_new_protected:Npn \@@_token_remove_generic:NNTF #1#2#3#4
{
- \cs_set_eq:NN \l_peek_search_token #2
- \tl_set:Nn \l_peek_search_tl {#2}
- \cs_set_eq:NN \peek_true:w \peek_true_remove:w
- \cs_set_nopar:Npx \peek_true_aux:w { \exp_not:n {#3} }
- \cs_set_nopar:Npx \peek_false:w
+ \cs_set_eq:NN \l_@@_search_token #2
+ \tl_set:Nn \l_@@_search_tl {#2}
+ \cs_set_eq:NN \@@_true:w \@@_true_remove:w
+ \cs_set_nopar:Npx \@@_true_aux:w { \exp_not:n {#3} }
+ \cs_set_nopar:Npx \@@_false:w
{
\exp_not:N \group_align_safe_end:
\exp_not:n {#4}
@@ -2030,45 +1971,45 @@
\group_align_safe_begin:
\peek_after:Nw #1
}
-\cs_new_protected:Npn \peek_token_remove_generic:NNT #1#2#3
- { \peek_token_remove_generic:NNTF #1 #2 {#3} { } }
-\cs_new_protected:Npn \peek_token_remove_generic:NNF #1#2#3
- { \peek_token_remove_generic:NNTF #1 #2 { } {#3} }
+\cs_new_protected:Npn \@@_token_remove_generic:NNT #1#2#3
+ { \@@_token_remove_generic:NNTF #1 #2 {#3} { } }
+\cs_new_protected:Npn \@@_token_remove_generic:NNF #1#2#3
+ { \@@_token_remove_generic:NNTF #1 #2 { } {#3} }
% \end{macrocode}
% \end{macro}
%
% \begin{macro}
-% {\peek_execute_branches_catcode:, \peek_execute_branches_meaning:}
+% {\@@_execute_branches_catcode:, \@@_execute_branches_meaning:}
% The category code and meaning tests are straight forward.
% \begin{macrocode}
-\cs_new_nopar:Npn \peek_execute_branches_catcode:
+\cs_new_nopar:Npn \@@_execute_branches_catcode:
{
\if_catcode:w
- \exp_not:N \l_peek_token \exp_not:N \l_peek_search_token
- \exp_after:wN \peek_true:w
+ \exp_not:N \l_peek_token \exp_not:N \l_@@_search_token
+ \exp_after:wN \@@_true:w
\else:
- \exp_after:wN \peek_false:w
+ \exp_after:wN \@@_false:w
\fi:
}
-\cs_new_nopar:Npn \peek_execute_branches_meaning:
+\cs_new_nopar:Npn \@@_execute_branches_meaning:
{
- \if_meaning:w \l_peek_token \l_peek_search_token
- \exp_after:wN \peek_true:w
+ \if_meaning:w \l_peek_token \l_@@_search_token
+ \exp_after:wN \@@_true:w
\else:
- \exp_after:wN \peek_false:w
+ \exp_after:wN \@@_false:w
\fi:
}
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\peek_execute_branches_charcode:}
-% \begin{macro}[aux]{\peek_execute_branches_charcode:NN}
+% \begin{macro}{\@@_execute_branches_charcode:}
+% \begin{macro}[aux]{\@@_execute_branches_charcode:NN}
% First the character code test there is a need to worry about \TeX{}
% grabbing brace group or skipping spaces. These are all tested for
% using a category code check before grabbing what must be a real
% single token and doing the comparison.
% \begin{macrocode}
-\cs_new_nopar:Npn \peek_execute_branches_charcode:
+\cs_new_nopar:Npn \@@_execute_branches_charcode:
{
\bool_if:nTF
{
@@ -2076,18 +2017,18 @@
|| \token_if_eq_catcode_p:NN \l_peek_token \c_group_end_token
|| \token_if_eq_meaning_p:NN \l_peek_token \c_space_token
}
- { \peek_false:w }
+ { \@@_false:w }
{
- \exp_after:wN \peek_execute_branches_charcode_aux:NN
- \l_peek_search_tl
+ \exp_after:wN \@@_execute_branches_charcode_aux:NN
+ \l_@@_search_tl
}
}
-\cs_new:Npn \peek_execute_branches_charcode_aux:NN #1#2
+\cs_new:Npn \@@_execute_branches_charcode_aux:NN #1#2
{
\if:w \exp_not:N #1 \exp_not:N #2
- \exp_after:wN \peek_true:w
+ \exp_after:wN \@@_true:w
\else:
- \exp_after:wN \peek_false:w
+ \exp_after:wN \@@_false:w
\fi:
#2
}
@@ -2095,46 +2036,46 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\peek_ignore_spaces_execute_branches:}
-% \begin{macro}[aux]{\peek_ignore_spaces_execute_branches_aux:}
+% \begin{macro}{\@@_ignore_spaces_execute_branches:}
+% \begin{macro}[aux]{\@@_ignore_spaces_execute_branches_aux:}
% This function removes one token at a time with a mechanism that can
% be applied to things other than spaces.
% \begin{macrocode}
-\cs_new_protected_nopar:Npn \peek_ignore_spaces_execute_branches:
+\cs_new_protected_nopar:Npn \@@_ignore_spaces_execute_branches:
{
\token_if_eq_meaning:NNTF \l_peek_token \c_space_token
{
- \tex_afterassignment:D \peek_ignore_spaces_execute_branches_aux:
- \cs_set_eq:NN \peek_tmp:w
+ \tex_afterassignment:D \@@_ignore_spaces_execute_branches_aux:
+ \cs_set_eq:NN \@@_tmp:w
}
- { \peek_execute_branches: }
+ { \@@_execute_branches: }
}
-\cs_new_protected_nopar:Npn \peek_ignore_spaces_execute_branches_aux:
- { \peek_after:Nw \peek_ignore_spaces_execute_branches: }
+\cs_new_protected_nopar:Npn \@@_ignore_spaces_execute_branches_aux:
+ { \peek_after:Nw \@@_ignore_spaces_execute_branches: }
% \end{macrocode}
% \end{macro}
% \end{macro}
%
-% \begin{macro}[aux]{\peek_def:nnnn}
-% \begin{macro}[aux]{\peek_def_aux:nnnnn}
+% \begin{macro}[aux]{\@@_def:nnnn}
+% \begin{macro}[aux]{\@@_def:nnnnn}
% The public functions themselves cannot be defined using
% \cs{prg_new_conditional:Npnn} and so a couple of auxiliary functions
% are used. As a result, everything is done inside a group. As a result
% things are a bit complicated.
% \begin{macrocode}
\group_begin:
- \cs_set:Npn \peek_def:nnnn #1#2#3#4
+ \cs_set:Npn \@@_def:nnnn #1#2#3#4
{
- \peek_def_aux:nnnnn {#1} {#2} {#3} {#4} { TF }
- \peek_def_aux:nnnnn {#1} {#2} {#3} {#4} { T }
- \peek_def_aux:nnnnn {#1} {#2} {#3} {#4} { F }
+ \@@_def:nnnnn {#1} {#2} {#3} {#4} { TF }
+ \@@_def:nnnnn {#1} {#2} {#3} {#4} { T }
+ \@@_def:nnnnn {#1} {#2} {#3} {#4} { F }
}
- \cs_set:Npn \peek_def_aux:nnnnn #1#2#3#4#5
+ \cs_set:Npn \@@_def:nnnnn #1#2#3#4#5
{
\cs_new_nopar:cpx { #1 #5 }
{
\tl_if_empty:nF {#2}
- { \exp_not:n { \cs_set_eq:NN \peek_execute_branches: #2 } }
+ { \exp_not:n { \cs_set_eq:NN \@@_execute_branches: #2 } }
\exp_not:c { #3 #5 }
\exp_not:n {#4}
}
@@ -2150,22 +2091,22 @@
% With everything in place the definitions can take place. First for
% category codes.
% \begin{macrocode}
- \peek_def:nnnn { peek_catcode:N }
+ \@@_def:nnnn { peek_catcode:N }
{ }
- { peek_token_generic:NN }
- { \peek_execute_branches_catcode: }
- \peek_def:nnnn { peek_catcode_ignore_spaces:N }
- { \peek_execute_branches_catcode: }
- { peek_token_generic:NN }
- { \peek_ignore_spaces_execute_branches: }
- \peek_def:nnnn { peek_catcode_remove:N }
+ { @@_token_generic:NN }
+ { \@@_execute_branches_catcode: }
+ \@@_def:nnnn { peek_catcode_ignore_spaces:N }
+ { \@@_execute_branches_catcode: }
+ { @@_token_generic:NN }
+ { \@@_ignore_spaces_execute_branches: }
+ \@@_def:nnnn { peek_catcode_remove:N }
{ }
- { peek_token_remove_generic:NN }
- { \peek_execute_branches_catcode: }
- \peek_def:nnnn { peek_catcode_remove_ignore_spaces:N }
- { \peek_execute_branches_catcode: }
- { peek_token_remove_generic:NN }
- { \peek_ignore_spaces_execute_branches: }
+ { @@_token_remove_generic:NN }
+ { \@@_execute_branches_catcode: }
+ \@@_def:nnnn { peek_catcode_remove_ignore_spaces:N }
+ { \@@_execute_branches_catcode: }
+ { @@_token_remove_generic:NN }
+ { \@@_ignore_spaces_execute_branches: }
% \end{macrocode}
% \end{macro}
% \begin{macro}[TF]
@@ -2175,22 +2116,22 @@
% }
% Then for character codes.
% \begin{macrocode}
- \peek_def:nnnn { peek_charcode:N }
+ \@@_def:nnnn { peek_charcode:N }
{ }
- { peek_token_generic:NN }
- { \peek_execute_branches_charcode: }
- \peek_def:nnnn { peek_charcode_ignore_spaces:N }
- { \peek_execute_branches_charcode: }
- { peek_token_generic:NN }
- { \peek_ignore_spaces_execute_branches: }
- \peek_def:nnnn { peek_charcode_remove:N }
+ { @@_token_generic:NN }
+ { \@@_execute_branches_charcode: }
+ \@@_def:nnnn { peek_charcode_ignore_spaces:N }
+ { \@@_execute_branches_charcode: }
+ { @@_token_generic:NN }
+ { \@@_ignore_spaces_execute_branches: }
+ \@@_def:nnnn { peek_charcode_remove:N }
{ }
- { peek_token_remove_generic:NN }
- { \peek_execute_branches_charcode: }
- \peek_def:nnnn { peek_charcode_remove_ignore_spaces:N }
- { \peek_execute_branches_charcode: }
- { peek_token_remove_generic:NN }
- { \peek_ignore_spaces_execute_branches: }
+ { @@_token_remove_generic:NN }
+ { \@@_execute_branches_charcode: }
+ \@@_def:nnnn { peek_charcode_remove_ignore_spaces:N }
+ { \@@_execute_branches_charcode: }
+ { @@_token_remove_generic:NN }
+ { \@@_ignore_spaces_execute_branches: }
% \end{macrocode}
% \end{macro}
% \begin{macro}[TF]
@@ -2201,22 +2142,22 @@
% Finally for meaning, with the group closed to remove the temporary
% definition functions.
% \begin{macrocode}
- \peek_def:nnnn { peek_meaning:N }
+ \@@_def:nnnn { peek_meaning:N }
{ }
- { peek_token_generic:NN }
- { \peek_execute_branches_meaning: }
- \peek_def:nnnn { peek_meaning_ignore_spaces:N }
- { \peek_execute_branches_meaning: }
- { peek_token_generic:NN }
- { \peek_ignore_spaces_execute_branches: }
- \peek_def:nnnn { peek_meaning_remove:N }
+ { @@_token_generic:NN }
+ { \@@_execute_branches_meaning: }
+ \@@_def:nnnn { peek_meaning_ignore_spaces:N }
+ { \@@_execute_branches_meaning: }
+ { @@_token_generic:NN }
+ { \@@_ignore_spaces_execute_branches: }
+ \@@_def:nnnn { peek_meaning_remove:N }
{ }
- { peek_token_remove_generic:NN }
- { \peek_execute_branches_meaning: }
- \peek_def:nnnn { peek_meaning_remove_ignore_spaces:N }
- { \peek_execute_branches_meaning: }
- { peek_token_remove_generic:NN }
- { \peek_ignore_spaces_execute_branches: }
+ { @@_token_remove_generic:NN }
+ { \@@_execute_branches_meaning: }
+ \@@_def:nnnn { peek_meaning_remove_ignore_spaces:N }
+ { \@@_execute_branches_meaning: }
+ { @@_token_remove_generic:NN }
+ { \@@_ignore_spaces_execute_branches: }
\group_end:
% \end{macrocode}
% \end{macro}
@@ -2226,7 +2167,7 @@
% \begin{macro}{\token_get_prefix_spec:N}
% \begin{macro}{\token_get_arg_spec:N}
% \begin{macro}{\token_get_replacement_spec:N}
-% \begin{macro}[aux]{\token_get_prefix_arg_replacement_aux:wN}
+% \begin{macro}[aux]{\@@_get_prefix_arg_replacement:wN}
% We sometimes want to test if a
% control sequence can be expanded to reveal a hidden
% value. However, we cannot just expand the macro blindly as it may
@@ -2234,18 +2175,18 @@
% these functions to pick either the prefix(es), the argument
% specification, or the replacement text from a macro. All of this
% information is returned as characters with catcode~$12$. If the
-% token in question isn't a macro, the token |\scan_stop:| is
+% token in question isn't a macro, the token \cs{scan_stop:} is
% returned instead.
% \begin{macrocode}
\exp_args:Nno \use:nn
- { \cs_new:Npn \token_get_prefix_arg_replacement_aux:wN #1 }
+ { \cs_new:Npn \@@_get_prefix_arg_replacement:wN #1 }
{ \tl_to_str:n { macro : } #2 -> #3 \q_stop #4 }
{ #4 {#1} {#2} {#3} }
\cs_new:Npn \token_get_prefix_spec:N #1
{
\token_if_macro:NTF #1
{
- \exp_after:wN \token_get_prefix_arg_replacement_aux:wN
+ \exp_after:wN \@@_get_prefix_arg_replacement:wN
\token_to_meaning:N #1 \q_stop \use_i:nnn
}
{ \scan_stop: }
@@ -2254,7 +2195,7 @@
{
\token_if_macro:NTF #1
{
- \exp_after:wN \token_get_prefix_arg_replacement_aux:wN
+ \exp_after:wN \@@_get_prefix_arg_replacement:wN
\token_to_meaning:N #1 \q_stop \use_ii:nnn
}
{ \scan_stop: }
@@ -2263,7 +2204,7 @@
{
\token_if_macro:NTF #1
{
- \exp_after:wN \token_get_prefix_arg_replacement_aux:wN
+ \exp_after:wN \@@_get_prefix_arg_replacement:wN
\token_to_meaning:N #1 \q_stop \use_iii:nnn
}
{ \scan_stop: }
@@ -2274,66 +2215,6 @@
% \end{macro}
% \end{macro}
%
-% \subsection{Experimental token functions}
-%
-% \begin{macro}{\char_set_active:Npn,\char_set_active:Npx}
-% \begin{macro}{\char_set_active:Npn,\char_set_active:Npx}
-% \begin{macro}{\char_set_active_eq:NN,\char_gset_active_eq:NN}
-% \begin{macrocode}
-\group_begin:
- \char_set_catcode_active:N \^^@
- \cs_set:Npn \char_tmp:NN #1#2
- {
- \cs_new:Npn #1 ##1
- {
- \char_set_catcode_active:n { `##1 }
- \group_begin:
- \char_set_lccode:nn { `\^^@ } { `##1 }
- \tl_to_lowercase:n { \group_end: #2 ^^@ }
- }
- }
- \char_tmp:NN \char_set_active:Npn \cs_set:Npn
- \char_tmp:NN \char_set_active:Npx \cs_set:Npx
- \char_tmp:NN \char_gset_active:Npn \cs_gset:Npn
- \char_tmp:NN \char_gset_active:Npx \cs_gset:Npx
- \char_tmp:NN \char_set_active_eq:NN \cs_set_eq:NN
- \char_tmp:NN \char_gset_active_eq:NN \cs_gset_eq:NN
-\group_end:
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[TF]{\peek_N_type:}
-% \begin{macro}{\peek_execute_branches_N_type:}
-% The next token is normal if it is neither a begin-group token,
-% nor an end-group token, nor a charcode-$32$ space token.
-% Note that implicit begin-group tokens, end-group tokens, and
-% spaces are also recognized as non-\texttt{N}-type.
-% Here, there is no \meta{search token}, so we feed a dummy
-% \cs{scan_stop:} to the \cs{peek_token_generic::NN} functions.
-% \begin{macrocode}
-\cs_new_protected_nopar:Npn \peek_execute_branches_N_type:
- {
- \bool_if:nTF
- {
- \token_if_eq_catcode_p:NN \l_peek_token \c_group_begin_token ||
- \token_if_eq_catcode_p:NN \l_peek_token \c_group_end_token ||
- \token_if_eq_meaning_p:NN \l_peek_token \c_space_token
- }
- { \peek_false:w }
- { \peek_true:w }
- }
-\cs_new_protected_nopar:Npn \peek_N_type:TF
- { \peek_token_generic:NNTF \peek_execute_branches_N_type: \scan_stop: }
-\cs_new_protected_nopar:Npn \peek_N_type:T
- { \peek_token_generic:NNT \peek_execute_branches_N_type: \scan_stop: }
-\cs_new_protected_nopar:Npn \peek_N_type:F
- { \peek_token_generic:NNF \peek_execute_branches_N_type: \scan_stop: }
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
% \subsection{Deprecated functions}
%
% Deprecated on 2011-05-27, for removal by 2011-08-31.