summaryrefslogtreecommitdiff
path: root/macros/generic
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-05-28 03:01:17 +0000
committerNorbert Preining <norbert@preining.info>2021-05-28 03:01:17 +0000
commitfd03eb3aab9edb9b15484a1130509cebe187d8bd (patch)
tree9e07ef2b8a29d7aaf170e72d934d3e9ecee6452c /macros/generic
parent5f1cfa686748068fedb95d8dafda3dc7f999c948 (diff)
CTAN sync 202105280301
Diffstat (limited to 'macros/generic')
-rw-r--r--macros/generic/polexpr/README.md4
-rw-r--r--macros/generic/polexpr/polexpr.html20
-rw-r--r--macros/generic/polexpr/polexpr.sty6
-rw-r--r--macros/generic/polexpr/polexprcore.tex4
-rw-r--r--macros/generic/polexpr/polexprexpr.tex8
-rw-r--r--macros/generic/polexpr/polexprsturm.tex2
-rw-r--r--macros/generic/tokcycle/README2
-rw-r--r--macros/generic/tokcycle/tokcycle-doc.pdfbin569457 -> 600633 bytes
-rw-r--r--macros/generic/tokcycle/tokcycle-doc.tex265
-rw-r--r--macros/generic/tokcycle/tokcycle-examples.pdfbin568281 -> 604836 bytes
-rw-r--r--macros/generic/tokcycle/tokcycle-examples.tex688
-rw-r--r--macros/generic/tokcycle/tokcycle.tex68
-rw-r--r--macros/generic/xint/CHANGES.html130
-rw-r--r--macros/generic/xint/README.md6
-rw-r--r--macros/generic/xint/sourcexint.pdfbin1152595 -> 1158797 bytes
-rw-r--r--macros/generic/xint/xint.dtx237
-rw-r--r--macros/generic/xint/xint.pdfbin1038928 -> 1038924 bytes
17 files changed, 1162 insertions, 278 deletions
diff --git a/macros/generic/polexpr/README.md b/macros/generic/polexpr/README.md
index 936520a622..8e99584aed 100644
--- a/macros/generic/polexpr/README.md
+++ b/macros/generic/polexpr/README.md
@@ -87,8 +87,10 @@ Releases
Bugfix: a typo broke the 0.8 ``diff1()`` and related functions.
- 0.8.2 (2021/05/05)
Track `xintexpr` 1.4e changes
+- 0.8.3 (2021/05/27)
+ Track `xintexpr` 1.4h changes
-Files of 0.8.2 release:
+Files of 0.8.3 release:
- polexpr.sty, polexprcore.tex, polexprexpr.tex, polexprsturm.tex,
- README.md,
diff --git a/macros/generic/polexpr/polexpr.html b/macros/generic/polexpr/polexpr.html
index 25b4fa170c..cc6e722926 100644
--- a/macros/generic/polexpr/polexpr.html
+++ b/macros/generic/polexpr/polexpr.html
@@ -598,7 +598,7 @@ a { text-decoration: none; }
<body>
<div class="document" id="package-polexpr-documentation">
<h1 class="title">Package polexpr documentation</h1>
-<p class="subtitle" id="id1">0.8.2 (2021/05/05)</p>
+<p class="subtitle" id="id1">0.8.3 (2021/05/27)</p>
<div class="contents topic" id="contents">
<p class="topic-title">Contents</p>
@@ -4073,10 +4073,11 @@ Thanks to Jürgen Gilg for report.</p></li>
<ul>
<li><p>As the usability of character <span class="docutils literal">'</span> in names has been extended
from <span class="docutils literal">\poldef</span> to also generally <span class="docutils literal">\xintexpr</span>, <span class="docutils literal">\xintdefvar</span>,
-and <span class="docutils literal">\xintdeffunc</span>, it breaks there the infix operators
-<span class="docutils literal">'and'</span>, <span class="docutils literal">'or'</span>, <span class="docutils literal">'xor'</span> and <span class="docutils literal">'mod'</span>. See the <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a>
-documentation for the <span class="docutils literal">&amp;&amp;</span>, <span class="docutils literal">||</span>, <span class="docutils literal">xor()</span> and <span class="docutils literal">/:</span>
-alternatives.</p></li>
+and <span class="docutils literal">\xintdeffunc</span>, it means that the infix operators
+<span class="docutils literal">'and'</span>, <span class="docutils literal">'or'</span>, and <span class="docutils literal">'mod'</span> must be replaced
+by <span class="docutils literal">&amp;&amp;</span>, <span class="docutils literal">||</span>, and <span class="docutils literal">/:</span> if they
+follow immediately a variable name (similarly <span class="docutils literal">'xor'</span> must
+be replaced by the <span class="docutils literal">xor()</span> function in such case).</p></li>
<li><p><a class="reference internal" href="#poltoexpr">\PolToExpr</a> by default uses a catcode 12
<span class="docutils literal">^</span>. See its documentation and the new configuration
<a class="reference internal" href="#poltoexprcaret">\PolToExprCaret</a>.</p></li>
@@ -4186,12 +4187,15 @@ this work-around. With this relase only <a class="reference internal" href="#po
not <a class="reference internal" href="#id8">\PolDef</a> needs the work-around.</p></li>
</ul>
</li>
+<li><p>track <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> <span class="docutils literal">1.4e</span> changes relative to powers.</p></li>
</ul>
-<blockquote>
+</li>
+<li><p>v0.8.3 (2021/05/27)</p>
<ul class="simple">
-<li><p>track <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> <span class="docutils literal">1.4e</span> changes relative to powers.</p></li>
+<li><p>small internal update to track an <a class="reference external" href="http://www.ctan.org/pkg/xint">xintexpr</a> <span class="docutils literal">1.4h</span> change
+regarding handling of exceptions. Will require this version at
+least on loading.</p></li>
</ul>
-</blockquote>
</li>
</ul>
</div>
diff --git a/macros/generic/polexpr/polexpr.sty b/macros/generic/polexpr/polexpr.sty
index 90b47050cf..c92f950adb 100644
--- a/macros/generic/polexpr/polexpr.sty
+++ b/macros/generic/polexpr/polexpr.sty
@@ -2,7 +2,7 @@
% License: LPPL 1.3c (author-maintained)
% Usage: \input polexpr.sty (Plain or other macro formats)
% or \usepackage{polexpr} (LaTeX macro format)
-% Release 0.8.2 (2021/05/05) of polexpr.sty. This file inputs
+% Release 0.8.3 (2021/05/27) of polexpr.sty. This file inputs
% polexprcore.tex
% polexprexpr.tex
% polexprsturm.tex
@@ -54,11 +54,11 @@
\XINTsetupcatcodes% (does \endlinechar13 in particular)
\XINT_providespackage
\ProvidesPackage{polexpr}%
- [2021/05/05 v0.8.2 Polynomial expressions with rational coefficients (JFB)]%
+ [2021/05/27 v0.8.3 Polynomial expressions with rational coefficients (JFB)]%
\begingroup
\def\x#1/#2/#3 #4\xint:{#1#2#3}%
\ifnum\expandafter\x\expanded{\csname ver@xintexpr.sty\endcsname}\xint:
- <20210505 %
+ <20210527 % xint 1.4h
\immediate\write128{! Package polexpr error: xintexpr too old, aborting input}%
\else\expandafter\xint_gobble_i
\fi
diff --git a/macros/generic/polexpr/polexprcore.tex b/macros/generic/polexpr/polexprcore.tex
index 66d8512379..d8a17e4fc2 100644
--- a/macros/generic/polexpr/polexprcore.tex
+++ b/macros/generic/polexpr/polexprcore.tex
@@ -1,4 +1,4 @@
-%% This file polexprcore.tex is part of the polexpr package (0.8.2, 2021/05/05)
+%% This file polexprcore.tex is part of the polexpr package (0.8.3, 2021/05/27)
%% Core routines to match infix operators +, -, *, //, /:, ^, ** and some
%% functions
%% The atoms representing polynomials inside \xintexpr are
@@ -410,7 +410,7 @@
}%
\def\POL_pow_neg_pol #1.#2\empty
{%
- \romannumeral0\XINT_signalcondition{InvalidOperation}%
+ \XINT_signalcondition{InvalidOperation}%
{Not supported: polynomial to negative power #1}{}{1/1[0]}%
}%
\def\POL_pow_aa #1.{\expandafter\POL_pow_a\the\numexpr\xintNum{#1}.}%
diff --git a/macros/generic/polexpr/polexprexpr.tex b/macros/generic/polexpr/polexprexpr.tex
index 3df136f9f8..8e025db1c7 100644
--- a/macros/generic/polexpr/polexprexpr.tex
+++ b/macros/generic/polexpr/polexprexpr.tex
@@ -1,10 +1,10 @@
-%% This file polexprexpr.tex is part of the polexpr package (0.8.2, 2021/05/05)
+%% This file polexprexpr.tex is part of the polexpr package (0.8.3, 2021/05/27)
%% Extending \xintexpr syntax:
%%
%% 1. Authorize ' in variable and function names
-%% This currently breaks infix operators 'and', 'or', 'xor', 'mod'
-%% hence forces usage everywhere of &&, ||, /: and xor() syntax
-%% (if : is active then use /\string : input syntax!)
+%% This partially breaks infix operators 'and', 'or', 'xor', 'mod'
+%% which must be replaced by &&, ||, /: and xor() syntax
+%% if immediately following a variable name
%%
%% 2. Map infix operators to the polexprcore macros
%%
diff --git a/macros/generic/polexpr/polexprsturm.tex b/macros/generic/polexpr/polexprsturm.tex
index 115a27d550..f2ac7c0d17 100644
--- a/macros/generic/polexpr/polexprsturm.tex
+++ b/macros/generic/polexpr/polexprsturm.tex
@@ -1,4 +1,4 @@
-%% This file polexprsturm.tex is part of the polexpr package (0.8.2, 2021/05/05)
+%% This file polexprsturm.tex is part of the polexpr package (0.8.3, 2021/05/27)
%% Sturm Algorithm (polexpr 0.4)
%% 0.5 uses primitive polynomials for faster evaluations afterwards
%% 0.6 corrects misuse of \@ifstar! (mumble). \PolToSturm* was broken.
diff --git a/macros/generic/tokcycle/README b/macros/generic/tokcycle/README
index ee682cbc05..f926917d49 100644
--- a/macros/generic/tokcycle/README
+++ b/macros/generic/tokcycle/README
@@ -5,7 +5,7 @@ Author: Steven B Segletes, Christian Tellechea (contributor)
Files : 1) tokcycle.tex (tex/generic/tokcycle)
2) tokcycle.sty (tex/latex/tokcycle)
- 3) tokcycle-doc.tex
+ 3) tokcycle-doc.tex (doc/latex/tokcycle)
4) tokcycle-doc.pdf (doc/latex/tokcycle)
5) tokcycle-examples.tex (doc/latex/tokcycle)
6) tokcycle-examples.pdf (doc/latex/tokcycle)
diff --git a/macros/generic/tokcycle/tokcycle-doc.pdf b/macros/generic/tokcycle/tokcycle-doc.pdf
index 3e4fe83347..bc646b0ccd 100644
--- a/macros/generic/tokcycle/tokcycle-doc.pdf
+++ b/macros/generic/tokcycle/tokcycle-doc.pdf
Binary files differ
diff --git a/macros/generic/tokcycle/tokcycle-doc.tex b/macros/generic/tokcycle/tokcycle-doc.tex
index dfacfd2e61..46da664c6f 100644
--- a/macros/generic/tokcycle/tokcycle-doc.tex
+++ b/macros/generic/tokcycle/tokcycle-doc.tex
@@ -25,7 +25,12 @@
\newcommand\Space{\textit{Space}}
\newcommand\CGMS{\textit{C-G-M-S}}
\newcommand\CGMnS{\textit{C}, \textit{G}, \textit{M}, and \textit{S}}
-\newcommand\macname[1]{\texttt{\char92#1}}
+\begingroup
+\catcode`|=\active
+\gdef|{\textbackslash}
+\gdef\xmacaux#1{\ttfamily\char92#1\endgroup}
+\endgroup
+\gdef\macname{\begingroup\catcode`|=\active \xmacaux}
\newcommand\thevbox{\medskip\theverbbox\par\medskip\noindent}
\newenvironment{specfig}
{\par\bigskip\vbox\bgroup\small\sffamily\centering}
@@ -153,7 +158,7 @@ As tokens/groups are read from the input stream, they are
with that category of token/group.
The \TokCycle{} categories by which the input stream
is dissected include \Character{},
- \Group{}, \Macro{}, and \Space{}.
+ \Group{}, \Macro{}, and \Space{} (alphabetized for easy recall).
Catcode-0 tokens are directed to the \Macro{} directive for processing.
Catcode-10 tokens are directed to the \Space{} directive.
@@ -170,6 +175,8 @@ The handling options of implicit cat-1 and 2 tokens are described later in
Valid tokens that are neither catcode 0, 1, 2, nor 10, except where noted,
are directed to the \Character{} directive for processing.
+\subsection{Provided (built-in) \TokCycle{} macros and environments}
+
The syntax of the non-\texttt{xpress} macros/environments is\medskip
\begin{verbbox}[\vbdelim]
@@ -206,6 +213,8 @@ or, alternately, for the \texttt{xpress}-pseudo-environment,
\thevbox
\begin{sloppypar}
+\subsection{Create your own \TokCycle{} environments}
+
In addition to the above macros/environments, the means is
provided to define new \TokCycle{} environments:
@@ -311,7 +320,7 @@ Let it suffice for now to say that the default directive settings
\section{Commands in the \TokCycle{} directives}\label{s:coms}
-The command-line token cycling tools provided in the package are
+The document-level token cycling tools provided in the package are
listed in section~\ref{s:intro}.
For each of those commands and/or pseudo-environments, the
user must (explicitly or implicitly) detail a set of directives to
@@ -326,7 +335,12 @@ There are, however, several macros provided by the package to assist
The recommended way to apply this package is to collect the
\TokCycle-transformed results of the input stream in a token register
provided by the package, named \macname{cytoks}.
-Its contents can then be typeset via \verb|\the\cytoks|.
+Its contents can then be typeset via \verb|\the\cytoks|.\footnote{%
+If a token-cycle input stream contains no macros, or is to be detokenized,
+ or if the input-stream tokens are not to be typeset, it may be possible
+ (though not required) to bypass \macname{cytoks} and typeset the output
+ directly.
+}
The macro for appending things to \macname{cytoks}, to be used in
the package directives, is \macname{addcytoks}.
@@ -365,7 +379,7 @@ The specification of all \TokCycle{} processing directives is structured
in such a way that ``\argone{}'' may be directly employed to indicate
the current token (or group) under consideration in the input stream.
-\subsubsection{Transforming the Input Stream}
+\subsubsection{Transforming the input stream}
Within the \TokCycle{} \CGMS{} directives, the command
\verb|\addcytoks{#1}| is used to echo the token being processed to
@@ -449,8 +463,8 @@ However, there are times where you might wish to perform a macro task
(for example, one that might add additional tokens to \macname{cytoks})
immediately \textit{outside} of the group, before or after.
If you were to add the task macro before or after the \macname{processtoks}
- invocation, it will still be performed, by default, \textit{inside}
- the \macname{cytoks} group.
+ invocation (anywhere in the \Group{} directive), it will still be
+ performed, by default, \textit{inside} the \macname{cytoks} group.
The macro \macname{groupedcytoks} allows one to manually specify the
grouping duties of the \Group{} directive.
@@ -518,6 +532,201 @@ Finally, the special case of $-$1 indicates that the implicit-group
Such a special treatment has limited application---for example,
when the intent is to detokenize these tokens.
+\subsection{Looking ahead at the input stream}
+
+In the normal mode of \TokCycle{} operation, each token of the input stream
+ is successively digested and sent to one of four user-defined directives
+ for processing.
+Such an approach works well if there is no interdependency of adjacent tokens
+ in the input stream.
+When such an interdepency exists (for example, the argument associated with
+ an invoked macro), one might typically use flags that are set or cleared
+ in one directive that can then be status-checked when the subsequent token
+ is processed.
+While such an approach is wholly valid, it can create a complex web of
+ flag setting/checking that can span across multiple directives.
+
+With the release of v1.4 of the package, an alternative approach to handle
+ such dependencies has been developed: look-ahead features, so that the
+ occurrence of a particular token or condition can provoke an immediate
+ examination of the input stream to handle a possible dependency, without
+ waiting for the next iteration of the token cycle.
+
+It should be noted that the use of look-ahead is perhaps more
+ \textit{dangerous} than the traditional use of flags---for if it is not
+ performed with care, tampering with the input stream can destroy its
+ integrity.
+The commands developed for these situations will now be described.
+They are designed to be employed as part of \TokCycle's \Character, \Macro,
+ and \Space{} directives for checking and/or handling successively linked
+ tokens in the input stream.
+They cannot be used inside the \Group{} directive.
+
+\subsubsection{\macname{tcpeek}}
+
+When issued witin a directive as, for example \macname{tcpeek|z}, the next
+ token from the input stream is \macname{futurelet} into \macname{z}.
+This has several implications.
+The input stream remains undisturbed, so that the peeked-at token will
+ still be the token to be digested in the next iteration of the token cycle.
+Because it has been \macname{let}, \macname{z} does not \textit{contain} the token
+ from the input stream in the manner of a \macname{def}, but rather it is a
+ separate token \textit{possessing the same properties} as the input-stream token.
+As such, it is ideal to be used for \macname{ifx} comparisons.
+For example, \macname{ifx|bgroup|z} will detect whether a cat-1 group-opening
+ token is at the head of the input stream, e.g., an opening brace, `\{';
+the comparison \macname{ifx|tcsptoken|z} will detect whether a cat-10 space
+ is at the head of the input stream.
+Such comparisons can be useful in directing the logic of the \TokCycle{}
+ directive.
+
+\subsubsection{\macname{tcpop}}
+
+When issued as, for example \macname{tcpop|z}, the next token(s) from the
+ input stream is \textit{immediately} digested as an argument and the
+ tokens are placed into the macro \macname{z}.
+This token (or tokens) will no longer be digested as part of the next
+ iteration within the token cycle, unless the tokens are subsequently
+ replaced at the head of the input stream (see \macname{tcpush} below).
+
+Beware that when \TeX{} absorbs an argument, leading white space is lost.
+Further, if the argument was enclosed in cat-1,2 braces, the braces are
+ stripped and the whole group is absorbed as the argument.
+In some cases, if the argument needs manipulation, this brace-stripping
+ behavior may be desired.
+However, if the retention of the leading white space and the braces are
+ desired, one can use manual techniques (possibly involving macros
+ such as \macname{tcpeek}, \macname{tcpopwhitespace} and
+ \macname{tcpushgroup}) or one can instead use \macname{tcpopliteral}
+ (see below) in lieu of \macname{tcpop}.
+
+If \macname{tcpop} is used nonetheless, to aid in such matters when
+ cat-10 space is at the head of the input stream, the flag
+ \macname{spacepoppedtrue} will be set when a \macname{tcpop} is issued.
+However, even \macname{ifspacepopped} will be unable to differentiate explicit
+ ``white'' space that is lost during argument absorption versus implicit
+ space (e.g., \macname{@sptoken} or active-implicit space) that is not
+ discarded.
+Another option for dealing with leading white space is
+ \macname{tcpopwhitespace} (see below).
+
+
+\subsubsection{\macname{tcpopliteral}}
+
+This macro is an alternative to \macname{tcpop}, if the retention of
+ leading white space and possibly braces are required when popping
+ an argument from the input stream.
+This can be particularly useful if the popped tokens must later be
+ placed back into the input stream in their original state.
+The syntax, \macname{tcpopliteral|z}, pops an argument into \macname{z},
+ while retaining possible leading whitespace and brace groups.
+
+\subsubsection{\macname{tcpopappto}\ and \macname{tcpopliteralappto}}
+
+When issued as, for example \macname{tcpopappto|z}, the next token(s) from the
+ input stream is absorbed as an argument and \textit{appended} to the
+ replacement text of \macname{z}.
+The same group/space provisos affecting \macname{tcpop} apply here as well.
+The control sequence to be appended, here \macname{z}, may not be undefined
+ when \macname{tcpopappto} is invoked.
+This macro is just a convenient joining of two macros: \macname{tcpop}
+ and \macname{tcappto\#1from\#2} (see below).
+
+The same applies for the macro \macname{tcpopliteralappto}, which conveniently
+ joins \macname{tcpopliteral} and \macname{tcappto\#1from\#2}.
+
+\subsubsection{\macname{tcpopuntil}}
+
+This command pops one or more tokens from the input stream in the manner of
+ a delimited argument.
+Thus, when issued as, for example \macname{tcpopuntil~0|z}, tokens from
+ the input stream are absorbed into \macname{z} until an \texttt{0} token is
+ reached.
+Unlike delimited-argument absorption, however, the delimiter (\texttt{0} in
+ this example) is also added to the specified control sequence, in this case
+ \macname{z}.
+This construct is very useful for obtaining optional-argument tokens from the
+ input stream.
+Consider the following code, with an input stream of \texttt{[1ex]\{2ex\}}:
+\begin{verbatim}
+ \tcpeek\z
+ \ifx[\z\tcpopuntil ]\q\else\def\q{}\fi
+\end{verbatim}
+Since an optional argument is next in the input stream, \macname{q} will
+ obtain the replacement text \texttt{[1ex]}, and the input stream will now
+ begin with \texttt{\{2ex\}}.
+If an optional argument had not been next in the input stream, then
+ \macname{q} would be empty and the input stream would still begin
+ with \texttt{\{2ex\}}.
+
+\subsubsection{\macname{tcpopwhitespace}}
+
+When issued as, for example \macname{tcpopwhitespace|z}, leading white space
+ from the input stream will be absorbed and set in \macname{z}, in the
+ manner of a \macname{def}.
+Unlike the flag \macname{ifspacepopped}, leading implicit space will not be
+ indicated by this macro---only leading explicit white space.
+If no leading white space is present, \macname{z} will be empty following
+ its invocation and no tokens will have been removed from the input stream.
+
+\subsubsection{\macname{tcpush}}
+
+To this point, several commands have been described for reading and/or
+ extracting tokens from the input stream.
+There are also a corresponding commands for placing material at the head
+ of the input stream, should that need arise.
+With an invocation of \macname{tcpush|z}, the replacement text of \macname{z}
+ will be pushed onto the input stream.
+Multiple pushes will be handled in a last-in-first-out fashion.
+
+Beware that, because argument absorption in \TeX{} will strip the braces of
+ an absorbed group, care must be taken. If the input stream leads with a
+ grouped quantity, such as \texttt{\{abc\}}, then \macname{tcpop|z|tcpush|z}
+ will end up with \texttt{abc} in the input stream, with the braces missing.
+\textit{The commands \macname{tcpop} and \macname{tcpush} are not strictly
+ inverse operations} (see \macname{tcpopliteral} as an alternative).
+For this reason, the command \macname{tcpushgroup} is also provided
+ (see below).
+
+The command \macname{tcpush} supports an optional argument that functions
+ in the same manner as that of \macname{addcytoks}, to provide additional
+ levels of expansion beyond the mere replacement text.
+Thus, \macname{tcpush[2]|z} will take the replacement text of \macname{z},
+ expand it twice, and push the result onto the input stream.
+In a similar way, \macname{tcpush[x]|z} will fully expand the replacement
+ text of \macname{z} and then place those tokens onto the input stream.
+Whereas \macname{addytoks} places tokens into the output stream (the
+ token list \macname{cytoks}), \macname{tcpush} places tokens at the
+ head of the input stream.
+
+\subsubsection{\macname{tcpushgroup}}
+
+The command \macname{tcpushgroup} functions in a manner similar to
+ \macname{tcpush}, except that the replacement text of the argument
+ is placed onto the input stream within a braced (cat-1,2) group.
+So if the replacement text of \macname{z} is \texttt{abc}, then the
+ invocation \macname{tcpushgroup|z} will place \texttt{\{abc\}} onto
+ the input stream.
+As with \macname{tcpush}, and with the identical syntax, the command
+ \macname{tcpushgroup} supports an optional argument that directs
+ addition levels of expansion beyond the mere replacement text.
+
+\subsubsection{\macname{tcappto\#1from\#2}}
+
+This macro does not touch the input stream, per se.
+However, as tokens are popped from the input stream and placed into macros,
+ this command conveniently allows for their aggregation
+Thus, if \macname{q} contains \texttt{abc} and the newly popped \macname{z}
+ contains \texttt{d}, then \macname{tcappto |q from |z} will append the
+ contents of \macname{z} to \macname{q}, so that, upon conclusion,
+ \macname{q} will contain the tokens \texttt{abcd}.
+Unexpandable tokens can also be appended directly using this macro, using
+ the syntax of \macname{tcappto |q from\{123\}}.
+Expandable tokens can also be added directly with the use of this macro,
+ by using a leading \macname{noexpand} or \macname{empty}, as in
+ \macname{tcappto |q from\{|noexpand|today\}}.
+
+
\subsection{Truncating the input stream}
The basic process of \TokCycle{} is one in which an input stream (or argument)
@@ -554,7 +763,7 @@ It may be examined within the \CGMS{} directives in order to
or for the remainder of the total \TokCycle{}
input stream.
-\subsubsection{\macname{truncategroup} and \macname{truncategroupiftokis}}
+\subsubsection{\macname{truncategroup}\ and \macname{truncategroupiftokis}}
\label{s:truncgrp}
As to truncating the input stream for the remainder of the \TokCycle{}
@@ -596,7 +805,7 @@ Thus, an example to echo macro tokens to the output stream, unless
Obviously, checks for particular character tokens would be placed in the
\Character{} directive, rather than the \Macro{} directive.
-\subsubsection{\macname{truncatecycle} and \macname{truncatecycleiftokis}}
+\subsubsection{\macname{truncatecycle}\ and \macname{truncatecycleiftokis}}
There are two commands that are in every way analogous to the
group-\hspace{0pt}terminating macros of section~\ref{s:truncgrp}.
@@ -746,7 +955,7 @@ i)~implicit grouping tokens (e.g., \macname{bgroup} and \macname{egroup})
ii)~implicit space tokens (e.g., \macname{@sptoken}) will be processed
by the \Space{} directive.
-\subsubsection{Active-Implicit Tokens, Including Spaces}
+\subsubsection{Active-implicit tokens, including spaces\label{s:acimsp}}
One may occasionally run across a token that is both active and implicit.
For example, in the following code, \texttt{Q} is made both active and implicit:
@@ -761,18 +970,20 @@ In general, both \macname{ifactivetok} and \macname{ifimplicittok}
This is true even in the case of active-implicit catcode-10 spaces, which
are always processed through the \Space{} directive.
-However, because of the process \TokCycle{} uses in digesting space
- tokens, the actual token passed to the \Space{} directive (so-called
- \verb|#1|), when an active-implicit space is encountered in the input
- stream, is a generic implicit space token named \macname{tc@sptoken}.
-However, the catcode-12 version of the active character that
- produced it will be, for that moment, retained in a definition
+As of \TokCycle{} v1.4, the actual active-implicit space, if
+ encountered in the input stream, will be passed as \verb|#1| to
+ the \Space{} directive, \textit{as long as the character code of the
+ token is still \macname{active}.}
+If the character code of that token is no longer active, a generic
+ implicit space token named \macname{tcsptoken} is instead passed
+ to the the \Space{} directive as \verb|#1|.
+In either case, the catcode-12 version of the active character that
+ was digested will be, for that moment, retained in a definition
named \macname{theactivespace}.
This can be useful if detokenization is required of the spaces.
Such an example is described in the \texttt{tokcycle-examples}
adjunct document.
-
\subsubsection{Parameter (cat-6) tokens (e.g., \texttt{\#}): \macname{ifcatSIX}}
\label{s:cat6}
@@ -846,7 +1057,7 @@ Note that unlike those macros requiring three arguments, the lone
catcodes of the two input toks \textbf{without expansion} (\texttt{nx}
denotes \macname{noexpand}).
-\subsection{\TokCycle{} Completion: \macname{aftertokcycle}
+\subsection{\TokCycle{} completion: \macname{aftertokcycle}\
and \macname{tcendgroup}}
The \TokCycle{} \textit{macros}, upon completion, do nothing.
@@ -957,12 +1168,18 @@ In any event, all cat-6 tokens are trapped and flag as \texttt{true}
\item A similar warning is to be made for active-implicit spaces as was
made for implicit-cat-6 tokens.
-In the case of active-implicit spaces, the name of the active character is
- momentarily stored in the \macname{theactivespace} macro.
-If one wishes to output the active \textit{name} to the \macname{cytoks} token list,
- one must make sure that \macname{theactivespace} is expanded once before
+In the case of active-implicit spaces, the name (a cat-12 string) of the
+ active character is momentarily stored in the \macname{theactivespace} macro.
+If one wishes to output the active \textit{name} to the \macname{cytoks} token
+ list, one must make sure that \macname{theactivespace} is expanded once before
being added to the token list.
+One difference here, however, is that, unlike a cat-6 token, an
+ active-implicit space (and not a string of it) is actually passed
+ to the \Space{} directive as \texttt{\#1}.
+In all but one special case, the active-implicit \texttt{\#1} will match that
+ which occurred in the input stream (see section~\ref{s:acimsp}).
+
\end{itemize}
\section*{Acknowledgments}
@@ -980,13 +1197,13 @@ The \texttt{tex.stackexchange} site provides a wonderful
opportunity to interact with the leading developers and
practitioners of \TeX{} and \LaTeX{}.
-\vspace{1in}
+\vspace{.6in}
\section*{Source Code}
%\vspace{-0.1in}
\Large\texttt{tokcycle.sty}
\verbfilenobox[\footnotesize]{tokcycle.sty}%
-%\vspace{-0.1in}
+\vspace{1.5in}
\noindent\texttt{tokcycle.tex}
\verbfilenobox[\footnotesize]{tokcycle.tex}
diff --git a/macros/generic/tokcycle/tokcycle-examples.pdf b/macros/generic/tokcycle/tokcycle-examples.pdf
index b5604b382a..72b188e887 100644
--- a/macros/generic/tokcycle/tokcycle-examples.pdf
+++ b/macros/generic/tokcycle/tokcycle-examples.pdf
Binary files differ
diff --git a/macros/generic/tokcycle/tokcycle-examples.tex b/macros/generic/tokcycle/tokcycle-examples.tex
index 891741bd4b..cdce49c48d 100644
--- a/macros/generic/tokcycle/tokcycle-examples.tex
+++ b/macros/generic/tokcycle/tokcycle-examples.tex
@@ -1,7 +1,11 @@
\documentclass[10pt]{article}
\usepackage[margin=1.3in]{geometry}
\usepackage[T1]{fontenc}
-\usepackage{tokcycle,xcolor,manfnt,lmodern}
+\usepackage{tokcycle,xcolor,manfnt,lmodern,mathtools}
+%%%%TRIAL PACKAGE CHANGES (MAKE SURE EXAMPLE FILE COMPILES CORRECTLY)
+\makeatletter
+\makeatother
+%%%%END TRIAL
\colorlet{bred}{red!90!blue}
\usepackage{tikz}
% MACROS: REDEFINE TO ALLOW \cytoks TO ESCAPE SCOPE OF exampleA
@@ -48,7 +52,8 @@
\def\altdecytoks{\par\medskip\begingroup\noindent\macname{cytoks}
\ \textit{alt}detokenization:\\\raggedright\footnotesize\ttfamily
- \expandafter\altdetokenize\expandafter{\the\cytoks}\normalsize\par\endgroup}
+ \expandafter\altdetokenize\expandafter{\the\cytoks}\normalsize\par
+ \endgroup\medskip}
\newcommand\TokCycle{\textsf{tokcycle}}
@@ -120,21 +125,21 @@
\newcommand\nextcap[1]{%
\edef\tmp{#1}%
- \tctestifx{-#1}{\def\capnext{T}}{}%
+ \tctestifx{-#1}{\def\capnext{T}}{}% <- TEST FOR HYPHEN
\tctestifcon{\if T\capnext}%
- {\tctestifcon{\ifcat\tmp A}%
- {\uppercase{#1}\def\capnext{F}}%
- {#1}}%
- {#1}%
+ {\tctestifcon{\ifcat\tmp A}% <- TEST FOR NEXT CAT-11
+ {\addcytoks{\uppercase{#1}}\def\capnext{F}}%
+ {\addcytoks{#1}}}%
+ {\addcytoks{#1}}%
}
\newcommand\TitleCase[1]{%
- \def\capnext{T}
+ \def\capnext{T}% <- INITIAL ENTRY
\tokcycle
- {\addcytoks{\nextcap{##1}}}
- {\processtoks{##1}}
+ {\nextcap{##1}}
+ {\def\capnext{T}\processtoks{##1}}% <- GROUP ENTRY
{\addcytoks{##1}}
- {\addcytoks{##1\def\capnext{T}}}
+ {\addcytoks{##1}\def\capnext{T}}% <-CAT-10 SPACE
{#1}%
\the\cytoks
}
@@ -201,24 +206,23 @@
\newcommand\nextcmptok[1]{\rotoradd{\rotcytoks{#1}}{\addcytoks{#1}}\testmatch{\tmp}}
\newcommand\nextctltok[1]{\stepcounter{runcount}\addcytoks{#1}}
-\newcommand\detokenizespacetok[1]{\tctestifcon{\ifimplicittok}%
- {\tctestifcon{\ifactivetok}{\theactivespace}{\string#1}}{\detokenize{#1}}}
-
\newcounter{sigd}
\newcounter{trailingz}
+\newif\iffounddot
+\newif\ifzerosig
\newcommand\sigdigits[1]{%
\setcounter{sigd}{0}% SIGNIFICANT DIGIT COUNT
\setcounter{trailingz}{0}% TRAILING ZERO COUNT
- \def\founddot{F}% MADE T WHEN DECIMAL HAS BEEN 1ST LOCATED
- \def\zerosig{F}% MADE T WHEN ZERO BECOMES SIGNIFICANT
+ \founddotfalse% MADE T WHEN DECIMAL HAS BEEN 1ST LOCATED
+ \zerosigfalse% MADE T WHEN ZERO BECOMES SIGNIFICANT
\tokcycle% CYCLE THROOUGH EACH TOKEN
{\tctestifx{.##1}%
- {\if T\founddot\throwerr\fi\def\founddot{T}}% IF .
+ {\iffounddot\throwerr\fi\founddottrue}% IF .
{\tctestifnum{`##1>`/}%
{\tctestifnum{`##1<`:}%
{\tctestifnum{##1>0}%
- {\stepcounter{sigd}\def\zerosig{T}\setcounter{trailingz}{0}}% IF 1-9
- {\if T\zerosig\stepcounter{sigd}\fi\stepcounter{trailingz}}% IF 0
+ {\stepcounter{sigd}\zerosigtrue\setcounter{trailingz}{0}}% IF 1-9
+ {\ifzerosig\stepcounter{sigd}\fi\stepcounter{trailingz}}% IF 0
}%
{\throwerr}% IF ASCII > `9
}%
@@ -229,7 +233,7 @@
{\throwerr}% IF CONTROL SEQUENCE
{}% IGNORE SPACES
{#1}% THE ARGUMENT
- \addtocounter{sigd}{-\thetrailingz}% SUBTRACT TRAILING ZEROS
+ \iffounddot\else\addtocounter{sigd}{-\thetrailingz}\fi% TRAILING ZEROS
\expandafter\ifx\expandafter\relax\detokenize\expandafter{\the\cytoks}%
\relax\else\setcounter{sigd}{-1}\fi% CHECK FOR INVALID INPUT
\thesigd
@@ -269,6 +273,81 @@
{\dumpword\ifrunningcount\else\tcafterenv{\par(Wordcount=\thewordcount,
Lettercount=\thelettercount)}\fi}
+\newcounter{pointcount}
+\newcommand\addtopoints[1]{(\textit{#1 point}%
+ \ifnum#1=1\relax\else\textit{s}\fi)}
+\NewEnviron{pointtracker}[2][points]{%
+ \par\bigskip\resettokcycle
+ \setcounter{pointcount}{0}%
+ \Macrodirective{\addcytoks{##1}\tctestifx{\addtopoints##1}{\sumpoints}{}}%
+ \def\tmp{\tokencyclexpress{\large\bfseries#2: \thepointcount\ #1}}%
+ \expandafter\tmp\BODY\endtokencyclexpress
+}
+\def\sumpoints{\tcpop\Q\addtocounter{pointcount}{\Q}\tcpushgroup{\Q}}
+
+\newcommand\scalerule[1]{%
+ \tcpeek\zA
+ \ifx[\zA\tcpopuntil]\opt\fi% IF PRESENT, POP OPTIONAL ARG
+ \tcpop\ArgA% POP ARG1
+ \tcpop\ArgB% POP ARG2
+ \tcpushgroup[x]{#1\dimexpr\ArgB}% PUSH BACK IN REVERSE (LIFO) FASHION
+ \tcpushgroup[x]{#1\dimexpr\ArgA}
+ \ifx[\zA\tcpush[x]{\expandafter\scaleopt\opt{#1}}\fi
+}
+\def\scaleopt[#1]#2{[#2\dimexpr#1]}
+
+\newcommand\protectruleargs[1]{\ifx\rule#1%
+ \tcpeek\zA
+ \ifx[\zA\tcpopuntil]\opt
+ \addcytoks[1]{\opt}\fi% IF OPTIONAL ARG PRESENT, POP AND SAVE TO \cytoks
+ \tcpopliteral\ArgA% MUST POP ARG 1 WITH BRACES
+ \addcytoks[1]{\ArgA}%
+ \tcpopliteral\ArgB% MUST POP ARG 2 WITH BRACES
+ \addcytoks[1]{\ArgB}%
+ \fi
+}
+
+\newif\iffoundstring
+\newcommand\findstring[4]{% {CURRENT TOK}{MATCH STRING}{SUCCESS OP}{FAIL CMDS}
+ \foundstringfalse% DEFAULT CONDITION
+ \def\poptoks{}% INITIALIZATION. IF MATCH FAILS, MUST TO RESTORE POPPED TOKENS
+ \expandafter\matchnextchar\ifx#1#2\relax\relax\fi\empty\relax
+ \iffoundstring\addcytoks{#3{#2}}\else\tcpush{\poptoks}#4\fi
+}
+\def\matchnextchar#1#2\relax{\tctestifx{#1\empty}{}{% NO MATCH FROM 1ST TOKEN
+ \tctestifx{\relax#1}{%
+ \foundstringtrue% NOTHING LEFT TO COMPARE; MATCH FOUND
+ }{%
+ \tcpeek\Q% WITHOUT POPPING...
+ \tctestifx{\Q\bgroup}{}{% PEEK FOR GROUPS OR...
+ \tctestifx{\Q\tcsptoken}{}{% SPACES THAT INDICATE MATCH FAILURE
+ \tcpopappto\poptoks% POP TOKEN AND APPEND TO \poptoks
+ \expandafter\tctestifx\expandafter{\Q#1}{%
+ \matchnextchar#2\relax% STILL MATCHING; KEEP GOING
+ }{}%
+ }%
+ }%
+ }%
+}}
+
+\newcommand\foo{$\bullet$}
+\newcommand\foocheck[1]{\tcpeek\z\ifx\foo\z\else
+ \ifx\par\z\else\addcytoks{#1}\fi\fi}
+\tokcycleenvironment\dofoo
+ {\addcytoks{##1}}
+ {\processtoks{##1}}
+ {\ifx\par##1\foocheck{##1}\else\addcytoks{##1}\fi}
+ {\foocheck{##1}}
+
+\newcommand\coleqchek[1]{\tcpeek\z
+ \ifx=\z\tcpop\z\addcytoks{\coloneqq}\else\addcytoks{#1}\fi}
+\tokcycleenvironment\subcoloneqq
+{\tctestifx{:##1}{\coleqchek{##1}}{\addcytoks{##1}}}
+{\processtoks{##1}}
+{\tctestifcon{\if\detokenize{:}\detokenize{##1}}
+ {\coleqchek{##1}}{\addcytoks{##1}}}
+{\addcytoks{##1}}
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Examples, examples, and more examples}
@@ -292,7 +371,8 @@ Apply different directives to Characters (under-dot), Groups
\begingroup
-\begin{exampleA}[lefthand width=7.8cm]{}
+\begin{exampleA}[lefthand width=7.8cm]{Apply different directives to
+ characters{,} groups{,} macros{,} and spaces}
\tokcycle{\addcytoks{\underdot{#1}}}
{\addcytoks{\{}\processtoks{#1}
\addcytoks{\}}}
@@ -307,9 +387,13 @@ Apply different directives to Characters (under-dot), Groups
\subsubsection{Escaping text}
Text between two successive escape characters is bypassed
- by \TokCycle{} and instead echoed to the output register.
-Default escape character is $|$. One can change it with
+ by \TokCycle{} and instead echoed to the output token list
+ (\macname{cytoks}).
+The default escape character is $|$.
+One can change the token-cycle escape character by way of the
\macname{settcEscapechar} macro.
+Below, the character codes are incremented by one; however, the
+ arguments of \macname{rule} are protected against that.
\begingroup
@@ -343,6 +427,7 @@ This section concerns the issue of whether the characters of the input
output token list (\macname{cytoks}).
\medskip
+\begin{minipage}[t]{\textwidth}
Transform characters (+1 ASCII) via unexpandable macro:\medskip
\begin{exampleA}[lefthand width=8.3cm]
@@ -361,6 +446,7 @@ Transform characters (+1 ASCII) via unexpandable macro:\medskip
Note how the above detokenization shows the actual transformation
instructions involving \macname{plusl}.
This is done because \macname{plusl} is not expandable.
+\end{minipage}
\par\noindent\hrulefill\medskip
\endgroup
@@ -394,7 +480,6 @@ Capitalize vowels (but don't expand the character directive)
\altdecytoks
-\medskip
The above detokenization also shows the transformation macro,
\macname{vowelcap}, as part of \macname{cytoks}.
But because \macname{vowelcap} is expandable, we did not need to
@@ -404,9 +489,16 @@ But because \macname{vowelcap} is expandable, we did not need to
\endgroup
\end{minipage}
+\begin{minipage}[t]{\textwidth}
\begingroup
Capitalize vowels (expanding the character directive)
+\medskip
+By using the \texttt{[x]} option of \macname{addcytoks}, the
+ \macname{vowelcap} is fully expanded prior to being placed in
+ the \macname{cytoks} token list.
+
+
\begin{exampleA}[lefthand width=8.3cm]
{Expanded Character directive}
\tokcycle
@@ -420,11 +512,12 @@ Capitalize vowels (expanding the character directive)
\altdecytoks
-\medskip
Here, we see no vestiges of \macname{vowelcap} in \macname{cytoks},
but only the transformed result.
\endgroup
+\end{minipage}
+\enlargethispage{12pt}
\subsubsection{Unexpanded vs. pre-expanded input stream}
\begingroup
@@ -446,7 +539,6 @@ Here, we see no vestiges of \macname{vowelcap} in \macname{cytoks},
\altdecytoks
-\medskip
In the above case, vowel-capping is not applied to the date, because
\macname{today} remains unexpanded in the \macname{cytoks} token list.
@@ -468,7 +560,6 @@ Note that, when pre-expanding the input stream, one must
\altdecytoks
-\medskip
Here, we see the date subjected to vowel-capping, because the \TokCycle{}
input was expanded prior to the token cycle.
Thus \macname{today} no longer appears \textit{explicitly} in the
@@ -494,7 +585,7 @@ The desired options are to be set prior to the \TokCycle{} invocation.
The macro
\macname{stripimplicitgroupingcase} can take three possible
integer arguments: 0 (default) to automatically place unaltered
- implicit group tokens in the output register; 1 to strip
+ implicit group tokens in the \macname{cytoks} output; 1 to strip
implicit group tokens from the output; or $-$1 to instead pass the
implicit group tokens to the Character directive (as implicit
tokens) for separate processing (typically, when detokenization
@@ -547,8 +638,8 @@ Group stripping, brought about by \macname{stripgroupingtrue},
involves removing the grouping braces from around the group.
The choice of \macname{processtoks} vs.\@ \macname{addcytoks}
affects whether the tokens inside the group are recommitted
- to \TokCycle{} for processing, or are merely sent to the output
- register in their original unprocessed form.
+ to \TokCycle{} for processing, or are merely sent to the
+ \macname{cytoks} token list in their original unprocessed form.
\medskip
Note that, in these examples, underdots and visible spaces
@@ -700,7 +791,6 @@ The final disposition of the \macname{cytoks} token list shows the effects of
\altdecytoks
-\medskip
Without \macname{stripgroupingtrue}, all tasks, A,B,C, and D, would have
been contained within the explicit \texttt{\{...\}} group.
@@ -785,7 +875,7 @@ In certain applications, it may offer a more pleasingly formatted
typesetting of detokenized material.
\medskip It is an unusual application of \TokCycle{} in that it does not
- actually use the \macname{cytoks} token register to collect
+ actually use the \macname{cytoks} token list to collect
its output.
This is only possible because all macros in the input stream
are detokenized, rather than executed.
@@ -821,29 +911,29 @@ versus \string\detokenize: \\
\subsubsection{Capitalize all words, including compound and
- parenthetical words}
+ parenthetical words\label{s:cap}}
\begingroup
\begin{exampleC}[]{The \macname{Titlecase} and \texttt{\string\nextcap} macros}
\newcommand\TitleCase[1]{%
- \def\capnext{T}
+ \def\capnext{T}% <- INITIAL ENTRY
\tokcycle
- {\addcytoks{\nextcap{##1}}}
- {\processtoks{##1}}
+ {\nextcap{##1}}
+ {\def\capnext{T}\processtoks{##1}}% <- GROUP ENTRY
{\addcytoks{##1}}
- {\addcytoks{##1\def\capnext{T}}}
+ {\addcytoks{##1}\def\capnext{T}}% <-CAT-10 SPACE
{#1}%
\the\cytoks
}
\newcommand\nextcap[1]{%
\edef\tmp{#1}%
- \tctestifx{-#1}{\def\capnext{T}}{}%
+ \tctestifx{-#1}{\def\capnext{T}}{}% <- TEST FOR HYPHEN
\tctestifcon{\if T\capnext}%
- {\tctestifcon{\ifcat\tmp A}%
- {\uppercase{#1}\def\capnext{F}}%
- {#1}}%
- {#1}%
+ {\tctestifcon{\ifcat\tmp A}% <- TEST FOR NEXT CAT-11
+ {\addcytoks{\uppercase{#1}}\def\capnext{F}}%
+ {\addcytoks{#1}}}%
+ {\addcytoks{#1}}%
}
\end{exampleC}
@@ -859,6 +949,19 @@ versus \string\detokenize: \\
(\textit{capitalizing} words).}
\end{exampleA}
+As it is currently set up, a future-capitalization of the next catcode-11 token will be triggered when any of the following is encountered in the input stream:
+\begin{itemize}
+\item The initial entry into the routine
+
+\item a catcode-10 space token
+
+\item a hyphen \texttt{-}
+
+\item upon entry into a group \texttt{\{...\}}
+\end{itemize}
+
+Obviously, additional tests could be added.
+
\endgroup
\subsubsection{Scaling rule dimensions}
@@ -890,7 +993,7 @@ versus \string\detokenize: \\
\endgroup
-\subsubsection{String search, including non-regex material}
+\subsubsection{String search, including non-regex material\label{s:searchA}}
\begingroup
@@ -953,8 +1056,8 @@ versus \string\detokenize: \\
\begingroup
The problem of counting the significant digits in a number is an interesting
- one, in that leading and trailing zeros are not significant, but zeros
- in the middle of the number are significant.
+ one, in that leading zeros are not significant, trailing zeros are sometimes
+ significant, but zeros in the middle of the number are significant.
In a problem like this, the \macname{cytoks} token list is not used to
carry a transformation of the input tokens, but only to carry a record
of errant tokens from the input (as seen from the helper macro
@@ -977,30 +1080,32 @@ The main work of the \macname{sigdigits} macro is to use the counters
\begin{exampleC}[]{The \macname{sigdigits} macro for counting significant digits}
\newcounter{sigd}
\newcounter{trailingz}
+\newif\iffounddot
+\newif\ifzerosig
\newcommand\sigdigits[1]{%
\setcounter{sigd}{0}% SIGNIFICANT DIGIT COUNT
\setcounter{trailingz}{0}% TRAILING ZERO COUNT
- \def\founddot{F}% MADE T WHEN DECIMAL HAS BEEN 1ST LOCATED
- \def\zerosig{F}% MADE T WHEN ZERO BECOMES SIGNIFICANT
+ \founddotfalse% MADE T WHEN DECIMAL HAS BEEN 1ST LOCATED
+ \zerosigfalse% MADE T WHEN ZERO BECOMES SIGNIFICANT
\tokcycle% CYCLE THROOUGH EACH TOKEN
- {\tctestifx{.##1}%
- {\if T\founddot\throwerr\fi\def\founddot{T}}% IF .
- {\tctestifnum{`##1>`/}%
- {\tctestifnum{`##1<`:}%
- {\tctestifnum{##1>0}%
- {\stepcounter{sigd}\def\zerosig{T}\setcounter{trailingz}{0}}% IF 1-9
- {\if T\zerosig\stepcounter{sigd}\fi\stepcounter{trailingz}}% IF 0
- }%
- {\throwerr}% IF ASCII > `9
- }%
- {\throwerr}% IF ASCII < `0
+ {\tctestifx{.##1}%
+ {\iffounddot\throwerr\fi\founddottrue}% IF .
+ {\tctestifnum{`##1>`/}%
+ {\tctestifnum{`##1<`:}%
+ {\tctestifnum{##1>0}%
+ {\stepcounter{sigd}\zerosigtrue\setcounter{trailingz}{0}}% IF 1-9
+ {\ifzerosig\stepcounter{sigd}\fi\stepcounter{trailingz}}% IF 0
}%
- }% APPLY ABOVE LOGIC FOR CHAR TOKENS
- {\throwerr}% IF BRACES
- {\throwerr}% IF CONTROL SEQUENCE
- {}% IGNORE SPACES
- {#1}% THE ARGUMENT
- \addtocounter{sigd}{-\thetrailingz}% SUBTRACT TRAILING ZEROS
+ {\throwerr}% IF ASCII > `9
+ }%
+ {\throwerr}% IF ASCII < `0
+ }%
+ }% APPLY ABOVE LOGIC FOR CHAR TOKENS
+ {\throwerr}% IF BRACES
+ {\throwerr}% IF CONTROL SEQUENCE
+ {}% IGNORE SPACES
+ {#1}% THE ARGUMENT
+ \iffounddot\else\addtocounter{sigd}{-\thetrailingz}\fi% TRAILING ZEROS
\expandafter\ifx\expandafter\relax\detokenize\expandafter{\the\cytoks}%
\relax\else\setcounter{sigd}{-1}\fi% CHECK FOR INVALID INPUT
\thesigd
@@ -1213,6 +1318,11 @@ We provide two modes of output: one that provides an ending summary, and
As with other \TokCycle{} environments and macros, portions can be
exempted from the count (for example macro arguments) by using the
escape delimiters provided.
+An even more elaborate version of this environment can be found at
+\texttt{https://tex.stackexchange.com/questions/\allowbreak
+ 44618/dynamically-count-and-return-number-of-words-in-a-section/587567\#587567},%
+\hfil in\-cluding a version that runs
+ in Plain \TeX.
\begin{exampleC}[]{The \macname{countem} extended-environment definition
and supporting macros}
@@ -1326,7 +1436,7 @@ Thus, ``-is loc'' is also added to the output stream.
}
\begin{exampleB}[text only, righthand width=0.01cm, colback=white]%
-{Effects of various truncation directives}
+{Example: Effects of various truncation directives}
{\footnotesize\ttfamily Input text}: \expandafter\altdetokenize\expandafter
{\thetext}
@@ -1350,9 +1460,338 @@ For example, a detokenization of the final case reveals this to be
\endgroup
-\subsection{Advanced topics: implicit tokens and catcode changes}
+\subsection{Look-ahead features}
+
+The whole concept of the \TokCycle{} package is to examine the input stream
+ one token at a time and use the directives to process the tokens.
+Occasionally, however, there are tasks that involve several adjacent tokens.
+In the example of section~\ref{s:cap}, for instance, in order to capitalize
+ words, each space token triggers an action on the character that follows.
+To accomplish this without any look-ahead features, the Space directive sets
+ a flag, \verb|\def\capnext{T}|, in order to communicate with a the Character
+ directive about a subsequent token.
+That is a perfectly valid approach to communicate conditional action.
+
+\medskip
+However, \TokCycle{} also provides look-ahead features, to avoid the necessity
+ of communicating with future tokens in the cycle by way of flag settings.
+These tools allow a directive to directly ``peek'' ahead at the input stream
+ (without disturbing it) and, if desired, push and pop tokens to and from
+ the input stream.
+The package manual should be consulted for a full list of macros provided to
+ facilitate look-ahead capability.
+But here are some examples to look at.
+
+\begingroup
+
+\subsubsection{Count in advance that which follows}
+
+Specify the point values for questions and let tokcycle perform the cumulative
+ tallies in advance, using a single-pass compilation.
+
+\begin{exampleC}[]{The \texttt{pointtracker} environment to count point values
+ in advance}
+\newcounter{pointcount}
+\newcommand\addtopoints[1]{(\textit{#1 point}%
+ \ifnum#1=1\relax\else\textit{s}\fi)}
+\NewEnviron{pointtracker}[2][points]{%
+ \par\bigskip\resettokcycle
+ \setcounter{pointcount}{0}%
+ \Macrodirective{\addcytoks{##1}\tctestifx{\addtopoints##1}{\sumpoints}{}}%
+ \def\tmp{\tokencyclexpress{\large\bfseries#2: \thepointcount\ #1}}%
+ \expandafter\tmp\BODY\endtokencyclexpress
+}
+\def\sumpoints{\tcpop\Q\addtocounter{pointcount}{\Q}\tcpushgroup{\Q}}
+\end{exampleC}
+
+\begin{exampleA}[lefthand width=6.2cm]{Demo of the pointtracker environment}
+\begin{pointtracker}[total points]{\Large Science Test}
+\begin{pointtracker}{Advanced Geology}
+ \begin{itemize}
+ \item Count the fingers on your left hand. Are there more than 9?
+ \addtopoints{1}
+ \item Draw a rectangle with five edges. \addtopoints{3}
+ \end{itemize}
+\end{pointtracker}
+\begin{pointtracker}{Meteorology}
+ \begin{itemize}
+ \item How many borgs does it take to brew a Danish beer?
+ \addtopoints{2}
+ \item What is the meaning of life? \addtopoints{4}
+ \end{itemize}
+\end{pointtracker}
+\end{pointtracker}
+\end{exampleA}
+
+Note that this example has several neat features.
+The points for Geology, Meteorology, and the Test total are not specified,
+ but calculated.
+They are calculated based on content that appears later in the environment.
+Traditionally, multiple compilations would be required with external data
+ written to the aux file, but that does not occur here---there is only
+ a single compilation.
+Finally, becaue we are nesting the \TokCycle{} part of \texttt{pointtracker}
+ inside of a \macname{NewEnviron}, we see that the \texttt{pointtracker}
+ environment can be nested, without adverse effect.
+
+\endgroup
+
+\subsubsection{Modify the arguments of every instance of a particular macro}
-\subsubsection{Trap Active Characters (catcode 13)}
+\begingroup
+
+This example, through the use of the \macname{scalerule} macro, shows how
+ the \macname{rule} arguments, including the optional argument, can be
+ popped off the input stream, adjusted, and placed back in the stream.
+
+\begin{exampleC}[]{The \macname{scalerule} macro to scale all
+ \macname{rule} arguments}
+\newcommand\scalerule[1]{%
+ \tcpeek\zA
+ \ifx[\zA\tcpopuntil]\opt\fi% IF PRESENT, POP OPTIONAL ARG
+ \tcpop\ArgA% POP ARG1
+ \tcpop\ArgB% POP ARG2
+ \tcpushgroup[x]{#1\dimexpr\ArgB}% PUSH BACK IN REVERSE (LIFO) FASHION
+ \tcpushgroup[x]{#1\dimexpr\ArgA}
+ \ifx[\zA\tcpush[x]{\expandafter\scaleopt\opt{#1}}\fi
+}
+\def\scaleopt[#1]#2{[#2\dimexpr#1]}
+\end{exampleC}
+
+\begin{exampleA}[lefthand width=9.2cm]{Scale every \macname{rule} argument}
+\resettokcycle
+\settcEscapechar{!}% SO AS NOT TO INTERFERE WITH `|' TOKS IN tabular
+\Macrodirective{\addcytoks{#1}\ifx\rule#1\scalerule{2}\fi}
+\tokencyclexpress
+The rules appearing in the following input stream are literally
+!\rule[-2pt]{1.5ex}{1.5ex}! and !\rule{2ex}{3pt}!:
+
+My environment can include all kinds of rules
+ \rule[-2pt]{1.5ex}{1.5ex} and other macros, such as \today{} and
+\begin{tabular}{c|c}
+23 & 454\\\hline
+x & y
+\end{tabular}
+but each rule \rule{2ex}{3pt} is grown by a factor of two.
+\endtokencyclexpress
+\end{exampleA}
+\settcEscapechar{|}
+
+\endgroup
+
+
+\subsubsection{Protect arguments of specified macro from Character
+ directive modification}
+
+\begingroup
+Tokcycle provides the escape character $|$ to delimit tokens to be protected
+ from processing by tokcycle directives.
+But that requires the input stream to be adjusted to include these delimiters.
+Here's an alternative, not requiring input stream adjustment.
+The Macro directive protects all \macname{rule} arguments against contamination
+ by the Character directive.
+
+\medskip
+When a \macname{rule} is encountered, \macname{protectruleargs} is called
+ to pop the rule arguments from the input stream and place them directly
+ in the \macname{cytoks} token list, out of reach from the Character directive.
+
+
+\begin{exampleC}[]{The \macname{protectruleargs} macro to prevent Character directive
+ contamination of arguments}
+\newcommand\protectruleargs[1]{\ifx\rule#1%
+ \tcpeek\zA
+ \ifx[\zA\tcpopuntil]\opt
+ \addcytoks[1]{\opt}\fi% IF OPTIONAL ARG PRESENT, POP AND SAVE TO \cytoks
+ \tcpopliteral\ArgA% MUST POP ARG 1 WITH BRACES
+ \addcytoks[1]{\ArgA}%
+ \tcpopliteral\ArgB% MUST POP ARG 2 WITH BRACES
+ \addcytoks[1]{\ArgB}%
+ \fi
+}
+\end{exampleC}
+
+Here, every character is typeset with a slash suffix.
+If this action were to be imposed to \macname{rule} argument characters,
+ it would destroy their integrity.
+Fortunately, when the Macro directive detects a \macname{rule}, it can
+ take evasive action.
+
+\begin{exampleA}[lefthand width=9.1cm]{Protect every \macname{rule} argument
+ from Character directive contamination}
+\resettokcycle
+\Characterdirective{\addcytoks{#1\textup{/}\allowbreak}}
+\Macrodirective{\addcytoks{#1}\protectruleargs{#1}}
+\tokencyclexpress
+My \textit{environment} modifies each character token, but rule
+ \rule[-4pt]{1.5ex}{1.5ex} arguments \rule{2ex}{3pt} are protected.
+\endtokencyclexpress
+\end{exampleA}
+\endgroup
+
+
+\begingroup
+
+\subsubsection{Find a string of character tokens}
+
+Earlier in this manuscript, in section~\ref{s:searchA}, a token cycle
+ was developed to search a token stream for a string match.
+Here, we do something similar, except we use the new ``look ahead'' features
+ of \TokCycle{} to achieve it.
+In this case, however, the search string cannot cross space or group
+ boundaries.
+The \macname{matchnextchar} macro demonstrates a use of \macname{tcpopappto},
+ which is one of the newly introduced \TokCycle{} commands; instead of
+ popping an argument from the input stream \textit{into} a macro, it pops it
+ and \textit{appends} it to a macro.
+
+\begin{exampleC}[]{The \macname{findstring} macro to perform a look{-}ahead string
+ search}
+\newcommand\findstring[4]{% {CURRENT TOK}{MATCH STRING}{SUCCESS OP}{FAIL CMDS}
+ \foundstringfalse% DEFAULT CONDITION
+ \def\poptoks{}% INITIALIZATION. IF MATCH FAILS, MUST TO RESTORE POPPED TOKENS
+ \expandafter\matchnextchar\ifx#1#2\relax\relax\fi\empty\relax
+ \iffoundstring\addcytoks{#3{#2}}\else\tcpush{\poptoks}#4\fi
+}
+\def\matchnextchar#1#2\relax{\tctestifx{#1\empty}{}{% NO MATCH FROM 1ST TOKEN
+ \tctestifx{\relax#1}{%
+ \foundstringtrue% NOTHING LEFT TO COMPARE; MATCH FOUND
+ }{%
+ \tcpeek\Q% WITHOUT POPPING...
+ \tctestifx{\Q\bgroup}{}{% PEEK FOR GROUPS OR...
+ \tctestifx{\Q\tcsptoken}{}{% SPACES THAT INDICATE MATCH FAILURE
+ \tcpopappto\poptoks% POP TOKEN AND APPEND TO \poptoks
+ \expandafter\tctestifx\expandafter{\Q#1}{%
+ \matchnextchar#2\relax% STILL MATCHING; KEEP GOING
+ }{}%
+ }%
+ }%
+ }%
+}}
+\end{exampleC}
+
+\begin{exampleA}[lefthand width=8cm]{Search for the string ``red''}
+\resettokcycle
+\Characterdirective{\findstring{#1}{red}%
+ {\textcolor{purple}}{\addcytoks{#1}}}
+\tokencyclexpress
+Can I \textit{find red in the text}, even in the
+ MIDredDLE of words and groups?
+\endtokencyclexpress
+\end{exampleA}
+
+\endgroup
+
+
+\subsubsection{Eliminate \textit{prior} spaces and pars before a particular
+ macro}
+
+The goal here is to eliminate spaces and paragraphs that occur
+ \textit{prior} to the occurrence of the macro \macname{foo}, which
+ sets a \macname{bullet}.
+Looking backwards is not part of the \TeX{} approach.
+Nonetheless, the problem can, with a token cycle, be turned on its head,
+ such that all occurrences of spaces and \macname{par} can be made
+ to look for a future instance of \macname{foo}.
+
+\medskip
+Here, if a space or \macname{par} is detected, \macname{foocheck} is called.
+ It peeks at the token that follows the space or \macname{par}.
+If the peeked argument is a \macname{par} or \macname{foo} itself, it discards
+ the current space or \macname{par}.
+
+\begingroup
+
+\begin{exampleC}[]{The \macname{dofoo} environment to remove prior spaces and
+ paragraphs before \macname{foo}}
+\newcommand\foo{$\bullet$}
+\newcommand\foocheck[1]{\tcpeek\z\ifx\foo\z\else
+ \ifx\par\z\else\addcytoks{#1}\fi\fi}
+\tokcycleenvironment\dofoo
+ {\addcytoks{##1}}
+ {\processtoks{##1}}
+ {\ifx\par##1\foocheck{##1}\else\addcytoks{##1}\fi}
+ {\foocheck{##1}}
+\end{exampleC}
+
+\begin{exampleA}[lefthand width=7cm]{Remove spaces and paragraphs before
+ \macname{foo}}
+\dofoo
+Lorem ipsum dolor sit amet. (No foo)
+
+Lorem ipsum dolor sit amet. \foo
+
+Lorem ipsum dolor sit amet.\foo
+
+Lorem ipsum dolor sit amet.
+\foo
+
+Lorem ipsum dolor sit amet.
+
+\foo
+\enddofoo
+\end{exampleA}
+\endgroup
+
+
+\subsubsection{Replace := with \macname{coloneqq} (\texttt{mathtools}
+ package required)}
+
+In most cases, creating a macro to signify a composite symbol makes the most
+ sense.
+However, sometimes you don't realize that until you've typed in a lot of code
+ that fails to use such a macro.
+In such a situation, \TokCycle{} can help.
+
+\medskip
+In the \texttt{mathtools} package, there is a symbol, \macname{coloneqq},
+ a colon followed by an equal sign, in which the colon has been
+ vertically adjusted to be symmetric with respect to the \texttt{=} sign.
+The adjustment is slight, but noticeable.
+A token cycle can be set up to look for instances of the \texttt{:} character,
+ peek ahead to see if it is followed by an \texttt{=} character and, if so,
+ replace the pair with \macname{coloneqq}.
+However, the process is further complicated, if one is a user of
+\macname{usepackage[french]\{babel\}}, where the \texttt{:} character is is made
+ an active character.
+
+\medskip
+Therefore, in this case, not only does \texttt{:} need to be located by
+ the Character directive (in the normal case), but it also need be searched
+ for by the Macro directive, in the event that
+ \macname{usepackage[french]\{babel\}} is being employed.
+In the example below, there are two such colons that satisfy the criterion for
+ replacement.
+
+\begingroup
+
+\begin{exampleC}[]{The \macname{coleqchek} macro and the \macname{subcoloneqq}
+ environment}
+\newcommand\coleqchek[1]{\tcpeek\z
+ \ifx=\z\tcpop\z\addcytoks{\coloneqq}\else\addcytoks{#1}\fi}
+\tokcycleenvironment\subcoloneqq
+{\tctestifx{:##1}{\coleqchek{##1}}{\addcytoks{##1}}}% <- IF : A CHARACTER
+{\processtoks{##1}}
+{\tctestifcon{\if\detokenize{:}\detokenize{##1}}% <- IF : AN ACTIVE MACRO
+ {\coleqchek{##1}}{\addcytoks{##1}}}
+{\addcytoks{##1}}
+\end{exampleC}
+
+\begin{exampleA}[lefthand width=6cm]{replace {:=} with \macname{coloneqq}}
+\subcoloneqq
+\LARGE Compare: $::=$
+
+$a := b$ vs
+ $a \ordinarycolon= b$ vs
+ $a:b$.
+\endsubcoloneqq
+\end{exampleA}
+
+\endgroup
+
+\section{Advanced topics: implicit tokens and catcode changes}
+
+\subsection{Trap active characters (catcode 13)}
%\begin{minipage}[t]{\textwidth}
\begingroup
@@ -1408,10 +1847,12 @@ This is a test!!\endtokencyclexpress
are made before reaching \TokCycle{} processing.
\svt hey are, thus, no longer detected as active, unless
\macname{noexpand} is applied before the pre-expansion.
-In this example, the `\texttt{!}' that is not \macname{noexpand}\kern.3pted
- is converted to a `\texttt{?}' prior to reaching \TokCycle{}
- processing (and thus, not detected as \macname{active}).
-Likewise, the `\texttt{T}' is pre-converted to a `\texttt{+}':
+In this example, the `\texttt{!}' that is \textit{not} subject to
+ a \macname{noexpand} is converted to a `\texttt{?}' prior to
+ reaching \TokCycle{} processing (and thus, not detected as
+ \macname{active}).
+However, the `\texttt{T}' is not pre-converted to a `\texttt{+}',
+ because it is implicit, and not a definition:
\catcode`!=\active
\def !{?}
@@ -1424,7 +1865,13 @@ Likewise, the `\texttt{T}' is pre-converted to a `\texttt{+}':
\detokenize\expandafter{\the\cytoks}
\end{exampleA}
-However, pre-tokenization does not suffer this behavior:
+\begingroup
+\catcode`T=11
+\catcode`!=12
+However, pre-tokenization does not suffer this behavior.
+The first `\texttt{!}' is tokenized as active during
+ its absorption into \macname{tmp}, as shown in the next example:
+\endgroup
\begin{exampleA}[lefthand width=7.8cm]{Pre-tokenized input stream
does not affect active characters}
\def\tmp{This is a test!!}
@@ -1473,7 +1920,7 @@ The following example demonstrates this concept, while showing,
\end{exampleA}
\endgroup
-\subsubsection{Trap Catcode 6 (explicit \& implicit) tokens}
+\subsection{Trap catcode 6 (explicit \& implicit) tokens}
\begingroup
@@ -1569,7 +2016,7 @@ In this example, a macro is defined and then executed, subject to
\endgroup
-\subsubsection{Trap implicit tokens in general}
+\subsection{Trap implicit tokens in general}
\begingroup
@@ -1656,7 +2103,7 @@ Active tokens processed through the character directive are followed with
in the input stream as duplicate, e.g. \texttt{\#\#}.
-\subsubsection{Changing grouping tokens (catcodes 1,2)}
+\subsection{Changing grouping tokens (catcodes 1,2)}
\begingroup
@@ -1755,7 +2202,7 @@ Bottom line:
\endgroup
-\subsubsection{Catcode 10 space tokens\label{s:spc}}
+\subsection{Catcode 10 space tokens\label{s:spc}}
\begingroup
@@ -1771,17 +2218,19 @@ However, \macname{ifimplicittok} may still be used to
\ddbend
-Also, if the implicit space is an active character, \macname{ifactivetok}
- is also set, for the user's benefit.
-Likewise, \macname{ifactivechar} is also checked for active spaces, to see
+If the implicit space is \textit{also} an active character,
+ \macname{ifactivetok} is also set, for the user's benefit.
+Likewise, \macname{ifactivechar} is also checked, to see
if the charcode of the active space is still, indeed, active.
While \verb|#1| may be used to represent the space in the space directive,
- a special technique is required to recover the detokenized name of the
+ a special technique may be required to recover the detokenized name of the
active space character.
-In particular, \verb|#1| will, for active spaces, contain a generic
- implicit space token, \macname{tc@sptoken}.
-However, the name of the associated active character in the input stream
- will be defined as a cat-12 token in \macname{theactivespace}.
+In particular, if the active token is an implicit space, but the charcode
+ of that token is no longer active, \verb|#1| will, for this case,
+ contain a generic implicit space token, \macname{tcsptoken}.
+However, for all active space tokens, the name of the associated active
+ character in the input stream will be defined as a cat-12 token in
+ \macname{theactivespace}.
\medskip
Note in the following examples that cat-10 tokens do \textit{not}
@@ -1827,15 +2276,9 @@ catcode settings for the space and the underscore.
\end{exampleA}
The next two examples introduce implicit and active-implicit spaces.
-The latter example also demonstrates detokenization of such spaces.
-
-\medskip
-Here is a useful expandable macro for detokenizing space tokens
- in the context of \TokCycle{}.
-It can process not only explicit cat-10 spaces, but also implicit and
- active-implicit spaces.
-To add it to the \macname{cytoks} token list, make sure you use the
- \verb|[x]| fully expanded option to \macname{addcytoks}.
+In the first example, functionally identical to the prior example,
+ we see that \TokCycle{} can digest and direct such
+ tokens to the Space directive, here in the form of \macname{z}.
%%%
\resettokcycle
@@ -1853,40 +2296,63 @@ To add it to the \macname{cytoks} token list, make sure you use the
\endtokencyclexpress
\end{exampleA}
-\begin{minipage}[t]{\textwidth}
-\begin{exampleC}[]{The \macname{detokenizespacetok} macro for handling
- implicit and active-implicit spaces}
-\newcommand\detokenizespacetok[1]{\tctestifcon{\ifimplicittok}%
- {\tctestifcon{\ifactivetok}{\theactivespace}{\string#1}}{\detokenize{#1}}}
-\end{exampleC}
+In the second example, an active implicit space token is created, \texttt{Q},
+ and stored in a definition, \macname{tmp}.
+A \macname{string} is applied by the token cycle at one point to the
+ space tokens and we see that the proper implicit tokens are decoded, whether
+ they are active or macro.
+
+\medskip
+The one case deserving special note is the final case of the example,
+ in which the catcode of \texttt{Q}, the active character, is restored
+ to a value of 12, before the previously tokenized, active-implicit
+ \texttt{Q} is passed to the token cycle.
+In such a case, where future incantations of \texttt{Q} are no longer active,
+ then the active-implicit space token that gets passed to the
+ Space directive (by way of \macname{tmp}) is taken as a generic
+ active-implicit \macname{tcsptoken}, instead of the original
+ active-implicit token (\texttt{Q}).
-\begin{exampleA}[lefthand width=10cm]{Active Implicit spaces work{,} too}
+\medskip
+Nonetheless, the original string of the active-implicit token (that is, a
+ cat-12 \texttt{Q}) is preserved in \macname{theactivespace}.
+The reason for this behavior is that the absorption of spaces in \TokCycle{}
+ is a destructive process, in which the spaces are absorbed as strings,
+ so that a proper interpretation of their implicitness can be ascertained.
+With the character no longer active, it would be more difficult to
+ recreate an active-implicit version of \textit{that} token to
+ pass to the Space directive.
+Thus, a generic active-implicit space token is, instead, employed.
+
+
+\begin{exampleA}[lefthand width=9.05cm]{Active Implicit spaces work{,} too}
\resettokcycle
-\Characterdirective{\addcytoks{\underdot{#1}}}
\def\:{\let\z= } \: %
\catcode`Q=\active %
\def\:{\let Q= } \: %
\catcode`\_=10 %
-\tokencyclexpress
-xQx x_x\z{}x%
-\endtokencyclexpress
+\def\tmp{xQx x_x\z{}x}
+\expandafter\tokencyclexpress\tmp\endtokencyclexpress
-\resettokcycle
\Spacedirective{\addcytoks{\textcolor{cyan}\bgroup}%
- \addcytoks[x]{(\detokenizespacetok{#1})}%
+ \addcytoks[x]{(\string#1\ifactivetok
+ \ifimplicittok\ifactivechar\else\noexpand
+ \textcolor{red}{:\theactivespace}\fi\fi\fi)}%
\addcytoks{\egroup}}
\medskip
-\tokencyclexpress
-xQx x_x\z{}x%
-\endtokencyclexpress
+\expandafter\tokencyclexpress\tmp\endtokencyclexpress
+
+\medskip
+\catcode`Q=12
+\expandafter\tokencyclexpress\tmp\endtokencyclexpress
+
\end{exampleA}
-\end{minipage}
\endgroup
-\subsubsection{Changes to catcode 0}
+\subsection{Changes to catcode 0}
\begingroup
diff --git a/macros/generic/tokcycle/tokcycle.tex b/macros/generic/tokcycle/tokcycle.tex
index 9aaec68b72..d2e3a059ca 100644
--- a/macros/generic/tokcycle/tokcycle.tex
+++ b/macros/generic/tokcycle/tokcycle.tex
@@ -1,7 +1,7 @@
\def\tcname {tokcycle}
-\def\tcver {1.3}
+\def\tcver {1.4}
%
-\def\tcdate {2021/03/10}
+\def\tcdate {2021/05/27}
%
% Author : Steven B Segletes, Christian Tellechea (contributor)
% Maintainer : Steven B Segletes
@@ -52,16 +52,18 @@
\long\def\tc@exsecond#1#2{#2}
\long\def\tc@testxifx{\tc@earg\tctestifx}
\long\def\test@ifmacro#1{\tctestifcatnx#1\relax}
-\def\tc@addtoks#1#2{\toks#1\expandafter{\the\toks#1#2}}
+\def\tc@addtoks#1#2{\toks#1\expandafter{\the\toks#1 #2}}
\def\add@tcdepth{\advance\tcdepth 1\relax}
-\def\sub@tcdepth{\advance\tcdepth-1\relax}\def\tc@resetifs{\activetokfalse\implicittokfalse\tc@implicitgrpfalse
- \catSIXfalse\activecharfalse\activetokunexpandablefalse
- \def\theactivespace{}}
+\def\sub@tcdepth{\advance\tcdepth-1\relax}
+\def\tc@resetifs{\activetokfalse\implicittokfalse\tc@implicitgrpfalse\catSIXfalse
+ \activecharfalse\activetokunexpandablefalse\def\theactivespace{}}
\long\def\count@stringtoks#1{\tc@earg\count@toks{\string#1}}
\long\def\count@toks#1{\the\numexpr-1\count@@toks#1.\tc@endcnt}
\long\def\count@@toks#1#2\tc@endcnt{+1\tc@ifempty{#2}{\relax}{\count@@toks#2\tc@endcnt}}
\def\sv@hash{##}
+\def\def@popname{\expandafter\def\tc@popname}
% EXTERNAL TOOLS
+\let\tcsptoken= \tc@sptoken
\long\def\tctestifcon#1{#1\expandafter\tc@exfirst\else\expandafter\tc@exsecond\fi}
\long\def\tctestifcatnx#1#2{\tctestifcon{\ifcat\noexpand#1\noexpand#2}}
\long\def\tctestifx#1{\tctestifcon{\ifx#1}}
@@ -73,6 +75,7 @@
\newif\ifactivetok
\newif\ifactivechar
\newif\ifactivetokunexpandable
+\newif\ifspacepopped
\newtoks\cytoks
\long\def\tokcycleenvironment#1#2#3#4#5{\expandafter\def\expandafter#1%
\expandafter{\expandafter\let\csname end\expandafter\tc@gobble
@@ -122,7 +125,9 @@
{\implicittoktrue\tctestifcon{\if\expandafter\@firstoftwo\string\\\tc@str}%
{\expandafter\@@@spcT\tc@gobble}% IMPLICIT MACRO SPACE
{\activetoktrue\@@@@spcT}}}% IMPLICIT ACTIVE SPACE
-\def\@@@@spcT#1{\def\theactivespace{#1}\trapactivechar{#1}\@@spcT{\tc@sptoken}}
+\def\@@@@spcT#1{\def\theactivespace{#1}\trapactivechar{#1}\ifactivechar\edef\tc@spc
+ {\scantokens{#1\noexpand}}\else\def\tc@spc{\tcsptoken}\fi\expandafter\@@spcT
+ \expandafter{\tc@spc}}
\def\@@@spcT{\csmk{\expandafter\@@spcT\thecs}}
\def\@@spcT#1{\@spcT{#1}\@tokcycle}
% GROUP DECODE
@@ -161,7 +166,7 @@
\addcytoks\expandafter{\expandafter#1}}}
\def\settcGrouping#1{\def\@tmp##1{#1}\tc@defx\@@tmp{\@tmp{\the\cytoks}}%
\tc@earg\defineexit@grouped{\@@tmp}}
-% FAUX TOKENIZATION OF COMMAND NAME (WHEN cat0 TOKEN HAS BEEN MADE cat12)
+% FAUX TOKENIZATION OF COMMAND NAME (WHEN \ AND COMMAND-NAME TOKS ARE NOW cat12)
\def\csmk#1{\def\csaftermk{#1}\toks0{}\@csmkA}
\def\@csmkA{\futurelet\@tmp\@csmkB}
\def\@csmkB{\tctestifx{\@tmp\tc@sptoken}%
@@ -184,6 +189,38 @@
%% WILL ALSO TRAP ACTIVE \let TO PRIMITIVES AS IMPLICIT; UNDO LATER IN \can@absorb@@
\def\trapactivetokunexpandable#1{\tctestifcon{\expandafter\if
\detokenize{#1}#1}{}{\activetoktrue\activetokunexpandabletrue\implicittoktrue}}
+% FEATURES TO LOOK-AHEAD INTO THE INPUT STREAM (INTRODUCED v1.4)
+\long\def\tcpeek#1#2\@tokcycle{\def\tc@tmp{\ifx#1\endtokcycraw
+ \let#1=\empty\fi#2\@tokcycle}\futurelet#1\tc@tmp}%___________________________PEEK_
+\def\tcpopliteral#1{\tcpopwhitespace#1\tcpeek\@tmp\ifx\@tmp\bgroup
+ \tcpop\@tmp\def\tc@tmp{\tcappto#1from}\expandafter\tc@tmp\expandafter
+ {\expandafter{\@tmp}}\else\tcpopappto#1\fi}
+\def\tcpop{\long\def\tc@@@pop##1{\tctestifx{\endtokcycraw##1}{\def@popname{}%
+ \tc@tmp\endtokcycraw}{\def@popname{##1}\tc@tmp}}\tc@pop}
+\long\def\tcpopuntil#1{\long\def\tc@@@pop##1#1{\def@popname{##1#1}\tc@tmp}\tc@pop}
+\long\def\tc@pop#1#2\@tokcycle{\def\tc@popname{#1}\def\tc@tmp
+ {#2\@tokcycle}\futurelet\tc@futuretok\tc@@pop}
+\def\tc@@pop{\tc@trapescape\tc@futuretok{\def@popname{}\tc@tmp}{\tctestifx{%
+ \endtokcycraw\tc@futuretok}{\def@popname{}\tc@tmp}{\tctestifx{\tc@sptoken%
+ \tc@futuretok}{\spacepoppedtrue\tc@@@pop}{\spacepoppedfalse\tc@@@pop}}}}%_____POP_
+\def\tcappto#1from#2{%
+ \expandafter\tc@defx\expandafter#1\expandafter{\expandafter#1#2}}
+\def\tcpopliteralappto#1{\tcpopliteral\@tmp\tcappto#1from\@tmp}
+\def\tcpopappto#1{\tcpop\@tmp\tcappto#1from\@tmp}%___________________________APPEND_
+\long\def\tcpopwhitespace#1#2\@tokcycle{\def\tc@popname{#1}\def@popname{}%
+ \def\tc@tmp{#2\@tokcycle}\futurelet\tc@futuretok\tc@popspc}
+\def\tc@popspc{\tctestifx{\tc@sptoken\tc@futuretok}{\discern@space}{\tc@tmp}}
+\def\discern@space{\begingroup\def\@@spcT##1{\tctestifcon\ifimplicittok{\gdef
+ \tc@nxt{\tc@tmp##1}}{\gdef\tc@nxt{\def@popname{##1}\tc@tmp}}\endgroup
+ \tc@nxt}\stringify\@@@@@@spcT}%_____________________________________________SPACE_
+\long\def\@tcpush#1#2\@tokcycle{\def\tc@tmp{#2\@tokcycle}\expandafter\tc@tmp#1}
+\long\def\@tcpushgroup#1#2\@tokcycle{\def\tc@tmp{#2\@tokcycle}\expandafter\tc@tmp
+ \expandafter{#1}}
+% ...BORROW \addcytoks OPTIONAL ARGUMENT EXPANSION FEATURE FOR \tcpush[group]
+\def\tcpush{\bgroup\long\def\tc@addtotoks##1{\egroup
+ \@tcpush{##1}}\futurelet\nxttok\addcytoks@A}
+\def\tcpushgroup{\bgroup\long\def\tc@addtotoks##1{\egroup
+ \@tcpushgroup{##1}}\futurelet\nxttok\addcytoks@A}%___________________________PUSH_
% EXPRESS-INTERFACE - ALLOWS TO EXTERNALLY DEFINE DIRECTIVES
\def\Characterdirective{\def\@chrT##1}
\def\Groupdirective{\long\def\@grpT##1}
@@ -247,7 +284,7 @@ v1.2 2020/10/01
in the definition \theactivespace. The flags \implicittok and \activetok
are both set true, and the \activechar flag is checked, as well.
-v1.3 2021/03/09
+v1.3 2021/03/10
- Introduced \xtokcycleenvironment, similar to \tokcycleenvironment, but
allows two additional arguments, defining the setup and trailing code
that will be run prior to the invocation and following conclusion of the
@@ -283,3 +320,16 @@ v1.3 2021/03/09
\tcdepth associated with the Group directive (also, outer token cycle
operates with depth = 0 rather than 1).
- Renamed \@defgroupedcytoks to \defineexit@grouped, to better match function.
+
+v1.4 2021/05/26
+ - Concerning the \@@@@spcT macro: previously, active-implicit spaces
+ were passed to the Spacedirective as \tc@sptoken, with the \string of the
+ active char passed in \theactivespace. Now, the active-implicit space token
+ itself is passed to the Spacedirective instead of \tc@sptoken, but only *IF*
+ the charcode of that character is currently active; otherwise, a generic
+ implicit space, \tcsptoken is passed.
+ - Introduced a set of "look ahead" macros: \tcpeek, \tcpop, \tcpopliteral,
+ \tcpopappto, \tcpopliteralappto, \tcappto#1from#2, \tcpopuntil,
+ \tcpopwhitespace, \tcpush, and \tcpushgroup.
+ - Bug fixed in \tc@addtoks definition, in the event that #2 was a number.
+
diff --git a/macros/generic/xint/CHANGES.html b/macros/generic/xint/CHANGES.html
index 21b66e96bc..f1edf6fd88 100644
--- a/macros/generic/xint/CHANGES.html
+++ b/macros/generic/xint/CHANGES.html
@@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
- <meta name="author" content="xint 1.4g" />
+ <meta name="author" content="xint 1.4h" />
<title>CHANGE LOG</title>
<style type="text/css">
code{white-space: pre-wrap;}
@@ -25,66 +25,69 @@
<body>
<header>
<h1 class="title">CHANGE LOG</h1>
-<p class="author">xint 1.4g</p>
-<p class="date">2021/05/25</p>
+<p class="author">xint 1.4h</p>
+<p class="date">2021/05/27</p>
</header>
<nav id="TOC">
<ul>
+<li><a href="#h-20210527"><code>1.4h (2021/05/27)</code></a><ul>
+<li><a href="#bug-fixes">Bug fixes</a></li>
+</ul></li>
<li><a href="#g-20210525"><code>1.4g (2021/05/25)</code></a><ul>
<li><a href="#breaking-changes">Breaking changes</a></li>
<li><a href="#deprecated">Deprecated</a></li>
-<li><a href="#bug-fixes">Bug fixes</a></li>
+<li><a href="#bug-fixes-1">Bug fixes</a></li>
<li><a href="#new-features">New features</a></li>
</ul></li>
<li><a href="#f-20210510"><code>1.4f (2021/05/10)</code></a><ul>
<li><a href="#breaking-changes-1">Breaking changes</a></li>
-<li><a href="#bug-fixes-1">Bug fixes</a></li>
+<li><a href="#bug-fixes-2">Bug fixes</a></li>
</ul></li>
<li><a href="#e-20210505"><code>1.4e (2021/05/05)</code></a><ul>
<li><a href="#breaking-changes-2">Breaking changes</a></li>
<li><a href="#new-features-1">New features</a></li>
-<li><a href="#bug-fixes-2">Bug fixes</a></li>
+<li><a href="#bug-fixes-3">Bug fixes</a></li>
</ul></li>
<li><a href="#d-20210329"><code>1.4d (2021/03/29)</code></a><ul>
<li><a href="#breaking-changes-3">Breaking changes</a></li>
-<li><a href="#bug-fixes-3">Bug fixes</a></li>
+<li><a href="#bug-fixes-4">Bug fixes</a></li>
</ul></li>
<li><a href="#c-20210220"><code>1.4c (2021/02/20)</code></a><ul>
-<li><a href="#bug-fixes-4">Bug fixes</a></li>
+<li><a href="#bug-fixes-5">Bug fixes</a></li>
</ul></li>
<li><a href="#b-20200225"><code>1.4b (2020/02/25)</code></a><ul>
<li><a href="#future">Future</a></li>
<li><a href="#new-features-2">New features</a></li>
-<li><a href="#bug-fixes-5">Bug fixes</a></li>
+<li><a href="#bug-fixes-6">Bug fixes</a></li>
</ul></li>
<li><a href="#a-20200219"><code>1.4a (2020/02/19)</code></a><ul>
<li><a href="#breaking-changes-4">Breaking changes</a></li>
<li><a href="#new-features-3">New features</a></li>
-<li><a href="#bug-fixes-6">Bug fixes</a></li>
+<li><a href="#bug-fixes-7">Bug fixes</a></li>
</ul></li>
<li><a href="#section"><code>1.4 (2020/01/31)</code></a><ul>
<li><a href="#breaking-changes-5">Breaking changes</a></li>
<li><a href="#improvements-and-new-features">Improvements and new features</a></li>
-<li><a href="#bug-fixes-7">Bug fixes</a></li>
+<li><a href="#bug-fixes-8">Bug fixes</a></li>
<li><a href="#todo">TODO</a></li>
</ul></li>
<li><a href="#f-20190910"><code>1.3f (2019/09/10)</code></a><ul>
<li><a href="#improvements-and-new-features-1">Improvements and new features</a></li>
-<li><a href="#bug-fixes-8">Bug fixes</a></li>
+<li><a href="#bug-fixes-9">Bug fixes</a></li>
</ul></li>
<li><a href="#e-20190405"><code>1.3e (2019/04/05)</code></a><ul>
<li><a href="#breaking-changes-6">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-2">Improvements and new features</a></li>
-<li><a href="#bug-fixes-9">Bug fixes</a></li>
+<li><a href="#bug-fixes-10">Bug fixes</a></li>
</ul></li>
<li><a href="#d-20190106"><code>1.3d (2019/01/06)</code></a><ul>
<li><a href="#breaking-changes-7">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-3">Improvements and new features</a></li>
-<li><a href="#bug-fixes-10">Bug fixes</a></li>
+<li><a href="#bug-fixes-11">Bug fixes</a></li>
</ul></li>
<li><a href="#c-20180617"><code>1.3c (2018/06/17)</code></a><ul>
<li><a href="#improvements-and-new-features-4">Improvements and new features</a></li>
-<li><a href="#bug-fixes-11">Bug fixes</a></li>
+<li><a href="#bug-fixes-12">Bug fixes</a></li>
</ul></li>
<li><a href="#b-20180518"><code>1.3b (2018/05/18)</code></a><ul>
<li><a href="#improvements-and-new-features-5">Improvements and new features</a></li>
@@ -92,7 +95,7 @@
<li><a href="#a-20180307"><code>1.3a (2018/03/07)</code></a><ul>
<li><a href="#removed">Removed</a></li>
<li><a href="#improvements-and-new-features-6">Improvements and new features</a></li>
-<li><a href="#bug-fixes-12">Bug fixes</a></li>
+<li><a href="#bug-fixes-13">Bug fixes</a></li>
</ul></li>
<li><a href="#section-1"><code>1.3 (2018/03/01)</code></a><ul>
<li><a href="#breaking-changes-8">Breaking changes</a></li>
@@ -100,12 +103,12 @@
</ul></li>
<li><a href="#q-20180206"><code>1.2q (2018/02/06)</code></a><ul>
<li><a href="#improvements-and-new-features-8">Improvements and new features</a></li>
-<li><a href="#bug-fixes-13">Bug fixes</a></li>
+<li><a href="#bug-fixes-14">Bug fixes</a></li>
</ul></li>
<li><a href="#p-20171205"><code>1.2p (2017/12/05)</code></a><ul>
<li><a href="#breaking-changes-9">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-9">Improvements and new features</a></li>
-<li><a href="#bug-fixes-14">Bug fixes</a></li>
+<li><a href="#bug-fixes-15">Bug fixes</a></li>
</ul></li>
<li><a href="#o-20170829"><code>1.2o (2017/08/29)</code></a><ul>
<li><a href="#breaking-changes-10">Breaking changes</a></li>
@@ -118,31 +121,31 @@
<li><a href="#m-20170731"><code>1.2m (2017/07/31)</code></a><ul>
<li><a href="#breaking-changes-12">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-11">Improvements and new features</a></li>
-<li><a href="#bug-fixes-15">Bug fixes</a></li>
+<li><a href="#bug-fixes-16">Bug fixes</a></li>
</ul></li>
<li><a href="#l-20170726"><code>1.2l (2017/07/26)</code></a><ul>
<li><a href="#removed-1">Removed</a></li>
<li><a href="#improvements-and-new-features-12">Improvements and new features</a></li>
-<li><a href="#bug-fixes-16">Bug fixes</a></li>
+<li><a href="#bug-fixes-17">Bug fixes</a></li>
</ul></li>
<li><a href="#k-20170106"><code>1.2k (2017/01/06)</code></a><ul>
<li><a href="#breaking-changes-13">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-13">Improvements and new features</a></li>
-<li><a href="#bug-fixes-17">Bug fixes</a></li>
+<li><a href="#bug-fixes-18">Bug fixes</a></li>
</ul></li>
<li><a href="#j-20161222"><code>1.2j (2016/12/22)</code></a><ul>
<li><a href="#improvements-and-new-features-14">Improvements and new features</a></li>
-<li><a href="#bug-fixes-18">Bug fixes</a></li>
+<li><a href="#bug-fixes-19">Bug fixes</a></li>
</ul></li>
<li><a href="#i-20161213"><code>1.2i (2016/12/13)</code></a><ul>
<li><a href="#breaking-changes-14">Breaking changes</a></li>
<li><a href="#removed-2">Removed</a></li>
<li><a href="#improvements-and-new-features-15">Improvements and new features</a></li>
-<li><a href="#bug-fixes-19">Bug fixes</a></li>
+<li><a href="#bug-fixes-20">Bug fixes</a></li>
</ul></li>
<li><a href="#h-20161120"><code>1.2h (2016/11/20)</code></a><ul>
<li><a href="#improvements-and-new-features-16">Improvements and new features</a></li>
-<li><a href="#bug-fixes-20">Bug fixes</a></li>
+<li><a href="#bug-fixes-21">Bug fixes</a></li>
</ul></li>
<li><a href="#g-20160319"><code>1.2g (2016/03/19)</code></a><ul>
<li><a href="#breaking-changes-15">Breaking changes</a></li>
@@ -151,26 +154,26 @@
<li><a href="#f-20160312"><code>1.2f (2016/03/12)</code></a><ul>
<li><a href="#breaking-changes-16">Breaking changes</a></li>
<li><a href="#improvements-and-new-features-18">Improvements and new features</a></li>
-<li><a href="#bug-fixes-21">Bug fixes</a></li>
+<li><a href="#bug-fixes-22">Bug fixes</a></li>
</ul></li>
<li><a href="#e-20151122"><code>1.2e (2015/11/22)</code></a><ul>
<li><a href="#improvements-and-new-features-19">Improvements and new features</a></li>
-<li><a href="#bug-fixes-22">Bug fixes</a></li>
+<li><a href="#bug-fixes-23">Bug fixes</a></li>
</ul></li>
<li><a href="#d-20151118"><code>1.2d (2015/11/18)</code></a><ul>
<li><a href="#improvements-and-new-features-20">Improvements and new features</a></li>
-<li><a href="#bug-fixes-23">Bug fixes</a></li>
+<li><a href="#bug-fixes-24">Bug fixes</a></li>
</ul></li>
<li><a href="#c-20151116"><code>1.2c (2015/11/16)</code></a><ul>
<li><a href="#improvements-and-new-features-21">Improvements and new features</a></li>
-<li><a href="#bug-fixes-24">Bug fixes</a></li>
+<li><a href="#bug-fixes-25">Bug fixes</a></li>
</ul></li>
<li><a href="#b-20151029"><code>1.2b (2015/10/29)</code></a><ul>
-<li><a href="#bug-fixes-25">Bug fixes</a></li>
+<li><a href="#bug-fixes-26">Bug fixes</a></li>
</ul></li>
<li><a href="#a-20151019"><code>1.2a (2015/10/19)</code></a><ul>
<li><a href="#improvements-and-new-features-22">Improvements and new features</a></li>
-<li><a href="#bug-fixes-26">Bug fixes</a></li>
+<li><a href="#bug-fixes-27">Bug fixes</a></li>
</ul></li>
<li><a href="#section-2"><code>1.2 (2015/10/10)</code></a><ul>
<li><a href="#removed-3">Removed</a></li>
@@ -184,7 +187,7 @@
<li><a href="#removed-4">Removed</a></li>
<li><a href="#deprecated-2">Deprecated</a></li>
<li><a href="#improvements-and-new-features-24">Improvements and new features</a></li>
-<li><a href="#bug-fixes-27">Bug fixes</a></li>
+<li><a href="#bug-fixes-28">Bug fixes</a></li>
</ul></li>
<li><a href="#n-20140401"><code>1.09n (2014/04/01)</code></a></li>
<li><a href="#m-20140226"><code>1.09m (2014/02/26)</code></a></li>
@@ -212,10 +215,17 @@
<li><a href="#section-10"><code>1.0 (2013/03/28)</code></a></li>
</ul>
</nav>
-<pre><code>Source: xint.dtx 1.4g 2021/05/25 (doc 2021/05/25)
+<pre><code>Source: xint.dtx 1.4h 2021/05/27 (doc 2021/05/27)
Author: Jean-Francois Burnol
Info: Expandable operations on big integers, decimals, fractions
License: LPPL 1.3c</code></pre>
+<h2 id="h-20210527"><code>1.4h (2021/05/27)</code></h2>
+<h3 id="bug-fixes">Bug fixes</h3>
+<ul>
+<li><p><strong>xintexpr</strong>: the recent <code>1.4g</code> introduced a bug breaking input of the type <code>&lt;operator&gt;&lt;space token&gt;&lt;macro&gt;</code>.</p></li>
+<li><p><strong>xintexpr</strong>: since <code>1.4</code> (<code>2020/01/31</code>) the <code>omit</code> and <code>abort</code> keywords were broken if used inside a substitution, itself nested in a <code>seq()</code> or similar construct.</p></li>
+<li><p><strong>xintexpr</strong>: since <code>1.4c</code> the <code>\xintthespaceseparated</code> (added at <code>1.4a</code>) inserted two, not one, spaces at one specific location near the end of its output. A bit cosmetic problem, fixed nevertheless.</p></li>
+</ul>
<h2 id="g-20210525"><code>1.4g (2021/05/25)</code></h2>
<h3 id="breaking-changes">Breaking changes</h3>
<ul>
@@ -226,7 +236,7 @@ License: LPPL 1.3c</code></pre>
<ul>
<li><strong>xintfrac</strong>: old typesetting macros dating back to <code>1.03</code> and <code>1.04</code> releases <code>\xintFrac</code>, <code>\xintSignedFrac</code>, <code>\xintFwOver</code>, <code>\xintSignedFwOver</code> are deprecated. Please use the new names <code>\xintTeXFrac</code>, <code>\xintTeXsignedFrac</code>, <code>\xintTeXOver</code>, <code>\xintTeXsignedOver</code>. The old names will emit warnings.</li>
</ul>
-<h3 id="bug-fixes">Bug fixes</h3>
+<h3 id="bug-fixes-1">Bug fixes</h3>
<ul>
<li><p><strong>xintexpr</strong>: with <strong>xintbinhex</strong> loaded, <code>&quot;</code> is recognized as prefix for hexadecimal input; but a bug (present ever since this support for hexadecimal input was added) caused syntax such as <code>&quot;\macro</code> to break the parser. Also, leading zeros such as in <code>&quot;0000A</code> where not properly trimmed since <code>1.2m</code>.</p></li>
<li><p><strong>xintexpr</strong>: authorize <code>x! == y</code> without parentheses. Formerly the parser mis-interpreted <code>!</code> as first character of the <code>!=</code> not-equal-to comparison operator, subsequently causing breakage when finding the second <code>=</code>.</p></li>
@@ -255,7 +265,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: further changes in the computation of powers, see the bug fixes below.</p></li>
<li><p><strong>xintexpr</strong>: the <code>float_()</code> function got renamed into <code>float_dgt()</code>.</p></li>
</ul>
-<h3 id="bug-fixes-1">Bug fixes</h3>
+<h3 id="bug-fixes-2">Bug fixes</h3>
<ul>
<li><p><strong>xintexpr</strong>: the documentation said <code>float_()</code> function had been renamed <code>float_dgt()</code> but actually that was not yet the case.</p></li>
<li><p><strong>xintexpr</strong>: powers <code>a^b</code> (with exponent <code>b</code> neither integer nor half-integer) stopped being accurate regarding the last digits for <code>|b|</code> about <code>1000</code> and beyond. Except for <code>0.8&lt;a&lt;1.25</code> for which accuracy was maintained up to about <code>|b|=10^7</code>. Fixed via keeping the same suitable number of extra digits for internal computations of logarithms, independently of whether <code>a</code> is close to <code>1</code> or not.</p></li>
@@ -284,7 +294,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintfrac</strong>: <code>\xintPFloatE</code> may be redefined as a macro which fetches the scientific exponent as a mandatory argument delimited with a dot, and outputs a suitable formatted result (f-expandably), also delimited with a dot which will be removed by internal processing. The default however simply expands to the letter <code>e</code>.</p></li>
<li><p><strong>xintfrac</strong>: <code>\xintDecToStringREZ</code> is like <code>\xintDecToString</code> but starts by removing trailing zeroes.</p></li>
</ul>
-<h3 id="bug-fixes-2">Bug fixes</h3>
+<h3 id="bug-fixes-3">Bug fixes</h3>
<ul>
<li><strong>xintfrac</strong>, <strong>xintexpr</strong>: it was not possible to use <code>\xinttheDigits</code> in the right hand side of an <code>\xintDigits</code> assignment. For example: <code>\xintDigits*:=\numexpr\xinttheDigits+4;</code>. This is now allowed, and the same applies to the macro interface, for example <code>\xintSetDigits*{\xinttheDigits+4}</code>.</li>
</ul>
@@ -295,7 +305,7 @@ License: LPPL 1.3c</code></pre>
<li><p>The output of <code>gcd()</code> and <code>lcm()</code> as applied to fractions is now always in lowest terms.</p></li>
<li><p>The log message to report a variable creation (if <code>\xintverbosetrue</code>) does not use (double) quotes anymore around the name. By the way, quotes were never used for function names.</p></li>
</ul>
-<h3 id="bug-fixes-3">Bug fixes</h3>
+<h3 id="bug-fixes-4">Bug fixes</h3>
<ul>
<li><p>Ever since <code>1.3</code> the <code>quo()</code> and <code>rem()</code> functions in <code>\xintexpr</code> (not the ones in <code>\xintiiexpr</code>) were broken as their (officially deprecated) support macros had been removed! They had somewhat useless definitions anyway. They have now been officially removed from the syntax. Their siblings in <code>\xintiieval</code> were renamed to <code>iquo()</code> and <code>irem()</code>.</p></li>
<li><p>Sadly, <code>gcd()</code> was broken in <code>\xintexpr</code> since <code>1.4</code>, if the first argument vanished. And <code>gcd()</code> was broken in <code>\xintiiexpr</code> since <code>1.3d</code> if <em>any</em> argument vanished. I did have a unit test! (which obviously was too limited …)</p>
@@ -303,7 +313,7 @@ License: LPPL 1.3c</code></pre>
<li><p>The <code>first()</code> and <code>last()</code> functions, if used as arguments to numerical functions such as <code>sqr()</code> inside an <code>\xintdeffunc</code> caused the defined function to be broken.</p></li>
</ul>
<h2 id="c-20210220"><code>1.4c (2021/02/20)</code></h2>
-<h3 id="bug-fixes-4">Bug fixes</h3>
+<h3 id="bug-fixes-5">Bug fixes</h3>
<ul>
<li>Fix <code>1.4</code> regression which broke syntax <code>varname(...)</code> which supposedly is allowed and inserts a tacit multiplication.</li>
</ul>
@@ -322,7 +332,7 @@ License: LPPL 1.3c</code></pre>
<li><p>Chaining of comparison operators (e.g. <code>x&lt;y&lt;z</code>) as in Python (but all comparisons are done even if one is found false) and l3fp.</p></li>
<li><p>It was possible since <code>1.4</code>’s <code>\xintFracToSciE</code> to configure the separator between mantissas and exponents in the output of <code>\xinteval</code> but strangely there was no way to customize the output of <code>\xintfloateval</code>. The added <code>\xintPFloatE</code> fixes this.</p></li>
</ul>
-<h3 id="bug-fixes-5">Bug fixes</h3>
+<h3 id="bug-fixes-6">Bug fixes</h3>
<ul>
<li><code>\xintieval{[D]...}</code> with a negative <code>D</code> (a feature added at <code>1.4a</code>) used erroneously a catcode 12 <code>e</code> in output, which moreover remained immuned to the <code>\xintFracToSciE</code> setting.</li>
</ul>
@@ -338,7 +348,7 @@ License: LPPL 1.3c</code></pre>
<li><p>The optional argument <code>[D]</code> to <code>\xintieval/\xintiexpr</code> can be negative, with the same meaning as the non-negative case, i.e. rounding to an integer multiple of <code>10^(-D)</code>.</p>
<p>The same applies to the functions <code>trunc()</code> and <code>round()</code>. And to the <code>\xintTrunc</code>, <code>\xintRound</code>, <code>\xintiTrunc</code>, and <code>\xintiRound</code> macros of <strong>xintfrac</strong>.</p></li>
</ul>
-<h3 id="bug-fixes-6">Bug fixes</h3>
+<h3 id="bug-fixes-7">Bug fixes</h3>
<ul>
<li><p>Usage of <code>round()</code> and <code>trunc()</code> within <code>\xintdeffunc</code> got broken at <code>1.4</code>.</p></li>
<li><p><code>add()</code> and <code>mul()</code> were supposedly accepting the <code>omit</code>, <code>abort</code> and <code>break()</code> keywords since <code>1.4</code> but this was broken.</p></li>
@@ -390,7 +400,7 @@ License: LPPL 1.3c</code></pre>
<li><p>Function declarations are able to parse a much wider part of the syntax, but some severe limitations remain. Refer to the user manual for related information.</p></li>
<li><p>We have made an effort on some error messages, and when working interactively in a shell it may even be sometimes possible to insert for example a correct variable or function name in place of the not recognized one. But don’t expect miracles when trying to intervene in the midst of a purely expandable expansion…</p></li>
</ul>
-<h3 id="bug-fixes-7">Bug fixes</h3>
+<h3 id="bug-fixes-8">Bug fixes</h3>
<p>Bugs? Those identified in <code>1.3f</code> were almost features. As per <code>1.4</code> the code base of <strong>xintexpr</strong> received multiple successive core refactorings and added numerous new features, and our test suite although significantly enlarged is not yet extensive enough. Please report bugs by mail.</p>
<h3 id="todo">TODO</h3>
<ul>
@@ -406,7 +416,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: add starred variants <code>\xintDigits*</code> and <code>\xintSetDigits*</code> which execute <code>\xintreloadxinttrig</code>.</p>
<p>Revert 1.3e ban on usage of <code>\xinteval</code> et al. inside expressions by <code>\xintdeffunc</code>. And make them usable also inside macro definitions via <code>\xintNewExpr</code>.</p></li>
</ul>
-<h3 id="bug-fixes-8">Bug fixes</h3>
+<h3 id="bug-fixes-9">Bug fixes</h3>
<ul>
<li><p><strong>xintexpr</strong>: fix bug preventing usage of <code>\xintdefefunc</code> to define a function without variables.</p>
<p>Fix some issue with <code>\xintfloatexpr[D]..\relax</code> if used inside an expression parsed by <code>\xintdeffunc</code> et al.</p></li>
@@ -426,7 +436,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: <code>\xintensuredummy</code>, <code>\xintrestorelettervar</code>.</p></li>
<li><p>The optional argument of <code>\xintfloatexpr</code> or <code>\xintfloateval</code> (it must be at start of braced argument) can be negative; it then means to trim (and round) from the output at float precision that many least significant digits.</p></li>
</ul>
-<h3 id="bug-fixes-9">Bug fixes</h3>
+<h3 id="bug-fixes-10">Bug fixes</h3>
<ul>
<li>Some bugfixes related to user functions with no variables at all; they were dysfunctional.</li>
</ul>
@@ -445,7 +455,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: functions <code>isone()</code> and <code>isint()</code>.</p></li>
<li><p><strong>xintexpr</strong>: <code>\xinteval</code>, <code>\xintieval</code>, <code>\xintiieval</code>, and <code>\xintfloateval</code> as synonyms to <code>\xinttheexpr...\relax</code> etc…, but with the (comma-separated) expression as a usual braced macro argument.</p></li>
</ul>
-<h3 id="bug-fixes-10">Bug fixes</h3>
+<h3 id="bug-fixes-11">Bug fixes</h3>
<ul>
<li><strong>xintcore</strong>, <strong>xintexpr</strong> : division in <code>\xintiiexpr</code> was broken for a zero dividend and a one-digit divisor (e.g. <code>0//7</code>) since <code>1.2p</code> due to a bug in <code>\xintiiDivMod</code> for such arguments. The bug was signaled (thanks to Kpym for report) and fixed shortly after <code>1.3c</code> release but I then completely forgot to upload a bugfix release to CTAN at that time, apologies for that.</li>
</ul>
@@ -458,7 +468,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: <code>\xintdefvar</code>, <code>\xintdeffunc</code> and their variants try to set the catcode of the semi-colon which delimits their arguments; of course this will not work if that catcode is already frozen.</p></li>
<li><p><code>\xintUniformDeviate</code> is better documented and <code>sourcexint.pdf</code> is better hyperlinked and includes indices for the macros defined by each package.</p></li>
</ul>
-<h3 id="bug-fixes-11">Bug fixes</h3>
+<h3 id="bug-fixes-12">Bug fixes</h3>
<ul>
<li><strong>xintfrac</strong>: since <code>1.3</code> release, it loaded <strong>xintgcd</strong> in contradiction to what the documentation says (hence also <strong>xintexpr</strong> loaded <strong>xintgcd</strong> automatically). There is no actual dependency so the loading is removed for now.</li>
</ul>
@@ -484,7 +494,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintfrac</strong>: <code>\xintREZ</code> is faster on inputs having one hundred digits or more.</p></li>
<li><p>Added to the user manual mention of macros such as <code>\xintDivFloor</code>, <code>\xintMod</code>, <code>\xintModTrunc</code>, which had been left out so far.</p></li>
</ul>
-<h3 id="bug-fixes-12">Bug fixes</h3>
+<h3 id="bug-fixes-13">Bug fixes</h3>
<ul>
<li><strong>xintexpr</strong>: the mechanism for adjunction to the expression parsers of user defined functions was refactored and improved at previous release <code>1.3</code>: in particular recursive definitions became possible. But an oversight made these recursive functions quite inefficient (to remain polite.) This release fixes the problem.</li>
</ul>
@@ -507,7 +517,7 @@ License: LPPL 1.3c</code></pre>
<ul>
<li><strong>xintexpr</strong>: tacit multiplication extended to cases such as <code>3!4!5!</code> or <code>(1+2)3</code>.</li>
</ul>
-<h3 id="bug-fixes-13">Bug fixes</h3>
+<h3 id="bug-fixes-14">Bug fixes</h3>
<ul>
<li><strong>xintcore</strong>: sadly, refactoring at <code>1.2l</code> of subtraction left an extra character in an inner macro causing breakage in some rare circumstances. This should not have escaped our test suite!</li>
</ul>
@@ -526,7 +536,7 @@ License: LPPL 1.3c</code></pre>
<li><p><strong>xintexpr</strong>: <code>\xintdefvar</code>’s syntax is extended to allow simultaneous assignments. Examples: <code>\xintdefvar x1, x2, x3 := 1, 3**10, 3**20;</code> or <code>\xintdefiivar A, B := B, A 'mod' B;</code> for already defined variables <code>A</code> and <code>B</code>.</p></li>
<li><p><strong>xintexpr</strong>: added <code>divmod()</code> to the built-in functions. It is associated with floored division, like the Python language <code>divmod()</code>. Related support macros added to <strong>xintcore</strong>, and <strong>xintfrac</strong>.</p></li>
</ul>
-<h3 id="bug-fixes-14">Bug fixes</h3>
+<h3 id="bug-fixes-15">Bug fixes</h3>
<ul>
<li><p><strong>xintgcd</strong>: <code>\xintBezout{6}{3}</code> (for example) expanded to <code>{6}{3}{-0}{-1}{3}</code>, but the <code>-0</code> should have been <code>0</code>.</p></li>
<li><p><strong>xintgcd</strong>: it still used macro <code>\xintiAbs</code> although the latter had been deprecated from <strong>xintcore</strong>.</p></li>
@@ -569,7 +579,7 @@ License: LPPL 1.3c</code></pre>
<ul>
<li><strong>xintbinhex</strong>: all macros have been rewritten using techniques from the 1.2 release (they had remained unmodified since <code>1.08</code> of <code>2013/06/07</code>.) The new macros are faster but limited to a few thousand digits. The <code>1.08</code> routines could handle tens of thousands of digits, but not in a reasonable time.</li>
</ul>
-<h3 id="bug-fixes-15">Bug fixes</h3>
+<h3 id="bug-fixes-16">Bug fixes</h3>
<ul>
<li><p>user manual: the <code>Changes</code> section wrongly stated at <code>1.2l</code> that the macros of <strong>xintbinhex</strong> had been made robust against non terminated input such as <code>\number\mathcode`\-</code>. Unfortunately the author fell into the trap of believing his own documentation and he forgot to actually implement the change. Now done.</p></li>
<li><p>user manual: the PDF bookmarks were messed up.</p></li>
@@ -590,7 +600,7 @@ License: LPPL 1.3c</code></pre>
<p>The situation with expressions is unchanged: syntax such as <code>\xintexpr \numexpr1+2\relax</code> is illegal as the ending <code>\relax</code> token will get swallowed by the <code>\numexpr</code>; but it is needed by the <code>xintexpr</code>-ession parser, hence the parser will expand forward and presumably end with in an “illegal token” error, or provoke some low-level TeX error (N.B.: a closing brace <code>}</code> for example can not terminate an <code>xintexpr</code>-ession, the parser must find a <code>\relax</code> token at some point). Thus there must be in this example a second <code>\relax</code>.</p></li>
<li><p>experimental code for error conditions; there is no complete user interface yet, it is done in preparation for next major release and is completely unstable and undocumented.</p></li>
</ul>
-<h3 id="bug-fixes-16">Bug fixes</h3>
+<h3 id="bug-fixes-17">Bug fixes</h3>
<ul>
<li><p><strong>xintbinhex</strong>: since <code>1.2 (2015/10/10)</code>, <code>\xintHexToDec</code> was broken due to an undefined macro (it was in <code>xint.sty</code>, but the module by itself is supposedly dependent only upon <code>xintcore.sty</code>).</p></li>
<li><p><strong>xintgcd</strong>: macro <code>\xintBezout</code> produced partially wrong output if one of its two arguments was zero.</p></li>
@@ -609,7 +619,7 @@ License: LPPL 1.3c</code></pre>
<li><p>added <code>\xintiSqrtR</code>, there was only <code>\xintiiSqrtR</code> alongside <code>\xintiSqrt</code> and <code>\xintiiSqrt</code> (<strong>xint</strong>).</p></li>
<li><p>added non public <code>\xintLastItem:f:csv</code> to <strong>xinttools</strong> for faster <code>last()</code> function, and improved <code>\xintNewExpr</code> compatibility. Also <code>\xintFirstItem:f:csv</code>.</p></li>
</ul>
-<h3 id="bug-fixes-17">Bug fixes</h3>
+<h3 id="bug-fixes-18">Bug fixes</h3>
<ul>
<li><p>the <code>1.2f</code> half-integer powers computed within <code>\xintfloatexpr</code> had a silly rounding to the target precision just <em>before</em> the final square-root extraction, thus possibly losing some precision. The <code>1.2k</code> implementation keeps guard digits for this final square root extraction. As for integer exponents, it is guaranteed that the computed value differs from the exact one by less than <code>0.52 ulp</code> (for inputs having at most <code>\xinttheDigits</code> digits.)</p></li>
<li><p>more regressions from <code>1.2i</code> were fixed: <code>\xintLen</code> (<strong>xint</strong>, <strong>xintfrac</strong>) and <code>\xintDouble</code> (<strong>xintcore</strong>) had forgotten that their argument was allowed to be negative. A regression test suite is now in place and is being slowly expanded to cover more macros.</p></li>
@@ -625,7 +635,7 @@ License: LPPL 1.3c</code></pre>
</ol></li>
<li><p>significant documentations tweaks (inclusive of suppressing things!), and among them two beautiful hyperlinked tables with both horizontal and vertical rules which bring the documentation of the <strong>xintexpr</strong> syntax to a kind of awe-inspiring perfection… except that implementation of some math functions is still lacking.</p></li>
</ul>
-<h3 id="bug-fixes-18">Bug fixes</h3>
+<h3 id="bug-fixes-19">Bug fixes</h3>
<ul>
<li>fix two <code>1.2i</code> regressions caused by undefined macros (<code>\xintNthElt</code> in certain branches and <code>[list][N]</code> item extraction in certain cases.) The test files existed but were not executed prior to release. Automation in progress.</li>
</ul>
@@ -657,7 +667,7 @@ License: LPPL 1.3c</code></pre>
<li><p>the documentation has again been (slightly) re-organized; it has a new sub-section on the Miller-Rabin primality test, to illustrate some use of <code>\xintNewFunction</code> for recursive definitions.</p></li>
<li><p>the documentation has dropped the LaTeX “command” terminology (which had been used initially in 2013 for some forgotten reasons and should have been removed long ago) and uses only the more apt “macro”, as after all, all of <strong>xint</strong> is about expansion of macros (plus the use of <code>\numexpr</code>).</p></li>
</ul>
-<h3 id="bug-fixes-19">Bug fixes</h3>
+<h3 id="bug-fixes-20">Bug fixes</h3>
<ul>
<li><code>\xintDecSplitL</code> and <code>\xintDecSplitR</code> from <strong>xint</strong> produced their output in a spurious brace pair (bug introduced in <code>1.2f</code>).</li>
</ul>
@@ -667,7 +677,7 @@ License: LPPL 1.3c</code></pre>
<li><p>new macro <code>\xintNewFunction</code> in <strong>xintexpr</strong> which allows to extend the parser syntax with functions in situations where <code>\xintdeffunc</code> is not usable (typically, because dummy variables are used over a not yet determined range of values because it depends on the variables).</p></li>
<li><p>after three years of strict obedience to <code>xint</code> prefix, now <code>\thexintexpr</code>, <code>\thexintiexpr</code>, <code>\thexintfloatexpr</code>, and <code>\thexintiiexpr</code> are provided as synonyms to <code>\xinttheexpr</code>, etc…</p></li>
</ul>
-<h3 id="bug-fixes-20">Bug fixes</h3>
+<h3 id="bug-fixes-21">Bug fixes</h3>
<ul>
<li><p>the <code>(cond)?{foo}{bar}</code> operator from <strong>xintexpr</strong> mis-behaved in certain circumstances (such as an empty <code>foo</code>).</p></li>
<li><p>the <strong>xintexpr</strong> <code>1.2f</code> <code>binomial</code> function (which uses <code>\xintiiBinomial</code> from <strong>xint.sty</strong> or <code>\xintFloatBinomial</code> from <strong>xintfrac.sty</strong>) deliberately raised an error for <code>binomial(x,y)</code> with <code>y&lt;0</code> or <code>x&lt;y</code>. This was unfortunate, and it now simply evaluates to zero in such cases.</p></li>
@@ -707,7 +717,7 @@ License: LPPL 1.3c</code></pre>
<li><p>(TeXperts only) the macros defined (internally) from <code>\xintdeffunc</code> et al. constructs do not incorporate an initial <code>\romannumeral</code> anymore.</p></li>
<li><p>renewed desperate efforts at improving the documentation by random shuffling of sections and well thought additions; cuts were considered and even performed.</p></li>
</ul>
-<h3 id="bug-fixes-21">Bug fixes</h3>
+<h3 id="bug-fixes-22">Bug fixes</h3>
<ul>
<li><p>squaring macro <code>\xintSqr</code> from <strong>xintfrac.sty</strong> was broken due to a misspelled sub-macro name. Dates back to <code>1.1</code> release of <code>2014/10/28</code> <code>:-((</code>.</p></li>
<li><p><code>1.2c</code>’s fix to the subtraction bug from <code>1.2</code> introduced another bug, which in some cases could create leading zeroes in the output, or even worse. This could invalidate other routines using subtractions, like <code>\xintiiSquareRoot</code>.</p></li>
@@ -721,7 +731,7 @@ License: LPPL 1.3c</code></pre>
<li><p>a space in <code>\xintdeffunc f(x)&lt;space&gt;:= expression ;</code> is now accepted.</p></li>
<li><p>documentation enhancements: the <em>Quick Sort</em> section with its included code samples has been entirely re-written; the <em>Commands of the xintexpr package</em> section has been extended and reviewed entirely.</p></li>
</ul>
-<h3 id="bug-fixes-22">Bug fixes</h3>
+<h3 id="bug-fixes-23">Bug fixes</h3>
<ul>
<li><p>in <strong>xintfrac</strong>: the <code>\xintFloatFac</code> from release <code>1.2</code> parsed its argument only through <code>\numexpr</code> but it should have used <code>\xintNum</code>.</p></li>
<li><p>in <strong>xintexpr</strong>: release <code>1.2d</code> had broken the recognition of sub-expressions immediately after variable names (with tacit multiplication).</p></li>
@@ -734,7 +744,7 @@ License: LPPL 1.3c</code></pre>
<li><p>tacit multiplication applies to more cases, for example (x+y)z, and always ties more than standard * infix operator, e.g. x/2y is like x/(2*y).</p></li>
<li><p>some documentation enhancements, particularly in the chapter on xintexpr.sty, and also in the code source comments.</p></li>
</ul>
-<h3 id="bug-fixes-23">Bug fixes</h3>
+<h3 id="bug-fixes-24">Bug fixes</h3>
<ul>
<li>in <strong>xintcore</strong>: release <code>1.2c</code> had inadvertently broken the <code>\xintiiDivRound</code> macro.</li>
</ul>
@@ -744,12 +754,12 @@ License: LPPL 1.3c</code></pre>
<li><p>macros <code>\xintdeffunc</code>, <code>\xintdefiifunc</code>, <code>\xintdeffloatfunc</code> and boolean <code>\ifxintverbose</code>.</p></li>
<li><p>on-going code improvements and documentation enhancements, but stopped in order to issue this bugfix release.</p></li>
</ul>
-<h3 id="bug-fixes-24">Bug fixes</h3>
+<h3 id="bug-fixes-25">Bug fixes</h3>
<ul>
<li>in <strong>xintcore</strong>: recent release <code>1.2</code> introduced a bug in the subtraction (happened when 00000001 was found under certain circumstances at certain mod 8 locations).</li>
</ul>
<h2 id="b-20151029"><code>1.2b (2015/10/29)</code></h2>
-<h3 id="bug-fixes-25">Bug fixes</h3>
+<h3 id="bug-fixes-26">Bug fixes</h3>
<ul>
<li>in <strong>xintcore</strong>: recent release <code>1.2</code> introduced a bug in the division macros, causing a crash when the divisor started with 99999999 (it was attempted to use with 1+99999999 a subroutine expecting only 8-digits numbers).</li>
</ul>
@@ -760,7 +770,7 @@ License: LPPL 1.3c</code></pre>
<li><p>added <code>\xintiiMaxof/\xintiiMinof</code> (<strong>xint</strong>).</p></li>
<li><p>TeX hackers only: replaced all code uses of <code>\romannumeral-`0</code> by the quicker <code>\romannumeral`&amp;&amp;@</code> (<code>^</code> being used as letter, had to find another character usable with catcode 7).</p></li>
</ul>
-<h3 id="bug-fixes-26">Bug fixes</h3>
+<h3 id="bug-fixes-27">Bug fixes</h3>
<ul>
<li>in <strong>xintexpr</strong>: recent release <code>1.2</code> introduced a bad bug in the parsing of decimal numbers and as a result <code>\xinttheexpr 0.01\relax</code> expanded to <code>0</code> ! (sigh…)</li>
</ul>
@@ -861,7 +871,7 @@ License: LPPL 1.3c</code></pre>
<li><p><code>\xintthecoords</code> converts a comma separated list of an even number of items to the format expected by the <code>TikZ</code> <code>coordinates</code> syntax,</p></li>
<li><p>completely new version <code>\xintNewExpr</code>, <code>protect</code> function to handle external macros. The dollar sign <code>$</code> for place holders is not accepted anymore, only the standard macro parameter <code>#</code>. Not all constructs are compatible with <code>\xintNewExpr</code>.</p></li>
</ul>
-<h3 id="bug-fixes-27">Bug fixes</h3>
+<h3 id="bug-fixes-28">Bug fixes</h3>
<ul>
<li><p><code>\xintZapFirstSpaces</code> hence also <code>\xintZapSpaces</code> from package <strong>xinttools</strong> were buggy when used with an argument either empty or containing only space tokens.</p></li>
<li><p><code>\xintiiexpr</code> did not strip leading zeroes, hence <code>\xinttheiiexpr 001+1\relax</code> did not obtain the expected result …</p></li>
diff --git a/macros/generic/xint/README.md b/macros/generic/xint/README.md
index b298c0d45a..7351ecd696 100644
--- a/macros/generic/xint/README.md
+++ b/macros/generic/xint/README.md
@@ -1,8 +1,8 @@
% README
-% xint 1.4g
-% 2021/05/25
+% xint 1.4h
+% 2021/05/27
- Source: xint.dtx 1.4g 2021/05/25 (doc 2021/05/25)
+ Source: xint.dtx 1.4h 2021/05/27 (doc 2021/05/27)
Author: Jean-Francois Burnol
Info: Expandable operations on big integers, decimals, fractions
License: LPPL 1.3c
diff --git a/macros/generic/xint/sourcexint.pdf b/macros/generic/xint/sourcexint.pdf
index a17634ba82..55fa981cdc 100644
--- a/macros/generic/xint/sourcexint.pdf
+++ b/macros/generic/xint/sourcexint.pdf
Binary files differ
diff --git a/macros/generic/xint/xint.dtx b/macros/generic/xint/xint.dtx
index 119cbe560f..e8dceb81d4 100644
--- a/macros/generic/xint/xint.dtx
+++ b/macros/generic/xint/xint.dtx
@@ -3,27 +3,27 @@
% Extract all files via "etex xint.dtx" and do "make help"
% or follow instructions from extracted README.md.
%<*dtx>
-\def\xintdtxtimestamp {Time-stamp: <25-05-2021 at 18:36:42 CEST>}
+\def\xintdtxtimestamp {Time-stamp: <27-05-2021 at 11:42:22 CEST>}
%</dtx>
%<*drv>
%% ---------------------------------------------------------------
-\def\xintdocdate {2021/05/25}
-\def\xintbndldate{2021/05/25}
-\def\xintbndlversion {1.4g}
+\def\xintdocdate {2021/05/27}
+\def\xintbndldate{2021/05/27}
+\def\xintbndlversion {1.4h}
%</drv>
%<readme>% README
%<changes>% CHANGE LOG
-%<readme|changes>% xint 1.4g
-%<readme|changes>% 2021/05/25
+%<readme|changes>% xint 1.4h
+%<readme|changes>% 2021/05/27
%<readme|changes>
-%<readme|changes> Source: xint.dtx 1.4g 2021/05/25 (doc 2021/05/25)
+%<readme|changes> Source: xint.dtx 1.4h 2021/05/27 (doc 2021/05/27)
%<readme|changes> Author: Jean-Francois Burnol
%<readme|changes> Info: Expandable operations on big integers, decimals, fractions
%<readme|changes> License: LPPL 1.3c
%<readme|changes>
%<*!readme&!changes&!dohtmlsh&!makefile>
%% ---------------------------------------------------------------
-%% The xint bundle 1.4g 2021/05/25
+%% The xint bundle 1.4h 2021/05/27
%% Copyright (C) 2013-2021 by Jean-Francois Burnol
%<xintkernel>%% xintkernel: Paraphernalia for the xint packages
%<xinttools>%% xinttools: Expandable and non-expandable utilities
@@ -152,6 +152,22 @@ See `xint.pdf` for contact information.
%</readme>--------------------------------------------------------
%<*changes>-------------------------------------------------------
+`1.4h (2021/05/27)`
+----
+
+### Bug fixes
+
+ - **xintexpr**: the recent `1.4g` introduced a bug breaking input of
+ the type `<operator><space token><macro>`.
+
+ - **xintexpr**: since `1.4` (`2020/01/31`) the `omit` and `abort`
+ keywords were broken if used inside a substitution, itself nested in
+ a `seq()` or similar construct.
+
+ - **xintexpr**: since `1.4c` the `\xintthespaceseparated` (added at
+ `1.4a`) inserted two, not one, spaces at one specific location near
+ the end of its output. A bit cosmetic problem, fixed nevertheless.
+
`1.4g (2021/05/25)`
----
@@ -19011,7 +19027,7 @@ Please refer to |CHANGES.html| for a (very) detailed history.
\url{http://mirrors.ctan.org/macros/generic/xint/CHANGES.html}}
\begin{itemize}
-\item Release \expandafter|\xintbndlversion| of \expandafter|\xintbndldate|:
+\item Release |1.4g| of |2021/05/25|:
powers are now parsed in a right associative way. Removal of the
single-character operators |&|, \verb=|=, and |=| (deprecated at |1.1|).
Reformatted expandable error messages.
@@ -19297,7 +19313,7 @@ math shift catcode.
\fi
\XINT_providespackage
\ProvidesPackage {xintkernel}%
- [2021/05/25 v1.4g Paraphernalia for the xint packages (JFB)]%
+ [2021/05/27 v1.4h Paraphernalia for the xint packages (JFB)]%
% \end{macrocode}
% \subsection{Constants}
% \begin{macrocode}
@@ -20257,7 +20273,7 @@ mode) and will go ahead hoping repair\endcsname
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xinttools}%
- [2021/05/25 v1.4g Expandable and non-expandable utilities (JFB)]%
+ [2021/05/27 v1.4h Expandable and non-expandable utilities (JFB)]%
% \end{macrocode}
% \lverb|\XINT_toks is used in macros such as \xintFor. It is not used
% elsewhere in the xint bundle.|
@@ -22601,7 +22617,7 @@ mode) and will go ahead hoping repair\endcsname
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintcore}%
- [2021/05/25 v1.4g Expandable arithmetic on big integers (JFB)]%
+ [2021/05/27 v1.4h Expandable arithmetic on big integers (JFB)]%
% \end{macrocode}
% \subsection{(WIP!) Error conditions and exceptions}
% \lverb|As per the Mike Cowlishaw/IBM's General Decimal Arithmetic Specification
@@ -25955,7 +25971,7 @@ mode) and will go ahead hoping repair\endcsname
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xint}%
- [2021/05/25 v1.4g Expandable operations on big integers (JFB)]%
+ [2021/05/27 v1.4h Expandable operations on big integers (JFB)]%
% \end{macrocode}
% \subsection{More token management}
% \begin{macrocode}
@@ -28534,7 +28550,7 @@ mode) and will go ahead hoping repair\endcsname
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintbinhex}%
- [2021/05/25 v1.4g Expandable binary and hexadecimal conversions (JFB)]%
+ [2021/05/27 v1.4h Expandable binary and hexadecimal conversions (JFB)]%
% \end{macrocode}
% \subsection{Constants, etc...}
% \lverb|1.2n switches to \csname-governed expansion at various places.|
@@ -29206,7 +29222,7 @@ mode) and will go ahead hoping repair\endcsname
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintgcd}%
- [2021/05/25 v1.4g Euclide algorithm with xint package (JFB)]%
+ [2021/05/27 v1.4h Euclide algorithm with xint package (JFB)]%
% \end{macrocode}
% \subsection{\csh{xintBezout}}
% \lverb|&
@@ -29806,7 +29822,7 @@ mode) and will go ahead hoping repair\endcsname
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintfrac}%
- [2021/05/25 v1.4g Expandable operations on fractions (JFB)]%
+ [2021/05/27 v1.4h Expandable operations on fractions (JFB)]%
% \end{macrocode}
% \subsection{\csh{XINT_cntSgnFork}}
% \lverb|1.09i. Used internally, #1 must expand to \m@ne, \z@, or \@ne or
@@ -35274,7 +35290,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintseries}%
- [2021/05/25 v1.4g Expandable partial sums with xint package (JFB)]%
+ [2021/05/27 v1.4h Expandable partial sums with xint package (JFB)]%
% \end{macrocode}
% \subsection{\csh{xintSeries}}
% \begin{macrocode}
@@ -35782,7 +35798,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintcfrac}%
- [2021/05/25 v1.4g Expandable continued fractions with xint package (JFB)]%
+ [2021/05/27 v1.4h Expandable continued fractions with xint package (JFB)]%
% \end{macrocode}
% \subsection{\csh{xintCFrac}}
% \begin{macrocode}
@@ -37175,7 +37191,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
% \begin{macrocode}
\XINT_providespackage
\ProvidesPackage{xintexpr}%
- [2021/05/25 v1.4g Expandable expression parser (JFB)]%
+ [2021/05/27 v1.4h Expandable expression parser (JFB)]%
\catcode`! 11
\let\XINT_Cmp \xintiiCmp
\def\XINTfstop{\noexpand\XINTfstop}%
@@ -37434,8 +37450,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
%
% Usage of \xintiRound{0} for \xintiexpr without optional [D] means that
% \xintiexpr ... \relax wrapper can be used to insert rounded-to-integers
-% values in \xintiiexpr context: no post-fix [0] which would break it. But
-% this does not apply to the \xintiexpr [D]...\relax form with negative D.
+% values in \xintiiexpr context: no post-fix [0] which would break it.
%
% 1.4a add support for the optional argument [D] for \xintiexpr being negative
% D, with same meaning as the 1.4a modified \xintRound from xintfrac.sty.
@@ -37444,6 +37459,11 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
% optional argument uses raw format, not fixed point format on output,
% delegating fixed point conversion to an \XINTiexprprint now separated from
% \XINTexprprint.
+%
+% In case of negative [D], \xintiexpr [D]...\relax internally has the [0]
+% post-fix so it can not be inserted as sub-expression in \xintiiexpr without
+% a num() or \xintiexpr ...\relax (extra) wrapper.
+%
% |
% \begin{macrocode}
\def\xintexpr {\romannumeral0\xintexpro }%
@@ -37765,17 +37785,31 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
% separately for usage with PSTricks \listplot|
% \begin{macrocode}
\def\xintthespaceseparated#1%
- {\romannumeral`&&@\expandafter\xintthespaceseparated_a\romannumeral0#1}%
+ {\expanded\expandafter\xintthespaceseparated_a\romannumeral0#1}%
\def\xintthespaceseparated_a #1#2.#3%
- {\expanded{\expandafter\xintthespaceseparated_b\expanded#2.{#3},!,!,!,!,!,!,!,!,!,^}}%
+ {{\expandafter\xintthespaceseparated_b\expanded#2.{#3},!,!,!,!,!,!,!,!,!,^}}%
\def\xintthespaceseparated_b #1,#2,#3,#4,#5,#6,#7,#8,#9,%
{\xint_gob_til_! #9\xintthespaceseparated_c !%
#1#2#3#4#5#6#7#8#9%
\xintthespaceseparated_b}%
% \end{macrocode}
-% \lverb|1.4c I add a space here to stop the \romannumeral`^^@ if #1 is empty.|
+% \lverb|1.4c I add a space here to stop the \romannumeral`$&$&@ in case of
+% empty input.
+% But this space induces an extra un-needed space token after 9, 18, 27,...
+% items before the last group of less than 9 items.
+%
+% Fix (at 1.4h) is simple because I already use \expanded anyhow: I don't need
+% at all the \romannumeral`$&$&@ which was first in \xintthespaceseparated,
+% let's move the first \expanded which was in \xintthespaceseparated_a to
+% \xintthespaceseparated, and remove the extra space here in _c.
+%
+% (alternative would have been to put the space after #1 and accept a
+% systematic trailing space, at least it is more aesthetic).
+%
+% Again, I did have a test file, but it was not incorporated in my test suite,
+% so I discovered the problem accidentally by compiling all files in an archive.|
% \begin{macrocode}
-\def\xintthespaceseparated_c !#1!#2^{ #1}%
+\def\xintthespaceseparated_c !#1!#2^{#1}%
% \end{macrocode}
% \subsection{Hooks into the numeric parser for usage by the
% \cshnolabel{xintdeffunc} symbolic parser}
@@ -38892,7 +38926,14 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
% re-written for code readability only. Once we see that #1#2 is not a
% candidate to be or start an operator, we need to check if single-character
% operator #1 is really an operator and this is done via the existence of the
-% precedence token.|
+% precedence token.
+%
+% Unfortunately the 1.4g refactoring of the scanop macros had a bad bug:
+% \XINT_expr_scanop_c inserted \romannumeral`^^@ in stream but did not grab a
+% token first so a space would stop the \romannumeral and then the #2 in
+% \XINT_expr_scanop_d was not pre-expanded and ended up alone in \ifcat. It
+% is too distant in the past the time when I wrote the core of xintexpr in
+% 2013... older and dumber now.|
% \begin{macrocode}
\def\XINT_expr_scanop_b #1#2%
{%
@@ -38902,11 +38943,11 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
\fi\fi
\XINT_expr_foundop_a #1#2%
}%
-\def\XINT_expr_scanop_c #1#2#3#4#5% #1#2=\fi\fi
+\def\XINT_expr_scanop_c #1#2#3#4#5#6% #1#2=\fi\fi
{%
#1#2%
\expandafter\XINT_expr_scanop_d\csname XINT_expr_itself_#4#5\expandafter\endcsname
- \romannumeral`&&@%
+ \romannumeral`&&@#6%
}%
\def\XINT_expr_scanop_d #1#2%
{%
@@ -38922,7 +38963,7 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
\csname XINT_expr_precedence_#1\expandafter\endcsname
\expandafter #1%
\else
- \expandafter\XINT_expr_getop_a\romannumeral`&&@%
+ \expandafter\XINT_expr_getop\romannumeral`&&@%
\xint_afterfi{\XINT_expandableerror
{Expected an operator but got `#1'. Ignoring.}}%
\fi
@@ -40719,7 +40760,36 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
% \paragraph{The \cshn{omit} and \cshn{abort} keywords}
% \lverb|&
% Comments are currently undergoing reconstruction.
-% |
+%
+% The mechanism is somewhat complex. The operator !? will fetch a dummy value
+% ! or ^ which is then recognized int the loops implementing the various seq
+% etc... construct using dummy variables and implement omit and abort.
+%
+% In May 2021 I realized that the January 2020 1.4 had broken omit and abort
+% if used inside a subs(). The definition
+%(\edef\XINT_expr_var_omit #1\relax !{1\string !?!\relax !}%
+%)
+% conflicted with the 1.4 refactoring of «subs» and similar things
+% which had replaced formerly clean-up macros (of ! and what's next, as in
+% now defunct
+% \def\XINT_expr_subx:_end #1!#2#3{#1} which was involved in subs mechanism,
+% and by the way would be incompatible with multi-letter dummy variables) by usage
+% of an \iffalse as in "\relax\iffalse\relax !" to delimite a sub-expression, which was
+% supposed to be clever (the "\relax !" being delimiter for dummy variables).
+%
+% This \iffalse from subs mechanism ended up being gobbled by omit/abort thus
+% inducing breakage.
+%
+% Grabbing \relax #2! would be a fix but looks a bit dangerous, as there can
+% be a subexpression after the omit or abort bringing its own \relax, although
+% this is very very unlikely.
+%
+% I considered to modify the dummy variables delimiter from \relax ! to
+% \xint_Bye ! for example but got afraid from the ramifications, as all
+% structures handling dummy variables would have needed refactoring.
+%
+% So finally things here remain unchanged and the refactoring to fix this
+% breakage was done in \XINT_allexpr_subsx (and also subsm). See there. |
%
% \begin{macrocode}
\edef\XINT_expr_var_omit #1\relax !{1\string !?!\relax !}%
@@ -40954,17 +41024,69 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
\def\XINT_iiexpr_func_subsx #1#2{\XINT_allexpr_subsx \xintbareiieval }%
% \end{macrocode}
% \lverb|
-% #2 is the value to assign to the dummy variable
-% #3 is the dummy variable name (possibly multi-letter), #4 is the expression to evaluate
+% #2 is the value to assign to the dummy variable
+% #3 is the dummy variable name (possibly multi-letter), #4 is the expression
+% to evaluate
+%
+% 1.4 was doing something clever to get rid of the ! and tokens following it,
+% via an \iffalse...\fi which erased them and propagated the expansion to
+% trigger the getopt:
+%
+%(\expanded\bgroup\romannumeral0#1#4\relax \iffalse\relax !#3{#2}{\fi\expandafter}
+%)
+%
+% But sadly, with a delay of more than one year later (right after having
+% released 1.4g) I realized that this had broken omit and abort if inside a
+% subs. As omit and abort would clean all up to \relax !, this meant here
+% swallowing in particular the above \iffalse, leaving a dangling \fi. I had
+% the files which show this bug already at time of 1.4 release but did not
+% compile them, and they were not included in my test suite.
+%
+% I hesitated with modifying the delimiter from "\relax !" (catcode 11 !) to
+% "\relax \xint_Bye" for the dummy variables which would have allowed some
+% trickery with clean-up from \xint_Bye but got afraid from the breakage
+% potential of such refactoring with many induced changes.
+%
+% A variant like this:
+%( \def\XINT_allexpr_subsx #1#2#3#4%
+%: {%
+%: \expandafter\XINT_expr_clean_and_put_op_first
+%: \expanded
+%: {\romannumeral0#1#4\relax !#3{#2}\xint:\expandafter}\romannumeral`$&$&\XINT_expr_getop
+%: }%
+%: \def\XINT_expr_clean_and_put_op_first #1#2\xint:#3#4{#3#4{#1}}%
+%)
+% breaks nesting: the braces make variables encountered in #4 unable to
+% match their definition. This would work:
+%
+%( \def\XINT_allexpr_subsx #1#2#3#4%
+%: {%
+%: \expandafter\XINT_allexpr_subsx_clean\romannumeral0#1#4\relax !#3{#2}\xint:
+%: }%
+%: \def\XINT_allexpr_subsx_clean #1#2\xint:
+%: {%
+%: \expandafter\XINT_expr_put_op_first
+%: \expanded{\unexpanded{{#1}}\expandafter}\romannumeral`$&$&@\XINT_expr_getop
+%: }%
+%)
+% (not tested).
+%
+% But in the end I decided to simply fix the first envisioned code above.
+% This accepts expansion of supposedly inert #3{#2}. There is again the
+% \iffalse but it is moved to the right. This change limits possibly hacky
+% future developments.
+%
+% No need for the \expandafter's from \XINT_expr_put_op_first in \XINT_expr_clean_and_put_op_first.
% |
% \begin{macrocode}
\def\XINT_allexpr_subsx #1#2#3#4%
{%
- \expandafter\XINT_expr_put_op_first
+ \expandafter\XINT_expr_clean_and_put_op_first
\expanded
- \bgroup\romannumeral0#1#4\relax \iffalse\relax !#3{#2}{\fi
- \expandafter}\romannumeral`&&@\XINT_expr_getop
+ \bgroup\romannumeral0#1#4\relax !#3{#2}\xint:\iffalse{\fi\expandafter}%
+ \romannumeral`&&@\XINT_expr_getop
}%
+\def\XINT_expr_clean_and_put_op_first #1#2\xint:#3#4{#3#4{#1}}%
% \end{macrocode}
% \subsubsection{\cshn{subsm()}: simultaneous independent substitutions}
% \lverb|New with 1.4. Globally the var1=expr1; var2=expr2; var2=expr3;...
@@ -41010,25 +41132,29 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
}%
% \end{macrocode}
% \lverb|
-% #1 = \xintbareeval, or \xintbarefloateval or \xintbareiieval
-% #2 = evaluation of last variable assignment
+%( #1 = \xintbareeval, or \xintbarefloateval or \xintbareiieval
+%: #2 = evaluation of last variable assignment
+%)
% |
% \begin{macrocode}
\def\XINT_allexpr_subsm_done #1#2{{#2}\iffalse{{\fi}}}%
% \end{macrocode}
% \lverb|
-% #1 = \xintbareeval or \xintbarefloateval or \xintbareiieval
-% #2 = {value1}\relax !var2{value2}....\relax !varN{valueN} (value's may be oples)
-% #3 = {var1}
-% #4 = the expression to evaluate
+%( #1 = \xintbareeval or \xintbarefloateval or \xintbareiieval
+%: #2 = {value1}\relax !var2{value2}....\relax !varN{valueN} (value's may be oples)
+%: #3 = {var1}
+%: #4 = the expression to evaluate
+%)
+% Refactored at 1.4h as for \XINT_allexpr_subsx, see comments there related
+% to the omit/abort conundrum.
% |
% \begin{macrocode}
\def\XINT_allexpr_subsmx #1#2#3#4%
{%
- \expandafter\XINT_expr_put_op_first
+ \expandafter\XINT_expr_clean_and_put_op_first
\expanded
- \bgroup\romannumeral0#1#4\relax \iffalse\relax !#3#2{\fi
- \expandafter}\romannumeral`&&@\XINT_expr_getop
+ \bgroup\romannumeral0#1#4\relax !#3#2\xint:\iffalse{\fi\expandafter}%
+ \romannumeral`&&@\XINT_expr_getop
}%
% \end{macrocode}
% \subsubsection{\cshn{subsn()}: leaner syntax for nesting (possibly dependent) substitutions}
@@ -41048,6 +41174,14 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
%: #2 = Expression in all variables which is to evaluate
%: #3 = all the stuff after Name1 = and up to final parenthesis
%)
+%
+% This one needed no reactoring at 1.4h to fix the omit/abort problem, as
+% there was no \iffalse..\fi clean-up: the clean-up is done directly via
+% \XINT_allexpr_subsnx_J.
+%
+% I only added usage of \XINT_expr_put_op_first_noexpand. There may be other
+% locations where it could be used, but I can't afford now reviewing
+% usage. For next release after 1.4h bugfix.
% |
% \begin{macrocode}
\def\XINT_allexpr_subsn_g #1#2#3%
@@ -41106,9 +41240,10 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
}%
\def\XINT_allexpr_subsnx_J #1#2^%
{%
- \expandafter\XINT_expr_put_op_first
+ \expandafter\XINT_expr_put_op_first_noexpand
\expanded{\unexpanded{{#1}}\expandafter}\romannumeral`&&@\XINT_expr_getop
}%
+\def\XINT_expr_put_op_first_noexpand#1#2#3{#2#3{#1}}%
% \end{macrocode}
% \subsubsection{\cshn{seq()}: sequences from assigning values to a
% dummy variable}
@@ -43854,10 +43989,10 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
\expandafter\xint_secondoftwo
\fi
{\immediate\write-1{Reloading xinttrig library using Digits=\xinttheDigits.}}%
-{\expandafter\gdef\csname xintlibver@trig\endcsname{2021/05/25 v1.4g}%
+{\expandafter\gdef\csname xintlibver@trig\endcsname{2021/05/27 v1.4h}%
\XINT_providespackage
\ProvidesPackage{xinttrig}%
-[2021/05/25 v1.4g Trigonometrical functions for xintexpr (JFB)]%
+[2021/05/27 v1.4h Trigonometrical functions for xintexpr (JFB)]%
}%
% \end{macrocode}
% \subsection{Ensure used letters are dummy letters}
@@ -45174,10 +45309,10 @@ on input line \noexpand\the\inputlineno.&&J}}#2%
\expandafter\xint_secondoftwo
\fi
{\immediate\write-1{Reloading xintlog library using Digits=\xinttheDigits.}}%
-{\expandafter\gdef\csname xintlibver@log\endcsname{2021/05/25 v1.4g}%
+{\expandafter\gdef\csname xintlibver@log\endcsname{2021/05/27 v1.4h}%
\XINT_providespackage
\ProvidesPackage{xintlog}%
-[2021/05/25 v1.4g Logarithms and exponentials for xintexpr (JFB)]%
+[2021/05/27 v1.4h Logarithms and exponentials for xintexpr (JFB)]%
}%
% \end{macrocode}
% \subsection{\csh{xintreloadxintlog}}
@@ -47264,8 +47399,8 @@ xinttrig.sty:64
\TeX\strut. Version {\xintbndlversion} of {\xintbndldate}.\par
}
-\CheckSum {38423}% 1.4g
-% 38212 pour 1.4f, 38813 pour 1.4e, 35184 pour 1.4d
+\CheckSum {38427}% 1.4h
+% 38423 pour 1.4g, 38212 pour 1.4f, 38813 pour 1.4e, 35184 pour 1.4d
% 35109 pour 1.4c, 35103 pour 1.4b, 34648 pour 1.4a, 34575 pour 1.4
% 33497 pour 1.3f, 33274 pour 1.3e, 31601 pour 1.3d, 31122 pour 1.3c
% 31069 pour 1.3b, 30482 pour 1.3a, 30621 pour 1.3, 30988 pour 1.2q,
diff --git a/macros/generic/xint/xint.pdf b/macros/generic/xint/xint.pdf
index 09b1f8bfaa..25d711ab0f 100644
--- a/macros/generic/xint/xint.pdf
+++ b/macros/generic/xint/xint.pdf
Binary files differ