summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel/l3skip.dtx')
-rw-r--r--Master/texmf-dist/source/latex/l3kernel/l3skip.dtx1675
1 files changed, 1675 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
new file mode 100644
index 00000000000..ecd3ca2e397
--- /dev/null
+++ b/Master/texmf-dist/source/latex/l3kernel/l3skip.dtx
@@ -0,0 +1,1675 @@
+% \iffalse meta-comment
+%
+%% File: l3skip.dtx Copyright (C) 2004-2011 Frank Mittelbach, The LaTeX3 Project
+%%
+%% It may be distributed and/or modified under the conditions of the
+%% LaTeX Project Public License (LPPL), either version 1.3c of this
+%% license or (at your option) any later version. The latest version
+%% of this license is in the file
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This file is part of the "expl3 bundle" (The Work in LPPL)
+%% and all files in that bundle must be distributed together.
+%%
+%% The released version of this bundle is available from CTAN.
+%%
+%% -----------------------------------------------------------------------
+%%
+%% The development version of the bundle can be found at
+%%
+%% http://www.latex-project.org/svnroot/experimental/trunk/
+%%
+%% for those people who are interested.
+%%
+%%%%%%%%%%%
+%% NOTE: %%
+%%%%%%%%%%%
+%%
+%% Snapshots taken from the repository represent work in progress and may
+%% not work or may contain conflicting material! We therefore ask
+%% people _not_ to put them into distributions, archives, etc. without
+%% prior consultation with the LaTeX3 Project.
+%%
+%% -----------------------------------------------------------------------
+%
+%<*driver|package>
+\RequirePackage{l3names}
+\GetIdInfo$Id: l3skip.dtx 2478 2011-06-19 21:34:23Z joseph $
+ {L3 Experimental dimensions and skips}
+%</driver|package>
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+ \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \title{^^A
+% The \pkg{l3skip} package\\ Dimensions and skips^^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}
+%
+% \LaTeX3 provides two general length variables: \texttt{dim} and
+% \texttt{skip}. Lengths stored as \texttt{dim} variables have a fixed
+% length, whereas \texttt{skip} lengths have a rubber (stretch/shrink)
+% component. In addition, the \texttt{muskip} type is available for
+% use in math mode: this is a special form of \texttt{skip} where the
+% lengths involved are determined by the current math font (in
+% \texttt{mu)}. There are common features in the creation and setting of
+% length variables, but for clarity the functions are grouped by variable
+% type.
+%
+% \section{Creating and initialising \texttt{dim} variables}
+%
+% \begin{function}{\dim_new:N, \dim_new:c}
+% \begin{syntax}
+% \cs{dim_new:N} \meta{dimension}
+% \end{syntax}
+% Creates a new \meta{dimension} or raises an error if the name is
+% already taken. The declaration is global. The \meta{dimension}
+% will initially be equal to $0$\,pt.
+% \end{function}
+%
+% \begin{function}{\dim_zero:N, \dim_zero:c}
+% \begin{syntax}
+% \cs{dim_zero:N} \meta{dimension}
+% \end{syntax}
+% Sets \meta{dimension} to $0$\,pt within the scope of the current
+% \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\dim_gzero:N, \dim_gzero:c}
+% \begin{syntax}
+% \cs{dim_gzero:N} \meta{dimension}
+% \end{syntax}
+% Sets \meta{dimension} to $0$\,pt globally, \emph{i.e.}~not
+% restricted by the current \TeX{} group level.
+% \end{function}
+%
+% \section{Setting \texttt{dim} variables}
+%
+% \begin{function}{\dim_add:Nn, \dim_add:cn}
+% \begin{syntax}
+% \cs{dim_add:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Adds the result of the \meta{dimension expression} to the current
+% content of the \meta{dimension}. This assignment is local.
+% \end{function}
+%
+% \begin{function}{\dim_gadd:Nn, \dim_gadd:cn}
+% \begin{syntax}
+% \cs{dim_gadd:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Adds the result of the \meta{dimension expression} to the
+% current content of the \meta{dimension}. This assignment is global.
+% \end{function}
+%
+% \begin{function}{\dim_set:Nn, \dim_set:cn}
+% \begin{syntax}
+% \cs{dim_set:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Sets \meta{dimension} to the value of \meta{dimension expression}, which
+% must evaluate to a length with units. This assignment is
+% restricted to the current \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\dim_gset:Nn, \dim_gset:cn}
+% \begin{syntax}
+% \cs{dim_gset:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Sets \meta{dimension} to the value of \meta{dimension expression}, which
+% must evaluate to a length with units and may include a rubber
+% component (for example |1 cm plus 0.5 cm|. This assignment is
+% global and is not limited to the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+% {\dim_set_eq:NN, \dim_set_eq:cN, \dim_set_eq:Nc, \dim_set_eq:cc}
+% \begin{syntax}
+% \cs{dim_set_eq:NN} \meta{dimension1} \meta{dimension2}
+% \end{syntax}
+% Sets the content of \meta{dimension1} equal to that of
+% \meta{dimension2}. This assignment is restricted to the current
+% \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+% {\dim_gset_eq:NN, \dim_gset_eq:cN, \dim_gset_eq:Nc, \dim_gset_eq:cc}
+% \begin{syntax}
+% \cs{dim_gset_eq:NN} \meta{dimension1} \meta{dimension2}
+% \end{syntax}
+% Sets the content of \meta{dimension1} equal to that of \meta{dimension2}.
+% This assignment is global and so is not limited by the current
+% \TeX{} group level.
+% \end{function}
+%
+% \begin{function}{\dim_set_max:Nn, \dim_set_max:cn}
+% \begin{syntax}
+% \cs{dim_set_max:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Compares the current value of the \meta{dimension} with that of the
+% \meta{dimension expression}, and sets the \meta{dimension} to the
+% larger of these two value. This assignment is local to the current
+% \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\dim_gset_max:Nn, \dim_gset_max:cn}
+% \begin{syntax}
+% \cs{dim_gset_max:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Compares the current value of the \meta{dimension} with that of the
+% \meta{dimension expression}, and sets the \meta{dimension} to the
+% larger of these two value. This assignment is global.
+% \end{function}
+%
+% \begin{function}{\dim_set_min:Nn, \dim_set_min:cn}
+% \begin{syntax}
+% \cs{dim_set_min:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Compares the current value of the \meta{dimension} with that of the
+% \meta{dimension expression}, and sets the \meta{dimension} to the
+% smaller of these two value. This assignment is local to the current
+% \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\dim_gset_min:Nn, \dim_gset_min:cn}
+% \begin{syntax}
+% \cs{dim_gset_min:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Compares the current value of the \meta{dimension} with that of the
+% \meta{dimension expression}, and sets the \meta{dimension} to the
+% smaller of these two value. This assignment is global.
+% \end{function}
+%
+% \begin{function}{\dim_sub:Nn, \dim_sub:cn}
+% \begin{syntax}
+% \cs{dim_sub:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Subtracts the result of the \meta{dimension expression} to the
+% current content of the \meta{dimension}. This assignment is local.
+% \end{function}
+%
+% \begin{function}{\dim_gsub:Nn, \dim_gsub:cn}
+% \begin{syntax}
+% \cs{dim_gsub:Nn} \meta{dimension} \Arg{dimension expression}
+% \end{syntax}
+% Subtracts the result of the \meta{dimension expression} to the
+% current content of the \meta{dimension}. This assignment is global.
+% \end{function}
+%
+% \section{Utilities for dimension calculations}
+%
+% \begin{function}[EXP]{\dim_ratio:nn}
+% \begin{syntax}
+% \cs{dim_ratio:nn} \Arg{dimexpr1} \Arg{dimexpr2}
+% \end{syntax}
+% Parses the two \meta{dimension expressions} and converts the ratio of
+% the two to a form suitable for use inside a \meta{dimension expression}.
+% This ratio is then left in the input stream, allowing syntax such as
+% \begin{verbatim}
+% \dim_set:Nn \l_my_dim
+% { 10 pt * \dim_ratio:nn { 5 pt } { 10 pt } }
+% \end{verbatim}
+% The output of \cs{dim_ratio:nn} on full expansion is a ration expression
+% between two integers, with all distances converted to scaled points.
+% Thus
+% \begin{verbatim}
+% \tl_set:Nx \l_my_tl { \dim_ratio:nn { 5 pt } { 10 pt } }
+% \tl_show:N \l_my_tl
+% \end{verbatim}
+% will display |327680/655360| on the terminal.
+% \end{function}
+%
+% \section{Dimension expression conditionals}
+%
+% \begin{function}[EXP,pTF]{\dim_compare:nNn}
+% \begin{syntax}
+% \cs{dim_compare_p:nNn}
+% ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2}
+% \cs{dim_compare:nNnTF}
+% ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% This function first evaluates each of the \meta{dimension expressions}
+% as described for \cs{dim_eval:n}. The two results are then
+% compared using the \meta{relation}:
+% \begin{center}
+% \begin{tabular}{ll}
+% Equal & |=| \\
+% Greater than & |>| \\
+% Less than & |<| \\
+% \end{tabular}
+% \end{center}
+% The branching versions then leave either \meta{true code} or
+% \meta{false code} in the input stream, as appropriate to the truth
+% of the test and the variant of the function chosen. The logical
+% truth of the test is left in the input stream by the predicate
+% version.
+% \end{function}
+%
+% \begin{function}[EXP,pTF]{\dim_compare:n}
+% \begin{syntax}
+% \cs{dim_compare_p:n}
+% ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \}
+% \cs{dim_compare:nTF}
+% ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% This function first evaluates each of the \meta{dimension expressions}
+% as described for \cs{dim_eval:n}. The two results are then
+% compared using the \meta{relation}:
+% \begin{center}
+% \begin{tabular}{ll}
+% Equal & |=| or |==| \\
+% Greater than or equal to & |=>| \\
+% Greater than & |>| \\
+% Less than or equal to & |=<| \\
+% Less than & |<| \\
+% Not equal & |!=| \\
+% \end{tabular}
+% \end{center}
+% The branching versions then leave either \meta{true code} or
+% \meta{false code} in the input stream, as appropriate to the truth
+% of the test and the variant of the function chosen. The logical
+% truth of the test is left in the input stream by the predicate
+% version.
+% \end{function}
+%
+% \section{Dimension expression loops}
+%
+% \begin{function}[EXP]{\dim_do_while:nNnn}
+% \begin{syntax}
+% \cs{dim_do_while:nNnn}
+% ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2} \Arg{code}
+% \end{syntax}
+% Evaluates the relationship between the two \meta{dimension expressions}
+% as described for \cs{dim_compare:nNnTF}, and then places the
+% \meta{code} in the input stream if the \meta{relation} is
+% \texttt{true}. After the \meta{code} has been processed by \TeX{} the
+% test will be repeated, and a loop will occur until the test is
+% \texttt{false}.
+% \end{function}
+%
+% \begin{function}[EXP]{\dim_do_until:nNnn}
+% \begin{syntax}
+% \cs{dim_do_until:nNnn}
+% ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2} \Arg{code}
+% \end{syntax}
+% Evaluates the relationship between the two \meta{dimension expressions}
+% as described for \cs{dim_compare:nNnTF}, and then places the
+% \meta{code} in the input stream if the \meta{relation} is
+% \texttt{false}. After the \meta{code} has been processed by \TeX{} the
+% test will be repeated, and a loop will occur until the test is
+% \texttt{true}.
+% \end{function}
+%
+% \begin{function}[EXP]{\dim_until_do:nNnn}
+% \begin{syntax}
+% \cs{dim_until_do:nNnn}
+% ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2} \Arg{code}
+% \end{syntax}
+% Places the \meta{code} in the input stream for \TeX{} to process, and
+% then evaluates the relationship between the two
+% \meta{dimension expressions} as described for \cs{dim_compare:nNnTF}.
+% If the test is \texttt{false} then the \meta{code} will be inserted
+% into the input stream again and a loop will occur until the
+% \meta{relation} is \texttt{true}.
+% \end{function}
+%
+% \begin{function}[EXP]{\dim_while_do:nNnn}
+% \begin{syntax}
+% \cs{dim_while_do:nNnn}
+% ~~\Arg{dimexpr1} \meta{relation} \Arg{dimexpr2} \Arg{code}
+% \end{syntax}
+% Places the \meta{code} in the input stream for \TeX{} to process, and
+% then evaluates the relationship between the two
+% \meta{dimension expressions} as described for \cs{dim_compare:nNnTF}.
+% If the test is \texttt{true} then the \meta{code} will be inserted
+% into the input stream again and a loop will occur until the
+% \meta{relation} is \texttt{false}.
+% \end{function}
+%
+% \begin{function}[EXP]{\dim_do_while:nn}
+% \begin{syntax}
+% \cs{dim_do_while:nNnn}
+% ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
+% \end{syntax}
+% Evaluates the relationship between the two \meta{dimension expressions}
+% as described for \cs{dim_compare:nTF}, and then places the
+% \meta{code} in the input stream if the \meta{relation} is
+% \texttt{true}. After the \meta{code} has been processed by \TeX{} the
+% test will be repeated, and a loop will occur until the test is
+% \texttt{false}.
+% \end{function}
+%
+% \begin{function}[EXP]{\dim_do_until:nn}
+% \begin{syntax}
+% \cs{dim_do_until:nn}
+% ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
+% \end{syntax}
+% Evaluates the relationship between the two \meta{dimension expressions}
+% as described for \cs{dim_compare:nTF}, and then places the
+% \meta{code} in the input stream if the \meta{relation} is
+% \texttt{false}. After the \meta{code} has been processed by \TeX{} the
+% test will be repeated, and a loop will occur until the test is
+% \texttt{true}.
+% \end{function}
+%
+% \begin{function}[EXP]{\dim_until_do:nn}
+% \begin{syntax}
+% \cs{dim_until_do:nn}
+% ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
+% \end{syntax}
+% Places the \meta{code} in the input stream for \TeX{} to process, and
+% then evaluates the relationship between the two
+% \meta{dimension expressions} as described for \cs{dim_compare:nTF}.
+% If the test is \texttt{false} then the \meta{code} will be inserted
+% into the input stream again and a loop will occur until the
+% \meta{relation} is \texttt{true}.
+% \end{function}
+%
+% \begin{function}[EXP]{\dim_while_do:nn}
+% \begin{syntax}
+% \cs{dim_while_do:nn}
+% ~~\{ \meta{dimexpr1} \meta{relation} \meta{dimexpr2} \} \Arg{code}
+% \end{syntax}
+% Places the \meta{code} in the input stream for \TeX{} to process, and
+% then evaluates the relationship between the two
+% \meta{dimension expressions} as described for \cs{dim_compare:nTF}.
+% If the test is \texttt{true} then the \meta{code} will be inserted
+% into the input stream again and a loop will occur until the
+% \meta{relation} is \texttt{false}.
+% \end{function}
+%
+% \section{Using \texttt{dim} expressions and variables}
+%
+% \begin{function}[EXP]{\dim_eval:n}
+% \begin{syntax}
+% \cs{dim_eval:n} \Arg{dimension expression}
+% \end{syntax}
+% Evaluates the \meta{dimension expression}, expanding any
+% dimensions and token list variables within the \meta{expression}
+% to their content (without requiring \cs{dim_use:N}/\cs{tl_use:N})
+% and applying the standard mathematical rules. The result of the
+% calculation is left in the input stream as a
+% \meta{dimension denotation} after two expansions. This will be
+% expressed in points (\texttt{pt}), and will require suitable
+% termination if used in a \TeX{}-style assignment as it is \emph{not}
+% an \meta{internal dimension}.
+% \end{function}
+%
+% \begin{function}[EXP]{\dim_use:N, \dim_use:c}
+% \begin{syntax}
+% \cs{dim_use:N} \meta{dimension}
+% \end{syntax}
+% Recovers the content of a \meta{dimension} 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
+% \meta{dimension} is required (such as in the argument of
+% \cs{dim_eval:n}).
+% \begin{texnote}
+% \cs{dim_use:N} is the \TeX{} primitive \cs{the}: this is one of
+% several \LaTeX3 names for this primitive.
+% \end{texnote}
+% \end{function}
+%
+% \section{Viewing \texttt{dim} variables}
+%
+% \begin{function}{\dim_show:N, \dim_show:c}
+% \begin{syntax}
+% \cs{dim_show:N} \meta{dimension}
+% \end{syntax}
+% Displays the value of the \meta{dimension} on the terminal.
+% \end{function}
+%
+% \section{Constant dimensions}
+%
+% \begin{variable}{\c_max_dim}
+% The maximum value that can be stored as a dimension or skip (these
+% are equivalent).
+% \end{variable}
+%
+% \begin{variable}{\c_zero_dim}
+% A zero length as a dimension or a skip (these are equivalent).
+% \end{variable}
+%
+% \section{Scratch dimensions}
+%
+% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim, \l_tmpc_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
+% code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \begin{variable}{\g_tmpa_dim, \g_tmpb_dim}
+% Scratch dimension 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{Creating and initialising \texttt{skip} variables}
+%
+% \begin{function}{\skip_new:N, \skip_new:c}
+% \begin{syntax}
+% \cs{skip_new:N} \meta{skip}
+% \end{syntax}
+% Creates a new \meta{skip} or raises an error if the name is
+% already taken. The declaration is global. The \meta{skip}
+% will initially be equal to $0$\,pt.
+% \end{function}
+%
+% \begin{function}{\skip_zero:N, \skip_zero:c}
+% \begin{syntax}
+% \cs{skip_zero:N} \meta{skip}
+% \end{syntax}
+% Sets \meta{skip} to $0$\,pt within the scope of the current
+% \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\skip_gzero:N, \skip_gzero:c}
+% \begin{syntax}
+% \cs{skip_gzero:N} \meta{skip}
+% \end{syntax}
+% Sets \meta{skip} to $0$\,pt globally, \emph{i.e.}~not
+% restricted by the current \TeX{} group level.
+% \end{function}
+%
+% \section{Setting \texttt{skip} variables}
+%
+% \begin{function}{\skip_add:Nn, \skip_add:cn}
+% \begin{syntax}
+% \cs{skip_add:Nn} \meta{skip} \Arg{skip expression}
+% \end{syntax}
+% Adds the result of the \meta{skip expression} to the current
+% content of the \meta{skip}. This assignment is local.
+% \end{function}
+%
+% \begin{function}{\skip_gadd:Nn, \skip_gadd:cn}
+% \begin{syntax}
+% \cs{skip_gadd:Nn} \meta{skip} \Arg{skip expression}
+% \end{syntax}
+% Adds the result of the \meta{skip expression} to the
+% current content of the \meta{skip}. This assignment is global.
+% \end{function}
+%
+% \begin{function}{\skip_set:Nn, \skip_set:cn}
+% \begin{syntax}
+% \cs{skip_set:Nn} \meta{skip} \Arg{skip expression}
+% \end{syntax}
+% Sets \meta{skip} to the value of \meta{skip expression}, which
+% must evaluate to a length with units and may include a rubber
+% component (for example |1 cm plus 0.5 cm|. This assignment is
+% restricted to the current \TeX{} group.
+% \end{function}
+%
+% \begin{function}
+% {\skip_gset_eq:NN, \skip_gset_eq:cN, \skip_gset_eq:Nc, \skip_gset_eq:cc}
+% \begin{syntax}
+% \cs{skip_gset_eq:NN} \meta{skip1} \meta{skip2}
+% \end{syntax}
+% Sets the content of \meta{skip1} equal to that of \meta{skip2}.
+% This assignment is global and so is not limited by the current
+% \TeX{} group level.
+% \end{function}
+%
+% \begin{function}{\skip_gset:Nn, \skip_gset:cn}
+% \begin{syntax}
+% \cs{skip_gset:Nn} \meta{skip} \Arg{skip expression}
+% \end{syntax}
+% Sets \meta{skip} to the value of \meta{skip expression}, which
+% must evaluate to a length with units and may include a rubber
+% component (for example |1 cm plus 0.5 cm|. This assignment is
+% global and is not limited to the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+% {\skip_set_eq:NN, \skip_set_eq:cN, \skip_set_eq:Nc, \skip_set_eq:cc}
+% \begin{syntax}
+% \cs{skip_set_eq:NN} \meta{skip1} \meta{skip2}
+% \end{syntax}
+% Sets the content of \meta{skip1} equal to that of
+% \meta{skip2}. This assignment is restricted to the current
+% \TeX{} group level.
+% \end{function}
+%
+% \begin{function}{\skip_sub:Nn, \skip_sub:cn}
+% \begin{syntax}
+% \cs{skip_sub:Nn} \meta{skip} \Arg{skip expression}
+% \end{syntax}
+% Subtracts the result of the \meta{skip expression} to the
+% current content of the \meta{skip}. This assignment is local.
+% \end{function}
+%
+% \begin{function}{\skip_gsub:Nn, \skip_gsub:cn}
+% \begin{syntax}
+% \cs{skip_gsub:Nn} \meta{skip} \Arg{skip expression}
+% \end{syntax}
+% Subtracts the result of the \meta{skip expression} to the
+% current content of the \meta{skip}. This assignment is global.
+% \end{function}
+%
+% \section{Skip expression conditionals}
+%
+% \begin{function}[EXP,pTF]{\skip_if_eq:nn}
+% \begin{syntax}
+% \cs{skip_if_eq_p:nn}
+% ~~\Arg{skipexpr1} \Arg{skipexpr2}
+% \cs{dim_compare:nTF}
+% ~~\Arg{skipexpr1} \Arg{skipexpr2}
+% ~~\Arg{true code} \Arg{false code}
+% \end{syntax}
+% This function first evaluates each of the
+% \meta{skip expressions} as described for \cs{skip_eval:n}.
+% The two results are then compared for exact equality,
+% \emph{i.e.}~both the fixed and rubber components must be the same
+% for the test to be true. The branching versions then leave either
+% \meta{true code} or \meta{false code} in the input stream, as
+% appropriate to the truth of the test and the variant of the function
+% chosen. The logical truth of the test is left in the input stream by
+% the predicate version.
+% \end{function}
+%
+% \begin{function}[EXP,pTF]{\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).
+% The branching versions then leave either \meta{true code} or
+% \meta{false code} in the input stream, as appropriate to the truth
+% of the test and the variant of the function chosen. The logical
+% truth of the test is left in the input stream by the predicate
+% \end{function}
+%
+% \section{Using \texttt{skip} expressions and variables}
+%
+% \begin{function}[EXP]{\skip_eval:n}
+% \begin{syntax}
+% \cs{skip_eval:n} \Arg{skip expression}
+% \end{syntax}
+% Evaluates the \meta{skip expression}, expanding any skips
+% and token list variables within the \meta{expression}
+% to their content (without requiring \cs{skip_use:N}/\cs{tl_use:N})
+% and applying the standard mathematical rules. The result of the
+% calculation is left in the input stream as a \meta{glue denotation}
+% after two expansions. This will be expressed in points (\texttt{pt}),
+% and will require suitable termination if used in a \TeX{}-style
+% assignment as it is \emph{not} an \meta{internal glue}.
+% \end{function}
+%
+% \begin{function}[EXP]{\skip_use:N, \skip_use:c}
+% \begin{syntax}
+% \cs{skip_use:N} \meta{skip}
+% \end{syntax}
+% Recovers the content of a \meta{skip} 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
+% \meta{dimension} is required (such as in the argument of
+% \cs{skip_eval:n}).
+% \begin{texnote}
+% \cs{skip_use:N} is the \TeX{} primitive \cs{the}: this is one of
+% several \LaTeX3 names for this primitive.
+% \end{texnote}
+% \end{function}
+%
+% \section{Viewing \texttt{skip} variables}
+%
+% \begin{function}{\skip_show:N, \skip_show:c}
+% \begin{syntax}
+% \cs{skip_show:N} \meta{skip}
+% \end{syntax}
+% Displays the value of the \meta{skip} on the terminal.
+% \end{function}
+%
+% \section{Constant skips}
+%
+% \begin{variable}{\c_max_skip}
+% The maximum value that can be stored as a dimension or skip (these
+% are equivalent).
+% \end{variable}
+%
+% \begin{variable}{\c_zero_skip}
+% A zero length as a dimension or a skip (these are equivalent).
+% \end{variable}
+%
+% \section{Scratch skips}
+%
+% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip, \l_tmpc_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
+% code and so should only be used for short-term storage.
+% \end{variable}
+%
+% \begin{variable}{\g_tmpa_skip, \g_tmpb_skip}
+% Scratch skip 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{Creating and initialising \texttt{muskip} variables}
+%
+% \begin{function}{\muskip_new:N, \muskip_new:c}
+% \begin{syntax}
+% \cs{muskip_new:N} \meta{muskip}
+% \end{syntax}
+% Creates a new \meta{muskip} or raises an error if the name is
+% already taken. The declaration is global. The \meta{muskip}
+% will initially be equal to $0$\,mu.
+% \end{function}
+%
+% \begin{function}{\muskip_zero:N, \muskip_zero:c}
+% \begin{syntax}
+% \cs{skip_zero:N} \meta{muskip}
+% \end{syntax}
+% Sets \meta{muskip} to $0$\,mu within the scope of the current
+% \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\muskip_gzero:N, \muskip_gzero:c}
+% \begin{syntax}
+% \cs{muskip_gzero:N} \meta{muskip}
+% \end{syntax}
+% Sets \meta{muskip} to $0$\,mu globally, \emph{i.e.}~not
+% restricted by the current \TeX{} group level.
+% \end{function}
+%
+% \section{Setting \texttt{muskip} variables}
+%
+% \begin{function}{\muskip_add:Nn, \muskip_add:cn}
+% \begin{syntax}
+% \cs{muskip_add:Nn} \meta{muskip} \Arg{muskip expression}
+% \end{syntax}
+% Adds the result of the \meta{muskip expression} to the current
+% content of the \meta{muskip}. This assignment is local.
+% \end{function}
+%
+% \begin{function}{\muskip_gadd:Nn, \muskip_gadd:cn}
+% \begin{syntax}
+% \cs{muskip_gadd:Nn} \meta{muskip} \Arg{muskip expression}
+% \end{syntax}
+% Adds the result of the \meta{muskip expression} to the
+% current content of the \meta{muskip}. This assignment is global.
+% \end{function}
+%
+% \begin{function}{\muskip_set:Nn, \muskip_set:cn}
+% \begin{syntax}
+% \cs{muskip_set:Nn} \meta{muskip} \Arg{muskip expression}
+% \end{syntax}
+% Sets \meta{muskip} to the value of \meta{muskip expression}, which
+% must evaluate to a math length with units and may include a rubber
+% component (for example |1 mu plus 0.5 mu|. This assignment is
+% restricted to the current \TeX{} group.
+% \end{function}
+%
+% \begin{function}{\muskip_gset:Nn, \muskip_gset:cn}
+% \begin{syntax}
+% \cs{muskip_gset:Nn} \meta{muskip} \Arg{muskip expression}
+% \end{syntax}
+% Sets \meta{muskip} to the value of \meta{muskip expression}, which
+% must evaluate to a math length with units and may include a rubber
+% component (for example |1 mu plus 0.5 mu|. This assignment is
+% global and is not limited to the current \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+% {
+% \muskip_set_eq:NN, \muskip_set_eq:cN,
+% \muskip_set_eq:Nc, \muskip_set_eq:cc
+% }
+% \begin{syntax}
+% \cs{muskip_set_eq:NN} \meta{muskip1} \meta{muskip2}
+% \end{syntax}
+% Sets the content of \meta{muskip1} equal to that of
+% \meta{muskip2}. This assignment is restricted to the current
+% \TeX{} group level.
+% \end{function}
+%
+% \begin{function}
+% {
+% \muskip_gset_eq:NN, \muskip_gset_eq:cN,
+% \muskip_gset_eq:Nc, \muskip_gset_eq:cc
+% }
+% \begin{syntax}
+% \cs{muskip_gset_eq:NN} \meta{muskip1} \meta{muskip2}
+% \end{syntax}
+% Sets the content of \meta{muskip1} equal to that of \meta{muskip2}.
+% This assignment is global and so is not limited by the current
+% \TeX{} group level.
+% \end{function}
+%
+% \begin{function}{\muskip_sub:Nn, \muskip_sub:cn}
+% \begin{syntax}
+% \cs{muskip_sub:Nn} \meta{muskip} \Arg{muskip expression}
+% \end{syntax}
+% Subtracts the result of the \meta{muskip expression} to the
+% current content of the \meta{skip}. This assignment is local.
+% \end{function}
+%
+% \begin{function}{\muskip_gsub:Nn, \muskip_gsub:cn}
+% \begin{syntax}
+% \cs{muskip_gsub:Nn} \meta{muskip} \Arg{muskip expression}
+% \end{syntax}
+% Subtracts the result of the \meta{muskip expression} to the
+% current content of the \meta{muskip}. This assignment is global.
+% \end{function}
+%
+% \section{Using \texttt{muskip} expressions and variables}
+%
+% \begin{function}[EXP]{\muskip_eval:n}
+% \begin{syntax}
+% \cs{muskip_eval:n} \Arg{muskip expression}
+% \end{syntax}
+% Evaluates the \meta{muskip expression}, expanding any skips
+% and token list variables within the \meta{expression}
+% to their content (without requiring \cs{muskip_use:N}/\cs{tl_use:N})
+% and applying the standard mathematical rules. The result of the
+% calculation is left in the input stream as a \meta{muglue denotation}
+% after two expansions. This will be expressed in \texttt{mu},
+% and will require suitable termination if used in a \TeX{}-style
+% assignment as it is \emph{not} an \meta{internal muglue}.
+% \end{function}
+%
+% \begin{function}[EXP]{\muskip_use:N, \muskip_use:c}
+% \begin{syntax}
+% \cs{muskip_use:N} \meta{muskip}
+% \end{syntax}
+% Recovers the content of a \meta{skip} 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
+% \meta{dimension} is required (such as in the argument of
+% \cs{muskip_eval:n}).
+% \begin{texnote}
+% \cs{muskip_use:N} is the \TeX{} primitive \cs{the}: this is one of
+% several \LaTeX3 names for this primitive.
+% \end{texnote}
+% \end{function}
+%
+% \section{Inserting skips into the output}
+%
+% \begin{function}{\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 \cs{hskip} renamed.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}{\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 \cs{vskip} renamed.
+% \end{texnote}
+% \end{function}
+%
+% \section{Viewing \texttt{muskip} variables}
+%
+% \begin{function}{\muskip_show:N, \muskip_show:c}
+% \begin{syntax}
+% \cs{muskip_show:N} \meta{muskip}
+% \end{syntax}
+% Displays the value of the \meta{muskip} on the terminal.
+% \end{function}
+%
+% \section{Internal functions}
+%
+% \begin{function}{\if_dim:w}
+% \begin{syntax}
+% \cs{if_dim:w} \meta{dimen1} \meta{relation} \meta{dimen1}
+% ~~\meta{true code}
+% \cs{else:}
+% ~~\meta{false}
+% \cs{fi:}
+% \end{syntax}
+% Compare two dimensions. The \meta{relation} is one of
+% |<|, |=| or |>| with category code $12$.
+% \begin{texnote}
+% This is the \TeX{} primitive \cs{ifdim}.
+% \end{texnote}
+% \end{function}
+%
+% \begin{function}[EXP]{\dim_eval:w, \dim_eval_end:}
+% \begin{syntax}
+% \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
+% reached. The latter is gobbled by the scanner mechanism:
+% \cs{dim_eval_end:} itself is unexpandable but used correctly
+% the entire construct is expandable.
+% \begin{texnote}
+% This is the \eTeX{} primitive \cs{dimexpr}.
+% \end{texnote}
+% \end{function}
+%
+% \section{Experimental skip functions}
+%
+% \begin{function}{\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}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{\pkg{l3skip} implementation}
+%
+% \begin{macrocode}
+%<*initex|package>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*package>
+\ProvidesExplPackage
+ {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription}
+\package_check_loaded_expl:
+%</package>
+% \end{macrocode}
+%
+% \subsection{Length primitives renamed}
+%
+% \begin{macro}{\if_dim:w}
+% \begin{macro}{\dim_eval:w}
+% \begin{macro}{\dim_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
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Creating and initialising \texttt{dim} variables}
+%
+% \begin{macro}{\dim_new:N,\dim_new:c}
+% Allocating \meta{dim} registers \ldots
+% \begin{macrocode}
+%<*initex>
+\alloc_new:nnnN { dim } \c_zero \c_max_register_int \tex_dimendef:D
+%</initex>
+%<*package>
+\cs_new_protected_nopar:Npn \dim_new:N #1
+ {
+ \chk_if_free_cs:N #1
+ \newdimen #1
+ }
+%</package>
+\cs_generate_variant:Nn \dim_new:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\dim_zero:N, \dim_zero:c}
+% \begin{macro}{\dim_gzero:N, \dim_gzero:c}
+% Reset the register to zero.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \dim_zero:N #1 { #1 \c_zero_dim }
+\cs_new_protected_nopar:Npn \dim_gzero:N { \pref_global:D \dim_zero:N }
+\cs_generate_variant:Nn \dim_zero:N { c }
+\cs_generate_variant:Nn \dim_gzero:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Setting \texttt{dim} variables}
+%
+% \begin{macro}{\dim_set:Nn, \dim_set:cn}
+% \begin{macro}{\dim_gset:Nn, \dim_gset:cn}
+% Setting dimensions is easy enough.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \dim_set:Nn #1#2
+ { #1 ~ \dim_eval:w #2 \dim_eval_end: }
+\cs_new_protected_nopar:Npn \dim_gset:Nn { \pref_global:D \dim_set:Nn }
+\cs_generate_variant:Nn \dim_set:Nn { c }
+\cs_generate_variant:Nn \dim_gset:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\dim_set_eq:NN,\dim_set_eq:cN, \dim_set_eq:Nc,\dim_set_eq:cc}
+% \begin{macro}
+% {\dim_gset_eq:NN,\dim_gset_eq:cN, \dim_gset_eq:Nc,\dim_gset_eq:cc}
+% All straightforward.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \dim_set_eq:NN #1#2 { #1 = #2 }
+\cs_generate_variant:Nn \dim_set_eq:NN { c }
+\cs_generate_variant:Nn \dim_set_eq:NN { Nc , cc }
+\cs_new_protected_nopar:Npn \dim_gset_eq:NN #1#2 { \pref_global:D #1 = #2 }
+\cs_generate_variant:Nn \dim_gset_eq:NN { c }
+\cs_generate_variant:Nn \dim_gset_eq:NN { Nc , cc }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\dim_set_max:Nn, \dim_set_max:cn}
+% \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}
+% 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 #1#2
+ { \dim_compare:nNnT {#1} < {#2} { \dim_set:Nn #1 {#2} } }
+\cs_new_protected_nopar:Npn \dim_gset_max:Nn #1#2
+ { \dim_compare:nNnT {#1} < {#2} { \dim_gset:Nn #1 {#2} } }
+\cs_new_protected_nopar:Npn \dim_set_min:Nn #1#2
+ { \dim_compare:nNnT {#1} > {#2} { \dim_set:Nn #1 {#2} } }
+\cs_new_protected_nopar:Npn \dim_gset_min:Nn #1#2
+ { \dim_compare:nNnT {#1} > {#2} { \dim_gset:Nn #1 {#2} } }
+\cs_generate_variant:Nn \dim_set_max:Nn { c }
+\cs_generate_variant:Nn \dim_gset_max:Nn { c }
+\cs_generate_variant:Nn \dim_set_min:Nn { c }
+\cs_generate_variant:Nn \dim_gset_min:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\dim_add:Nn, \dim_add:cn}
+% \begin{macro}{\dim_gadd:Nn, \dim_gadd:cn}
+% \begin{macro}{\dim_sub:Nn, \dim_sub:cn}
+% \begin{macro}{\dim_gsub:Nn, \dim_gsub:cn}
+% Using |by| here deals with the (incorrect) case |\dimen123|.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \dim_add:Nn #1#2
+ { \tex_advance:D #1 by \dim_eval:w #2 \dim_eval_end: }
+\cs_new_protected_nopar:Npn \dim_gadd:Nn { \pref_global:D \dim_add:Nn }
+\cs_generate_variant:Nn \dim_add:Nn { c }
+\cs_generate_variant:Nn \dim_gadd:Nn { c }
+\cs_new_protected_nopar:Npn \dim_sub:Nn #1#2
+ { \tex_advance:D #1 by - \dim_eval:w #2 \dim_eval_end: }
+\cs_new_protected_nopar:Npn \dim_gsub:Nn { \pref_global:D \dim_sub:Nn }
+\cs_generate_variant:Nn \dim_sub:Nn { c }
+\cs_generate_variant:Nn \dim_gsub:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Utilities for dimension calculations}
+%
+% \begin{macro}{\dim_ratio:nn}
+% \begin{macro}[aux]{\dim_ratio_aux: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
+% any decimal parts.
+% \begin{macrocode}
+\cs_new_nopar:Npn \dim_ratio:nn #1#2
+ { \dim_ratio_aux:n {#1} / \dim_ratio_aux:n {#2} }
+\cs_new_nopar:Npn \dim_ratio_aux:n #1
+ { \exp_after:wN \int_value:w \dim_eval:w #1 \dim_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{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:
+ \prg_return_true: \else: \prg_return_false: \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\dim_compare:n}
+% \begin{macro}[aux]{\dim_compare_aux:wNN}
+% \begin{macro}[aux]{\dim_compare_<:nw}
+% \begin{macro}[aux]{\dim_compare_=:nw}
+% \begin{macro}[aux]{\dim_compare_>:nw}
+% \begin{macro}[aux]{\dim_compare_==:nw}
+% \begin{macro}[aux]{\dim_compare_<=:nw}
+% \begin{macro}[aux]{\dim_compare_!=:nw}
+% \begin{macro}[aux]{\dim_compare_>=:nw}
+% [This code plus comments are adapted from the \cs{int_compare:nTF}
+% function.]
+% Comparison tests using a simple syntax where only one set of braces
+% is required and additional operators such as |!=| and |>=| are
+% supported. First some notes on the idea behind this. We wish to
+% support writing code like
+% \begin{verbatim}
+% \dim_compare_p:n { 5mm + \l_tmpa_dim >= 4pt - \l_tmpb_dim }
+% \end{verbatim}
+% In other words, we want to somehow add the missing |\dim_eval:w|
+% where required. We can start evaluating from the left using
+% |\dim_use:N \dim_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.
+%
+% Eventually, we will convert the relation symbol to the appropriate
+% version of \cs{if_dim:w}, and add \cs{dim_eval:w} after it. We
+% optimize by placing the end-code already here: this avoids needless
+% grabbing of arguments later.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \dim_compare:n #1 { p , T , F , TF }
+ {
+ \exp_after:wN \dim_compare_aux:wNN \dim_use:N \dim_eval:w #1
+ \dim_eval_end:
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+%
+% Contrarily to the case of integers, where we have to remove the
+% result in order to access the relation, \cs{dim_use:N} nicely
+% produces a result which ends in |pt|. We can thus use a delimited
+% argument to find the relation. \cs{tl_to_str:n} is needed to
+% convert |pt| to \enquote{other} characters.
+%
+% The relation might be one character, |#2|, or two characters |#2#3|.
+% We support the following forms: |=|, |<|, |>| and the extended |!=|,
+% |==|, |<=| and |>=|. All the extended forms have an extra |=| so we
+% check if that is present as well. Then use specific function to
+% perform the (unbalanced) test.
+% \begin{macrocode}
+\exp_args:Nno \use:nn
+ { \cs_new:Npn \dim_compare_aux:wNN #1 }
+ { \tl_to_str:n { pt } }
+ #2 #3
+ {
+ \use:c
+ {
+ dim_compare_ #2
+ \if_meaning:w = #3 = \fi:
+ :nw
+ }
+ { #1 pt } #3
+ }
+% \end{macrocode}
+% Here, \cs{dim_eval:w} will begin the right hand side of a dimension
+% comparison (with \cs{if_dim:w}), closed cleanly by the trailing tokens
+% we put in the definition of \cs{dim_compare:n}.
+%
+% The actual comparisons take as a first argument the left-hand side
+% of the comparison (a length). In the case of normal comparisons,
+% just place the relevant \cs{if_dim:w}, with a trailing \cs{dim_eval:w}
+% to evaluate the right hand side. For extended comparisons, remove
+% the trailing |=| that we left, before evaluating with \cs{dim_eval:w}.
+% In both cases, the expansion of \cs{dim_eval:w} is stopped properly,
+% and the conditional ended correctly by the tokens we put in the
+% definition of \cs{dim_compare:n}.
+%
+% Equal, less than and greater than are straighforward.
+% \begin{macrocode}
+\cs_new:cpn { dim_compare_<:nw } #1 { \if_dim:w #1 < \dim_eval:w }
+\cs_new:cpn { dim_compare_=:nw } #1 { \if_dim:w #1 = \dim_eval:w }
+\cs_new:cpn { dim_compare_>:nw } #1 { \if_dim:w #1 > \dim_eval:w }
+% \end{macrocode}
+% For the extended syntax |==|, we remove |#2|, trailing |=| sign,
+% and otherwise act as for |=|.
+% \begin{macrocode}
+\cs_new:cpn {dim_compare_==:nw} #1#2 { \if_dim:w #1 = \dim_eval:w }
+% \end{macrocode}
+%
+% Not equal, greater than or equal, less than or equal follow the
+% same scheme as the extended equality syntax, with an additional
+% \cs{reverse_if:N} to get the opposite of their \enquote{simple}
+% analog.
+% \begin{macrocode}
+\cs_new:cpn {dim_compare_<=:nw} #1#2 {\reverse_if:N \if_dim:w #1 > \dim_eval:w}
+\cs_new:cpn {dim_compare_!=:nw} #1#2 {\reverse_if:N \if_dim:w #1 = \dim_eval:w}
+\cs_new:cpn {dim_compare_>=:nw} #1#2 {\reverse_if:N \if_dim:w #1 < \dim_eval:w}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+% \subsection{Dimension expression loops}
+%
+% \begin{macro}{\dim_while_do:nn}
+% \begin{macro}{\dim_until_do:nn}
+% \begin{macro}{\dim_do_while:nn}
+% \begin{macro}{\dim_do_until:nn}
+% |while_do| and |do_while| functions for dimensions. Same as for the
+% |int| type only the names have changed.
+% \begin{macrocode}
+\cs_set:Npn \dim_while_do:nn #1#2
+ {
+ \dim_compare:nT {#1}
+ {
+ #2
+ \dim_while_do:nn {#1} {#2}
+ }
+ }
+\cs_set:Npn \dim_until_do:nn #1#2
+ {
+ \dim_compare:nF {#1}
+ {
+ #2
+ \dim_until_do:nn {#1} {#2}
+ }
+ }
+\cs_set:Npn \dim_do_while:nn #1#2
+ {
+ #2
+ \dim_compare:nT {#1}
+ { \dim_do_while:nNnn {#1} {#2} }
+ }
+\cs_set:Npn \dim_do_until:nn #1#2
+ {
+ #2
+ \dim_compare:nF {#1}
+ { \dim_do_until:nn {#1} {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\dim_while_do:nNnn}
+% \begin{macro}{\dim_until_do:nNnn}
+% \begin{macro}{\dim_do_while:nNnn}
+% \begin{macro}{\dim_do_until:nNnn}
+% |while_do| and |do_while| functions for dimensions. Same as for the
+% |int| type only the names have changed.
+% \begin{macrocode}
+\cs_set:Npn \dim_while_do:nNnn #1#2#3#4
+ {
+ \dim_compare:nNnT {#1} #2 {#3}
+ {
+ #4
+ \dim_while_do:nNnn {#1} #2 {#3} {#4}
+ }
+ }
+\cs_set:Npn \dim_until_do:nNnn #1#2#3#4
+ {
+ \dim_compare:nNnF {#1} #2 {#3}
+ {
+ #4
+ \dim_until_do:nNnn {#1} #2 {#3} {#4}
+ }
+ }
+\cs_set:Npn \dim_do_while:nNnn #1#2#3#4
+ {
+ #4
+ \dim_compare:nNnT {#1} #2 {#3}
+ { \dim_do_while:nNnn {#1} #2 {#3} {#4} }
+ }
+\cs_set:Npn \dim_do_until:nNnn #1#2#3#4
+ {
+ #4
+ \dim_compare:nNnF {#1} #2 {#3}
+ { \dim_do_until:nNnn {#1} #2 {#3} {#4} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Using \texttt{dim} expressions and variables}
+%
+% \begin{macro}{\dim_eval:n}
+% Evaluating a dimension expression expandably.
+% \begin{macrocode}
+\cs_new_nopar:Npn \dim_eval:n #1
+ { \dim_use:N \dim_eval:w #1 \dim_eval_end: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\dim_use:N, \dim_use:c}
+% Accessing a \meta{dim}.
+% \begin{macrocode}
+\cs_new_eq:NN \dim_use:N \tex_the:D
+\cs_generate_variant:Nn \dim_use:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Viewing \texttt{dim} variables}
+%
+% \begin{macro}{\dim_show:N, \dim_show:c}
+% Diagnostics.
+% \begin{macrocode}
+\cs_new_eq:NN \dim_show:N \kernel_register_show:N
+\cs_generate_variant:Nn \dim_show:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Constant dimensions}
+%
+% \begin{variable}{\c_zero_dim}
+% \begin{variable}{\c_max_dim}
+% The source for these depends on whether we are in package mode.
+% \begin{macrocode}
+%<*initex>
+\dim_new:N \c_zero_dim
+\dim_new:N \c_max_dim
+\dim_set:Nn \c_max_dim { 16383.99999 pt }
+%</initex>
+%<*package>
+\cs_new_eq:NN \c_zero_dim \z@
+\cs_new_eq:NN \c_max_dim \maxdimen
+%</package>
+% \end{macrocode}
+% \end{variable}
+% \end{variable}
+%
+% \subsection{Scratch dimensions}
+%
+% \begin{variable}{\l_tmpa_dim, \l_tmpb_dim, \l_tmpc_dim}
+% \begin{variable}{\g_tmpa_dim, \g_tmpb_dim}
+% We provide three 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}
+% \end{variable}
+% \end{variable}
+%
+% \subsection{Creating and initialising \texttt{skip} variables}
+%
+% \begin{macro}{\skip_new:N,\skip_new:c}
+% Allocation of a new internal registers.
+% \begin{macrocode}
+%<*initex>
+\alloc_new:nnnN { skip } \c_zero \c_max_register_int \tex_skipdef:D
+%</initex>
+%<*package>
+\cs_new_protected_nopar:Npn \skip_new:N #1
+ {
+ \chk_if_free_cs:N #1
+ \newskip #1
+ }
+%</package>
+\cs_generate_variant:Nn \skip_new:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\skip_zero:N, \skip_zero:c}
+% \begin{macro}{\skip_gzero:N, \skip_gzero:c}
+% Reset the register to zero.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \skip_zero:N #1 { #1 \c_zero_skip }
+\cs_new_protected_nopar:Npn \skip_gzero:N { \pref_global:D \skip_zero:N }
+\cs_generate_variant:Nn \skip_zero:N { c }
+\cs_generate_variant:Nn \skip_gzero:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Setting \texttt{skip} variables}
+%
+% \begin{macro}{\skip_set:Nn, \skip_set:cn}
+% \begin{macro}{\skip_gset:Nn, \skip_gset:cn}
+% Much the same as for dimensions.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \skip_set:Nn #1#2
+ { #1 ~ \etex_glueexpr:D #2 \scan_stop: }
+\cs_new_protected_nopar:Npn \skip_gset:Nn { \pref_global:D \skip_set:Nn }
+\cs_generate_variant:Nn \skip_set:Nn { c }
+\cs_generate_variant:Nn \skip_gset:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {\skip_set_eq:NN,\skip_set_eq:cN, \skip_set_eq:Nc,\skip_set_eq:cc}
+% \begin{macro}
+% {\skip_gset_eq:NN,\skip_gset_eq:cN, \skip_gset_eq:Nc,\skip_gset_eq:cc}
+% All straightforward.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \skip_set_eq:NN #1#2 { #1 = #2 }
+\cs_generate_variant:Nn \skip_set_eq:NN { c }
+\cs_generate_variant:Nn \skip_set_eq:NN { Nc , cc }
+\cs_new_protected_nopar:Npn \skip_gset_eq:NN #1#2 { \pref_global:D #1 = #2 }
+\cs_generate_variant:Nn \skip_gset_eq:NN { c }
+\cs_generate_variant:Nn \skip_gset_eq:NN { Nc , cc }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\skip_add:Nn, \skip_add:cn}
+% \begin{macro}{\skip_gadd:Nn, \skip_gadd:cn}
+% \begin{macro}{\skip_sub:Nn, \skip_sub:cn}
+% \begin{macro}{\skip_gsub:Nn, \skip_gsub:cn}
+% Using |by| here deals with the (incorrect) case |\skip123|.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \skip_add:Nn #1#2
+ { \tex_advance:D #1 by \etex_glueexpr:D #2 \scan_stop: }
+\cs_new_protected_nopar:Npn \skip_gadd:Nn { \pref_global:D \skip_add:Nn }
+\cs_generate_variant:Nn \skip_add:Nn { c }
+\cs_generate_variant:Nn \skip_gadd:Nn { c }
+\cs_new_protected_nopar:Npn \skip_sub:Nn #1#2
+ { \tex_advance:D #1 by - \etex_glueexpr:D #2 \scan_stop: }
+\cs_new_protected_nopar:Npn \skip_gsub:Nn { \pref_global:D \skip_sub:Nn }
+\cs_generate_variant:Nn \skip_sub:Nn { c }
+\cs_generate_variant:Nn \skip_gsub:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Skip expression conditionals}
+%
+% \begin{macro}[pTF]{\skip_if_eq:nn}
+% Comparing skips means doing two expansions to make strings, and then
+% testing them. As a result, only equality is tested.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \skip_if_eq:nn #1#2 { p , T , F , TF }
+ {
+ \if_int_compare:w
+ \pdftex_strcmp:D { \skip_eval:n { #1 } } { \skip_eval:n { #2 } }
+ = \c_zero
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\skip_if_infinite_glue:n}
+% With \eTeX{} we all of a sudden get access to a lot information we
+% should otherwise consider ourselves lucky to get. One is
+% the stretch and shrink components of a skip register and the order
+% or those components. cs{skip_if_infinite_glue:nTF} tests it directly by
+% looking at the stretch and shrink order. If either of the predicate
+% functions return \meta{true}, |\bool_if:nTF| will return \meta{true}
+% and the logic test will take the true branch.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \skip_if_infinite_glue:n #1 { p , T , F , TF }
+ {
+ \bool_if:nTF
+ {
+ \int_compare_p:nNn { \etex_gluestretchorder:D #1 } > \c_zero ||
+ \int_compare_p:nNn { \etex_glueshrinkorder:D #1 } > \c_zero
+ }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Using \texttt{skip} expressions and variables}
+%
+% \begin{macro}{\skip_eval:n}
+% Evaluating a skip expression expandably.
+% \begin{macrocode}
+\cs_new_nopar:Npn \skip_eval:n #1
+ { \skip_use:N \etex_glueexpr:D #1 \scan_stop: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\skip_use:N, \skip_use:c}
+% Accessing a \meta{skip}.
+% \begin{macrocode}
+\cs_new_eq:NN \skip_use:N \tex_the:D
+\cs_generate_variant:Nn \skip_use:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Inserting skips into the output}
+%
+% \begin{macro}{\skip_horizontal:N, \skip_horizontal:c, \skip_horizontal:n}
+% \begin{macro}{\skip_vertical:N, \skip_vertical:c, \skip_vertical:n}
+% Inserting skips.
+% \begin{macrocode}
+\cs_new_eq:NN \skip_horizontal:N \tex_hskip:D
+\cs_new_nopar:Npn \skip_horizontal:n #1
+ { \skip_horizontal:N \etex_glueexpr:D #1 \scan_stop: }
+\cs_new_eq:NN \skip_vertical:N \tex_vskip:D
+\cs_new_nopar:Npn \skip_vertical:n #1
+ { \skip_vertical:N \etex_glueexpr:D #1 \scan_stop: }
+\cs_generate_variant:Nn \skip_horizontal:N { c }
+\cs_generate_variant:Nn \skip_vertical:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Viewing \texttt{skip} variables}
+%
+% \begin{macro}{\skip_show:N, \skip_show:c}
+% Diagnostics.
+% \begin{macrocode}
+\cs_new_eq:NN \skip_show:N \kernel_register_show:N
+\cs_generate_variant:Nn \skip_show:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Constant skips}
+%
+% \begin{macro}{\c_zero_skip}
+% \begin{macro}{\c_max_skip}
+% Skips with no rubber component are just dimensions
+% \begin{macrocode}
+\cs_new_eq:NN \c_zero_skip \c_zero_dim
+\cs_new_eq:NN \c_max_skip \c_max_dim
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Scratch skips}
+%
+% \begin{variable}{\l_tmpa_skip, \l_tmpb_skip, \l_tmpc_skip}
+% \begin{variable}{\g_tmpa_skip, \g_tmpb_skip}
+% We provide three 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}
+% \end{variable}
+% \end{variable}
+%
+% \subsection{Creating and initialising \texttt{muskip} variables}
+%
+% \begin{macro}{\muskip_new:N, \muskip_new:c}
+% And then we add muskips.
+% \begin{macrocode}
+%<*initex>
+\alloc_new:nnnN { muskip } \c_zero \c_max_register_int \tex_muskipdef:D
+%</initex>
+%<*package>
+\cs_new_protected_nopar:Npn \muskip_new:N #1
+ {
+ \chk_if_free_cs:N #1
+ \newmuskip #1
+ }
+%</package>
+\cs_generate_variant:Nn \muskip_new:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\muskip_zero:N, \muskip_zero:c}
+% \begin{macro}{\muskip_gzero:N, \muskip_gzero:c}
+% Reset the register to zero.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \muskip_zero:N #1
+ { #1 \c_zero_muskip }
+\cs_new_protected_nopar:Npn \muskip_gzero:N { \pref_global:D \muskip_zero:N }
+\cs_generate_variant:Nn \muskip_zero:N { c }
+\cs_generate_variant:Nn \muskip_gzero:N { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Setting \texttt{muskip} variables}
+%
+% \begin{macro}{\muskip_set:Nn, \muskip_set:cn}
+% \begin{macro}{\muskip_gset:Nn, \muskip_gset:cn}
+% This should be pretty familiar.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \muskip_set:Nn #1#2
+ { #1 ~ \etex_muexpr:D #2 \scan_stop: }
+\cs_new_protected_nopar:Npn \muskip_gset:Nn { \pref_global:D \muskip_set:Nn }
+\cs_generate_variant:Nn \muskip_set:Nn { c }
+\cs_generate_variant:Nn \muskip_gset:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}
+% {
+% \muskip_set_eq:NN, \muskip_set_eq:cN,
+% \muskip_set_eq:Nc, \muskip_set_eq:cc
+% }
+% \begin{macro}
+% {
+% \muskip_gset_eq:NN,\muskip_gset_eq:cN,
+% \muskip_gset_eq:Nc,\muskip_gset_eq:cc
+% }
+% All straightforward.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \muskip_set_eq:NN #1#2 { #1 = #2 }
+\cs_generate_variant:Nn \muskip_set_eq:NN { c }
+\cs_generate_variant:Nn \muskip_set_eq:NN { Nc , cc }
+\cs_new_protected_nopar:Npn \muskip_gset_eq:NN #1#2 { \pref_global:D #1 = #2 }
+\cs_generate_variant:Nn \muskip_gset_eq:NN { c }
+\cs_generate_variant:Nn \muskip_gset_eq:NN { Nc , cc }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\muskip_add:Nn, \muskip_add:cn}
+% \begin{macro}{\muskip_gadd:Nn, \muskip_gadd:cn}
+% \begin{macro}{\muskip_sub:Nn, \muskip_sub:cn}
+% \begin{macro}{\muskip_gsub:Nn, \muskip_gsub:cn}
+% Using |by| here deals with the (incorrect) case |\muskip123|.
+% \begin{macrocode}
+\cs_new_protected_nopar:Npn \muskip_add:Nn #1#2
+ { \tex_advance:D #1 by \etex_muexpr:D #2 \scan_stop: }
+\cs_new_protected_nopar:Npn \muskip_gadd:Nn { \pref_global:D \muskip_add:Nn }
+\cs_generate_variant:Nn \muskip_add:Nn { c }
+\cs_generate_variant:Nn \muskip_gadd:Nn { c }
+\cs_new_protected_nopar:Npn \muskip_sub:Nn #1#2
+ { \tex_advance:D #1 by - \etex_muexpr:D #2 \scan_stop: }
+\cs_new_protected_nopar:Npn \muskip_gsub:Nn { \pref_global:D \muskip_sub:Nn }
+\cs_generate_variant:Nn \muskip_sub:Nn { c }
+\cs_generate_variant:Nn \muskip_gsub:Nn { c }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \subsection{Using \texttt{muskip} expressions and variables}
+%
+% \begin{macro}{\muskip_eval:n}
+% Evaluating a muskip expression expandably.
+% \begin{macrocode}
+\cs_new_nopar:Npn \muskip_eval:n #1
+ { \muskip_use:N \etex_muexpr:D #1 \scan_stop: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\muskip_use:N, \muskip_use:c}
+% Accessing a \meta{muskip}.
+% \begin{macrocode}
+\cs_new_eq:NN \muskip_use:N \tex_the:D
+\cs_generate_variant:Nn \muskip_use:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Viewing \texttt{muskip} variables}
+%
+% \begin{macro}{\muskip_show:N, \muskip_show:c}
+% Diagnostics.
+% \begin{macrocode}
+\cs_new_eq:NN \muskip_show:N \kernel_register_show:N
+\cs_generate_variant:Nn \muskip_show:N { c }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Experimental skip functions}
+%
+% \begin{macro}{\skip_split_finite_else_action:nnNN}
+% This macro is useful when performing error checking in certain
+% circumstances. If the \m{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 global.
+% \begin{macrocode}
+\cs_new_nopar:Npn \skip_split_finite_else_action:nnNN #1#2#3#4
+ {
+ \skip_if_infinite_glue:nTF {#1}
+ {
+ #3 = \c_zero_skip
+ #4 = \c_zero_skip
+ #2
+ }
+ {
+ #3 = \etex_gluestretch:D #1 \scan_stop:
+ #4 = \etex_glueshrink:D #1 \scan_stop:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</initex|package>
+% \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintIndex