summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/base
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2020-10-02 21:49:18 +0000
committerKarl Berry <karl@freefriends.org>2020-10-02 21:49:18 +0000
commit5255c37137345163348d22ab46af2304cf9f55a6 (patch)
tree88246497477ddcc26834e5708566ad4c1c862a19 /Master/texmf-dist/source/latex/base
parent1922ba4684a59cde742dcef9ed152381d2d7b110 (diff)
latex2e (2oct20)
git-svn-id: svn://tug.org/texlive/trunk@56514 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/base')
-rw-r--r--Master/texmf-dist/source/latex/base/classes.dtx135
-rw-r--r--Master/texmf-dist/source/latex/base/doc.dtx19
-rw-r--r--Master/texmf-dist/source/latex/base/docstrip.dtx199
-rw-r--r--Master/texmf-dist/source/latex/base/fontdef.dtx34
-rw-r--r--Master/texmf-dist/source/latex/base/format.ins22
-rw-r--r--Master/texmf-dist/source/latex/base/inputenc.dtx14
-rw-r--r--Master/texmf-dist/source/latex/base/latex209.dtx8
-rw-r--r--Master/texmf-dist/source/latex/base/latexrelease.ins4
-rw-r--r--Master/texmf-dist/source/latex/base/letter.dtx100
-rw-r--r--Master/texmf-dist/source/latex/base/ltboxes.dtx47
-rw-r--r--Master/texmf-dist/source/latex/base/ltclass.dtx791
-rw-r--r--Master/texmf-dist/source/latex/base/ltdefns.dtx822
-rw-r--r--Master/texmf-dist/source/latex/base/ltdirchk.dtx6
-rw-r--r--Master/texmf-dist/source/latex/base/ltexpl.dtx261
-rw-r--r--Master/texmf-dist/source/latex/base/ltfilehook.dtx1543
-rw-r--r--Master/texmf-dist/source/latex/base/ltfiles.dtx531
-rw-r--r--Master/texmf-dist/source/latex/base/ltfinal.dtx39
-rw-r--r--Master/texmf-dist/source/latex/base/ltfloat.dtx66
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssaxes.dtx59
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssbas.dtx4
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssdcl.dtx65
-rw-r--r--Master/texmf-dist/source/latex/base/ltfssini.dtx1013
-rw-r--r--Master/texmf-dist/source/latex/base/ltfsstrc.dtx6
-rw-r--r--Master/texmf-dist/source/latex/base/lthooks.dtx4012
-rw-r--r--Master/texmf-dist/source/latex/base/ltlists.dtx8
-rw-r--r--Master/texmf-dist/source/latex/base/ltluatex.dtx68
-rw-r--r--Master/texmf-dist/source/latex/base/ltmath.dtx152
-rw-r--r--Master/texmf-dist/source/latex/base/ltmiscen.dtx510
-rw-r--r--Master/texmf-dist/source/latex/base/ltoutenc.dtx92
-rw-r--r--Master/texmf-dist/source/latex/base/ltoutput.dtx15
-rw-r--r--Master/texmf-dist/source/latex/base/ltpage.dtx8
-rw-r--r--Master/texmf-dist/source/latex/base/ltpictur.dtx624
-rw-r--r--Master/texmf-dist/source/latex/base/ltplain.dtx32
-rw-r--r--Master/texmf-dist/source/latex/base/ltsect.dtx29
-rw-r--r--Master/texmf-dist/source/latex/base/ltshipout.dtx1739
-rw-r--r--Master/texmf-dist/source/latex/base/ltspace.dtx200
-rw-r--r--Master/texmf-dist/source/latex/base/lttab.dtx45
-rw-r--r--Master/texmf-dist/source/latex/base/lttextcomp.dtx37
-rw-r--r--Master/texmf-dist/source/latex/base/ltvers.dtx14
-rw-r--r--Master/texmf-dist/source/latex/base/ltxdoc.dtx18
-rw-r--r--Master/texmf-dist/source/latex/base/ltxref.dtx21
-rw-r--r--Master/texmf-dist/source/latex/base/slides.dtx8
-rw-r--r--Master/texmf-dist/source/latex/base/unpack.ins1
43 files changed, 12375 insertions, 1046 deletions
diff --git a/Master/texmf-dist/source/latex/base/classes.dtx b/Master/texmf-dist/source/latex/base/classes.dtx
index ea3b014c897..d6f2bb64e6a 100644
--- a/Master/texmf-dist/source/latex/base/classes.dtx
+++ b/Master/texmf-dist/source/latex/base/classes.dtx
@@ -53,7 +53,7 @@
%<*driver>
\ProvidesFile{classes.drv}
%</driver>
- [2019/12/20 v1.4l
+ [2020/04/10 v1.4m
%<article|report|book> Standard LaTeX document class]
%<10pt|11pt|12pt> Standard LaTeX file (size option)]
% \end{macrocode}
@@ -214,6 +214,7 @@
% options that are new in \LaTeXe.}
% \changes{v1.3v}{1997/06/16}{Documentation fixes.}
% \changes{v1.4j}{2019/08/27}{Various commands made robust}
+% \changes{v1.4m}{2020/04/10}{(JLB) prettyprinting the code}
%
%
% \title{Standard Document Classes for \LaTeX{} version 2e\thanks{This
@@ -221,7 +222,7 @@
%
% \author{%
% Copyright (C) 1992 by Leslie Lamport \and
-% Copyright (C) 1994-2019 by Frank Mittelbach \and Johannes Braams \and
+% Copyright (C) 1994-2020 by Frank Mittelbach \and Johannes Braams \and
% \LaTeX3 Project Team
% }
% \date{\filedate}
@@ -322,34 +323,34 @@
% \changes{v1.0g}{1993/12/09}{Removed typo, A4 is not 279 mm high}
% \begin{macrocode}
\if@compatibility\else
-\DeclareOption{a4paper}
- {\setlength\paperheight {297mm}%
- \setlength\paperwidth {210mm}}
-\DeclareOption{a5paper}
- {\setlength\paperheight {210mm}%
- \setlength\paperwidth {148mm}}
-\DeclareOption{b5paper}
- {\setlength\paperheight {250mm}%
- \setlength\paperwidth {176mm}}
-\DeclareOption{letterpaper}
- {\setlength\paperheight {11in}%
- \setlength\paperwidth {8.5in}}
-\DeclareOption{legalpaper}
- {\setlength\paperheight {14in}%
- \setlength\paperwidth {8.5in}}
-\DeclareOption{executivepaper}
- {\setlength\paperheight {10.5in}%
- \setlength\paperwidth {7.25in}}
+ \DeclareOption{a4paper}
+ {\setlength\paperheight {297mm}%
+ \setlength\paperwidth {210mm}}
+ \DeclareOption{a5paper}
+ {\setlength\paperheight {210mm}%
+ \setlength\paperwidth {148mm}}
+ \DeclareOption{b5paper}
+ {\setlength\paperheight {250mm}%
+ \setlength\paperwidth {176mm}}
+ \DeclareOption{letterpaper}
+ {\setlength\paperheight {11in}%
+ \setlength\paperwidth {8.5in}}
+ \DeclareOption{legalpaper}
+ {\setlength\paperheight {14in}%
+ \setlength\paperwidth {8.5in}}
+ \DeclareOption{executivepaper}
+ {\setlength\paperheight {10.5in}%
+ \setlength\paperwidth {7.25in}}
% \end{macrocode}
%
% The option \Lopt{landscape} switches the values of |\paperheight|
% and |\paperwidth|, assuming the dimensions were given for portrait
% paper.
% \begin{macrocode}
-\DeclareOption{landscape}
- {\setlength\@tempdima {\paperheight}%
- \setlength\paperheight {\paperwidth}%
- \setlength\paperwidth {\@tempdima}}
+ \DeclareOption{landscape}
+ {\setlength\@tempdima {\paperheight}%
+ \setlength\paperheight {\paperwidth}%
+ \setlength\paperwidth {\@tempdima}}
\fi
% \end{macrocode}
%
@@ -368,7 +369,7 @@
\if@compatibility
\renewcommand\@ptsize{0}
\else
-\DeclareOption{10pt}{\renewcommand\@ptsize{0}}
+ \DeclareOption{10pt}{\renewcommand\@ptsize{0}}
\fi
\DeclareOption{11pt}{\renewcommand\@ptsize{1}}
\DeclareOption{12pt}{\renewcommand\@ptsize{2}}
@@ -382,7 +383,7 @@
% paragraphs into the outside margin.
% \begin{macrocode}
\if@compatibility\else
-\DeclareOption{oneside}{\@twosidefalse \@mparswitchfalse}
+ \DeclareOption{oneside}{\@twosidefalse \@mparswitchfalse}
\fi
\DeclareOption{twoside}{\@twosidetrue \@mparswitchtrue}
% \end{macrocode}
@@ -395,7 +396,7 @@
% \begin{macrocode}
\DeclareOption{draft}{\setlength\overfullrule{5pt}}
\if@compatibility\else
-\DeclareOption{final}{\setlength\overfullrule{0pt}}
+ \DeclareOption{final}{\setlength\overfullrule{0pt}}
\fi
% \end{macrocode}
%
@@ -405,7 +406,7 @@
% \begin{macrocode}
\DeclareOption{titlepage}{\@titlepagetrue}
\if@compatibility\else
-\DeclareOption{notitlepage}{\@titlepagefalse}
+ \DeclareOption{notitlepage}{\@titlepagefalse}
\fi
% \end{macrocode}
%
@@ -427,7 +428,7 @@
% Two-column and one-column printing is again realized via a switch.
% \begin{macrocode}
\if@compatibility\else
-\DeclareOption{onecolumn}{\@twocolumnfalse}
+ \DeclareOption{onecolumn}{\@twocolumnfalse}
\fi
\DeclareOption{twocolumn}{\@twocolumntrue}
% \end{macrocode}
@@ -468,7 +469,7 @@
% First some hook into the bibliography environment is filled.
% \begin{macrocode}
\AtEndOfPackage{%
- \renewcommand\@openbib@code{%
+ \renewcommand\@openbib@code{%
\advance\leftmargin\bibindent
\itemindent -\bibindent
\listparindent \itemindent
@@ -477,7 +478,7 @@
% \end{macrocode}
% In addition the definition of |\newblock| is overwritten.
% \begin{macrocode}
- \renewcommand\newblock{\par}}%
+ \renewcommand\newblock{\par}}%
}
% \end{macrocode}
%
@@ -950,7 +951,7 @@
% |\topskip|.
% \begin{macrocode}
\if@compatibility \setlength\maxdepth{4\p@} \else
-\setlength\maxdepth{.5\topskip} \fi
+ \setlength\maxdepth{.5\topskip} \fi
% \end{macrocode}
% \end{macro}
%
@@ -1106,7 +1107,7 @@
% between two marginal notes is controlled by |\marginparpush|.
% \begin{macrocode}
\if@twocolumn
- \setlength\marginparsep {10\p@}
+ \setlength\marginparsep {10\p@}
\else
%<10pt&!bk> \setlength\marginparsep{11\p@}
%<11pt&!bk> \setlength\marginparsep{10\p@}
@@ -1801,7 +1802,7 @@
% \changes{v1.3o}{1995/11/02}{(CAR) Make \cs{footnote} always work in
% title, etc}
% \begin{macrocode}
- \if@titlepage
+\if@titlepage
\newcommand\maketitle{\begin{titlepage}%
\let\footnotesize\small
\let\footnoterule\relax
@@ -1867,7 +1868,7 @@
\global\let\author\relax
\global\let\date\relax
\global\let\and\relax
-}
+ }
% \end{macrocode}
% When the title is not on a page of its own, the layout of the
% title is a little different. We use symbols to mark the footnotes
@@ -1884,12 +1885,12 @@
% \cs{@makefntext} to a) work and b) without using math}
% \begin{macrocode}
\else
-\newcommand\maketitle{\par
- \begingroup
- \renewcommand\thefootnote{\@fnsymbol\c@footnote}%
- \def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}%
- \long\def\@makefntext##1{\parindent 1em\noindent
- \hb@xt@1.8em{%
+ \newcommand\maketitle{\par
+ \begingroup
+ \renewcommand\thefootnote{\@fnsymbol\c@footnote}%
+ \def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}%
+ \long\def\@makefntext##1{\parindent 1em\noindent
+ \hb@xt@1.8em{%
\hss\@textsuperscript{\normalfont\@thefnmark}}##1}%
% \end{macrocode}
% If this is a twocolumn document we start a new page in twocolumn
@@ -1899,27 +1900,27 @@
% \changes{v1.2k}{1994/05/06}{Added check on number of columns in use
% locally}
% \begin{macrocode}
- \if@twocolumn
- \ifnum \col@number=\@ne
- \@maketitle
+ \if@twocolumn
+ \ifnum \col@number=\@ne
+ \@maketitle
+ \else
+ \twocolumn[\@maketitle]%
+ \fi
\else
- \twocolumn[\@maketitle]%
- \fi
- \else
% \end{macrocode}
% When this is not a twocolumn document we just start a new page,
% prevent floating objects from appearing on the top of this page
% and print the title information.
% \begin{macrocode}
\newpage
- \global\@topnum\z@ % Prevents figures from going at top of page.
- \@maketitle
- \fi
+ \global\@topnum\z@ % Prevents figures from going at top of page.
+ \@maketitle
+ \fi
% \end{macrocode}
% This page gets a \pstyle{plain} layout. We call |\@thanks| to
% produce the footnotes.
% \begin{macrocode}
- \thispagestyle{plain}\@thanks
+ \thispagestyle{plain}\@thanks
% \end{macrocode}
% Now we can close the group, reset the \Lcount{footnote} counter,
% disable |\thanks|, |\maketitle| and |\@maketitle| and save some
@@ -1928,20 +1929,20 @@
% \changes{v1.3k}{1995/08/27}{Disable \cs{title} and similar decls}
% \changes{v1.3n}{1995/10/29}{Empty \cs{@date} as well}
% \begin{macrocode}
- \endgroup
- \setcounter{footnote}{0}%
- \global\let\thanks\relax
- \global\let\maketitle\relax
- \global\let\@maketitle\relax
- \global\let\@thanks\@empty
- \global\let\@author\@empty
- \global\let\@date\@empty
- \global\let\@title\@empty
- \global\let\title\relax
- \global\let\author\relax
- \global\let\date\relax
- \global\let\and\relax
-}
+ \endgroup
+ \setcounter{footnote}{0}%
+ \global\let\thanks\relax
+ \global\let\maketitle\relax
+ \global\let\@maketitle\relax
+ \global\let\@thanks\@empty
+ \global\let\@author\@empty
+ \global\let\@date\@empty
+ \global\let\@title\@empty
+ \global\let\title\relax
+ \global\let\author\relax
+ \global\let\date\relax
+ \global\let\and\relax
+ }
% \end{macrocode}
% \end{macro}
%
@@ -3144,7 +3145,7 @@
% First we do give the definition for compatibility mode.
% \begin{macrocode}
\if@compatibility
-\newenvironment{titlepage}
+ \newenvironment{titlepage}
{%
%<book> \cleardoublepage
\if@twocolumn
@@ -3162,7 +3163,7 @@
% And here is the one for native \LaTeXe{}.
% \begin{macrocode}
\else
-\newenvironment{titlepage}
+ \newenvironment{titlepage}
{%
%<book> \cleardoublepage
\if@twocolumn
diff --git a/Master/texmf-dist/source/latex/base/doc.dtx b/Master/texmf-dist/source/latex/base/doc.dtx
index 1341f56b8b2..7e7817153c8 100644
--- a/Master/texmf-dist/source/latex/base/doc.dtx
+++ b/Master/texmf-dist/source/latex/base/doc.dtx
@@ -35,7 +35,7 @@
%<+package|shortvrb>\NeedsTeXFormat{LaTeX2e}[1994/12/01]
%<+package> \ProvidesPackage{doc}
%<+shortvrb>\ProvidesPackage{shortvrb}
-%<+package|shortvrb> [2019/12/16 v2.1l
+%<+package|shortvrb> [2020/06/15 v2.1m
%<+package|shortvrb> Standard LaTeX documentation package (FMi)]
%\catcode`\<=12
%
@@ -132,14 +132,14 @@
% \setcounter{StandardModuleDepth}{1}
%
% {\catcode`\p=12 \catcode`\t=12 ^^A hack used later on to print
-% \gdef\dimenvalue#1pt{$#1$pt}} ^^A a register value with a - sign
+% \gdef\dimenvalue#1pt{$#1$pt}} ^^A register values with a - sign
%
% \newcommand{\DOC}{\texttt{doc}}
%
% \changes{v1.9t}{1995/05/11}{Use \cs{GetFileInfo}}
% \GetFileInfo{doc.sty}
%
-% \CheckSum{2208} ^^A % keep the checksum in this file
+% \CheckSum{2213} ^^A % keep the checksum in this file
%
% \title{The \DOC{} and \texttt{shortvrb} Packages\thanks
% {This file has version number \fileversion{} dated \filedate{}.}}
@@ -1324,6 +1324,16 @@
\if@inlabel\leavevmode\fi
\trivlist \parskip \z@ \item[]%
% \end{macrocode}
+% The \cs{item} command sets the \cs{@labels} box but that box is
+% never typeset (as \cs{everypar} that normally does this gets
+% redefined later). That is normally not an issue, but produces a
+% problem when typesetting in mixed directions, (e.g., in
+% Japanese), so we explicitly clear it for that use case.
+% \changes{v2.1m}{2020/06/15}{Void \cs{@labels} for vertical
+% typesetting (gh/344)}
+% \begin{macrocode}
+ \global\setbox\@labels\box\voidb@x
+% \end{macrocode}
% Additionally, everything should be set in \texttt{typewriter} font.
% Some people might prefer it somewhat differently; because of this
% the font choice is
@@ -1448,7 +1458,8 @@
% bothered since doc-sources should be up-to-date but since the
% request came from someone called David Carlisle \ldots :-)
% \changes{v1.9y}{1996/01/26}{Support compat mode}
-% \changes{v2.1l}{2019/12/16}{Use \cs{shapedefault} not \cs{updefault} for extended NFSS}
+% \changes{v2.1l}{2019/12/16}{Use \cs{shapedefault} not
+% \cs{updefault} for extended NFSS}
% \begin{macrocode}
\def\MacroFont{\small
\usefont\encodingdefault
diff --git a/Master/texmf-dist/source/latex/base/docstrip.dtx b/Master/texmf-dist/source/latex/base/docstrip.dtx
index 9cc7945d602..a0a06311edb 100644
--- a/Master/texmf-dist/source/latex/base/docstrip.dtx
+++ b/Master/texmf-dist/source/latex/base/docstrip.dtx
@@ -29,9 +29,9 @@
\catcode`\{=1
\catcode`\}=2
\def\filename{docstrip.dtx}
-\def\fileversion{2.5g}
-\def\filedate{2018/05/03}
-\def\docdate {2018/05/03}
+\def\fileversion{v2.6a}
+\def\filedate{2020-07-07}
+\def\docdate {2020-07-11}
%%
%
%\iffalse
@@ -42,7 +42,7 @@
%% Frank Mittelbach
%% Copyright (C) 1995 Marcin Woli\'nski
%% Copyright (C) 1996-1997 Mark Wooding, Marcin Woli\'nski
-%% Copyright (C) 1998-2003 LaTeX3 project and the above authors
+%% Copyright (C) 1998-2020 LaTeX3 project and the above authors
%% All rights are reserved.
%%
%
@@ -82,6 +82,8 @@
% \changes{2.3e}{1996/10/02}{Introduced ``open lists''}
% \changes{2.4a}{1996/06/06}{Add stream limits (MDW)}
% \changes{2.4c}{1996/06/11}{Add initex support (DPC)}
+% \changes{v2.6a}{2020-07-07}{Added the handling of @@-modules from
+% \texttt{l3docstrip.dtx} (gh/337)}
%
% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ }
% \DoNotIndex{\@ne}
@@ -785,6 +787,57 @@
% When a block of code is {\em not\/} included, any guards that occur
% within that block are {\em not\/} evaluated.
%
+% \section{Internal functions and variables}
+%
+% An important consideration for \LaTeX3 development is separating
+% out public and internal functions. Functions and variables which
+% are private to one module should not be used or modified by any
+% other module. As \TeX{} does not have any formal namespacing
+% system, this requires a convention for indicating which functions
+% in a code-level module are public and which are private.
+%
+% Using \ds\ allows internal functions to be indicated
+% using a `two part' system. Within the \texttt{.dtx} file,
+% internal functions may be indicated using |@@| in place of the
+% module name, for example
+% \begin{verbatim}
+% \cs_new_protected:Npn \@@_some_function:nn #1#2
+% {
+% % Some code here
+% }
+% \tl_new:N \l_@@_internal_tl
+% \end{verbatim}
+%
+% To extract the code using \ds, the original `guard'
+% mecahnism is extended by the introduction of the syntax
+% \texttt{\%<@@=\meta{module}>}. The \meta{module} name then
+% replaces the |@@| when the code is extracted, so that
+% \begin{verbatim}
+% %<*package>
+% %<@@=foo>
+% \cs_new_protected:Npn \@@_some_function:nn #1#2
+% {
+% % Some code here
+% }
+% \tl_new:N \l_@@_internal_tl
+% %</package>
+% \end{verbatim}
+% is extracted as
+% \begin{verbatim}
+% \cs_new_protected:Npn \__foo_some_function:nn #1#2
+% {
+% % Some code here
+% }
+% \tl_new:N \l__foo_internal_tl
+% \end{verbatim}
+% where the |__| indicates that the functions and variables are
+% internal to the \texttt{foo} module.
+%
+% Use |@@@@| to obtain |@@| in the output (|@@@@@| to get |@@@|).
+% For longer pieces of code the replacement can be completely
+% suppressed by giving an empty module name, namely using the
+% syntax \texttt{\%<@@=>}.
+%
% \section{Those other languages}
% Since \TeX\ is an open system some of \TeX\ packages include
% non-\TeX\ files. Some authors use \ds\ to generate PostScript
@@ -853,7 +906,7 @@
%
% \subsection{Verbatim mode}
% If your programming language uses some construct that can
-% interferes badly with \ds\ (e.g., percent in column one) you may
+% interfere badly with \ds\ (e.g., percent in column one) you may
% need a way for preventing it from being stripped off. For that
% purpose \ds\ features `verbatim mode'.
%
@@ -1635,6 +1688,16 @@ Z
\x
% \end{macrocode}
%
+% \begin{macro}{\quote@name}
+% \changes{v2.5h}{2020/04/18}{Macro added gfh/221)}
+% A macro copied from \texttt{ltfiles.dtx} in order to be able to
+% allow spaces in filenames.
+% \begin{macrocode}
+\def\quote@name#1{"\quote@@name#1\@gobble""}
+\def\quote@@name#1"{#1\quote@@name}
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\StreamOpen}\begin{macro}{\StreamPut}
% \begin{macro}{\StreamClose}
% Here is stream opening operator. Its parameter should be a macro
@@ -1642,6 +1705,10 @@ Z
% write to file |foo.tex| use |\StreamOpen\foo|, then
% |\StreamPut\foo| and |\StreamClose\foo|.
%
+% \changes{v2.5h}{2020/04/18}{Allow spaces in filenames by enclosing
+% them in quotes (gh/221)}
+% \changes{v2.5h}{2020/04/18}{Added two times two \cs{expandafters} to
+% make the case with a filename in quotes work as well}
% \begin{macrocode}
\chardef\stream@closed=16
\def\StreamOpen#1{%
@@ -1649,7 +1716,10 @@ Z
\def\s@do##1{\ifnum##1=0
\chardef#1=\expandafter\@stripstr\string##1 %
\global\chardef##1=1 %
- \immediate\openout#1=\csname pth@\@stripstring#1\endcsname %
+ \edef\q@curr@file{%
+ \expandafter\expandafter\expandafter\quote@name
+ \expandafter\expandafter\expandafter{\csname pth@\@stripstring#1\endcsname}}
+ \immediate\openout#1=\q@curr@file\relax
\@streamfound
\fi}
\@outputstreams
@@ -2228,9 +2298,14 @@ Z
% \subsection{Processing the input lines}
%
% \begin{macro}{\normalLine}
+% \changes{v2.6a}{2020-07-07}{The search-and-replace macro
+% \cs{replaceModuleInLine} added from \textsf{l3docstrip.dtx}
+% (gh/337)}
% The macro |\normalLine| writes its argument (which has to be
% delimited with |\endLine|) on all active output files i.e.
-% those with off-counters equal to zero.
+% those with off-counters equal to zero. It uses the
+% search-and-replace macro \cs{replaceModuleInLine} to replace any
+% occurences of \texttt{@@} with the current module name.
% If statistics are included, the counter
% |\codeLinesPassed| is incremented by $1$.
% \begin{macrocode}
@@ -2240,6 +2315,7 @@ Z
%</stats>
\maybeMsg{.}%
\def\inLine{#1}%
+ \replaceModuleInLine
\let\do\putline@do
\activefiles
}
@@ -2400,14 +2476,17 @@ Z
% \changes{2.3a}{1995/08/18}{Adapted to concurrent version}
% \changes{2.3a}{1995/08/20}{Trying to avoid assignments}
% \changes{2.3e}{1996/09/16}{Verbatim mode}
+% \changes{v2.6a}{2020-07-07}{Add the @-sign option from
+% \textsf{l3docstrip.dtx} (gh/337)}
+%
% When the macros that process a line have found that the line
% starts with `\texttt{\%<}', a guard line has been encountered.
% The first character of a guard can be an asterisk (\texttt{*}), a
% slash (\texttt{/}) a plus (\texttt{+}), a minus (\texttt{-}), a
-% less-than sign (\texttt{<}) starting verbatim mode or
-% any other character that can be found in an option name. This
-% means that we have to peek at the next token and
-% decide what kind of guard we have.
+% less-than sign (\texttt{<}) starting verbatim mode, a commercial
+% at (\texttt{@}) or any other character that can be found in an
+% option name. This means that we have to peek at the next token
+% and decide what kind of guard we have.
%
% We reinsert |#1| as it may be needed by |\doOption|.
% \begin{macrocode}
@@ -2415,12 +2494,13 @@ Z
\ifcase
\ifx*#10\else \ifx/#11\else
\ifx+#12\else \ifx-#13\else
- \ifx<#14\else 5\fi\fi\fi\fi\fi\relax
+ \ifx<#14\else \ifx @#15\else 6\fi\fi\fi\fi\fi\fi\relax
\expandafter\starOption\or
\expandafter\slashOption\or
\expandafter\plusOption\or
\expandafter\minusOption\or
\expandafter\verbOption\or
+ \expandafter\moduleOption\or
\expandafter\doOption\fi
#1}
% \end{macrocode}
@@ -2435,12 +2515,17 @@ Z
% result of the test |\if1\Expr{|\meta{options}|}|, the current
% line is either copied to the output stream or removed. Then
% the test is computed for all active output files.
+% \changes{v2.6a}{2020-07-07}{Now use \cs{InLine} and call
+% \cs{replaceModuleInline} (gh/337)}
% \begin{macrocode}
\def\doOption#1>#2\endLine{%
\maybeMsg{<#1 . >}%
\Evaluate{#1}%
\def\do##1##2##3{%
- \if1\Expr{##2}\StreamPut##1{#2}\fi
+ \if1\Expr{##2}%
+ \def\inLine{#2}%
+ \replaceModuleInLine
+ \StreamPut##1{\inLine}\fi
}%
\activefiles
}
@@ -2664,6 +2749,94 @@ Z
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\moduleOption}
+% \changes{v2.6a}{2020-07-07}{Macro added from
+% \textsf{l3docstrip.dtx} (gh/337)}
+%
+% In the case where the line starts |%<@|: the defined syntax requires that
+% this continues to |%<@@=|. At the moment, we assume that the syntax is
+% correct and |#1| here is the module name for substitution into any
+% internal functions in the extracted material.
+% \begin{macrocode}
+\def\moduleOption @@=#1>#2\endLine{%
+ \maybeMsg{<@@=#1>}%
+ \prepareActiveModule{#1}%
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\prepareActiveModule}
+% \changes{v2.6a}{2020-07-07}{Macro added from
+% \textsf{l3docstrip.dtx} (gh/337)}
+% \begin{macro}{\replaceModuleInLine}
+% \changes{v2.6a}{2020-07-07}{Macro added from
+% \textsf{l3docstrip.dtx} (gh/337)}
+% Here, we set up to do the search-and-replace when doing the
+% extraction. The argument (|#1|) is the replacement text to use,
+% or if empty an indicator that no replacement should be done. The
+% search material is one of |__@@|, |_@@| or |@@|, done in order
+% such that all three end up the same in the output. The string
+% |@@@@| is hidden from these replacements by temporarily turning
+% it into a pair of letters with different category codes, not
+% produced by \ds; this allows to get |@@| in the
+% output. The replacement function is initialised as a do-nothing
+% for the case where |%<@@=| is never seen.
+% \begin{macrocode}
+\begingroup
+ \catcode`\_ = 12 %
+ \long\gdef\prepareActiveModule#1{%
+ \ifx\relax#1\relax
+ \let\replaceModuleInLine\empty
+ \else
+ \edef\replaceModuleInLine{%
+ \noexpand\replaceAllIn\noexpand\inLine{@@@@}{\string aa}%
+ \noexpand\replaceAllIn\noexpand\inLine{__@@}{__#1}%
+ \noexpand\replaceAllIn\noexpand\inLine{_@@}{__#1}%
+ \noexpand\replaceAllIn\noexpand\inLine{@@}{__#1}%
+ \noexpand\replaceAllIn\noexpand\inLine{\string aa}{@@}%
+ }%
+ \fi
+ }
+\endgroup
+\let\replaceModuleInLine\empty
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\replaceAllIn}
+% \changes{v2.6a}{2020-07-07}{Macro added from
+% \textsf{l3docstrip.dtx} (gh/337)}
+% \begin{macro}{\replaceAllInAuxI}
+% \changes{v2.6a}{2020-07-07}{Macro added from
+% \textsf{l3docstrip.dtx} (gh/337)}
+% \begin{macro}{\replaceAllInAuxII}
+% \changes{v2.6a}{2020-07-07}{Macro added from
+% \textsf{l3docstrip.dtx} (gh/337)}
+% \begin{macro}{\replaceAllInAuxIII}
+% \changes{v2.6a}{2020-07-07}{Macro added from
+% \textsf{l3docstrip.dtx} (gh/337)}
+% The code here is a simple search-and-replace routine for a macro
+% |#1|, replacing |#2| by |#3|. As set up here, there is an
+% assumption that nothing is going to be expandable, which is
+% reasonable as \ds\ deals with `string' material.
+% \begin{macrocode}
+\long\def\replaceAllIn#1#2#3{%
+ \long\def\tempa##1##2#2{%
+ ##2\qMark\replaceAllInAuxIII#3##1%
+ }%
+ \edef#1{\expandafter\replaceAllInAuxI#1\qMark#2\qStop}%
+}
+\def\replaceAllInAuxI{%
+ \expandafter\replaceAllInAuxII\tempa\replaceAllInAuxI\empty
+}
+\long\def\replaceAllInAuxII#1\qMark#2{#1}
+\long\def\replaceAllInAuxIII#1\qStop{}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
% \subsection{Batchfile commands}
% \changes{2.3e}{1996/10/02}{Added doc}
% \ds{} keeps information needed to control inclusion of sources in
diff --git a/Master/texmf-dist/source/latex/base/fontdef.dtx b/Master/texmf-dist/source/latex/base/fontdef.dtx
index c5623c5566e..632f1c9be56 100644
--- a/Master/texmf-dist/source/latex/base/fontdef.dtx
+++ b/Master/texmf-dist/source/latex/base/fontdef.dtx
@@ -39,7 +39,7 @@
%<driver, >\ProvidesFile{fontdef.drv}
% \fi
% \ProvidesFile{fontdef.dtx}
-%<-latexrelease> [2020/02/11 v3.0g LaTeX Kernel
+%<-latexrelease> [2020/08/01 v3.0i LaTeX Kernel
% \iftrue (\else
%<text, >(Text
%<math, >(Math
@@ -269,7 +269,7 @@
%
% \changes{v3.0a}{2016/12/03}{(DPC) Default to TU encoding for Unicode TeX engines}
% \begin{macrocode}
-\ifx\Umathchar\@undefined
+\ifx\Umathcode\@undefined
% \end{macrocode}
%
% We then set the default text font encoding. This will
@@ -436,7 +436,7 @@
% The following three definitions set up the meaning for
% |\rmfamily|, |\sffamily|, and |\ttfamily|.
% \begin{macrocode}
-\ifx\Umathchar\@undefined
+\ifx\Umathcode\@undefined
\newcommand\encodingdefault{OT1}
\newcommand\rmdefault{cmr}
\newcommand\sfdefault{cmss}
@@ -451,7 +451,7 @@
%</text>
%<latexrelease>\IncludeInRelease{2017/01/01}%
%<latexrelease> {\encodingdefault}{TU encoding default}%
-%<latexrelease>\ifx\Umathchar\@undefined
+%<latexrelease>\ifx\Umathcode\@undefined
%<latexrelease>\renewcommand\encodingdefault{OT1}
%<latexrelease>\fontencoding{\encodingdefault}
%<latexrelease>\renewcommand\rmdefault{cmr}
@@ -489,8 +489,8 @@
% Series changing commands are influenced by the following hooks.
% \changes{v3.0e}{2019/12/17}{Set \cs{bfdefault} to ``b''}
% \begin{macrocode}
-\newcommand\bfdefault{b} % overwritten below
-\newcommand\mddefault{m}
+\newcommand\bfdefault{b} % overwritten below (for rollback)
+\newcommand\mddefault{m} % overwritten below (for rollback)
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -506,7 +506,7 @@
\newcommand\itdefault{it}
\newcommand\sldefault{sl}
\newcommand\scdefault{sc}
-\newcommand\updefault{up} % overwritten below
+\newcommand\updefault{up} % overwritten below (for rollback)
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -519,8 +519,21 @@
%<*text|latexrelease>
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\updefault}{font defaults change}%
+% \begin{macrocode}
\renewcommand\updefault{up}
-\renewcommand\bfdefault{b}
+% \end{macrocode}
+% We append \cs{@empty} to the series value so that we can detect
+% if it got changed via \cs{def} or \cs{renewcommand} later.
+% \changes{v3.0h}{2020/03/19}{Support legacy use of \cs{bfdefault}
+% and \cs{mddefault} (gh/306)}
+% \begin{macrocode}
+\renewcommand\bfdefault{b\@empty}
+\renewcommand\mddefault{m\@empty}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\let\bfdefault@previous\bfdefault
+\let\mddefault@previous\mddefault
%</text|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
@@ -528,6 +541,9 @@
%<latexrelease>
%<latexrelease>\renewcommand\updefault{n}
%<latexrelease>\renewcommand\bfdefault{bx}
+%<latexrelease>
+%<latexrelease>\let\bfdefault@previous\undefined
+%<latexrelease>\let\mddefault@previous\undefined
%<latexrelease>\EndIncludeInRelease
%<*text>
% \end{macrocode}
@@ -549,8 +565,8 @@
% which resolved to \texttt{n}, but these days that is no longer
% the case (and \texttt{up} is wrong when you want to do a
% reset. So we now use \texttt{n} explicitly.
-% \begin{macrocode}
% \changes{v3.0e}{2019/12/17}{Set \cs{shapedefault} explicitly to ``n''}
+% \begin{macrocode}
\newcommand\shapedefault{n}
% \end{macrocode}
% \end{macro}
diff --git a/Master/texmf-dist/source/latex/base/format.ins b/Master/texmf-dist/source/latex/base/format.ins
index 940161edd5b..8796d16d3e2 100644
--- a/Master/texmf-dist/source/latex/base/format.ins
+++ b/Master/texmf-dist/source/latex/base/format.ins
@@ -161,7 +161,12 @@ the system are in the document `cfgguide.tex'.
\from{ltdirchk.dtx}{initex,2ekernel,dircheck}
\from{ltplain.dtx}{2ekernel}
\from{ltvers.dtx}{2ekernel}
+ \from{ltluatex.dtx}{2ekernel}
+% This is done as soon as possible here before \texttt{ltdefns.dtx} so that
+% we have the extensions as soon as possible.
+ \from{ltexpl.dtx}{2ekernel} % expl3-based extensions
\from{ltdefns.dtx}{2ekernel}
+ \from{lthooks.dtx}{2ekernel} % L3 layer module
\from{ltalloc.dtx}{2ekernel}
\from{ltcntrl.dtx}{2ekernel}
\from{lterror.dtx}{2ekernel}
@@ -194,9 +199,10 @@ the system are in the document `cfgguide.tex'.
\from{ltidxglo.dtx}{2ekernel}
\from{ltbibl.dtx}{2ekernel}
\from{ltpage.dtx}{2ekernel}
+ \from{ltclass.dtx}{2ekernel,tracerollback}
+ \from{ltfilehook.dtx}{2ekernel} % L3 layer module
+ \from{ltshipout.dtx}{2ekernel} % L3 layer module
\from{ltoutput.dtx}{2ekernel}
- \from{ltclass.dtx}{2ekernel,tracerollback}
- \from{ltluatex.dtx}{2ekernel}
\from{ltfinal.dtx}{2ekernel}}
\file{tracefnt.sty}{%
\from{ltfsstrc.dtx}{package,trace}}
@@ -225,8 +231,16 @@ the system are in the document `cfgguide.tex'.
}
-% expl3-based extensions
-\generate{\file{ltexpl.ltx}{\from{ltexpl.dtx}{2ekernel}}}
+% hook management support
+
+\generate{\file{everyshi-ltx.sty}{\from{ltshipout.dtx}{everyshi-ltx}}} % emulating everyshi
+\generate{\file{atbegshi-ltx.sty}{\from{ltshipout.dtx}{atbegshi-ltx}}} % emulating atbegshi
+\generate{\file{atveryend-ltx.sty}{\from{ltfilehook.dtx}{atveryend-ltx}}} % emulating atveryend
+
+\generate{\file{structuredlog.sty}{\from{ltfilehook.dtx}{structuredlog}}}
+
+
+
% luatex support (TeX part)
diff --git a/Master/texmf-dist/source/latex/base/inputenc.dtx b/Master/texmf-dist/source/latex/base/inputenc.dtx
index 641125cc75d..c1d08b4830f 100644
--- a/Master/texmf-dist/source/latex/base/inputenc.dtx
+++ b/Master/texmf-dist/source/latex/base/inputenc.dtx
@@ -261,18 +261,18 @@
% turn should ``hopefully'' set up the corresponding UTF-8 mapping).
%
% This works well enough for the main Western languages for which \LaTeX{}
-% has proper font encoding support, but currently already falls short on
-% languages like Greek (which has some semi-official font support, but for
-% which corresponding UTF-8 mappings still need to be defined).
+% has proper font encoding support, but can fall short on other
+% languages.
%
-% For some languages (such as Greek mentioned above) all that remains doing is
+% For some of these languages all that remains doing is
% to provide the necessary mappings and stick them into |utf8ienc.dtx|, so
% volunteers are welcome. For other languages that do not fit well into
% \LaTeX{} font selection scheme, e.g., Asian languages the outlined inputenc
% approach will not work. If that is the case one can try using Dominique
% Unruh's option |utf8x| for inputenc which has a somewhat different approach
% and encodes many more UTF-8 characters than the standard |utf8| option.
-% However, we recommend to do so only if you really need such alphabets as
+% However, we recommend to do so only if you really need such alphabets and can not
+% switch to one of the unicode engines xelatex or lualatex as
% there are problems with this extended approach which were precisely the
% reason that we decided to limit the support to what is properly supported
% within the boundaries of \LaTeX's font selection.
@@ -410,7 +410,7 @@
%<cp1252&!ansinew> \ProvidesFile{cp1252.def}
%<cp1250> \ProvidesFile{cp1250.def}
%<cp1257> \ProvidesFile{cp1257.def}
- [2018/08/11 v1.3c Input encoding file]
+ [2020/08/01 v1.3d Input encoding file]
%<cp850>%%
%<cp850>%% If you need a Euro symbol, try cp858 instead.
%<cp850>%%
@@ -545,7 +545,7 @@
% produces a warning message if no suitable definitions get read.
%
% \begin{macrocode}
-\ifx\Umathchar\@undefined
+\ifx\Umathcode\@undefined
% \end{macrocode}
%
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/latex209.dtx b/Master/texmf-dist/source/latex/base/latex209.dtx
index 6523e65286f..d08a8001b56 100644
--- a/Master/texmf-dist/source/latex/base/latex209.dtx
+++ b/Master/texmf-dist/source/latex/base/latex209.dtx
@@ -200,7 +200,7 @@
% \end{macrocode}
% Describe the file.
% \begin{macrocode}
-\ProvidesFile{latex209.def}[2018/08/11 v0.54 Standard LaTeX file]
+\ProvidesFile{latex209.def}[2020/08/21 v0.55 Standard LaTeX file]
% \end{macrocode}
% \changes{v0.24}{1994/05/14}{Removed date.}
% \changes{v0.40}{1995/03/21}
@@ -469,6 +469,12 @@
\saved@missingfileerror{#1}{#2}%
\fi
}
+\@ifundefined{@missing@onefilewithoptions}{}{%
+ \def\@missing@onefilewithoptions#1{%
+ \@pass@ptions\@currext{#1}{\@currname}%
+ \@missingfileerror\@currname\@currext
+ \let\@currname\@empty}%
+}
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/base/latexrelease.ins b/Master/texmf-dist/source/latex/base/latexrelease.ins
index ff55e7d8c0e..99af17e8fb6 100644
--- a/Master/texmf-dist/source/latex/base/latexrelease.ins
+++ b/Master/texmf-dist/source/latex/base/latexrelease.ins
@@ -86,7 +86,9 @@ extension .ins) which are part of the distribution.
\from{ltvers.dtx} {latexrelease}%
\from{latexrelease.dtx}{latexrelease}%
\from{ltdirchk.dtx} {latexrelease}%
+ \from{ltexpl.dtx} {latexrelease}% empty
\from{ltdefns.dtx} {latexrelease}%
+ \from{lthooks.dtx} {latexrelease}% empty % L3 layer module
\from{ltalloc.dtx} {latexrelease}% empty
\from{ltcntrl.dtx} {latexrelease}% empty
\from{lterror.dtx} {latexrelease}% empty
@@ -106,6 +108,8 @@ extension .ins) which are part of the distribution.
\from{ltidxglo.dtx} {latexrelease}% empty
\from{ltbibl.dtx} {latexrelease}% empty
\from{ltpage.dtx} {latexrelease}% empty
+ \from{ltfilehook.dtx} {latexrelease}% empty % L3 layer module
+ \from{ltshipout.dtx} {latexrelease}% empty % L3 layer module
\from{ltoutput.dtx} {latexrelease}%
\from{ltclass.dtx} {latexrelease,tracerollback}%
\from{ltspace.dtx} {latexrelease}%
diff --git a/Master/texmf-dist/source/latex/base/letter.dtx b/Master/texmf-dist/source/latex/base/letter.dtx
index ee9a87cf849..7b31dfbbc96 100644
--- a/Master/texmf-dist/source/latex/base/letter.dtx
+++ b/Master/texmf-dist/source/latex/base/letter.dtx
@@ -45,7 +45,7 @@
%<*driver>
\ProvidesFile{letter.drv}
%</driver>
- [2014/09/29 v1.2z
+ [2020/03/11 v1.3b
%<+letter> Standard LaTeX document class]
% \end{macrocode}
%
@@ -115,10 +115,10 @@
% \end{macrocode}
% Some commonly used abbreviations
% \begin{macrocode}
-\newcommand*{\Lopt}[1]{\textsf {#1}}
-\newcommand*{\file}[1]{\texttt {#1}}
-\newcommand*{\Lcount}[1]{\textsl {\small#1}}
-\newcommand*{\pstyle}[1]{\textsl {#1}}
+\newcommand*\Lopt[1]{\textsf {#1}}
+\newcommand*\file[1]{\texttt {#1}}
+\newcommand*\Lcount[1]{\textsl {\small#1}}
+\newcommand*\pstyle[1]{\textsl {#1}}
% \end{macrocode}
% We also want the full details.
% \begin{macrocode}
@@ -162,6 +162,7 @@
% \changes{v1.2q}{1995/05/17}{cleaned up \cs{changes entries}}
% \changes{v1.2q}{1995/05/18}{replaced \cs{hbox to} by \cs{hb@xt@}}
% \changes{v1.2r}{1995/05/23}{removed a superfluous brace}
+% \changes{v1.3a}{2020/03/07}{merged changes to classes.dtx into letter.dtx}
%
% \iffalse
% Copyright (C) 1994 LaTeX3 project, Frank Mittelbach
@@ -751,29 +752,29 @@
% \item |\name{Dr. L. User}| : to be used for the return address on
% the envelope.
% \begin{macrocode}
-\newcommand*{\name}[1]{\def\fromname{#1}}
+\newcommand*\name[1]{\def\fromname{#1}}
% \end{macrocode}
% \item |\signature{Larry User}| : goes after the closing.
% \begin{macrocode}
-\newcommand*{\signature}[1]{\def\fromsig{#1}}
+\newcommand*\signature[1]{\def\fromsig{#1}}
% \end{macrocode}
% \item |\address{3245 Foo St.\\Gnu York}| : used as the return
% address in the
% letter and on the envelope. If not declared, then an
% institutional standard address is used.
% \begin{macrocode}
-\newcommand*{\address}[1]{\def\fromaddress{#1}}
+\newcommand*\address[1]{\def\fromaddress{#1}}
% \end{macrocode}
% \item |\location{Room 374}| : Acts as modifier to the standard
% institutional address.
% \begin{macrocode}
-\newcommand*{\location}[1]{\def\fromlocation{#1}}
+\newcommand*\location[1]{\def\fromlocation{#1}}
% \end{macrocode}
% \item |\telephone{(415)123-4567}| : Just in case some style puts it
% on the letter.
% \changes{v1.2m}{1994/06/23}{Removed typo (\#[] instead of [1])}
% \begin{macrocode}
-\newcommand*{\telephone}[1]{\def\telephonenum{#1}}
+\newcommand*\telephone[1]{\def\telephonenum{#1}}
% \end{macrocode}
% \end{itemize}
% \end{macro}
@@ -805,7 +806,7 @@
% \begin{macro}{\makelabels}
% The |\makelabels| declaration causes mailing labels to be made.
% \begin{macrocode}
-\newcommand*{\makelabels}{%
+\newcommand*\makelabels{%
% \end{macrocode}
% At the beginning of the document, we need to activate the
% |\@mlabel| and |\@startlabels| commands, as well as write
@@ -914,7 +915,7 @@
% When the command |\stopbreaks| is issued no page breaks should
% occur until |\startbreaks| is called.
% \begin{macrocode}
-\newcommand*{\stopbreaks}{%
+\newcommand*\stopbreaks{%
\interlinepenalty\@M
\def\par{\@@par\nobreak}%
\let\\\@nobreakcr
@@ -953,7 +954,7 @@
% \begin{macro}{\startbreaks}
% This cancels the effect of |\stopbreaks|.
% \begin{macrocode}
-\newcommand*{\startbreaks}{%
+\newcommand*\startbreaks{%
\let\\\@normalcr
\interlinepenalty 200%
\def\par{\@@par\penalty 200\relax}}
@@ -1004,7 +1005,7 @@
% declaration--null if none.
% \end{itemize}
% \begin{macrocode}
-\newcommand*{\opening}[1]{\ifx\@empty\fromaddress
+\newcommand*\opening[1]{\ifx\@empty\fromaddress
\thispagestyle{firstpage}%
{\raggedleft\@date\par}%
\else % home address
@@ -1039,7 +1040,7 @@
% \item |\stopbreaks| : a macro that inhibits page breaking.
% \end{itemize}
% \begin{macrocode}
-\newcommand{\closing}[1]{\par\nobreak\vspace{\parskip}%
+\newcommand\closing[1]{\par\nobreak\vspace{\parskip}%
\stopbreaks
\noindent
\ifx\@empty\fromaddress\else
@@ -1085,7 +1086,7 @@
% \changes{v1.2s}{1995/05/25}{replace \cs{reset@font} with
% \cs{normalfont}; remove \cs{rm}}
% \begin{macrocode}
-\newcommand*{\cc}[1]{%
+\newcommand*\cc[1]{%
\par\noindent
\parbox[t]{\textwidth}{%
\@hangfrom{\normalfont\ccname: }%
@@ -1100,7 +1101,7 @@
% & Bar
% \end{tabular}
% \begin{macrocode}
-\newcommand*{\encl}[1]{%
+\newcommand*\encl[1]{%
\par\noindent
\parbox[t]{\textwidth}{%
\@hangfrom{\normalfont\enclname: }%
@@ -1110,7 +1111,7 @@
% The only thing |\ps| needs to do is call |\startbreaks|,
% which allows page breaking again.
% \begin{macrocode}
-\newcommand*{\ps}{\par\startbreaks}
+\newcommand*\ps{\par\startbreaks}
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1137,7 +1138,7 @@
% |\protect\standardreturnaddress|.
% \end{itemize}
% \begin{macrocode}
-\newcommand*{\stopletter}{}
+\newcommand*\stopletter{}
% \end{macrocode}
% \end{macro}
%
@@ -1159,7 +1160,7 @@
% The return address for the mailing labels can be stored in this
% macro.
% \begin{macrocode}
-\newcommand*{\returnaddress}{}
+\newcommand*\returnaddress{}
% \end{macrocode}
% \end{macro}
%
@@ -1177,7 +1178,7 @@
% 5352 address labels.
% \changes{v1.2q}{1995/03/14}{changed value of \cs{columnsep} by 1pt}
% \begin{macrocode}
-\newcommand*{\startlabels}{\labelcount\z@
+\newcommand*\startlabels{\labelcount\z@
\pagestyle{empty}%
\let\@texttop\relax
\topmargin -50\p@
@@ -1226,7 +1227,7 @@
% \changes{v1.2q}{1995/03/14}{changed width of the labels slightly to
% prevent \LaTeX\ stuffing two on each line}
% \begin{macrocode}
-\newcommand*{\mlabel}[2]{%
+\newcommand*\mlabel[2]{%
\parbox[b][2in][c]{262\p@}{\strut\ignorespaces #2}%
}
% \end{macrocode}
@@ -1267,7 +1268,7 @@
% For efficiency, level-one list's values are defined at top level, and
% |\@listi| is defined to set only |\leftmargin|.
% \begin{macrocode}
-\setlength\leftmargini {2.5em}
+\setlength\leftmargini {2.5em}
% \end{macrocode}
% The following three are calculated so that they are larger than
% the sum of |\labelsep| and the width of the default labels (which
@@ -1276,8 +1277,8 @@
\setlength\leftmarginii {2.2em}
\setlength\leftmarginiii {1.87em}
\setlength\leftmarginiv {1.7em}
-\setlength\leftmarginv {1em}
-\setlength\leftmarginvi {1em}
+\setlength\leftmarginv {1em}
+\setlength\leftmarginvi {1em}
% \end{macrocode}
% Here we set the top level leftmargin.
% \begin{macrocode}
@@ -1453,11 +1454,30 @@
% \changes{v1.2x}{1997/04/16}{Changed to \cs{textbullet},
% \cs{textasteriskcentered} and \cs{textperiodcentered}}
% \begin{macrocode}
-\newcommand\labelitemi{\textbullet}
-\newcommand\labelitemii{\normalfont\bfseries \textendash}
-\newcommand\labelitemiii{\textasteriskcentered}
-\newcommand\labelitemiv{\textperiodcentered}
+\newcommand\labelitemi {\labelitemfont \textbullet}
+\newcommand\labelitemii {\labelitemfont \bfseries \textendash}
+\newcommand\labelitemiii{\labelitemfont \textasteriskcentered}
+\newcommand\labelitemiv {\labelitemfont \textperiodcentered}
% \end{macrocode}
+%
+% \begin{macro}{\labelitemfont}
+% The default definition for \cs{labelitemfont} is to reset the
+% font to \cs{normalfont} so that always the same symbol is
+% produced regardless of surrounding conditions.
+%
+% \changes{v1.3a}{2020/03/07}{Normalize label fonts}
+% A possible alternative would be
+%\begin{verbatim}
+%\renewcommand\labelitemfont{%
+% \fontseries\seriesdefault
+% \fontshape\shapedefault\selectfont}
+%\end{verbatim}
+% which resets series and shape doesn't touch the family.
+% \begin{macrocode}
+\newcommand\labelitemfont{\normalfont}
+% \end{macrocode}
+% \changes{v1.3b}{2020/03/11}{Added a missing \cs{end{macro}} statement}
+% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
@@ -1484,8 +1504,8 @@
%
% \changes{v1.2q}{1995/03/14}{made command short}
% \begin{macrocode}
-\newcommand*{\descriptionlabel}[1]{\hspace\labelsep
- \normalfont\bfseries #1}
+\newcommand*\descriptionlabel[1]{\hspace\labelsep
+ \normalfont\bfseries #1}
% \end{macrocode}
% \end{macro}
%
@@ -1795,8 +1815,10 @@
% |\parindent| to the appropriate value for succeeding paragraphs
% and put the proper indentation before the mark.
%
+% \changes{v1.3b}{2020/03/11}{make the switch to the use of
+% \cs{newcommand} complete.}
% \begin{macrocode}
-\long\def\@makefntext#1{%
+\newcommand\@makefntext[1]{%
\noindent
\hangindent 5\p@
\hb@xt@5\p@{\hss\@makefnmark}#1}
@@ -1808,10 +1830,12 @@
% footnotes should be produced by the macro |\@makefnmark|. We use
% the default definition for it.
% \begin{macrocode}
-%\def\@makefnmark{\hbox{$^{\@thefnmark}\m@th$}}
+%\renewcommand\@makefnmark{\hbox{$^{\@thefnmark}\m@th$}}
% \end{macrocode}
% \end{macro}
%
+% \section{Initialization}
+%
% \subsection{Words}
%
% \begin{macro}{\ccname}
@@ -1823,10 +1847,10 @@
% English words must be replaced. All the English words that
% require replacement are defined below in command names.
% \begin{macrocode}
-\newcommand*{\ccname}{cc}
-\newcommand*{\enclname}{encl}
-\newcommand*{\pagename}{Page}
-\newcommand*{\headtoname}{To}
+\newcommand*\ccname{cc}
+\newcommand*\enclname{encl}
+\newcommand*\pagename{Page}
+\newcommand*\headtoname{To}
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1839,7 +1863,7 @@
% This macro uses the \TeX\ primitives |\month|, |\day| and |\year|
% to provide the date of the \LaTeX-run.
% \begin{macrocode}
-\newcommand*{\today}{\ifcase\month\or
+\newcommand*\today{\ifcase\month\or
January\or February\or March\or April\or May\or June\or
July\or August\or September\or October\or November\or December\fi
\space\number\day, \number\year}
diff --git a/Master/texmf-dist/source/latex/base/ltboxes.dtx b/Master/texmf-dist/source/latex/base/ltboxes.dtx
index 61ea87235ab..39c134b3bfd 100644
--- a/Master/texmf-dist/source/latex/base/ltboxes.dtx
+++ b/Master/texmf-dist/source/latex/base/ltboxes.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltboxes.dtx}
- [2019/08/27 v1.3b LaTeX Kernel (Box Commands)]
+ [2020/09/27 v1.4a LaTeX Kernel (Box Commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltboxes.dtx}
@@ -365,8 +365,13 @@
% \begin{macro}{\@imakepicbox}
% picture mode version
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@imakepicbox}{default units}%
\long\def\@imakepicbox(#1,#2)[#3]#4{%
- \vbox to#2\unitlength
+ \@defaultunitsset\@tempdimc{#2}\unitlength
+ \vbox to\@tempdimc
{\let\mb@b\vss \let\mb@l\hss\let\mb@r\hss
\let\mb@t\vss
\@tfor\reserved@a :=#3\do{%
@@ -376,14 +381,38 @@
\expandafter\let\csname mb@\reserved@a\endcsname\relax
\fi}%
\mb@t
- \hb@xt@ #1\unitlength{\mb@l #4\mb@r}%
+ \@defaultunitsset\@tempdimc{#1}\unitlength
+ \hb@xt@\@tempdimc{\mb@l #4\mb@r}%
\mb@b
% \end{macrocode}
% This kern ensures that a |b| option aligns on the bottom of the
% text rather than the baseline. this is the documented behaviour in
-% the \LaTeX Book. The kern is removed in compatibility mode.
+% the \LaTeX\ Book. The kern is removed in compatibility mode.
% \begin{macrocode}
\kern\z@}}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@imakepicbox}{default units}%
+%<latexrelease>\long\def\@imakepicbox(#1,#2)[#3]#4{%
+%<latexrelease> \vbox to#2\unitlength
+%<latexrelease> {\let\mb@b\vss \let\mb@l\hss\let\mb@r\hss
+%<latexrelease> \let\mb@t\vss
+%<latexrelease> \@tfor\reserved@a :=#3\do{%
+%<latexrelease> \if s\reserved@a
+%<latexrelease> \let\mb@l\relax\let\mb@r\relax
+%<latexrelease> \else
+%<latexrelease> \expandafter\let\csname mb@\reserved@a\endcsname\relax
+%<latexrelease> \fi}%
+%<latexrelease> \mb@t
+%<latexrelease> \hb@xt@ #1\unitlength{\mb@l #4\mb@r}%
+%<latexrelease> \mb@b
+%<latexrelease> \kern\z@}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -1290,13 +1319,21 @@
%
% \begin{macro}{\rlap}
% \begin{macro}{\llap}
+% \begin{macro}{\clap}
% These macros place text to the left or right of the current
% reference point without taking up space.
-% \end{macro}
% \begin{macrocode}
\DeclareRobustCommand\rlap[1]{\hb@xt@\z@{#1\hss}}
\DeclareRobustCommand\llap[1]{\hb@xt@\z@{\hss#1}}
% \end{macrocode}
+% And here is the version that centers, it was initially introduced by
+% \texttt{mathtools}.
+% \changes{v1.3c}{2020/03/06}{Macro \cs{clap} added}
+% \begin{macrocode}
+\DeclareRobustCommand\clap[1]{\hb@xt@\z@{\hss#1\hss}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
% \end{macro}
%
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltclass.dtx b/Master/texmf-dist/source/latex/base/ltclass.dtx
index 578443921b8..bc6500541e5 100644
--- a/Master/texmf-dist/source/latex/base/ltclass.dtx
+++ b/Master/texmf-dist/source/latex/base/ltclass.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltclass.dtx}
- [2020/02/20 v1.3j LaTeX Kernel (Class & Package Interface)]
+ [2020/10/01 v1.3r LaTeX Kernel (Class & Package Interface)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltclass.dtx}
@@ -44,6 +44,9 @@
\date{\filedate}
\MaintainedByLaTeXTeam{latex}
\maketitle
+
+ \providecommand\pkg[1]{\texttt{#1}}
+
\DocInput{\filename}
\end{document}
%</driver>
@@ -64,6 +67,7 @@
% \changes{v1.0l}{1994/11/17}{\cs{@tempa} to \cs{reserved@a}}
% \changes{v1.0z}{1998/03/21}{Added to documentation of filecontents}
% \changes{v1.1c}{1998/08/17}{(RmS) Minor documentation fixes.}
+% \changes{v1.3o}{2020/08/21}{Integration of new hook management interface}
%
%
% \section{Introduction}
@@ -161,7 +165,7 @@
% option \texttt{nosearch} will only check the current directory
% when looking if the file exists. This can be useful if you want to
% generate a local (modified) copy of some file that is already in the
-% search tree of \TeX{}. Finally, you can use \texttt{nopremable} to
+% search tree of \TeX{}. Finally, you can use \texttt{noheader} to
% prevent it from writing the standard blurb at the top of the file
% (this is actually the same as using the star form of the environment).
%
@@ -256,8 +260,9 @@
% \PassOptionsToPackage{foo,bar}{fred}
% \RequirePackage[baz]{fred}\end{verbatim}
% is the same as:
-% \begin{verbatim}
-% \RequirePackage[foo,bar,baz]{fred}\end{verbatim}
+%\begin{verbatim}
+% \RequirePackage[foo,bar,baz]{fred}
+%\end{verbatim}
%
% \DescribeMacro\LoadClassWithOptions
% |\LoadClassWithOptions|\marg{name}\oarg{version}:\\
@@ -458,7 +463,9 @@
% \end{macro}
%
% \begin{macro}{\@documentclasshook}
-% The hook called after the first |\documentclass| command. By
+% This legacy hook is called after the first |\documentclass| command.
+% It is \emph{not} integrated with the new 2020 hook management system!
+% By
% default this checks to see if |\@normalsize| is undefined, and if
% so, sets it to |\normalsize|.
% \changes{v0.2q}{1993/12/17}
@@ -552,22 +559,75 @@
% |#2| current extension. \\
% |#3| current catcode of |@|. \\
% |#4| Rest of the stack.
+% \changes{v1.3l}{2020/06/05}{Added \cs{@expl@push@filename@@}
+% and \cs{@expl@push@filename@aux@@}}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@pushfilename}%
+%<latexrelease> {Add \@expl@push@filename@@ and \@expl@push@filename@aux@@}%
\def\@pushfilename{%
+% \end{macrocode}
+% The push and pop macros are injected in \cs{@pushfilename} and
+% \cs{@popfilename} so that they correctly keep track of the hook
+% labels.
+%
+% This needs cleanup with the \pkg{expl3} interfaces also playing
+% here, e.g., \cs{@expl@push@filename@@} needs cleanup and (and
+% should probably not have this name either).
+% \begin{macrocode}
+ \@expl@@@hook@curr@name@push@@n{}%
+ \@expl@push@filename@@
\xdef\@currnamestack{%
{\@currname}%
{\@currext}%
{\the\catcode`\@}%
- \@currnamestack}}
+ \@currnamestack}%
+ \@expl@push@filename@aux@@}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{0000/00/00}{\@pushfilename}%
+%<latexrelease> {Add \@expl@push@filename@@ and \@expl@push@filename@aux@@}%
+%<latexrelease>\def\@pushfilename{%
+%<latexrelease> \xdef\@currnamestack{%
+%<latexrelease> {\@currname}%
+%<latexrelease> {\@currext}%
+%<latexrelease> {\the\catcode`\@}%
+%<latexrelease> \@currnamestack}}
+%<latexrelease>\EndIncludeInRelease
\@onlypreamble\@pushfilename
% \end{macrocode}
%
+%
+%
+%
+%
+% \changes{v1.3l}{2020/06/05}{Added \cs{@expl@pop@filename@@}}
% \begin{macrocode}
-\def\@popfilename{\expandafter\@p@pfilename\@currnamestack\@nil}
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@popfilename}%
+%<latexrelease> {Add \@expl@pop@filename@@}%
+\def\@popfilename{\@expl@@@hook@curr@name@pop@@
+ \expandafter\@p@pfilename\@currnamestack\@nil
+ \@expl@pop@filename@@}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
+%<latexrelease>\IncludeInRelease{0000/00/00}{\@popfilename}%
+%<latexrelease> {Add \@expl@push@filename@@ and \@expl@push@filename@aux@@}%
+%<latexrelease>\def\@popfilename{\expandafter\@p@pfilename\@currnamestack\@nil}
+%<latexrelease>\EndIncludeInRelease
\@onlypreamble\@popfilename
% \end{macrocode}
%
% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<*2ekernel>
+% \end{macrocode}
+%
+%
+%
+% \begin{macrocode}
\def\@p@pfilename#1#2#3#4\@nil{%
\gdef\@currname{#1}%
\gdef\@currext{#2}%
@@ -620,15 +680,60 @@
%
% \begin{macro}{\@ifpackagelater}
% \begin{macro}{\@ifclasslater}
-% |\@ifpackagelater{|\meta{name}|}{YYYY/MM/DD}|
-% Checks that the package loaded is more recent than the given date.
+% |\@ifpackagelater{|\meta{name}|}{YYYY/MM/DD}{|\meta{true
+% code}|}{|\meta{false code}|}|
+% Checks that the package loaded is more recent or equal to the
+% given date.
+% A better name for it would therefore been
+% |\@ifpackagelaterorequal| but it is in use for more than 30
+% years, so \ldots
% \begin{macrocode}
\def\@ifpackagelater{\@ifl@ter\@pkgextension}
\def\@ifclasslater{\@ifl@ter\@clsextension}
\@onlypreamble\@ifpackagelater
\@onlypreamble\@ifclasslater
% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\IfPackageAtLeastTF}
+% \begin{macro}{\IfClassAtLeastTF}
+% \begin{macro}{\IfFormatAtLeastTF}
+% |\IfFormatAtLeastTF{YYYY/MM/DD}{|\meta{true
+% code}|}{|\meta{false code}|}|
+% Test if the format is later or equal to the given date.
+% \changes{v1.3k}{2020/04/07}{Macro added; also in rollback (gh/168)}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\IfFormatAtLeastTF}{Test format date}%
+\def\IfFormatAtLeastTF{\@ifl@t@r\fmtversion}
+\let\IfPackageAtLeastTF\@ifpackagelater
+\let\IfClassAtLeastTF\@ifclasslater
+\@onlypreamble\IfFormatAtLeastTF
+\@onlypreamble\IfPackageAtLeastTF
+\@onlypreamble\IfClassAtLeastTF
+% \end{macrocode}
+% For rollback pretend it was available since the beginning of dawn.
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\IfFormatAtLeastTF}{Test format date}%
+%<latexrelease>\def\IfFormatAtLeastTF{\@ifl@t@r\fmtversion}
+%<latexrelease>\let\IfPackageAtLeastTF\@ifpackagelater
+%<latexrelease>\let\IfClassAtLeastTF\@ifclasslater
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
%
+% \begin{macro}{\@ifl@ter}
% \begin{macrocode}
\def\@ifl@ter#1#2{%
\expandafter\@ifl@t@r
@@ -675,6 +780,7 @@
% \begin{macrocode}
\@onlypreamble\@ifl@t@r
% \end{macrocode}
+% \end{macro}
%
% \changes{v1.1j}{2016/06/20}
% {don't declare as \cs{@onlypreamble}}
@@ -695,8 +801,8 @@
%</2ekernel|latexreleasefirst>
%<*2ekernel>
% \end{macrocode}
-% \end{macro}
-% \end{macro}
+%
+%
%
% \begin{macro}{\@ifpackagewith}
% \begin{macro}{\@ifclasswith}
@@ -800,14 +906,17 @@
% be cautious when handling the identification string in case it
% contains UTF-8 characters.
% \changes{v1.3e}{2019/11/29}{Protect package info text (gh/52)}
+% \changes{v1.3r}{2020/10/01}{Allow for package subsitution}
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/02/02}%
-%<latexrelease> {\@pr@videpackage}{Protection for package info}%
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@pr@videpackage}{Allow for package subsitution}%
\def\@pr@videpackage[#1]{%
\expandafter\protected@xdef % <-- protected...
- \csname ver@\@currname.\@currext\endcsname{#1}%
+ \csname ver@\@currname.\@currext\endcsname{#1}% Loaded package
+ \expandafter\protected@xdef % <-- protected...
+ \csname ver@\@currpkg@reqd\endcsname{#1}% Requested package
\ifx\@currext\@clsextension
\typeout{Document Class: \@gtempa\space#1}%
\else
@@ -832,6 +941,19 @@
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\@pr@videpackage}{Protection for package info}%
+%<latexrelease>
+%<latexrelease>\def\@pr@videpackage[#1]{%
+%<latexrelease> \expandafter\protected@xdef % <-- protected...
+%<latexrelease> \csname ver@\@currname.\@currext\endcsname{#1}%
+%<latexrelease>\ifx\@currext\@clsextension
+%<latexrelease> \typeout{Document Class: \@gtempa\space#1}%
+%<latexrelease> \else
+%<latexrelease> \protected@wlog{Package: \@gtempa\space#1}% <--- protected
+%<latexrelease> \fi}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\@pr@videpackage}{Protection for package info}%
%<latexrelease>
@@ -915,11 +1037,28 @@
% If the package has been loaded, we check that it was first loaded with
% the options. Otherwise we add the option list to that of the package.
% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2020/10/01}{\@pass@ptions}
+%<latexrelease> {Add file replacement in \@pass@ptions}%
+%<*2ekernel|latexrelease>
\def\@pass@ptions#1#2#3{%
- \expandafter\xdef\csname opt@#3.#1\endcsname{%
- \@ifundefined{opt@#3.#1}\@empty
- {\csname opt@#3.#1\endcsname,}%
+ \edef\reserved@a{\@expl@@@filehook@resolve@file@subst@@w #3.#1\@nil}%
+ \expandafter\xdef\csname opt@\reserved@a\endcsname{%
+ \@ifundefined{opt@\reserved@a}\@empty
+ {\csname opt@\reserved@a\endcsname,}%
\zap@space#2 \@empty}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%
+%<latexrelease>\IncludeInRelease{0000/00/00}{\@pass@ptions}
+%<latexrelease> {\@pass@ptions}%
+%<latexrelease>\def\@pass@ptions#1#2#3{%
+%<latexrelease> \expandafter\xdef\csname opt@#3.#1\endcsname{%
+%<latexrelease> \@ifundefined{opt@#3.#1}\@empty
+%<latexrelease> {\csname opt@#3.#1\endcsname,}%
+%<latexrelease> \zap@space#2 \@empty}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
\@onlypreamble\@pass@ptions
% \end{macrocode}
%
@@ -1050,6 +1189,10 @@
%
% The common part of |\ProcessOptions| and |\ProcessOptions*|.
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@process@pti@ns}{Unused options issue}%
\def\@process@pti@ns{%
\@for\CurrentOption:=\@curroptions\do{%
\@ifundefined{ds@\CurrentOption}%
@@ -1073,11 +1216,33 @@
% \end{macrocode}
% \changes{v1.0r}{1995/10/17}
% {Reset \cs{CurrentOption} for graphics/1873}
+% \changes{v1.3k}{2020/04/07}{Use different method to ignore
+% unprocessed options (gh/22)}
% \begin{macrocode}
\let\CurrentOption\@empty
\let\@fileswith@pti@ns\@@fileswith@pti@ns
- \AtEndOfPackage{\let\@unprocessedoptions\relax}}
+ \AtEndOfPackage{\expandafter\let
+ \csname unprocessedoptions-\@currname.\@currext\endcsname
+ \relax}}
\@onlypreamble\@process@pti@ns
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@process@pti@ns}{Unused options issue}%
+%<latexrelease>
+%<latexrelease>\def\@process@pti@ns{%
+%<latexrelease> \@for\CurrentOption:=\@curroptions\do{%
+%<latexrelease> \@ifundefined{ds@\CurrentOption}%
+%<latexrelease> {\@use@ption
+%<latexrelease> \default@ds}%
+%<latexrelease> \@use@ption}%
+%<latexrelease> \@for\CurrentOption:=\@declaredoptions\do{%
+%<latexrelease> \expandafter\let\csname ds@\CurrentOption\endcsname\relax}%
+%<latexrelease> \let\CurrentOption\@empty
+%<latexrelease> \let\@fileswith@pti@ns\@@fileswith@pti@ns
+%<latexrelease> \AtEndOfPackage{\let\@unprocessedoptions\relax}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1243,13 +1408,45 @@
% \changes{v1.0v}{1996/10/04}{Reset \cs{@unprocessedoptions} for /2269}
% Load package `|#1|' with the current option list.
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\RequirePackageWithOptions}{Unused options issue}%
\def\RequirePackageWithOptions{%
- \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+% \end{macrocode}
+% The resetting of the unprocessed options is now done on a par package basis.
+% \changes{v1.3k}{2020/04/07}{Use different method to ignore
+% unprocessed options (gh/22)}
+% \begin{macrocode}
+ \AtEndOfPackage{\expandafter\let
+ \csname unprocessedoptions-\@currname.\@currext\endcsname
+ \relax}%
\@loadwithoptions\@pkgextension\RequirePackage}
\@onlypreamble\RequirePackageWithOptions
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\RequirePackageWithOptions}{Unused options issue}%
+%<latexrelease>
+%<latexrelease>\def\RequirePackageWithOptions{%
+%<latexrelease> \AtEndOfPackage{\let\@unprocessedoptions\relax}%
+%<latexrelease> \@loadwithoptions\@pkgextension\RequirePackage}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
+%
+
+
+
+
+
+
+%
% \begin{macro}{\usepackage}
% To begin with, |\usepackage| produces an error. This is reset by
% |\documentclass|.
@@ -1469,6 +1666,9 @@
\@onlypreamble\@fileswith@pti@ns
% \end{macrocode}
%
+% \begin{macro}{\load@onefilewithoptions}
+% This macro is used when loading packages or classes.
+%
% Have the main argument as |#1|, so we only need one |\expandafter|
% above.
% \changes{v0.2a}{1993/11/14}
@@ -1482,91 +1682,338 @@
% \changes{v1.3d}{2019/10/18}{Initialize \cs{...-h@@k} only when loading
% the package or class (gh/198)}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@onefilewithoptions}{Hooks and unused options issue}%
\def\@onefilewithoptions#1[#2][#3]#4{%
\@pushfilename
\xdef\@currname{#1}%
\global\let\@currext#4%
+% \end{macrocode}
+% The command \cs{ver@\meta{file}.\meta{ext}} is used to signal that
+% a package is already loaded, either because it is in fact loaded, or
+% because it's loading was suppressed. In minimal installations, said
+% package may not exist but still have its loading suppressed with
+% \cs{ver@\meta{file}.\meta{ext}}, so before checking if the file
+% exists we have to check that we do need to load it with
+% \cs{@ifl@aded}. If we don't, then there's no point in checking for
+% a typo or load-disabling.
+% \begin{macrocode}
+ \@ifl@aded\@currext\@currname
+% \end{macrocode}
+% If the package is already loaded, check that there were no option
+% clashes:
+% \changes{v1.1b}{1998/05/07}
+% {Modify help message for latex/2805}
+% \begin{macrocode}
+ {\@if@ptions\@currext{\@currname}{#2}{}%
+ {\@latex@error
+ {Option clash for \@cls@pkg\space \@currname}%
+ {The package \@currname\space has already been loaded
+ with options:\MessageBreak
+ \space\space[\@ptionlist{\@currname.\@currext}]\MessageBreak
+ There has now been an attempt to load it
+ with options\MessageBreak
+ \space\space[#2]\MessageBreak
+ Adding the global options:\MessageBreak
+ \space\space
+ \@ptionlist{\@currname.\@currext},#2\MessageBreak
+ to your \noexpand\documentclass declaration may fix this.%
+ \MessageBreak
+ Try typing \space <return> \space to proceed.}}%
+ \@firstofone}%
+ {\makeatletter
+% \end{macrocode}
+% The next line seems to be necessary for 2.09 compatibility (the
+% way the code is written there) This seems questionable and should be
+% look at as in 2e it is definitely unnecessary at this point!
+% \begin{macrocode}
+ \@reset@ptions
+% \end{macrocode}
+% First we take the \meta{name} and \meta{ext} given in the argument
+% and check if the file exists, and issue an error otherwise asking
+% for a correction with \cs{@missingfileerror}.
+% \begin{macrocode}
+ \IfFileExists{\@currname.\@currext}{}%
+ {\@missing@onefilewithoptions{#2}}%
+% \end{macrocode}
+% If \cs{@currname} is empty (the user replied to the ``Enter file
+% name'' prompt with \meta{RETURN}), so stop here
+% (do \cs{@popfilename} to pop the item just added above).
+%
+% This \cs{@gobble} omits the date check at the end.
+% \begin{macrocode}
+ \ifx\@currname\@empty
+ \expandafter\@gobble
+ \else
+% \end{macrocode}
+% If the file exists, check if it was load-prevented, and otherwise
+% do the bookkeeping with \cs{@filehook@file@push}
+% then call \cs{set@curr@file} to set \cs{@curr@file} (and do any
+% required substitution), then actually load the class/package with
+% \cs{load@onefile@withoptions}.
+% \begin{macrocode}
+ \@disable@packageload@do{\@currname.\@currext}%
+ {\@expl@@@filehook@file@push@@
+ \set@curr@file{\@currname.\@currext}%
+ \@filehook@set@CurrentFile
+% \end{macrocode}
+% \changes{v1.3q}{2020/09/06}
+% {Save \cs{@currpkg@reqd} so that we don't lose track of
+% package substitutions.}
+% The \cs{set@curr@file} line above might have replaced the file, so
+% \cs{@currname} and \cs{@currext} may no longer hold the actual
+% package being loaded, so in that case we need to update these two
+% token lists (\cs{@curr@file} holds the file name after replacement,
+% so we parse that).
+%
+% The requested file is saved in \cs{@currpkg@reqd} to be used in
+% \cs{InputIfFileExists} later: if the updated \cs{@currname} and
+% \cs{@currext} are used we lose track of the substitution, so
+% \cs{CurrentFile} and \cs{CurrentFileUsed} will be (incorrectly)
+% the same.
+% \begin{macrocode}
+ \edef\@currpkg@reqd{\@currname.\@currext}%
+ \ifx\CurrentFile\CurrentFileUsed
+ \else
+ \filename@parse\@curr@file
+ \edef\@currname{\string@makeletter\filename@base}%
+ \edef\@currext{\string@makeletter\filename@ext}%
+ \fi
+ \load@onefile@withoptions{#2}%
+% \end{macrocode}
+% Now just clean up and exit.
+% \begin{macrocode}
+ \@expl@@@filehook@file@pop@@}%
+ \expandafter\@firstofone
+ \fi}%
+% \end{macrocode}
+% Except in the case where \cs{@currname} is empty, the date is
+% checked against the date marked in the package file:
+% \begin{macrocode}
+ {\@ifl@ter\@currext{\@currname}{#3}{}%
+ {\@latex@warning@no@line
+ {You have requested,\on@line,
+ version\MessageBreak
+ `#3' of \@cls@pkg\space \@currname,\MessageBreak
+ but only version\MessageBreak
+ `\csname ver@\@currname.\@currext\endcsname'\MessageBreak
+ is available}}%
+% \end{macrocode}
+% \changes{v0.2c}{1993/11/17}
+% {Added trap for two \cs{LoadClass} commands.}
+% \begin{macrocode}
+ \ifx\@currext\@clsextension\let\LoadClass\@twoloadclasserror\fi}%
+ \@popfilename
+ \@reset@ptions}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\@onlypreamble\@onefilewithoptions
+% \end{macrocode}
+%
+% The kernel no longer uses \cs{@unprocessedoptions}
+% \begin{macrocode}
+\let\@unprocessedoptions\@undefined
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@missing@onefilewithoptions}
+% Now the action taken when a file is not found.
+% \begin{macrocode}
+\def\@missing@onefilewithoptions#1{%
+ \@missingfileerror\@currname\@currext
+ \xdef\@currname{\@missingfile@area\@missingfile@base}%
+ \global\let\@currext\@missingfile@ext}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\load@onefile@withoptions}
+% Now the code that actually does the file loading:
+% \begin{macrocode}
+\def\load@onefile@withoptions#1{%
\let\CurrentOption\@empty
\@reset@ptions
- \makeatletter
% \end{macrocode}
% Grab everything in a macro, so the parameter stack is popped before
% any processing begins.
% \changes{v0.2s}{1994/01/17}
% {Modify to reduce parameter stack usage}
-% \changes{v1.1b}{1998/05/07}
-% {Modify help message for latex/2805}
% \begin{macrocode}
\def\reserved@a{%
- \@ifl@aded\@currext{#1}%
- {\@if@ptions\@currext{#1}{#2}{}%
- {\@latex@error
- {Option clash for \@cls@pkg\space #1}%
- {The package #1 has already been loaded
- with options:\MessageBreak
- \space\space[\@ptionlist{#1.\@currext}]\MessageBreak
- There has now been an attempt to load it
- with options\MessageBreak
- \space\space[#2]\MessageBreak
- Adding the global options:\MessageBreak
- \space\space
- \@ptionlist{#1.\@currext},#2\MessageBreak
- to your \noexpand\documentclass declaration may fix this.%
- \MessageBreak
- Try typing \space <return> \space to proceed.}}}%
- {\@pass@ptions\@currext{#2}{#1}%
-% \end{macrocode}
-% \changes{v0.3c}{1994/03/12}
-% {Do not use \cs{@pr@videpackage} to avoid typeout}
-% \begin{macrocode}
- \global\expandafter
- \let\csname ver@\@currname.\@currext\endcsname\@empty
+ \@pass@ptions\@currext{#1}{\@currname}%
+ \global\expandafter
+ \let\csname ver@\@currname.\@currext\endcsname\@empty
% \end{macrocode}
% We initialize \cs{...-h@@k} here and only if we load the file so that it
% remains undefined otherwise.
% \begin{macrocode}
- \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty
- \InputIfFileExists
- {\@currname.\@currext}%
- {}%
- {\@missingfileerror\@currname\@currext}%
+ \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty
+% \end{macrocode}
+% When the current extension is \cs{@pkgextension} we are loading a
+% package otherwise, if it is \cs{@clsextension}, a class, so
+% depending on that we execute different hooks. If the extension is
+% neither, then it is another type of file without special hooks.
+% \begin{macrocode}
+%-----------------------------------------
+ \ifx\@currext\@pkgextension
+ \UseHook{package/before}%
+ \UseHook{package/before/\@currname}%
+ \else
+ \ifx\@currext\@clsextension
+ \UseHook{class/before}%
+ \UseHook{class/before/\@currname}%
+ \fi
+ \fi
% \end{macrocode}
-% |\@unprocessedoptions| will generate an error for each specified
-% option in a package unless a |\ProcessOptions| has appeared in the
-% package file.
+% Now actually load the file (at this point we are certain it exists,
+% but use \cs{InputIfFileExists} so that file hooks are executed):
+% \begin{macrocode}
+ \InputIfFileExists{\@currpkg@reqd}{}%
+ {\@latex@error
+ {The \@cls@pkg\space\@currpkg@reqd\space failed to load.}\@ehd}%
+%-----------------------------------------
+% \end{macrocode}
+% In older versions of the code |\@unprocessedoptions| would
+% generate an error for each specified
+% option in a package unless a |\ProcessOptions| has appeared in the
+% package file.
% \changes{v0.2v}{1994/01/29}
% {All options raise error if no \cs{ProcessOptions} appears}
% \changes{v0.2x}{1994/02/02}
-% {Only run the hook and options check if the file was loaded.}
-% \begin{macrocode}
- \let\@unprocessedoptions\@@unprocessedoptions
+% {Only run the hook and options check if the file was
+% loaded.}
+%
+% This has changed in 2020. We now use a separate macro per package
+% to avoid interferences in case of nested packages. The whole
+% code for handling this issue (GitHub 22) was provided by Hironobu
+% Yamashita, thanks for that.
+% \changes{v1.3k}{2020/04/07}{Use different method to ignore
+% unprocessed options (gh/22)}
+% \begin{macrocode}
+ \expandafter\let\csname unprocessedoptions-\@currname.\@currext\endcsname
+ \@@unprocessedoptions
\csname\@currname.\@currext-h@@k\endcsname
\expandafter\let\csname\@currname.\@currext-h@@k\endcsname
\@undefined
- \@unprocessedoptions}%
% \end{macrocode}
-%
+% Catch the case where the packages has handled the options and
+% redefined \cs{@unprocessedoptions} to \cs{relax} (old interface).
+% In that case no error should be produced.
+% \changes{v1.3k}{2020/04/07}{Use different method to ignore
+% unprocessed options (gh/22)}
% \begin{macrocode}
- \@ifl@ter\@currext{#1}{#3}{}%
- {\@latex@warning@no@line
- {You have requested,\on@line,
- version\MessageBreak
- `#3' of \@cls@pkg\space #1,\MessageBreak
- but only version\MessageBreak
- `\csname ver@#1.\@currext\endcsname'\MessageBreak
- is available}}%
+ \ifx\@unprocessedoptions\relax
+ \let\@unprocessedoptions\@undefined
% \end{macrocode}
-% \changes{v0.2c}{1993/11/17}
-% {Added trap for two \cs{LoadClass} commands.}
+% Otherwise run the per package set of unused options.
% \begin{macrocode}
- \ifx\@currext\@clsextension\let\LoadClass\@twoloadclasserror\fi
- \@popfilename
- \@reset@ptions}%
- \reserved@a}
-\@onlypreamble\@onefilewithoptions
+ \else
+ \csname unprocessedoptions-\@currname.\@currext\endcsname
+ \fi
+% \end{macrocode}
+% In either case we drop the macro afterwards as it is no longer needed.
+% \begin{macrocode}
+ \expandafter\let
+ \csname unprocessedoptions-\@currname.\@currext\endcsname
+ \@undefined
+% \end{macrocode}
+% And same procedure, James, when we are finished loading, except
+% that the hook order is now reversed.
+% \begin{macrocode}
+%-----------------------------------------
+ \ifx\@currext\@pkgextension
+ \UseHook{package/after/\@currname}%
+ \UseHook{package/after}%
+ \else
+ \ifx\@currext\@clsextension
+ \UseHook{class/after/\@currname}%
+ \UseHook{class/after}%
+ \fi
+ \fi}%
+%-----------------------------------------
+ \@ifl@aded\@currext\@currname{}{\reserved@a}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@onefilewithoptions}{Hooks and unused options issue}%
+%<latexrelease>
+% \end{macrocode}
+% Because of the way \cs{@onfilewithoptions} is changed for
+% rollback handling below we have to define
+% \cs{load@onefilewithoptions} when rolling back!
+% \begin{macrocode}
+%<latexrelease>\def\load@onefilewithoptions#1[#2][#3]#4{%
+%<latexrelease> \@pushfilename
+%<latexrelease> \xdef\@currname{#1}%
+%<latexrelease> \global\let\@currext#4%
+%<latexrelease> \let\CurrentOption\@empty
+%<latexrelease> \@reset@ptions
+%<latexrelease> \makeatletter
+%<latexrelease> \def\reserved@a{%
+%<latexrelease> \@ifl@aded\@currext{#1}%
+%<latexrelease> {\@if@ptions\@currext{#1}{#2}{}%
+%<latexrelease> {\@latex@error
+%<latexrelease> {Option clash for \@cls@pkg\space #1}%
+%<latexrelease> {The package #1 has already been loaded
+%<latexrelease> with options:\MessageBreak
+%<latexrelease> \space\space[\@ptionlist{#1.\@currext}]\MessageBreak
+%<latexrelease> There has now been an attempt to load it
+%<latexrelease> with options\MessageBreak
+%<latexrelease> \space\space[#2]\MessageBreak
+%<latexrelease> Adding the global options:\MessageBreak
+%<latexrelease> \space\space
+%<latexrelease> \@ptionlist{#1.\@currext},#2\MessageBreak
+%<latexrelease> to your \noexpand\documentclass declaration may fix this.%
+%<latexrelease> \MessageBreak
+%<latexrelease> Try typing \space <return> \space to proceed.}}}%
+%<latexrelease> {\@pass@ptions\@currext{#2}{#1}%
+%<latexrelease> \global\expandafter
+%<latexrelease> \let\csname ver@\@currname.\@currext\endcsname\@empty
+%<latexrelease> \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty
+%<latexrelease> \InputIfFileExists
+%<latexrelease> {\@currname.\@currext}%
+%<latexrelease> {}%
+%<latexrelease> {\@missingfileerror\@currname\@currext}%
+%<latexrelease> \let\@unprocessedoptions\@@unprocessedoptions
+%<latexrelease> \csname\@currname.\@currext-h@@k\endcsname
+%<latexrelease> \expandafter\let\csname\@currname.\@currext-h@@k\endcsname
+%<latexrelease> \@undefined
+%<latexrelease> \@unprocessedoptions}%
+%<latexrelease> \@ifl@ter\@currext{#1}{#3}{}%
+%<latexrelease> {\@latex@warning@no@line
+%<latexrelease> {You have requested,\on@line,
+%<latexrelease> version\MessageBreak
+%<latexrelease> `#3' of \@cls@pkg\space #1,\MessageBreak
+%<latexrelease> but only version\MessageBreak
+%<latexrelease> `\csname ver@#1.\@currext\endcsname'\MessageBreak
+%<latexrelease> is available}}%
+%<latexrelease> \ifx\@currext\@clsextension\let\LoadClass\@twoloadclasserror\fi
+%<latexrelease> \@popfilename
+%<latexrelease> \@reset@ptions}%
+%<latexrelease> \reserved@a}
+%<latexrelease>
+%<latexrelease>\let \load@onefile@withoptions \@undefined
+%<latexrelease>\let \@missing@onefilewithoptions \@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
+%
+%
% \begin{macro}{\@@fileswith@pti@ns}
% Save the definition (for error checking).
% \changes{v0.2c}{1993/11/17}
@@ -1593,9 +2040,12 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
% \subsection{Hooks}
%
-% Allow code do be saved to be executed at specific later times.
+% Allow code to be saved to be executed at specific later times.
%
% Save things in macros, I considered using toks registers, (and
% |\addto@hook| from the NFSS code, that would require stacking the
@@ -1615,25 +2065,6 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\g@addto@macro}
-% Globally add to the end of a macro.
-% \changes{v0.2a}{1993/11/14}{Made global}
-% \changes{v0.2w}{1994/01/31}
-% {Use toks register to avoid `hash' problems}
-% \changes{v1.0o}{1995/05/17}
-% {Make long for latex/1522}
-% \changes{v1.0w}{1996/12/17}
-% {Use \cs{begingroup} to save making a mathord}
-% \changes{v1.0x}{1997/02/05}
-% {missing percent /2402}
-% \begin{macrocode}
-\long\def\g@addto@macro#1#2{%
- \begingroup
- \toks@\expandafter{#1#2}%
- \xdef#1{\the\toks@}%
- \endgroup}
-% \end{macrocode}
-% \end{macro}
%
% \begin{macro}{\AtEndOfPackage}
% \begin{macro}{\AtEndOfClass}
@@ -1652,8 +2083,29 @@
% \end{macrocode}
%
% \begin{macrocode}
-\DeclareRobustCommand\AtBeginDocument{\g@addto@macro\@begindocumenthook}
-\DeclareRobustCommand\AtEndDocument{\g@addto@macro\@enddocumenthook}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\AtBeginDocument}{Use hook system}%
+\DeclareRobustCommand\AtBeginDocument{\AddToHook{begindocument}}
+\DeclareRobustCommand\AtEndDocument {\AddToHook{enddocument}}
+%\DeclareRobustCommand\AtEndDocument {\AddToHook{env/document/end}} % alternative impl
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\AtBeginDocument}{Use hook system}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\AtBeginDocument{\g@addto@macro\@begindocumenthook}
+%<latexrelease>\DeclareRobustCommand\AtEndDocument{\g@addto@macro\@enddocumenthook}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% \begin{macrocode}
\@onlypreamble\AtBeginDocument
% \end{macrocode}
% \end{macro}
@@ -1760,6 +2212,7 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{environment}{filecontents}
% \begin{macro}{\filecontents}
% \begin{macro}{\endfilecontents}
% This environment implements inline files.
@@ -1776,17 +2229,16 @@
% \changes{v1.0m}{1995/04/21}
% {Close input check stream: latex/1487}
% \changes{v1.0p}{1995/05/25}{Delete \cs{filec@ntents} after preamble}
-% \begin{macrocode}
% \changes{v1.3a}{2019/07/01}{Support UTF8 and spaces in
% filecontents environment file name}
% \changes{v1.3b}{2019/08/27}{Make various commands robust}
% \changes{v1.3c}{2019/09/11}{Support optional argument for filecontents}
% \changes{v1.3f}{2020/01/05}{Support more write streams in LuaTeX gh/238}
-%
+% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2019/10/01}%
-%<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}%
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\filec@ntents}{Define \q@curr@file directly (gh/220)}%
%
% \end{macrocode}
% We use |@tempswa| to mean no preamble writing and reuse |@filesw|
@@ -1817,7 +2269,7 @@
\filec@ntents
}
% \end{macrocode}
-% Option \texttt{force}) (or \texttt{overwrite}) changes the
+% Option \texttt{force} (or \texttt{overwrite}) changes the
% overwriting switch
% \begin{macrocode}
\let\filec@ntents@force\@fileswfalse
@@ -1829,7 +2281,7 @@
\let\filec@ntents@noheader\@tempswafalse
% \end{macrocode}
% Option \texttt{nosearch} only checks the current directory not
-% the how \TeX{} tree for the existence of the file to write.
+% the whole \TeX{} tree for the existence of the file to write.
% \begin{macrocode}
\def\filec@ntents@nosearch{%
\let\filec@ntents@checkdir\@currdir
@@ -1855,10 +2307,12 @@
\catcode`\^^I\active%
% \end{macrocode}
%
+% \changes{v1.3m}{2020-08-08}{define \cs{q@curr@file} directly as the
+% quotes have already been removed (gh/220)}
% \begin{macrocode}
\gdef\filec@ntents#1{%
\set@curr@file{\filec@ntents@checkdir#1}%
- \edef\q@curr@file{\expandafter\quote@name\expandafter{\@curr@file}}%
+ \edef\q@curr@file{"\@curr@file"}%
% \end{macrocode}
%
% Lua\TeX\ has more writes (and 18 is safe here).
@@ -2019,6 +2473,136 @@
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}%
+%<latexrelease>\def\filecontents{\@tempswatrue\@fileswtrue
+%<latexrelease> \@ifnextchar[\filec@ntents@opt\filec@ntents
+%<latexrelease>}
+%<latexrelease>\@namedef{filecontents*}{\@tempswafalse\@fileswtrue
+%<latexrelease> \@ifnextchar[\filec@ntents@opt\filec@ntents
+%<latexrelease>}
+%<latexrelease>\def\filec@ntents@opt[#1]{%
+%<latexrelease> \edef\@fortmp{\zap@space#1 \@empty}%
+%<latexrelease> \@for\reserved@a:=\@fortmp\do{%
+%<latexrelease> \ifcsname filec@ntents@\reserved@a\endcsname
+%<latexrelease> \csname filec@ntents@\reserved@a\endcsname
+%<latexrelease> \else
+%<latexrelease> \@latex@error{Unknown filecontents option \reserved@a}%
+%<latexrelease> {Valid options are force (or overwrite), nosearch, noheader}%
+%<latexrelease> \fi}%
+%<latexrelease> \filec@ntents
+%<latexrelease>}
+%<latexrelease>\let\filec@ntents@force\@fileswfalse
+%<latexrelease>\let\filec@ntents@overwrite\@fileswfalse % alternative name
+%<latexrelease>\let\filec@ntents@noheader\@tempswafalse
+%<latexrelease>\def\filec@ntents@nosearch{%
+%<latexrelease> \let\filec@ntents@checkdir\@currdir
+%<latexrelease> \def\filec@ntents@where{in current directory}}
+%<latexrelease>\let\filec@ntents@checkdir\@empty
+%<latexrelease>\def\filec@ntents@where{exists on the system}
+%<latexrelease>\begingroup%
+%<latexrelease>\@tempcnta=1
+%<latexrelease>\loop
+%<latexrelease> \catcode\@tempcnta=12 %
+%<latexrelease> \advance\@tempcnta\@ne %
+%<latexrelease>\ifnum\@tempcnta<32 %
+%<latexrelease>\repeat %
+%<latexrelease>\catcode`\*=11 %
+%<latexrelease>\catcode`\^^M\active%
+%<latexrelease>\catcode`\^^L\active\let^^L\relax%
+%<latexrelease>\catcode`\^^I\active%
+%<latexrelease>\gdef\filec@ntents#1{%
+%<latexrelease> \set@curr@file{\filec@ntents@checkdir#1}%
+%<latexrelease> \edef\q@curr@file{\expandafter\quote@name\expandafter{\@curr@file}}%
+%<latexrelease> \chardef\reserved@c\ifx\directlua\@undefined 15 \else 127 \fi%
+%<latexrelease> \openin\@inputcheck\q@curr@file \space %
+%<latexrelease> \ifeof\@inputcheck%
+%<latexrelease> \@latex@warning@no@line%
+%<latexrelease> {Writing file `\@currdir\@curr@file'}%
+%<latexrelease> \ch@ck7\reserved@c\write\relax%
+%<latexrelease> \immediate\openout\reserved@c\q@curr@file\relax%
+%<latexrelease> \else%
+%<latexrelease> \if@filesw%
+%<latexrelease> \@latex@warning@no@line%
+%<latexrelease> {File `\@curr@file' already \filec@ntents@where.\MessageBreak%
+%<latexrelease> Not generating it from this source}%
+%<latexrelease> \let\write\@gobbletwo%
+%<latexrelease> \let\closeout\@gobble%
+%<latexrelease> \else%
+%<latexrelease> \edef\reserved@a{#1}%
+%<latexrelease> \edef\reserved@a{\detokenize\expandafter{\reserved@a}}%
+%<latexrelease> \edef\reserved@b{\detokenize\expandafter{\jobname}}%
+%<latexrelease> \ifx\reserved@a\reserved@b%
+%<latexrelease> \@fileswtrue%
+%<latexrelease> \else%
+%<latexrelease> \edef\reserved@b{\reserved@b\detokenize{.tex}}%
+%<latexrelease> \ifx\reserved@a\reserved@b
+%<latexrelease> \@fileswtrue%
+%<latexrelease> \fi%
+%<latexrelease> \fi%
+%<latexrelease> \ch@ck7\reserved@c\write\relax%
+%<latexrelease> \if@filesw% % Foul ... trying to overwrite \jobname!
+%<latexrelease> \@latex@error{Trying to overwrite `\jobname.tex'}{You can't %
+%<latexrelease> write to the file you are reading from!\MessageBreak%
+%<latexrelease> Data is written to screen instead.}%
+%<latexrelease> \else%
+%<latexrelease> \@latex@warning@no@line%
+%<latexrelease> {Writing or overwriting file `\@currdir\@curr@file'}%
+%<latexrelease> \immediate\openout\reserved@c\q@curr@file\relax%
+%<latexrelease> \fi%
+%<latexrelease> \fi%
+%<latexrelease> \fi%
+%<latexrelease> \closein\@inputcheck%
+%<latexrelease> \if@tempswa%
+%<latexrelease> \immediate\write\reserved@c{%
+%<latexrelease> \@percentchar\@percentchar\space%
+%<latexrelease> \expandafter\@gobble\string\LaTeX2e file `\@curr@file'^^J%
+%<latexrelease> \@percentchar\@percentchar\space generated by the %
+%<latexrelease> `\@currenvir' \expandafter\@gobblefour\string\newenvironment^^J%
+%<latexrelease> \@percentchar\@percentchar\space from source `\jobname' on %
+%<latexrelease> \number\year/\two@digits\month/\two@digits\day.^^J%
+%<latexrelease> \@percentchar\@percentchar}%
+%<latexrelease> \fi%
+%<latexrelease> \let\do\@makeother\dospecials%
+%<latexrelease> \count@ 128\relax%
+%<latexrelease> \loop%
+%<latexrelease> \catcode\count@ 11\relax%
+%<latexrelease> \advance\count@ \@ne%
+%<latexrelease> \ifnum\count@<\@cclvi%
+%<latexrelease> \repeat%
+%<latexrelease> \edef\E{\@backslashchar end\string{\@currenvir\string}}%
+%<latexrelease> \edef\reserved@b{%
+%<latexrelease> \def\noexpand\reserved@b%
+%<latexrelease> ####1\E####2\E####3\relax}%
+%<latexrelease> \reserved@b{%
+%<latexrelease> \ifx\relax##3\relax%
+%<latexrelease> \immediate\write\reserved@c{##1}%
+%<latexrelease> \else%
+%<latexrelease> \edef^^M{\noexpand\end{\@currenvir}}%
+%<latexrelease> \ifx\relax##1\relax%
+%<latexrelease> \else%
+%<latexrelease> \@latex@warning{Writing text `##1' before %
+%<latexrelease> \string\end{\@currenvir}\MessageBreak as last line of \@curr@file}%
+%<latexrelease> \immediate\write\reserved@c{##1}%
+%<latexrelease> \fi%
+%<latexrelease> \ifx\relax##2\relax%
+%<latexrelease> \else%
+%<latexrelease> \@latex@warning{%
+%<latexrelease> Ignoring text `##2' after \string\end{\@currenvir}}%
+%<latexrelease> \fi%
+%<latexrelease> \fi%
+%<latexrelease> ^^M}%
+%<latexrelease> \catcode`\^^L\active%
+%<latexrelease> \let\L\@undefined%
+%<latexrelease> \def^^L{\expandafter\ifx\csname L\endcsname\relax\fi ^^J^^J}%
+%<latexrelease> \catcode`\^^I\active%
+%<latexrelease> \let\I\@undefined%
+%<latexrelease> \def^^I{\expandafter\ifx\csname I\endcsname\relax\fi\space}%
+%<latexrelease> \catcode`\^^M\active%
+%<latexrelease> \edef^^M##1^^M{%
+%<latexrelease> \noexpand\reserved@b##1\E\E\relax}}%
+%<latexrelease>\endgroup%
+%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\filec@ntents}{Spaces in file names + optional arg}%
%<latexrelease>
@@ -2142,6 +2726,7 @@
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{environment}
%
%
%
@@ -2763,7 +3348,7 @@
%<*afterpreamble>
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{pkgindoc}
- [1994/10/20 v1.1 Package Interface in Document (DPC)]
+ [2020-08-08 v1.3m Package Interface in Document (DPC)]
\def\reserved@a#1\do\@classoptionslist#2\do\filec@ntents#3\relax{%
\gdef\@preamblecmds{#1#3}}
\expandafter\reserved@a\@preamblecmds\relax
diff --git a/Master/texmf-dist/source/latex/base/ltdefns.dtx b/Master/texmf-dist/source/latex/base/ltdefns.dtx
index 303b9e5604b..569c9db4df9 100644
--- a/Master/texmf-dist/source/latex/base/ltdefns.dtx
+++ b/Master/texmf-dist/source/latex/base/ltdefns.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltdefns.dtx}
- [2020/02/27 v1.5g LaTeX Kernel (definition commands)]
+ [2020/09/25 v1.5n LaTeX Kernel (definition commands)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltdefns.dtx}
@@ -90,6 +90,7 @@
% \changes{v1.0p}{1995/07/13}{Updates to documentation}
% \changes{v1.4b}{2015/02/21}
% {Removed autoload support}
+% \changes{v1.5l}{2020/08/21}{Integration of new hook management interface}
%
% \section{Definitions}
%
@@ -101,6 +102,7 @@
%<*2ekernel>
% \end{macrocode}
%
+%
% \subsection{Initex initialisations}
%
% \task{???}{This section needs extension}
@@ -118,9 +120,25 @@
%
% \begin{macro}{\typeout}
% Display something on the terminal.
+% \changes{v1.5g}{2020/05/15}{Allow \cs{par} in the argument (gh/335)}
% \begin{macrocode}
-\def\typeout#1{\begingroup\set@display@protect
- \immediate\write\@unused{#1}\endgroup}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\typeout}{Allow "par" in \typeout}%
+\protected\long\def\typeout#1{\begingroup
+ \set@display@protect
+ \def\par{^^J^^J}%
+ \immediate\write\@unused{#1}\endgroup}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\typeout}{Allow "par" in \typeout}%
+%<latexrelease>
+%<latexrelease>\def\typeout#1{\begingroup\set@display@protect
+%<latexrelease> \immediate\write\@unused{#1}\endgroup}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -366,8 +384,9 @@
%
% \begin{macro}{\@carcube}
% |\@carcube T1 ... Tn\@nil| = |T1| |T2| |T3| , $n > 3$
+% \changes{v1.5k}{2020/08/19}{Made \cs{long} for \cs{NewCommandCopy}}
% \begin{macrocode}
-\def\@carcube#1#2#3#4\@nil{#1#2#3}
+\long\def\@carcube#1#2#3#4\@nil{#1#2#3}
% \end{macrocode}
% \end{macro}
%
@@ -645,7 +664,7 @@
% \begin{macro}{\@ifdefinable}
% \begin{macro}{\@@ifdefinable}
% \begin{macro}{\@rc@ifdefinable}
-% Test is user is allowed to define a command.
+% Test if user is allowed to define a command.
% \begin{macrocode}
\long\def\@ifdefinable #1#2{%
\edef\reserved@a{\expandafter\@gobble\string #1}%
@@ -980,7 +999,7 @@
% evaluates its argument fully.
% \end{itemize}
% The method \LaTeX{} uses for making fragile commands robust is to
-% precede them with |\protect|. This can have one of five possible
+% precede them with |\protect|. This can have one of four possible
% values:
% \begin{itemize}
% \item |\relax|, for normal typesetting. So |\protect\foo| will
@@ -1174,6 +1193,8 @@
% \changes{v1.4a}{2015/01/08}{Added macro}
% \changes{v1.5f}{2019/08/27}{Make the assignments global as we may
% need to apply them inside a group}
+% \changes{v1.5m}{2020/08/21}{Make \cs{MakeRobust} produce the same
+% command structure as \cs{DeclareRobustCommand}}
%
% This macro makes an existing fragile macro robust, but only if it
% hasn't been robust in the past, i.e., it checks for the existence
@@ -1192,9 +1213,11 @@
% at all.
% \begin{macrocode}
%</2ekernel>
-%<latexrelease>\IncludeInRelease{2019/10/01}{\MakeRobust}{\MakeRobust}%
+%<latexrelease>\IncludeInRelease{2020/10/01}{\MakeRobust}{\MakeRobust}%
%<*2ekernel|latexrelease>
\def\MakeRobust#1{%
+ \count@=\escapechar
+ \escapechar=`\\
\@ifundefined{\expandafter\@gobble\string#1}{%
\@latex@error{The control sequence `\string#1' is undefined!%
\MessageBreak There is nothing here to make robust}%
@@ -1206,12 +1229,15 @@
% \verb*=\foo =. If it is already defined do nothing, otherwise set
% \verb*=\foo = equal to \verb*=\foo= and redefine \verb*=\foo= so
% that it acts like a macro defined with \verb=\DeclareRobustCommand=.
+% We use \cs{@kernel@rename@newcommand} to copy \verb*=\foo= over to
+% \verb*=\foo =, including a possible default optional argument.
% \begin{macrocode}
{%
\@ifundefined{\expandafter\@gobble\string#1\space}%
{%
- \global\expandafter\let\csname
- \expandafter\@gobble\string#1\space\endcsname=#1%
+ \expandafter\@kernel@rename@newcommand
+ \csname\expandafter\@gobble\string#1\space\endcsname
+ #1%
\edef\reserved@a{\string#1}%
\def\reserved@b{#1}%
\edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}%
@@ -1223,10 +1249,72 @@
\csname\expandafter\@gobble\string#1\space\endcsname}%
}%
{\@latex@info{The control sequence `\string#1' is already robust}}%
- }%
+ }%
+ \escapechar=\count@
}%
+% \end{macrocode}
+%
+% \begin{macro}{\@kernel@rename@newcommand}
+% This macro renames a command, possibly with an optional argument (defined
+% with \cs{newcommand}) from |#2| to |#1|, by renaming the internal macro
+% \verb=\\#2= to \verb=\\#1= and defining \verb=\#1= appropriately, then
+% undefining \verb=\#2= and \verb=\\#2=. The \cs{afterassignment} trick is
+% to make both definitions in \cs{@copy@newcommand} global (which are local
+% by default).
+%
+% In case the macro was defined with \cs{newcommand} and an optional
+% argument, to replicate exactly the behaviour of \cs{DeclareRobustCommand}
+% we have to move also the internal \verb*=\\foo= to \verb*=\\foo =. In that
+% case, \verb=#1= will be a parameterless macro (\cs{robust@command@chk@safe}
+% checks that), and \cs{@if@newcommand} will return true (both defined below
+% in this file). If so, we can use \cs{@copy@newcommand} rather than plain
+% \cs{let} to copy the command over. \cs{@kernel@rename@newcommand} does
+% this test and carries out the renaming.
+% \begin{macrocode}
+\def\@kernel@rename@newcommand#1#2{%
+ \robust@command@chk@safe#2%
+ {\@if@newcommand#2%
+ {\afterassignment\global
+ \global\@copy@newcommand#1#2%
+ \global\let#2\@undefined
+ \global\expandafter\let\csname\string#2\endcsname\@undefined}%
+ {\global\let#1=#2}}%
+ {\global\let#1=#2}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%
+%<latexrelease>\IncludeInRelease{2019/10/01}{\MakeRobust}{\MakeRobust}%
+%<latexrelease>\def\MakeRobust#1{%
+%<latexrelease> \@ifundefined{\expandafter\@gobble\string#1}{%
+%<latexrelease> \@latex@error{The control sequence `\string#1' is undefined!%
+%<latexrelease> \MessageBreak There is nothing here to make robust}%
+%<latexrelease> \@eha
+%<latexrelease> }%
+%<latexrelease> {%
+%<latexrelease> \@ifundefined{\expandafter\@gobble\string#1\space}%
+%<latexrelease> {%
+%<latexrelease> \global\expandafter\let\csname
+%<latexrelease> \expandafter\@gobble\string#1\space\endcsname=#1%
+%<latexrelease> \edef\reserved@a{\string#1}%
+%<latexrelease> \def\reserved@b{#1}%
+%<latexrelease> \edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}%
+%<latexrelease> \xdef#1{%
+%<latexrelease> \ifx\reserved@a\reserved@b
+%<latexrelease> \noexpand\x@protect\noexpand#1%
+%<latexrelease> \fi
+%<latexrelease> \noexpand\protect\expandafter\noexpand
+%<latexrelease> \csname\expandafter\@gobble\string#1\space\endcsname}%
+%<latexrelease> }%
+%<latexrelease> {\@latex@info{The control sequence `\string#1' is already robust}}%
+%<latexrelease> }%
+%<latexrelease>}%
+%<latexrelease>\let\@kernel@rename@newcommand\@undefined
+%<latexrelease>\EndIncludeInRelease
+%
%<latexrelease>\IncludeInRelease{2015/01/01}{\MakeRobust}{\MakeRobust}%
%<latexrelease>\def\MakeRobust#1{%
%<latexrelease> \@ifundefined{\expandafter\@gobble\string#1}{%
@@ -1252,17 +1340,17 @@
%<latexrelease> {\@latex@info{The control sequence `\string#1' is already robust}}%
%<latexrelease> }%
%<latexrelease>}%
+%<latexrelease>\let\@kernel@rename@newcommand\@undefined
%<latexrelease>\EndIncludeInRelease
+%
%<latexrelease>\IncludeInRelease{0000/00/00}{\MakeRobust}{\MakeRobust}%
%<latexrelease>\let\MakeRobust\@undefined
+%<latexrelease>\let\@kernel@rename@newcommand\@undefined
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
-%
-%
-
% \begin{macro}{\kernel@make@fragile}
% The opposite of |\MakeRobust| execpt that it doesn't do many
% checks as it is internal to the kernel. Why does one want such a
@@ -1276,7 +1364,7 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease> {\kernel@make@fragile}{Undo robustness}%
\def\kernel@make@fragile#1{%
\@ifundefined{\expandafter\@gobble\string#1\space}%
@@ -1285,16 +1373,39 @@
% \begin{macrocode}
{}%
% \end{macrocode}
-% Otherwise copy \verb*=\foo = back to \verb=\foo= and then undefine
-% the payload command.
+% Otherwise copy \verb*=\foo = back to \verb=\foo=.
+% Then use \cs{@kernel@rename@newcommand} to check and copy
+% \verb*=\\foo = back to \verb*=\\foo= in case the command has an optional
+% argument. If so, also undefine \verb*=\\foo =, and at the end undefine
+% \verb*=\foo =.
% \begin{macrocode}
{%
\global\expandafter\let\expandafter #1\csname
- \expandafter\@gobble\string#1\space\endcsname
+ \expandafter\@gobble\string#1\space\endcsname
+ \expandafter\@kernel@rename@newcommand
+ \csname\expandafter\@gobble\string#1\expandafter\endcsname
+ \csname\expandafter\@gobble\string#1\space\endcsname
\global\expandafter\let\csname
- \expandafter\@gobble\string#1\space\endcsname\@undefined
+ \expandafter\@gobble\string#1\space\endcsname\@undefined
}%
}
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\kernel@make@fragile}{Undo robustness}%
+%<latexrelease>\def\kernel@make@fragile#1{%
+%<latexrelease> \@ifundefined{\expandafter\@gobble\string#1\space}%
+%<latexrelease> {}%
+%<latexrelease> {%
+%<latexrelease> \global\expandafter\let\expandafter #1\csname
+%<latexrelease> \expandafter\@gobble\string#1\space\endcsname
+%<latexrelease> \global\expandafter\let\csname
+%<latexrelease> \expandafter\@gobble\string#1\space\endcsname\@undefined
+%<latexrelease> }%
+%<latexrelease>}
%<latexrelease>\EndIncludeInRelease
%</2ekernel|latexrelease>
%<*2ekernel>
@@ -1302,6 +1413,552 @@
% \end{macro}
%
%
+% \subsection{Acting on robust commands}
+%
+% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2020-10-01}{\robust@command@act}
+%<latexrelease> {Add \robust@command@act}%
+%<*2ekernel|latexrelease>
+% \end{macrocode}
+%
+% With most document level commands being robust now there is more of a
+% requirement to have a standard way of aliasing (or copying) a command to a
+% new name, for example to save an original definition before changing a
+% command. \cs{DeclareCommandCopy} is analogous to \TeX's \cs{let}, except
+% that it copes with the different types of robust commands defined by
+% \LaTeX's mechanisms.
+%
+% A couple of ``types of robustness'' are defined by the \LaTeXe{} kernel,
+% namely robust commands defined with \cs{DeclareRobustCommand} and commands
+% with optional arguments defined with \cs{newcommand}. However there are
+% other types of robust commands that are frequently used, which are not
+% defined in the \LaTeXe{} kernel, like commands defined with
+% \textsf{xparse}'s \cs{NewDocumentCommand} and \textsf{etoolbox}'s
+% \cs{newrobustcmd}.
+%
+% In this section we will define a generic extensible machinery to act on
+% robust commands. This code will then be used to test if a command is
+% robust, considered the different types of robustness, and then either copy
+% that definition, if \cs{DeclareCommandCopy} (or similar) is used, or show
+% the definition of the command, if \cs{ShowCommmand} is used.
+%
+% \begin{macro}{\robust@command@act}
+% \changes{v1.5k}{2020/08/19}{Made \cs{robust@command@act}
+% (was \cs{declare@command@copy}) more generic}
+%
+% The looping machinery is generic and knows nothing about what is to be done
+% for each case. The syntax of the main macro \cs{robust@command@act} is:
+% \begin{quote}
+% |\robust@command@act|\meta{action-list}\meta{robust-cmd}\\
+% \meta{fallback-action}\meta{act-arg}
+% \end{quote}
+% \meta{action-list} is a token list of the form:
+% \begin{quote}
+% |{|\meta{if-type-1} \meta{act-type-1}|}|\\
+% |{|\meta{if-type-2} \meta{act-type-2}|}|\\
+% \ldots
+% \end{quote}
+% \cs{robust@command@act} will iterate over the \meta{action-list}, evaluating
+% each \meta{if-type-$n$}\meta{robust-cmd}|{|\meta{true}|}{|\meta{false}|}|.
+% If the \meta{if-type-$n$} conditional returns \meta{true}, then
+% \meta{act-type-$n$}\meta{act-arg} is executed, and the loop ends. If the
+% conditional returns \meta{false}, then \meta{if-type-$n+1$} is executed in
+% the same way, until either one of the conditionals return \meta{true}, or
+% the end of the \meta{action-list} is reached. If the end is reached, then
+% \meta{fallback-action}\meta{act-arg} is executed before
+% \cs{robust@command@act} exits.
+%
+% \cs{robust@command@act} will start by using \cs{robust@command@act@chk@args}
+% to check if the \meta{robust-cmd} (|#2|) is a parameterless (possibly
+% \cs{protected}) macro. If it is not, the command is not a robust command:
+% these always start with a parameterless user-level macro; in that case,
+% \cs{robust@command@act@end} is used to short-circuit the process and do the
+% \meta{fallback-action} (|#3|). This first test is necessary because later
+% on we need to be able to expand the \meta{robust-cmd} without the risk of it
+% Breaking Badly, and as a bonus, this speeds up the process in case we used
+% \cs{NewCommandCopy} in a ``normal'' macro.
+% \begin{macrocode}
+\long\def\robust@command@act#1#2#3#4{%
+ \robust@command@chk@safe#2%
+ {\expandafter\robust@command@act@loop
+ \expandafter#2%
+ #1{\@nnil\@nnil}%
+ \robust@command@act@end}%
+ {\robust@command@act@end}%
+ {#3}{#4}}%
+% \end{macrocode}
+%
+% \begin{macro}{\robust@command@act@loop}
+% \begin{macro}{\robust@command@act@loop@aux}
+% \begin{macro}{\robust@command@act@do}
+% If \cs{robust@command@act@chk@args} branched to false, then
+% \cs{robust@command@act@loop} will loop over the list of items in the
+% \meta{action-list} (|#1|), and process each item as described earlier.
+% If the \meta{if-type-$n$} command expands to \meta{true} then
+% \cs{robust@command@act@do} is used to execute \meta{act-type-$n$} on the
+% \meta{act-arg}, otherwise the loop resumes with the next item.
+% \begin{macrocode}
+\long\def\robust@command@act@loop#1#2{\robust@command@act@loop@aux#1#2}
+\long\def\robust@command@act@loop@aux#1#2#3{%
+ \ifx\@nnil#2%
+ \else
+ #2{#1}%
+ {\robust@command@act@do{#3}}%
+ {\expandafter\robust@command@act@loop\expandafter#1}%
+ \fi}
+\long\def\robust@command@act@do#1%
+ \fi#2%
+ \robust@command@act@end#3#4{%
+ \fi
+ #1#4}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\robust@command@act@end}
+% If the end is reached and no action was taken, then do
+% \meta{fallback-action}\meta{act-arg}.
+% \begin{macrocode}
+\long\def\robust@command@act@end#1#2{#1#2}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\robust@command@chk@safe}
+% \begin{macro}{\robust@command@act@chk@args}
+% \begin{macrocode}
+\long\def\robust@command@chk@safe#1{%
+ \begingroup
+ \escapechar=`\\
+ \expandafter\endgroup\expandafter
+ \robust@command@act@chk@args\meaning#1:->\@nil}
+\def\robust@command@act@chk@args#1:->#2\@nil{%
+ \@expl@str@if@eq@@nnTF{#1}{macro}%
+ {\@firstoftwo}%
+ {\@expl@str@if@eq@@nnTF{#1}{\protected macro}%
+ {\@firstoftwo}%
+ {\@secondoftwo}}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000-00-00}{\robust@command@act}
+%<latexrelease> {Add \robust@command@act}%
+%<latexrelease>\let\robust@command@act\@undefined
+%<latexrelease>\let\robust@command@act@loop\@undefined
+%<latexrelease>\let\robust@command@act@loop@aux\@undefined
+%<latexrelease>\let\robust@command@act@do\@undefined
+%<latexrelease>\let\robust@command@act@end\@undefined
+%<latexrelease>\let\robust@command@chk@safe\@undefined
+%<latexrelease>\let\robust@command@act@chk@args\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% \end{macro}
+%
+%
+% \subsubsection{Copying robust commands}
+%
+% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2020-10-01}{\DeclareCommandCopy}
+%<latexrelease> {Add \NewCommandCopy, \RenewCommandCopy, and \DeclareCommandCopy}%
+%<*2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macro}{\NewCommandCopy}
+% \begin{macro}{\RenewCommandCopy}
+% \begin{macro}{\DeclareCommandCopy}
+% \changes{v1.5j}{2020/05/09}{Added \cs{DeclareCommandCopy} (gh/239)}
+%
+% \cs{NewCommandCopy} starts by checking if \verb=#1= is already defined, and
+% raises an error if so, otherwise the definition is carried out.
+% \cs{RenewCommandCopy} does (almost) the opposite. If the command is
+% \emph{not} defined, then an error is raised. But the definition is carried
+% out anyhow, so the behaviour is consistent with \cs{renewcommand}.
+%
+% A \cs{ProvideCommandCopy} isn't defined because it's not reasonably useful.
+% \verb=\provide...= commands mean ``define this if there's no other
+% definition'', but copying a command (usually) implies that the command being
+% copied is defined, so \cs{ProvideCommandCopy} doesn't make a lot of sense.
+% But more importantly, the most common use case of copying a command is to
+% redefine it later, while preserving the old definition, as in:
+% \begin{verbatim}
+% \ProvideComandCopy \A \B
+% \renewcommand \B { ... \A ... }
+% \end{verbatim}
+% then, if \verb=\A= is already defined the first line is skipped, an in this
+% case \verb=\B= won't work as expected.
+%
+% The three versions call the internal \cs{declare@commandcopy} with the
+% proper action. \cs{@firstofone} will carry out the copy. The only case
+% when the copy is not made is the \meta{false} case for \cs{NewCommandCopy},
+% in which the command already exists and the definition is aborted.
+% \begin{macrocode}
+\def\NewCommandCopy{%
+ \declare@commandcopy
+ {\@firstofone}%
+ {\@firstoftwo\@notdefinable}}
+\def\RenewCommandCopy{%
+ \declare@commandcopy
+ {\@latex@error{Command \@backslashchar\reserved@a\space undefined}\@ehc
+ \@firstofone}%
+ {\@firstofone}}
+\def\DeclareCommandCopy{%
+ \declare@commandcopy
+ {\@firstofone}%
+ {\@firstofone}}
+% \end{macrocode}
+%
+% \begin{macro}{\declare@commandcopy}
+% Start by checking if the command is already defined. The proper action is
+% taken by each specific command above. If all's good, then
+% \cs{robust@command@act} is called with the proper arguments as described
+% earlier, with \cs{@declarecommandcopylisthook} as the \meta{action-list} and
+% \cs{declare@commandcopy@let} as the \meta{fallback-action}.
+% \begin{macrocode}
+\long\def\declare@commandcopy#1#2#3#4{%
+ \edef\reserved@a{\@expl@cs@to@str@@N#3}%
+ \@ifundefined\reserved@a{#1}{#2}%
+ {\robust@command@act
+ \@declarecommandcopylisthook#4%
+ \declare@commandcopy@let{#3#4}}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@declarecommandcopylisthook}
+% The initial definition of \cs{@declarecommandcopylisthook} contains the
+% tests for the two types of robust command in the kernel.
+% \begin{macrocode}
+\def\@declarecommandcopylisthook{%
+ {\@if@DeclareRobustCommand \@copy@DeclareRobustCommand}%
+ {\@if@newcommand \@copy@newcommand}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\declare@commandcopy@let}
+% The initial definition of \cs{@declarecommandcopylisthook} contains the
+% tests for the two types of robust command in the kernel.
+% \begin{macrocode}
+\long\def\declare@commandcopy@let#1#2{\let#1=#2\relax}
+% \end{macrocode}
+% \end{macro}
+%
+% Now the rollback code.
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000-00-00}{\DeclareCommandCopy}
+%<latexrelease> {Undefine \NewCommandCopy, \RenewCommandCopy, and \DeclareCommandCopy}%
+%<latexrelease>\let\NewCommandCopy\@undefined
+%<latexrelease>\let\RenewCommandCopy\@undefined
+%<latexrelease>\let\DeclareCommandCopy\@undefined
+%<latexrelease>\let\declare@commandcopy\@undefined
+%<latexrelease>\let\@declarecommandcopylisthook\@undefined
+%<latexrelease>\let\declare@commandcopy@let\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsubsection{Showing robust commands}
+%
+% \begin{macro}{\ShowCommand}
+% \changes{v1.5k}{2020/08/19}{Added \cs{ShowCommand} (gh/373)}
+%
+% Most of the machinery defined for \cs{NewCommandCopy} can be used to show
+% the definition of a robust command, in a similar fashion to \texttt{texdef}.
+% The difference is that after the command's is detected to has a given type
+% of robustness, rather than making a copy, we use a separate routine to show
+% its definition.
+%
+% With all the machinery in place, \cs{ShowCommand} itself is quite simple:
+% use \cs{robust@command@act} to iterate through the \cs{@showcommandlisthook}
+% list, and if nothing is found, fallback to \cs{show}.
+% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2020-10-01}{\ShowCommand}%
+%<latexrelease> {Add \ShowCommand}%
+%<*2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\long\def\ShowCommand#1{%
+ \robust@command@act
+ \@showcommandlisthook#1%
+ \show#1}
+% \end{macrocode}
+%
+% \begin{macro}{\@showcommandlisthook}
+% The initial definition of \cs{@showcommandlisthook} contains the same tests
+% as used for copying, but \cs{@show@...} commands instead of \cs{@copy@...}.
+% Same as before, it is initialised to cope with \cs{DeclareRobustCommand} and
+% \cs{newcommand} with optional arguments.
+% \begin{macrocode}
+\def\@showcommandlisthook{%
+ {\@if@DeclareRobustCommand \@show@DeclareRobustCommand}%
+ {\@if@newcommand \@show@newcommand}}
+% \end{macrocode}
+% \end{macro}
+%
+% Now the rollback code.
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000-00-00}{\ShowCommand}
+%<latexrelease> {Undefine \ShowCommand}%
+%<latexrelease>\let\ShowCommand\@undefined
+%<latexrelease>\let\@showcommandlisthook\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2020-10-01}{\@if@DeclareRobustCommand}
+%<latexrelease> {Add \@if@DeclareRobustCommand, \@if@newcommand,
+%<latexrelease> \@copy@DeclareRobustCommand, \@copy@newcommand,
+%<latexrelease> \@show@DeclareRobustCommand, \@show@newcommand}%
+%<*2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \subsubsection{Commands defined with \cs{DeclareRobustCommand}}
+%
+% \begin{macro}{\@if@DeclareRobustCommand}
+% \changes{v1.5j}{2020/05/09}{Added \cs{DeclareCommandCopy} (gh/239)}
+%
+% Now that we provided a generic way to copy one macro to another, we need to
+% define a way to check if a command is one of \LaTeXe's robust types. These
+% tests are heavily based on Heiko's \cs{LetLtxMacro}, but chopped into
+% separate macros.
+%
+% \cs{@if@DeclareRobustCommand} checks if a command \verb=\cmd= was defined by
+% \cs{DeclareRobustCommand}. The test returns true if the expansion of
+% \verb=\cmd= is exactly \verb*=\protect\cmd =.
+%
+% \begin{macrocode}
+\long\def\@if@DeclareRobustCommand#1{%
+ \begingroup
+ \escapechar=`\\
+ \edef\reserved@a{\string#1}%
+ \edef\reserved@b{\detokenize{#1}}%
+ \xdef\@gtempa{%
+ \ifx\reserved@a\reserved@b
+ \noexpand\x@protect
+ \noexpand#1%
+ \fi
+ \noexpand\protect
+ \expandafter\noexpand\csname\@expl@cs@to@str@@N#1 \endcsname}%
+ \endgroup
+ \ifx\@gtempa#1\relax
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi}
+% \end{macrocode}
+%
+% \begin{macro}{\@copy@DeclareRobustCommand}
+% \begin{macro}{\copy@kernel@robust@command}
+% If a command was defined by \cs{DeclareRobustCommand} (that is,
+% \cs{@if@DeclareRobustCommand} returns true), then to make a copy of \verb=\cmd=
+% into \verb=\foo= we define the latter such that it expands to
+% \verb*=\protect\foo =, then make \verb*=\foo = equal to \verb*=\cmd =.
+%
+% There is one detail we need to take care of: if a command was defined with
+% \cs{DeclareRobustCommand} it may still have an optional argument, in which
+% case there is one more macro layer before the actual definition of the
+% command. We use \cs{@if@newcommand} to check that and
+% \cs{@copy@newcommand} to do the copying.
+% \begin{macrocode}
+\long\def\@copy@DeclareRobustCommand#1#2{%
+ \begingroup
+ \escapechar=`\\
+ \edef\reserved@a{\string#1}%
+ \edef\reserved@b{\detokenize{#1}}%
+ \edef\reserved@a{%
+ \endgroup
+ \def\noexpand#1{%
+ \ifx\reserved@a\reserved@b
+ \noexpand\x@protect
+ \noexpand#1%
+ \fi
+ \noexpand\protect
+ \expandafter\noexpand\csname\@expl@cs@to@str@@N#1 \endcsname}%
+ \noexpand\copy@kernel@robust@command
+ \expandafter\noexpand\csname\@expl@cs@to@str@@N#1 \endcsname
+ \expandafter\noexpand\csname\@expl@cs@to@str@@N#2 \endcsname}%
+ \reserved@a}
+\long\def\copy@kernel@robust@command#1#2{%
+ \robust@command@chk@safe#2%
+ {\@if@newcommand#2%
+ {\@copy@newcommand}%
+ {\declare@commandcopy@let}}
+ {\declare@commandcopy@let}%
+ #1#2}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@show@DeclareRobustCommand}
+% \begin{macro}{\show@kernel@robust@command}
+% Showing the command is pretty simple. This command prints the top-level
+% expansion as \TeX's \cs{show} would, but with |robust macro:| rather than
+% just |macro:|, then a blank line and then \cs{show} the inner command.
+% For a macro defined with, say, |\DeclareRobustCommand\foo[1]{bar}|, it will
+% print:
+% \begin{verbatim}
+% > \foo=robust macro:
+% ->\protect \foo .
+%
+% > \foo =\long macro:
+% #1->bar.
+% \end{verbatim}
+% If the inner command is defined with an optional argument, then
+% \cs{@show@newcommand} is also used.
+%
+% The value of \cs{escapechar} is deliberately not enforced, so
+% \cs{ShowCommand} behaves more like \cs{show}.
+% \begin{macrocode}
+\long\def\@show@DeclareRobustCommand#1{%
+ \typeout{> \string#1=robust macro:}%
+ \typeout{->\@expl@cs@replacement@spec@@N#1.^^J}%
+ \expandafter\show@kernel@robust@command
+ \csname\@expl@cs@to@str@@N#1 \endcsname}
+\long\def\show@kernel@robust@command#1{%
+ \robust@command@chk@safe#1%
+ {\@if@newcommand#1%
+ {\@show@newcommand}%
+ {\show}}%
+ {\show}%
+ #1}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \end{macro}
+%
+% \subsubsection{Commands defined with \cs{newcommand} (with optional argument)}
+%
+% \begin{macro}{\@if@newcommand}
+% A command \verb=\cmd= (or \verb*=\cmd =, if it was defined with
+% \cs{DeclareRobustCommand}) with an optional argument will expand to
+% \verb*=\@protected@testopt\cmd\\cmd{<opt>}=. To check that we look at the
+% first three tokens in the expansion of \verb=\cmd=, and return true or false
+% accordingly.
+%
+% This test \emph{requires} that the command be a parameterless macro,
+% otherwise it will not work (and probably break). This is ensured with
+% \cs{robust@command@chk@safe} before calling \cs{@if@newcommand}.
+% \begin{macrocode}
+\long\def\@if@newcommand#1{%
+ \edef\reserved@a{%
+ \noexpand\@protected@testopt
+ \noexpand#1%
+ \expandafter\noexpand\csname\@backslashchar\@expl@cs@to@str@@N#1\endcsname}%
+ \edef\reserved@b{%
+ \unexpanded\expandafter\expandafter\expandafter
+ {\expandafter\@carcube#1{}{}{}\@nil}}%
+ \ifx\reserved@a\reserved@b
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi}
+% \end{macrocode}
+%
+% \begin{macro}{\@copy@newcommand}
+% Then, if a command \verb=\cmd= takes an optional argument, we copy it to
+% \verb=\foo= by defining the latter to expand to
+% \verb=\@protected@testopt\foo\\foo{<opt>}=.
+% \begin{macrocode}
+\long\def\@copy@newcommand#1#2{%
+ \edef#1{\noexpand\@protected@testopt
+ \noexpand#1%
+ \expandafter\noexpand\csname\@backslashchar\@expl@cs@to@str@@N#1\endcsname
+ \unexpanded\expandafter\expandafter\expandafter
+ {\expandafter\@gobblethree#2}}%
+ \expandafter
+ \let\csname\@backslashchar\@expl@cs@to@str@@N#1\expandafter\endcsname
+ \csname\@backslashchar\@expl@cs@to@str@@N#2\endcsname}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@show@newcommand}
+% \begin{macro}{\@show@newcommand@aux}
+% A command being \cs{show}n here is guaranteed to have an optional argument.
+% Start by showing the top-level expansion of the command (using \cs{typeout}
+% to avoid TeX asking for interaction and extra context lines), then call
+% \cs{@show@newcommand@aux} with the internal command, which contains the
+% actual definition, and with the expansion of the command to extract the
+% default value of the optional argument.
+% \begin{macrocode}
+\long\def\@show@newcommand#1{%
+ \typeout{> \string#1=robust macro:}%
+ \typeout{->\@expl@cs@replacement@spec@@N#1.^^J}%
+ \expandafter\@show@newcommand@aux
+ \csname\@backslashchar\@expl@cs@to@str@@N#1\expandafter\endcsname
+ \expandafter{#1}}
+% \end{macrocode}
+%
+% For a macro defined with, say, |\newcommand\foo[1][opt]{bar}|, it will
+% print:
+% \begin{verbatim}
+% > \foo=robust macro:
+% ->\@protected@testopt \foo \\foo {opt}.
+%
+% > \\foo=\long macro:
+% > default #1=opt.
+% [#1]->bar.
+% \end{verbatim}
+% If the command was defined with \cs{DeclareRobustCommand}, then another pair
+% of lines show the top-level expansion \verb*|\protect \foo |.
+%
+% The extra gymnastics with \cs{showtokens} ensures that \cs{showtokens}
+% itself, and the internals of this macro aren't showed in the context lines.
+% \begin{macrocode}
+\long\def\@show@newcommand@aux#1#2{%
+ \typeout{> \string#1=\@expl@cs@prefix@spec@@N#1macro:}%
+ \edef\reserved@a{%
+ default \string##1=\expandafter\detokenize\@gobblethree#2.^^J%
+ \@expl@cs@argument@spec@@N#1->\@expl@cs@replacement@spec@@N#1}%
+ \showtokens\expandafter\expandafter\expandafter{\expandafter\reserved@a}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% Now the rollback code.
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000-00-00}{\@if@DeclareRobustCommand}
+%<latexrelease> {Undefine \@if@DeclareRobustCommand, \@if@newcommand,
+%<latexrelease> \@copy@DeclareRobustCommand, \@copy@newcommand,
+%<latexrelease> \@show@DeclareRobustCommand, \@show@newcommand}%
+%<latexrelease>\let\@if@DeclareRobustCommand\@undefined
+%<latexrelease>\let\@copy@DeclareRobustCommand\@undefined
+%<latexrelease>\let\@show@DeclareRobustCommand\@undefined
+%<latexrelease>\let\@if@newcommand\@undefined
+%<latexrelease>\let\@copy@newcommand\@undefined
+%<latexrelease>\let\@show@newcommand\@undefined
+%
+%<latexrelease>\let\copy@kernel@robust@command\@undefined
+%<latexrelease>\let\show@kernel@robust@command\@undefined
+%<latexrelease>\let\@show@newcommand@aux\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% \end{macro}
+%
%
% \subsection{Internal defining commands}
%
@@ -1537,6 +2194,56 @@
% \end{macro}
%
%
+% \begin{macro}{\string@makeletter}
+% \begin{macro}{\@string@makeletter}
+% \begin{macro}{\char@if@alph}
+% Iterates through a string, turning each alphabetic character into
+% a catcode-11 token (partly undoes a \cs{detokenize}). Useful for
+% \cs{ifx}-based string comparisons where \cs{detokenize}-ing the
+% other string would break too much code.
+%
+% \changes{v1.5n}{2020/09/06}
+% {Macro added}
+%
+% The macro uses \textsf{expl3}'s \cs{@expl@str@map@function@@NN} to
+% iterate on the string (without losing spaces) and applies
+% \cs{@string@makeletter} on each character. The latter checks if
+% character is between a--z or A--Z, and uses \cs{@alph} or \cs{@Alph}
+% to get the corresponding catcode-11 token. Other tokens are passed
+% through unchanged.
+% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2020/10/01}{\string@makeletter}
+%<latexrelease> {Add \string@makeletter}%
+%<*2ekernel|latexrelease>
+\def\string@makeletter#1{%
+ \@expl@str@map@function@@NN#1\@string@makeletter}
+\def\@string@makeletter#1{%
+ \char@if@alph{#1}%
+ {\@expl@char@generate@@nn{`#1}{11}}%
+ {#1}}
+\def\char@if@alph#1{%
+ \ifnum0\ifnum`#1<`A 1\fi\ifnum`#1>`z 1\fi
+ \if\ifnum`#1>`Z @\fi\ifnum`#1<`a @\fi01\fi>0
+ \expandafter\@secondoftwo
+ \else
+ \expandafter\@firstoftwo
+ \fi}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%
+%<latexrelease>\IncludeInRelease{0000/00/00}{\string@makeletter}
+%<latexrelease> {Undefine \string@makeletter}%
+%<latexrelease>\let\string@makeletter\@undefined
+%<latexrelease>\let\@string@makeletter\@undefined
+%<latexrelease>\let\char@if@alph\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
%
% \begin{macro}{\makeatletter}
% \begin{macro}{\makeatother}
@@ -1550,7 +2257,6 @@
% \end{macro}
% \end{macro}
%
-
%
% \section{Discretionary Hyphenation}
% \begin{macro}{\-}
@@ -1560,6 +2266,7 @@
% \changes{v1.0g}{1994/04/12}
% {Define \cs{@dischyph}, was previously in ltboxes.dtx}
% \changes{v1.5b}{2017/03/27}{Define \cs{@dischyph} after \cs{-}}
+% \changes{v1.5j}{2020/05/11}{Do not overwrite \cs{-} under Lua\TeX}
% \end{macro}
% Moved here to be after the definition of |\DeclareRobustCommand|.
%
@@ -1589,35 +2296,56 @@
% older \LaTeX\ definition accessible via \textsf{latexrelease}
% as usual.
%
-% \begin{macrocode}
-%</2ekernel>
-%<latexrelease>\IncludeInRelease{2017/04/15}{\-}{Use \hyphenchar in \-}%
-% \end{macrocode}
+% In Lua\LaTeX\ the primitive definition of \cs{-} is used directly
+% because it's use of extended hyphenation parameters means that \cs{-}
+% works correctly even with \cs{hyphenchar} set to $-1$. This change
+% makes \cs{-} under Lua\LaTeX\ compatible with language specific
+% hyphenation characters.
+%
% Temporary definition of |\@latex@info|, final definition is later.
% \begin{macrocode}
-%<*2ekernel>
\def\@latex@info#1{}
-%</2ekernel>
% \end{macrocode}
%
% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2020/10/01}{\-}{Use primitive \- in Lua\LaTeX}%
%<*2ekernel|latexrelease>
-\DeclareRobustCommand{\-}{%
- \discretionary{%
- \char \ifnum\hyphenchar\font<\z@
- \defaulthyphenchar
- \else
- \hyphenchar\font
- \fi
- }{}{}%
-}
-\let\@dischyph=\-
+\ifx\directlua\@undefined
+ \DeclareRobustCommand{\-}{%
+ \discretionary{%
+ \char \ifnum\hyphenchar\font<\z@
+ \defaulthyphenchar
+ \else
+ \hyphenchar\font
+ \fi
+ }{}{}%
+ }
+\else
+ \let\-\@@hyph
+\fi
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2017/04/15}{\-}{Use \hyphenchar in \-}%
+%<latexrelease>\DeclareRobustCommand{\-}{%
+%<latexrelease> \discretionary{%
+%<latexrelease> \char \ifnum\hyphenchar\font<\z@
+%<latexrelease> \defaulthyphenchar
+%<latexrelease> \else
+%<latexrelease> \hyphenchar\font
+%<latexrelease> \fi
+%<latexrelease> }{}{}%
+%<latexrelease>}
+%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}{\-}{Use \hyphenchar in \-}%
%<latexrelease>\def\-{\discretionary{-}{}{}}
-%<latexrelease>\let\@dischyph=\-
%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+\let\@dischyph=\-
+%</2ekernel|latexrelease>
%<*2ekernel>
% \end{macrocode}
% \end{macro}
@@ -1678,6 +2406,28 @@
%<*2ekernel>
% \end{macrocode}
%
+%
+% \begin{macro}{\g@addto@macro}
+% Globally add to the end of a macro.
+% \changes{v0.2a}{1993/11/14}{Made global}
+% \changes{v0.2w}{1994/01/31}
+% {Use toks register to avoid `hash' problems}
+% \changes{v1.0o}{1995/05/17}
+% {Make long for latex/1522}
+% \changes{v1.0w}{1996/12/17}
+% {Use \cs{begingroup} to save making a mathord}
+% \changes{v1.0x}{1997/02/05}
+% {missing percent /2402}
+% \begin{macrocode}
+\long\def\g@addto@macro#1#2{%
+ \begingroup
+ \toks@\expandafter{#1#2}%
+ \xdef#1{\the\toks@}%
+ \endgroup}
+% \end{macrocode}
+% \end{macro}
+%
+%
% \begin{macrocode}
%</2ekernel>
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltdirchk.dtx b/Master/texmf-dist/source/latex/base/ltdirchk.dtx
index 25fb9480ddd..3abd49aced5 100644
--- a/Master/texmf-dist/source/latex/base/ltdirchk.dtx
+++ b/Master/texmf-dist/source/latex/base/ltdirchk.dtx
@@ -37,7 +37,7 @@
%<*driver>
% \fi
\ProvidesFile{ltdirchk.dtx}
- [2019/11/01 v1.3a LaTeX Kernel (System Dependent Parts)]
+ [2020/08/21 v1.3a LaTeX Kernel (System Dependent Parts)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltdirchk.dtx}
@@ -172,7 +172,9 @@
%, \LaTeX\ will not work around a bug in old \TeX\ versions, and
% so error messages will appear in a very strange format, with |^^J|
% appearing instead of line breaks:
-% \begingroup\catcode`\==\active \def=#1#2{}\hfuzz\maxdimen
+% \begingroup
+% ^^A FMi next line doesn't work with hacked class
+% ^^A\catcode`\==\active \def=#1#2{}\hfuzz\maxdimen
%\begin{verbatim}
%! LaTeX Error: \rubbish undefined.^^J^^JSee the LaTeX manual or LaTeX=
% Companion
diff --git a/Master/texmf-dist/source/latex/base/ltexpl.dtx b/Master/texmf-dist/source/latex/base/ltexpl.dtx
index 230cd911588..4100da79c28 100644
--- a/Master/texmf-dist/source/latex/base/ltexpl.dtx
+++ b/Master/texmf-dist/source/latex/base/ltexpl.dtx
@@ -33,67 +33,278 @@
%<*driver>
% \fi
\ProvidesFile{ltexpl.dtx}
- [2019-10-02 v0.0 LaTeX Kernel (expl3-dependent code)]
+ [2020/09/06 v1.2f LaTeX Kernel (expl3-dependent code)]
% \iffalse
\documentclass{ltxdoc}
-\GetFileInfo{ltfinal.dtx}
+\GetFileInfo{ltexpl.dtx}
\title{\filename}
\date{\filedate}
\author{%
Joseph Wright}
+
+\providecommand\pkg[1]{\texttt{#1}}
+
\begin{document}
\MaintainedByLaTeXTeam{latex}
\maketitle
- \DocInput{ltfinal.dtx}
+ \DocInput{ltexpl.dtx}
\end{document}
%</driver>
% \fi
%
+%
+% \changes{v1.2d}{2020/08/21}{Dropped unused command}
+%
% \section{\pkg{expl3}-dependent code}
%
% \StopEventually{}
%
% \changes{v0.0}{2019-10-02}{Initial version}
%
+% \subsection{Loader}
+%
+% \changes{v1.0a}{2020/03/02}
+% {Don't load expl3 if already in the format (gh/295)}
+% \changes{v1.1}{2020/03/05}
+% {Load xparse.ltx if \cs{NewDocumentCommand} is not defined
+% by expl3.ltx}
+% \changes{v1.2c}{2020/06/04}
+% {Define a local version of some \LaTeXe{} basic macros to support
+% package loading}
+%
+% First define some blank commands, so that in case something goes wrong while
+% loading \textsf{expl3}, we won't get strange \texttt{Undefined control
+% sequence} errors.
% \begin{macrocode}
%<*2ekernel>
+\def\@expl@sys@load@backend@@{}
+\def\@expl@push@filename@@{}
+\def\@expl@push@filename@aux@@{}
+\def\@expl@pop@filename@@{}
+%</2ekernel>
% \end{macrocode}
%
-% \subsection{Loader}
+% \changes{v1.2d}{2020/07/08}
+% {Add a last-minute hook for \textsf{expl3}}
+% Create a hook for last-minute \pkg{expl3} material.
+% \begin{macrocode}
+%<*2ekernel>
+\def\@expl@finalise@setup@@{}
+%</2ekernel>
+% \end{macrocode}
+%
+% Now define some basics to support loading \textsf{expl3}. These macros can
+% be defined here safely, because they are redefined later on by the kernel,
+% so we define simpler versions just to suit our needs.
+% \begin{macrocode}
+%<*2ekernel>
+\long\def\@gobble#1{}
+\long\def\@firstofone#1{#1}
+\long\def\@firstoftwo#1#2{#1}
+\long\def\@secondoftwo#1#2{#2}
+\long\def\IfFileExists#1{%
+ \openin\@inputcheck"#1" %
+ \ifeof\@inputcheck
+ \expandafter\@secondoftwo
+ \else
+ \closein\@inputcheck
+ \expandafter\@firstoftwo
+ \fi}
+\long\def\@ifnextchar#1#2#3{%
+ \let\reserved@d=#1%
+ \def\reserved@a{#2}%
+ \def\reserved@b{#3}%
+ \futurelet\@let@token\@ifnch}
+\def\@ifnch{%
+ \ifx\@let@token\reserved@d
+ \expandafter\reserved@a
+ \else
+ \expandafter\reserved@b
+ \fi}
+%</2ekernel>
+% \end{macrocode}
+%
+% If we are doing a rollback with a format containing expl3 we
+% aren't reloading it as that creates havoc. This may need a
+% refined version!
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {expl3}{Pre-load expl3}%
+\expandafter\ifx\csname tex\string _let:D\endcsname\relax
+ \expandafter\@firstofone
+\else
+ \GenericInfo{}{Skipping: expl3 code already part of the format}%
+%<2ekernel> \expandafter\endinput
+%<latexrelease> \expandafter\@gobble
+\fi
+% \end{macrocode}
%
% Check for the required primitive/engine support and the existence of
% a loader.
% \begin{macrocode}
+ {%
+ \IfFileExists{expl3.ltx}
+ {%
+ \ifnum0%
+ \ifdefined\pdffilesize 1\fi
+ \ifdefined\filesize 1\fi
+ \ifdefined\luatexversion\ifnum\luatexversion>94 1\fi\fi
+ \ifdefined\kanjiskip 1\fi
+ >0 %
+ \expandafter\@firstofone
+ \else
+% \end{macrocode}
+%
+% In \texttt{2ekernel} mode, an error is fatal and building the format
+% is aborted. Use \verb=\batchmode \read -1 to \tokenlist=, which errors
+% with
+% \verb=! Emergency stop. (cannot \read from terminal in nonstop modes)=
+% and aborts the \TeX{} run. In \texttt{latexrelease} mode, raise an
+% error and do nothing. Both ways, the error message shows the minimum
+% \textsf{expl3} engine requirements.
+% \begin{macrocode}
+%<2ekernel> \def~{ }\def\MessageBreak{^^J~~~~~~~~~~~~~~~}%
+%<2ekernel> \errmessage{LaTeX Error:
+%<latexrelease> \@latex@error{%
+ LaTeX requires the e-TeX primitives and additional\MessageBreak
+ functionality available in the engines:\MessageBreak
+ - pdfTeX v1.40\MessageBreak
+ - XeTeX v0.99992\MessageBreak
+ - LuaTeX v0.95\MessageBreak
+ - e-(u)pTeX mid-2012\MessageBreak
+ or later%
+%<latexrelease> }\@ehd \expandafter\@gobble
+%<2ekernel> }\batchmode \read -1 to \reserved@a
+ \fi
+ }
+ {%
+%<*2ekernel>
+ \errmessage{LaTeX requires expl3}%
+ \batchmode \read -1 to \reserved@a
%</2ekernel>
-%<*2ekernel|latexrelease>
+%<*latexrelease>
+ \@latex@error{LaTeX requires expl3}\@ehd
+ \@gobble
+%</latexrelease>
+ }%
+ {%
+ \input expl3.ltx
+ \ifdefined\NewDocumentCommand
+ \else
+ \IfFileExists{xparse.ltx}
+ {\input xparse.ltx }
+ {}%
+ \fi
+ }%
+ }
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {expl3}{Pre-load expl3}%
-\IfFileExists{expl3.ltx}
- {%
- \ifnum0%
- \ifdefined\pdffilesize 1\fi
- \ifdefined\filesize 1\fi
- \ifdefined\luatexversion\ifnum\luatexversion>94 1\fi\fi
- >0 %
- \else
- \message{Skipping expl3-dependent extensions}
-%<2ekernel> \expandafter\endinput
+%<latexrelease>\IfFileExists{expl3.ltx}
+%<latexrelease> {%
+%<latexrelease> \ifnum0%
+%<latexrelease> \ifdefined\pdffilesize 1\fi
+%<latexrelease> \ifdefined\filesize 1\fi
+%<latexrelease> \ifdefined\luatexversion\ifnum\luatexversion>94 1\fi\fi
+%<latexrelease> >0 %
+%<latexrelease> \else
+%<latexrelease> \message{Skipping expl3-dependent extensions}
%<latexrelease> \expandafter\@gobbletwo
- \fi
- }
- {%
- \message{Skipping expl3-dependent extensions}%
-%<2ekernel> \endinput
+%<latexrelease> \fi
+%<latexrelease> }
+%<latexrelease> {%
+%<latexrelease> \message{Skipping expl3-dependent extensions}%
%<latexrelease> \@gobbletwo
- }%
-\input{expl3.ltx}
-%</2ekernel|latexrelease>
+%<latexrelease> }%
+%<latexrelease>\input{expl3.ltx}
%<latexrelease>\EndIncludeInRelease
-%<*2ekernel>
% \end{macrocode}
%
+% \subsection{Using expl3 code}
+%
+% In order to ease the implemantation of some new features in
+% \LaTeXe\ we may (temporarily) use some coding based on the
+% \pkg{expl3}-code.
+% Such macros will eventually vanish and may be changed
+% unannounced. They are there for internal use in the \LaTeXe\
+% kernel and are not meant to be used in third-party
+% packages. These macros will always have the \verb|@expl@|
+% prefix in their name.
+%
+% The rest of the name matches the \pkg{expl3} name but with all
+% underscores replaced by \texttt{@}s and the \texttt{:} replaced
+% by \texttt{@@}, e.g.,
+%\begin{verbatim}
+% \cs_new_eq:NN \@expl@tl@trim@spaces@apply@@nN \tl_trim_spaces_apply:nN
+%\end{verbatim}
+% if that \pkg{expl3} command is needed in places that are others
+% coded in \LaTeXe{} conventions.
+%
% \begin{macrocode}
-%</2ekernel>
+\ExplSyntaxOn
+% \end{macrocode}
+%
+% In this file, each release of LaTeX adds an \cs{IncludeInRelease}
+% block, in which the macros copied for that release were defined.
+% In case a rollback is requested, the entire block is changed.
+%
+% Each macro copied has a \cs{changes} entry to explain when and why
+% it was copied, so that further to that may spot it easily.
+%
+% Here \cs{cs\string_gset\string_eq:NN} is used, instead of the |new|
+% variant because if different releases use that same name for
+% different purposes, each can copy the macro without worrying about
+% redefinitions.
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/10/01}{expl3~2020-10-01}%
+%<latexrelease> {expl3~macros~added~for~the~2020-10-01~release}%
+% \end{macrocode}
+%
+% \changes{v1.2e}{2020/08/19}
+% {Add \cs{@expl@cs@to@str@@N} and \cs{@expl@str@if@eq@@nnTF}
+% for \cs{NewCommandCopy} (gh/239)}
+% \begin{macrocode}
+\cs_gset_eq:NN \@expl@cs@to@str@@N \cs_to_str:N
+\cs_gset_eq:NN \@expl@str@if@eq@@nnTF \str_if_eq:nnTF
+% \end{macrocode}
+%
+% \changes{v1.2e}{2020/08/19}
+% {Add \cs{@expl@cs@\meta{thing}@spec@@N}
+% for \cs{ShowCommand} (gh/373)}
+% \begin{macrocode}
+\cs_gset_eq:NN \@expl@cs@prefix@spec@@N \cs_prefix_spec:N
+\cs_gset_eq:NN \@expl@cs@argument@spec@@N \cs_argument_spec:N
+\cs_gset_eq:NN \@expl@cs@replacement@spec@@N \cs_replacement_spec:N
+% \end{macrocode}
+%
+% \changes{v1.2f}{2020/09/06}
+% {Add \cs{@expl@str@map@function@@NN
+% and \cs{@expl@char@generate@@nn}}
+% for \cs{string@makeletter} (gh/386)}
+% \begin{macrocode}
+\cs_gset_eq:NN \@expl@str@map@function@@NN \str_map_function:NN
+\cs_gset_eq:NN \@expl@char@generate@@nn \char_generate:nn
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}{expl3~2020-10-01}%
+%<latexrelease> {expl3~macros~added~for~the~2020-10-01~release}%
+%<latexrelease>\cs_undefine:N \@expl@cs@to@str@@N
+%<latexrelease>\cs_undefine:N \@expl@str@if@eq@@nnTF
+%<latexrelease>\cs_undefine:N \@expl@cs@prefix@spec@@N
+%<latexrelease>\cs_undefine:N \@expl@cs@argument@spec@@N
+%<latexrelease>\cs_undefine:N \@expl@cs@replacement@spec@@N
+%<latexrelease>\cs_undefine:N \@expl@str@map@function@@NN
+%<latexrelease>\EndIncludeInRelease
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOff
% \end{macrocode}
%
% \Finale
diff --git a/Master/texmf-dist/source/latex/base/ltfilehook.dtx b/Master/texmf-dist/source/latex/base/ltfilehook.dtx
new file mode 100644
index 00000000000..24ba88f576c
--- /dev/null
+++ b/Master/texmf-dist/source/latex/base/ltfilehook.dtx
@@ -0,0 +1,1543 @@
+% \iffalse meta-comment
+%%
+%% File: ltfilehook.dtx (C) Copyright 2020 Frank Mittelbach,
+%% Phelype Oleinik & LaTeX Team
+%
+% This file is part of the LaTeX base system.
+% -------------------------------------------
+%
+% It may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% https://www.latex-project.org/lppl.txt
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008 or later.
+%
+% This file has the LPPL maintenance status "maintained".
+%
+% The list of all files belonging to the LaTeX base distribution is
+% given in the file `manifest.txt'. See also `legal.txt' for additional
+% information.
+%
+% The list of derived (unpacked) files belonging to the distribution
+% and covered by LPPL is defined by the unpacking scripts (with
+% extension .ins) which are part of the distribution.
+%
+% \fi
+%
+% \iffalse
+%
+%%% From File: ltfilehook.dtx
+%
+% \begin{macrocode}
+\providecommand\ltfilehookversion{v1.0b}
+\providecommand\ltfilehookdate{2020/09/26}
+% \end{macrocode}
+%
+%<*driver>
+
+\documentclass{l3doc}
+
+% bug fix fo l3doc.cls
+\ExplSyntaxOn
+\cs_set_protected:Npn \__codedoc_macro_typeset_one:nN #1#2
+ {
+ \vbox_set:Nn \l__codedoc_macro_box
+ {
+ \vbox_unpack_drop:N \l__codedoc_macro_box
+ \hbox { \llap { \__codedoc_print_macroname:nN {#1} #2
+ \MacroFont % <----- without it the \ is in lmr10 if a link is made
+ \
+ } }
+ }
+ \int_incr:N \l__codedoc_macro_int
+ }
+\ExplSyntaxOff
+
+\usepackage{structuredlog} % for demonstration
+
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{ltfilehook.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+%
+% \long\def\fmi#1{\begin{quote}\itshape Todo: #1\end{quote}}
+%
+% \let\hook\texttt
+%
+% \title{The \texttt{ltfilehook} package\thanks{This package has version
+% \ltfilehookversion\ dated \ltfilehookdate, \copyright\ \LaTeX\
+% Project.}}
+%
+% \author{Frank Mittelbach}
+%
+% \maketitle
+%
+%
+%
+% \tableofcontents
+%
+% \section{Introduction}
+%
+%
+%
+% \subsection{Provided hooks}
+%
+% The code offers a number of hooks into which packages (or the
+% user) can add code to support different use cases.
+% Many hooks are offered as pairs (i.e., the second hook is
+% reversed. Also important to know is that these pairs are
+% properly nested with respect to other pairs of hooks.
+%
+% There are hooks that are executed for all files of a certain type
+% (if they contain code), e.g., for all \enquote{include files} or
+% all \enquote{packages},
+% and there are also hooks that are specific to a single file,
+% e.g., do something after the package \texttt{foo.sty} has been
+% loaded.
+%
+%
+% \subsection{General hooks for file reading}
+% \label{sec:general-file-hooks}
+%
+% There are four hooks that are called for each file that is read
+% using document-level commands such as \cs{input}, \cs{include},
+% \cs{usepackage}, etc. They are not called for files read using
+% internal low-level methods, such as \cs{@input} or \cs{openin}.
+%
+% \begin{variable}{file/before,file/before/...,
+% file/after/...,file/after,
+% }
+% These are:
+% \begin{description}
+% \item[\texttt{file/before}, \texttt{file/before/\meta{file-name}}]
+%
+% These hooks are executed in that order just before the file is
+% loaded for reading. The code of the first hook is used
+% with every file, while the second is executed only for the
+% file with matching \meta{file-name} allowing you to specify
+% code that only applies to one file.
+%
+% \item[\texttt{file/after/\meta{file-name}}, \texttt{file/after}]
+%
+% These hooks are after the file with name \meta{file-name} has
+% been fully consumed. The order is swapped (the specific one
+% comes first) so that the \texttt{before} and \texttt{after}
+% hooks nest properly, which is important if any of them involve
+% grouping (e.g., contain environments, for example).
+% Furthermore both hooks are reversed hooks to support correct
+% nesting of different packages adding code to both
+% \texttt{/before} and \texttt{/after} hooks.
+%
+% \end{description}
+% \end{variable}
+%
+%
+% So the overall sequence of hook processing for any file read
+% through the user interface commands of \LaTeX{} is:
+%
+% \begin{tabbing}
+% mm\=mm\=mm\=mm\=\kill
+% \>\cs{UseHook}\marg{\hook{file/before}} \\
+% \>\cs{UseHook}\marg{\hook{file/before/\meta{file name}}} \\
+% \>\> \meta{file contents} \\
+% \>\cs{UseHook}\marg{\hook{file/after/\meta{file name}}} \\
+% \>\cs{UseHook}\marg{\hook{file/after}}
+% \end{tabbing}
+%
+% The file hooks only refer to the file by its name and extension,
+% so the \meta{file name} should be the file name as it is on the
+% filesystem with extension (if any) and without paths. Different
+% from \cs{input} and similar commands, the \texttt{.tex}
+% extension is not assumed in hook \meta{file name}, so \texttt{.tex}
+% files must be specified
+% with their extension to be recognized.
+% Files within subfolders should also be addressed by their name and
+% extension only.
+%
+% Extensionless files also work, and should then be given without
+% extension. Note however that \TeX{} prioritizes \texttt{.tex}
+% files, so if two files \texttt{foo} and \texttt{foo.tex} exist in
+% the search path, only the latter will be seen.
+%
+% When a file is input, the \meta{file name} is available in
+% \cs{CurrentFile}, which is then used when accessing the
+% \hook{file/before/\meta{file name}} and
+% \hook{file/after/\meta{file name}}.
+%
+% \begin{variable}{\CurrentFile}
+% The name of the file about to be read (or just finished) is
+% available to the hooks through \cs{CurrentFile} (there is no
+% \texttt{expl3} name for it for now). The file is always provided
+% with its extension, i.e., how it appears on your hard drive, but
+% without any specified path to it. For example,
+% \verb=\input{sample}= and \verb=\input{app/sample.tex}= would
+% both have \cs{CurrentFile} being \texttt{sample.tex}.
+% \end{variable}
+%
+% \begin{variable}{\CurrentFilePath}
+% The path to the current file (complement to \cs{CurrentFile}) is
+% available in \cs{CurrentFilePath} if needed.
+% The paths returned in \cs{CurrentFilePath} are only user paths,
+% given through \cs{input@path} (or \pkg{expl3}'s equivalent
+% \cs{l_file_search_path_seq}) or by directly typing in the path
+% in the \cs{input} command or equivalent. Files located by
+% \texttt{kpsewhich} get the path added internally by the \TeX{}
+% implementation, so at the macro level it looks as if the file were
+% in the current folder, so the path in \cs{CurrentFilePath} is empty
+% in these cases (package and class files, mostly).
+% \end{variable}
+%
+% \begin{variable}{\CurrentFileUsed,\CurrentFilePathUsed}
+% In normal circumstances these are identical to \cs{CurrentFile} and
+% \cs{CurrentFilePath}. They will differ when a file substitution
+% has occurred for \cs{CurrentFile}. In that case,
+% \cs{CurrentFileUsed} and \cs{CurrentFilePathUsed} will hold the
+% actual file name and path loaded by \LaTeX, while \cs{CurrentFile}
+% and \cs{CurrentFilePath} will hold the names that were
+% \emph{asked for}. Unless doing very specific work on the file
+% being read, \cs{CurrentFile} and \cs{CurrentFilePath} should be
+% enough.
+% \end{variable}
+%
+% \subsection{Hooks for package and class files}
+%
+% Commands to load package and class files (e.g., \cs{usepackage},
+% \cs{RequirePackage}, \cs{LoadPackageWithOptions}, etc.) offer the
+% hooks from section~\ref{sec:general-file-hooks} when they are
+% used to load a package or class file, e.g.,
+% \texttt{file/after/array.sty} would be called after the
+% \pkg{array} package got loaded. But as packages and classes form as special group
+% of files, there are some additional hooks available that only
+% apply when a package or class is loaded.
+%
+%
+% \begin{variable}{
+% package/before,package/after,
+% package/before/...,package/after/...,
+% class/before,class/after,
+% class/before/...,class/after/...,
+% }
+% These are:
+% \begin{description}
+% \item[\texttt{package/before}, \texttt{package/after}]
+%
+% These hooks are called for each package being loaded.
+%
+% \item[\texttt{package/before/\meta{name}},
+% \texttt{package/after/\meta{name}}]
+%
+% These hooks are additionally called if the package name is
+% \meta{name} (without extension).
+%
+% \item[\texttt{class/before}, \texttt{class/after}]
+%
+% These hooks are called for each class being loaded.
+%
+% \item[\texttt{class/before/\meta{name}}, \texttt{class/after/\meta{name}}]
+%
+% These hooks are additionally called if the class name is
+% \meta{name} (without extension).
+%
+% \end{description}
+% \end{variable}
+% All \hook{/after} hooks are implemented as reversed hooks.
+%
+% \noindent The overall sequence of execution for \cs{usepackage}
+% and friends is therefore:
+% \begin{tabbing}
+% mm\=mm\=mm\=mm\=\kill
+% \>\cs{UseHook}\marg{\hook{package/before}} \\
+% \>\cs{UseHook}\marg{\hook{package/before/\meta{package name}}} \\[5pt]
+% \>\>\cs{UseHook}\marg{\hook{file/before}} \\
+% \>\>\cs{UseHook}\marg{\hook{file/before/\meta{package name}.sty}} \\
+% \>\>\> \meta{package contents} \\
+% \>\>\cs{UseHook}\marg{\hook{file/after/\meta{package name}.sty}} \\
+% \>\>\cs{UseHook}\marg{\hook{file/after}} \\[5pt]
+% \>\>\emph{code from \cs{AtEndOfPackage} if
+% used inside the package} \\[5pt]
+% \>\cs{UseHook}\marg{\hook{package/after/\meta{package name}}} \\
+% \>\cs{UseHook}\marg{\hook{package/after}}
+% \end{tabbing}
+% and similar for class file loading, except that \texttt{package/}
+% is replaced by \texttt{class/} and \cs{AtEndOfPackage} by
+% \cs{AtEndOfClass}.
+%
+% If a package or class is not loaded (or it was loaded before the
+% hooks were set) none of the hooks are executed!
+%
+% \subsection{Hooks for \cs{include} files}
+%
+% To manage \cs{include} files, \LaTeX{} issues a \cs{clearpage}
+% before and after loading such a file. Depending on the use case
+% one may want to execute code before or after these
+% \cs{clearpage}s especially for the one that is issued at the end.
+%
+% Executing code before the final \cs{clearpage}, means that the
+% code is processed while the last page of the included material is
+% still under construction. Executing code after it means that all
+% floats from inside the include file are placed (which
+% might have added further pages) and the final page has finished.
+%
+% Because of these different scenarios we offer hooks in three
+% places.\footnote{If you want to execute code before the first
+% \cs{clearpage} there is no need to use a hook---you can write it
+% directly in front of the \cs{include}.}
+% None of the hooks are executed when an \cs{include} file is
+% bypassed because of an \cs{includeonly} declaration. They are,
+% however, all executed if \LaTeX{} makes an attempt to load the
+% \cs{include} file (even if it doesn't exist and all that happens
+% is \enquote{\texttt{No file \meta{filename}.tex}}).
+%
+%
+% \begin{variable}{include/before,include/before/...,
+% include/end,include/end/...,
+% include/after,include/after/...,
+% }
+% These are:
+% \begin{description}
+%
+% \item[\texttt{include/before}, \texttt{include/before/\meta{name}}]
+%
+% These hooks are executed (in that order) after the initial
+% \cs{clearpage} and after \texttt{.aux} file is changed to use
+% \texttt{\meta{name}.aux}, but before the
+% \texttt{\meta{name}.tex} file is loaded. In other words they are executed
+% at the very beginning of the first page of the \cs{include}
+% file.
+%
+%
+% \item[\texttt{include/end/\meta{name}}, \texttt{include/end}]
+%
+% These hooks are executed (in that order) after \LaTeX{} has
+% stopped reading from the \cs{include} file, but before it has
+% issued a \cs{clearpage} to output any deferred floats.
+%
+%
+% \item[\texttt{include/after/\meta{name}}, \texttt{include/after}]
+%
+% These hooks are executed (in that order) after \LaTeX{} has
+% issued the \cs{clearpage} but before is has switched back
+% writing to the main \texttt{.aux} file. Thus technically we are
+% still inside the \cs{include} and if the hooks generate any
+% further typeset material including anything that writes to the
+% \texttt{.aux} file, then it would be considered part of the
+% included material and bypassed if it is not loaded because of
+% some \cs{includeonly} statement.\footnotemark
+%
+% \end{description}
+% \end{variable}\footnotetext{For that reason
+% another \cs{clearpage} is executed after these hooks which
+% normally does nothing, but starts a new page if further material
+% got added this way.}
+%
+% \subsection{High-level interfaces for \LaTeX{}}
+%
+% We do not provide any high-level \LaTeX{} commands (like
+% \pkg{filehook} or \pkg{scrlfile} do) but think that for package
+% writers the commands from for hook management are sufficient.
+%
+%
+%
+% \subsection{Internal interfaces for \LaTeX{}}
+%
+% \begin{function}{\declare@file@substitution,\undeclare@file@substitution}
+% \begin{syntax}
+% \cs{declare@file@substitution} \Arg{file} \Arg{replacement-file}
+% \cs{undeclare@file@substitution} \Arg{file}
+% \end{syntax}
+% If \meta{file} is requested for loading replace it with
+% \meta{replacement-file}. \cs{CurrentFile} remains pointing to
+% \meta{file} but \cs{CurrentFileUsed} will show the file actually
+% loaded.
+%
+% The main use case for this declaration is to provide a corrected
+% version of a package that can't be changed (due to its license)
+% but no longer functions because of \LaTeX{} kernel changes, for
+% example, or to provide a version that makes use of new kernel
+% functionality while the original package remains available for
+% use with older releases.
+%
+% The \cs{undeclare@file@substitution} declaration undoes a
+% substitution made earlier.
+%
+% \begin{quote}
+% \em
+% Please do not misuse this functionality and replace a file with
+% another unless if really needed and only if the new version is
+% implementating the same functionality as the original one!
+% \end{quote}
+% \end{function}
+%
+% \begin{function}{\disable@package@load,\reenable@package@load}
+% \begin{syntax}
+% \cs{disable@package@load} \Arg{package} \Arg{alternate-code}
+% \cs{reenable@package@load} \Arg{package}
+% \end{syntax}
+% If \meta{package} is requested do not load it but instead run
+% \meta{alternate-code} which could issue a warning, error or any
+% other code.
+%
+% The main use case is for classes that want to restrict the set of
+% supported packages or contain code that make the use of some
+% packages impossible. So rather than waiting until the document
+% breaks they can set up informative messages why certain packages
+% are not available.
+%
+% The function is only implemented for packages not for arbitrary
+% files.
+% \end{function}
+%
+%
+% \subsection{A sample package for structuring the log output}
+%
+% As an application we provide the package \pkg{structuredlog} that
+% adds lines to the \texttt{.log} when a file is opened and closed
+% for reading keeping track of nesting level es well.
+% For example, for the current document it adds the lines
+%\begin{verbatim}
+% = (LEVEL 1 START) t1lmr.fd
+% = (LEVEL 1 STOP) t1lmr.fd
+% = (LEVEL 1 START) supp-pdf.mkii
+% = (LEVEL 1 STOP) supp-pdf.mkii
+% = (LEVEL 1 START) nameref.sty
+% == (LEVEL 2 START) refcount.sty
+% == (LEVEL 2 STOP) refcount.sty
+% == (LEVEL 2 START) gettitlestring.sty
+% == (LEVEL 2 STOP) gettitlestring.sty
+% = (LEVEL 1 STOP) nameref.sty
+% = (LEVEL 1 START) ltfilehook-doc.out
+% = (LEVEL 1 STOP) ltfilehook-doc.out
+% = (LEVEL 1 START) ltfilehook-doc.out
+% = (LEVEL 1 STOP) ltfilehook-doc.out
+% = (LEVEL 1 START) ltfilehook-doc.hd
+% = (LEVEL 1 STOP) ltfilehook-doc.hd
+% = (LEVEL 1 START) ltfilehook.dtx
+% == (LEVEL 2 START) ot1lmr.fd
+% == (LEVEL 2 STOP) ot1lmr.fd
+% == (LEVEL 2 START) omllmm.fd
+% == (LEVEL 2 STOP) omllmm.fd
+% == (LEVEL 2 START) omslmsy.fd
+% == (LEVEL 2 STOP) omslmsy.fd
+% == (LEVEL 2 START) omxlmex.fd
+% == (LEVEL 2 STOP) omxlmex.fd
+% == (LEVEL 2 START) umsa.fd
+% == (LEVEL 2 STOP) umsa.fd
+% == (LEVEL 2 START) umsb.fd
+% == (LEVEL 2 STOP) umsb.fd
+% == (LEVEL 2 START) ts1lmr.fd
+% == (LEVEL 2 STOP) ts1lmr.fd
+% == (LEVEL 2 START) t1lmss.fd
+% == (LEVEL 2 STOP) t1lmss.fd
+% = (LEVEL 1 STOP) ltfilehook.dtx
+%\end{verbatim}
+% Thus if you inspect an issue in the \texttt{.log} it is easy to
+% figure out in which file it occurred, simply by searching back for
+% \texttt{LEVEL} and if it is a \texttt{STOP} then remove 1 from
+% the level value and search further for \texttt{LEVEL} with that value
+% which should then be the \texttt{START} level of the file you are in.
+%
+% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex }
+%
+%
+% \section{The Implementation}
+% \begin{macrocode}
+%<*2ekernel>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=filehook>
+% \end{macrocode}
+%
+%
+% \subsection{Document and package-level commands}
+%
+%
+% \begin{macro}{\CurrentFile,\CurrentFilePath}
+% \begin{macro}{\CurrentFileUsed,\CurrentFilePathUsed}
+% User-level macros that hold the current file name and file path.
+% These are used internally as well because the code takes care to
+% protect against a possible redefinition of these macros in the
+% loaded file (it's necessary anyway to make hooks work with nested
+% \cs{input}). The versions |\...Used| hold the \emph{actual} file
+% name and path that is loaded by \LaTeX, whereas the other two hold
+% the name as requested. They will differ in case there's a file
+% substitution.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\CurrentFile}{Hook management file}%
+\ExplSyntaxOn
+\tl_new:N \CurrentFile
+\tl_new:N \CurrentFilePath
+\tl_new:N \CurrentFileUsed
+\tl_new:N \CurrentFilePathUsed
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\CurrentFile}{Hook management file}%
+%<latexrelease>
+%<latexrelease>\let \CurrentFile \@undefined
+%<latexrelease>\let \CurrentFilePath \@undefined
+%<latexrelease>\let \CurrentFileUsed \@undefined
+%<latexrelease>\let \CurrentFilePathUsed \@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+% \subsection{\pkg{expl3} helpers}
+%
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@@_file_parse_full_name:nN}{File helpers}%
+\ExplSyntaxOn
+% \end{macrocode}
+%
+% \begin{macro}{
+% \@@_file_parse_full_name:nN,
+% \@@_full_name:nn,
+% \@@_set_curr_file_assign:nnnNN
+% }
+% A utility macro to trigger \pkg{expl3}'s file-parsing and lookup,
+% and return a normalized representation of the file name. If the
+% queried file doesn't exist, no normalisation takes place.
+% The output of \cs{@@_file_parse_full_name:nN} is passed on to the
+% |#2|---a 3-argument macro that takes the \meta{path}, \meta{base},
+% and \meta{ext} parts of the file name.
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_file_parse_full_name:nN #1
+ {
+ \exp_args:Nf \file_parse_full_name_apply:nN
+ {
+ \exp_args:Nf \@@_full_name:nn
+ { \file_full_name:n {#1} } {#1}
+ }
+ }
+\cs_new:Npn \@@_full_name:nn #1 #2
+ {
+ \tl_if_empty:nTF {#1}
+ { \tl_trim_spaces:n {#2} }
+ { \tl_trim_spaces:n {#1} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \@@_if_no_extension:nTF,
+% \@@_drop_extension:N
+% }
+% Some actions depend on whether the file extension was explicitly
+% given, and sometimes the extension has to be removed. The macros
+% below use \cs{@@_file_parse_full_name:nN} to split up the file name
+% and either check if \meta{ext} (|#3|) is empty, or discard it.
+% \begin{macrocode}
+\cs_new:Npn \@@_if_no_extension:nTF #1
+ {
+ \exp_args:Ne \tl_if_empty:nTF
+ { \file_parse_full_name_apply:nN {#1} \use_iii:nnn }
+ }
+\cs_new_protected:Npn \@@_drop_extension:N #1
+ {
+ \tl_gset:Nx #1
+ {
+ \exp_args:NV \@@_file_parse_full_name:nN #1
+ \@@_drop_extension_aux:nnn
+ }
+ }
+\cs_new:Npn \@@_drop_extension_aux:nnn #1 #2 #3
+ { \tl_if_empty:nF {#1} { #1 / } #2 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_input_file_seq,\l_@@_internal_tl}
+% \begin{macro}{\@@_file_push:,\@@_file_pop:}
+% \begin{macro}{\@@_file_pop_assign:nnnn}
+% Yet another stack, to keep track of \cs{CurrentFile} and
+% \cs{CurrentFilePath} with nested \cs{input}s. At the beginning of
+% \cs{InputIfFileExists}, the current value of \cs{CurrentFilePath}
+% and \cs{CurrentFile} is pushed to \cs{g_@@_input_file_seq}, and
+% at the end, it is popped and the value reassigned. Some other
+% places don't use \cs{InputIfFileExists} directly (\cs{include}) or
+% need \cs{CurrentFile} earlier (\cs{@onefilewithoptions}), so these
+% are manually used elsewhere as well.
+% \begin{macrocode}
+\tl_new:N \l_@@_internal_tl
+\seq_new:N \g_@@_input_file_seq
+\cs_new_protected:Npn \@@_file_push:
+ {
+ \seq_gpush:Nx \g_@@_input_file_seq
+ {
+ { \CurrentFilePathUsed } { \CurrentFileUsed }
+ { \CurrentFilePath } { \CurrentFile }
+ }
+ }
+\cs_new_protected:Npn \@@_file_pop:
+ {
+ \seq_gpop:NNTF \g_@@_input_file_seq \l_@@_internal_tl
+ { \exp_after:wN \@@_file_pop_assign:nnnn \l_@@_internal_tl }
+ {
+ \msg_error:nnn { hooks } { should-not-happen }
+ { Tried~to~pop~from~an~empty~file~name~stack. }
+ }
+ }
+\cs_new_protected:Npn \@@_file_pop_assign:nnnn #1 #2 #3 #4
+ {
+ \tl_set:Nn \CurrentFilePathUsed {#1}
+ \tl_set:Nn \CurrentFileUsed {#2}
+ \tl_set:Nn \CurrentFilePath {#3}
+ \tl_set:Nn \CurrentFile {#4}
+ }
+\ExplSyntaxOff
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+% \subsection{Declaring the file-related hooks}
+%
+% All hooks starting with \texttt{file/} \texttt{include/},
+% \texttt{class/} or \texttt{package/} are generic and will be
+% allocated if code is added to them. Thus there is no need to
+% explicitly declare any hook in the code below.
+%
+% Furthermore, those named \texttt{.../after} or \texttt{.../end} are
+% automatically declared as reversed hooks if filled with code, so this
+% is also automatically taken care of.
+%
+%
+%
+%
+% \subsection{Patching \LaTeX{}'s \cs{InputIfFileExists} command}
+%
+% Most of what we have to do is adding \cs{UseHook} into several
+% \LaTeXe{} core commands, because of some circular dependencies in the
+% kernel we do this only now and not in \texttt{ltfiles}.
+%
+% \begin{macro}{\InputIfFileExists}
+% \cs{InputIfFileExists} loads any file if it is available so we
+% have to add the hooks \texttt{file/before} and
+% \texttt{file/after} in the right places. If the file doesn't
+% exist no hooks should be executed.
+% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\InputIfFileExists}{Hook management (files)}%
+%<*2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\let\InputIfFileExists\@undefined
+\DeclareRobustCommand \InputIfFileExists[2]{%
+ \IfFileExists{#1}%
+ {%
+ \@expl@@@filehook@file@push@@
+ \@filehook@set@CurrentFile
+% \end{macrocode}
+% If the file exists then \cs{CurrentFile} holds its name. But we
+% can't rely on that still being true after the file has been
+% processed. Thus for using the name in the file hooks we need to
+% preserve the name and then restored it for the
+% \texttt{file/after/...} hook.
+%
+% The hook always refers to the file requested by the user. The hook
+% is \emph{always} loaded for \cs{CurrentFile} which usually is the
+% same as \cs{CurrentFileUsed}. In the case of a file replacement,
+% the \cs{CurrentFileUsed} holds the actual file loaded. In any case
+% the file names are normalized so that the hooks work on the real
+% file name, rather than what the user typed in.
+%
+% \pkg{expl3}'s \cs{file_full_name:n} normalizes the file
+% name (to factor out differences in the |.tex| extension), and
+% then does a file lookup to take into account a possible path from
+% \cs{l_file_search_path_seq} and \cs{input@path}. However only
+% the file name and extension are returned so that file hooks can
+% refer to the file by their name only. The path to the file is
+% returned in \cs{CurrentFilePath}.
+% \begin{macrocode}
+ \edef\reserved@a{\@filef@und
+ \@expl@@@filehook@file@pop@assign@@nnnn
+ {\CurrentFilePathUsed}%
+ {\CurrentFileUsed}%
+ {\CurrentFilePath}%
+ {\CurrentFile}}%
+ \expandafter\@swaptwoargs\expandafter
+ {\reserved@a}%
+ {%
+ #2%
+ \@addtofilelist{#1}%
+ \UseHook{file/before}%
+% \end{macrocode}
+% The current file name is available in \cs{CurrentFile} so we use
+% that in the specific hook.
+% \begin{macrocode}
+ \UseHook{file/before/\CurrentFile}%
+ \@@input
+ }%
+% \end{macrocode}
+% And it is restored here so we can use it once more.
+% \begin{macrocode}
+ \UseHook{file/after/\CurrentFile}%
+ \UseHook{file/after}%
+ \@expl@@@filehook@file@pop@@
+ }%
+}
+%<latexrelease>\EndIncludeInRelease
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \changes{v0.9b}
+% {1993/12/04}{Macro added}
+% \changes{v0.9p}
+% {1994/01/18}{New Definition}
+% \changes{v0.3b}{1994/03/13}
+% {Use new cmd \cs{@addtofilelist}}
+% Now define |\InputIfFileExists| to input |#1| if it seems to exist.
+% Immediately prior to the input, |#2| is executed.
+% If the file |#1| does not exist, execute `|#3|'.
+% \changes{v1.0t}{1995/05/25}
+% {(CAR) added \cs{long}}
+% \changes{v1.1o}{2019/02/07}{Expand \cs{@filef@und} before executing
+% second argument (github/109)}
+% \changes{v1.2b}{2019/08/27}{Make command robust}
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\InputIfFileExists}{Hook management (files)}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand \InputIfFileExists[2]{%
+%<latexrelease> \IfFileExists{#1}%
+%<latexrelease> {%
+%<latexrelease> \expandafter\@swaptwoargs\expandafter
+%<latexrelease> {\@filef@und}{#2\@addtofilelist{#1}\@@input}}}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\InputIfFileExists}{Hook management (files)}%
+%<latexrelease>\long\def \InputIfFileExists#1#2{%
+%<latexrelease> \IfFileExists{#1}%
+%<latexrelease> {#2\@addtofilelist{#1}\@@input \@filef@und}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
+%
+% \subsection{Declaring a file substitution}
+%
+% \begin{macrocode}
+%<@@=filehook>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@@_subst_add:nn}{Declaring file substitution}%
+\ExplSyntaxOn
+% \end{macrocode}
+%
+%
+% \begin{macro}{\@@_subst_add:nn,\@@_subst_remove:n,
+% \@@_subst_file_normalize:n,\@@_subst_empty_name_chk:NN}
+% \cs{@@_substitution_lthooadd:nn} declares a file substitution by
+% doing a (global) definition of the form
+% |\def|\cs{@file-subst@\meta{file}}|{|\meta{replacement}|}|.
+% The file names are properly sanitised, and normalized with the same
+% treatment done for the file hooks. That is, a file replacement is
+% declared by using the file name (and extension, if any) only, and
+% the file path should not be given. If a file name is empty it is
+% replaced by |.tex| (the empty csname is used to check that).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_subst_add:nn #1 #2
+ {
+ \group_begin:
+ \cs_set:cpx { } { \exp_not:o { \cs:w\cs_end: } }
+ \int_set:Nn \tex_escapechar:D { -1 }
+ \cs_gset:cpx { @file-subst@ \@@_subst_file_normalize:n {#1} }
+ { \@@_subst_file_normalize:n {#2} }
+ \group_end:
+ }
+\cs_new_protected:Npn \@@_subst_remove:n #1
+ {
+ \group_begin:
+ \cs_set:cpx { } { \exp_not:o { \cs:w\cs_end: } }
+ \int_set:Nn \tex_escapechar:D { -1 }
+ \cs_undefine:c { @file-subst@ \@@_subst_file_normalize:n {#1} }
+ \group_end:
+ }
+\cs_new:Npn \@@_subst_file_normalize:n #1
+ {
+ \exp_after:wN \@@_subst_empty_name_chk:NN
+ \cs:w \exp_after:wN \cs_end:
+ \cs:w \@@_file_parse_full_name:nN {#1} \use_ii_iii:nnn \cs_end:
+ }
+\cs_new:Npn \@@_subst_empty_name_chk:NN #1 #2
+ { \if_meaning:w #1 #2 .tex \else: \token_to_str:N #2 \fi: }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[int]{\use_ii_iii:nnn}
+% A variant of \cs[no-index]{use_...} to discard the first of three
+% arguments.
+% \fmi{this should move to \pkg{expl3}}
+% \begin{macrocode}
+\cs_gset:Npn \use_ii_iii:nnn #1 #2 #3 {#2 #3}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+%
+%
+% \begin{macro}{\declare@file@substitution}
+% \begin{macro}{\undeclare@file@substitution}
+% For two internals we provide \LaTeXe{} names so that we can use
+% them elsewhere in the kernel (and so that they can be used in
+% packages if really needed, e.g., \pkg{scrlfile}).
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\declare@file@substitution}{File substitution}%
+\ExplSyntaxOn
+\cs_new_eq:NN \declare@file@substitution \@@_subst_add:nn
+\cs_new_eq:NN \undeclare@file@substitution \@@_subst_remove:n
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\declare@file@substitution}{File substitution}%
+%<latexrelease>
+%<latexrelease>\let \declare@file@substitution \@undefined
+%<latexrelease>\let \undeclare@file@substitution \@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macrocode}
+%<@@=>
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \subsection{Selecting a file (\cs{set@curr@file})}
+%
+% \begin{macro}{\set@curr@file,\@curr@file,\@curr@file@reqd}
+% Now we hook into \cs{set@curr@file} to resolve a possible file
+% substitution, and add \cs{@expl@@@filehook@set@curr@file@@N} at the end, after
+% \cs{@curr@file} is set.
+%
+% A file name is built using
+% \cs{expandafter}\cs{string}\cs{csname}\meta{filename}\cs{endcsname}
+% to avoid expanding utf8 active characters. The \cs{csname} expands
+% the normalisation machinery and the routine to resolve a file
+% substitution, returning a control sequence with the same name as the
+% file.
+%
+% It happens that when \meta{filename} is empty, the generated control
+% sequence is \cs{csname\cs{endcsname}}, and doing \cs{string} on
+% that results in the file |csnameendcsname.tex|. To guard against
+% that we \cs{ifx}-compare the generated control sequence with the
+% empty csname. To do so, \cs{csname\cs{endcsname}} has to be
+% defined, otherwise it would be equal to \cs{relax} and we would have
+% false positives. Here we define \cs{csname\cs{endcsname}} to
+% expand to itself to avoid it matching the definition of some other
+% control sequence.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\set@curr@file}{Setting current file name}%
+\def\set@curr@file#1{%
+ \begingroup
+ \escapechar\m@ne
+ \expandafter\def\csname\expandafter\endcsname
+ \expandafter{\csname\endcsname}%
+% \end{macrocode}
+% Two file names are set here: \cs{@curr@file@reqd} which is the file
+% requested by the user, and \cs{@curr@file} which should be the same,
+% except when we have a file substitution, in which case it holds the
+% actual loaded file. \cs{@curr@file} is resolved first, to check if
+% a substitution happens. If it doesn't,
+% \cs{@expl@@@filehook@if@file@replaced@@TF} short-cuts and just copies
+% \cs{@curr@file}, otherwise the full normalisation procedure is
+% executed.
+%
+% At this stage the file name is parsed and normalized, but if the
+% input doesn't have an extension, the default |.tex| is \emph{not}
+% added to \cs{@curr@file} because for applications other than
+% \cs{input} (graphics, for example) the default extension may not
+% be |.tex|. First check if the input has an extension, then if the
+% input had no extension, call \cs{@expl@@@filehook@drop@extension@@N}. In case
+% of a file substitution, \cs{@curr@file} will have an extension.
+% \begin{macrocode}
+ \@expl@@@filehook@if@no@extension@@nTF{#1}%
+ {\@tempswatrue}{\@tempswafalse}%
+ \@kernel@make@file@csname\@curr@file
+ \@expl@@@filehook@resolve@file@subst@@w {#1}%
+ \@expl@@@filehook@if@file@replaced@@TF
+ {\@kernel@make@file@csname\@curr@file@reqd
+ \@expl@@@filehook@normalize@file@name@@w{#1}%
+ \if@tempswa \@expl@@@filehook@drop@extension@@N\@curr@file@reqd \fi}%
+ {\if@tempswa \@expl@@@filehook@drop@extension@@N\@curr@file \fi
+ \global\let\@curr@file@reqd\@curr@file}%
+ \endgroup}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\set@curr@file}{Setting current file name}%
+%<latexrelease>\def\set@curr@file#1{%
+%<latexrelease> \begingroup
+%<latexrelease> \escapechar\m@ne
+%<latexrelease> \xdef\@curr@file{%
+%<latexrelease> \expandafter\expandafter\expandafter\unquote@name
+%<latexrelease> \expandafter\expandafter\expandafter{%
+%<latexrelease> \expandafter\string
+%<latexrelease> \csname\@firstofone#1\@empty\endcsname}}%
+%<latexrelease> \endgroup
+%<latexrelease>}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\set@curr@file}{Setting current file name}%
+%<latexrelease>\let\set@curr@file\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\@filehook@set@CurrentFile}
+% \begin{macro}{\@kernel@make@file@csname,\@set@curr@file@aux}
+%
+% \fmi{This should get internalized using \texttt{@expl@} names}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@kernel@make@file@csname}{Make file csname}%
+% \end{macrocode}
+%
+% \begin{macrocode}
+\def\@kernel@make@file@csname#1#2#3{%
+ \xdef#1{\expandafter\@set@curr@file@aux
+ \csname\expandafter#2\@firstofone#3\@nil\endcsname}}
+% \end{macrocode}
+% This auxiliary compares \cs{\meta{filename}} with
+% \cs{csname\cs{endcsname}} to check if the empty |.tex| file was
+% requested.
+% \begin{macrocode}
+\def\@set@curr@file@aux#1{%
+ \expandafter\ifx\csname\endcsname#1%
+ .tex\else\string#1\fi}
+% \end{macrocode}
+%
+% Then we call \cs{@expl@@@filehook@set@curr@file@@N} once for \cs{@curr@file}
+% to set \cs[no-index]{CurrentFile(Path)Used} and once for
+% \cs{@curr@file@reqd} to set \cs[no-index]{CurrentFile(Path)}.
+% Here too the slower route is only used if a substitution happened,
+% but here \cs{@expl@@@filehook@if@file@replaced@@TF} can't be used because the
+% flag is reset at the \cs{endgroup} above, so we check if
+% \cs{@curr@file} and \cs{@curr@file@reqd} differ. This macro is
+% issued separate from \cs{set@curr@file} because it changes
+% \cs{CurrentFile}, and side-effects would quickly get out of control.
+% \begin{macrocode}
+\def\@filehook@set@CurrentFile{%
+ \@expl@@@filehook@set@curr@file@@N{\@curr@file}%
+ \CurrentFileUsed\CurrentFilePathUsed
+ \ifx\@curr@file@reqd\@curr@file
+ \let\CurrentFile\CurrentFileUsed
+ \let\CurrentFilePath\CurrentFilePathUsed
+ \else
+ \@expl@@@filehook@set@curr@file@@N{\@curr@file@reqd}%
+ \CurrentFile\CurrentFilePath
+ \fi}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_set_curr_file:N,
+% \@@_set_curr_file:nNN,
+% \@@_set_curr_file_assign:nnnNN}
+% When inputting a file, \cs{set@curr@file} does a file lookup
+% (in \cs{input@path} and \cs{l_file_search_path_seq}) and returns the
+% actual file name (\meta{base} plus \meta{ext}) in
+% \cs{CurrentFileUsed}, and in case there's a file substitution, the
+% requested file in \cs{CurrentFile} (otherwise both are the same).
+% Only the base and extension are returned,
+% regardless of the input (both \texttt{path/to/file.tex} and
+% \texttt{file.tex} end up as \texttt{file.tex} in \cs{CurrentFile}).
+% The path is returned in \cs{CurrentFilePath}, in case it's needed.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {@@_set_curr_file:N}{Set curr file}%
+\ExplSyntaxOn
+%<@@=filehook>
+\cs_new_protected:Npn \@@_set_curr_file:N #1
+ { \exp_args:NV \@@_set_curr_file:nNN #1 }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_set_curr_file:nNN #1
+ {
+ \@@_file_parse_full_name:nN {#1}
+ \@@_set_curr_file_assign:nnnNN
+ }
+\cs_new_protected:Npn \@@_set_curr_file_assign:nnnNN #1 #2 #3 #4 #5
+ {
+ \str_set:Nn #5 {#1}
+ \str_set:Nn #4 {#2#3}
+ }
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \subsection{Replacing a file and detecting loops}
+%
+% \begin{macro}{\@@_resolve_file_subst:w}
+% \begin{macro}{\@@_normalize_file_name:w}
+% \begin{macro}{\@@_file_name_compose:nnn}
+% Start by sanitising the file with \cs{@@_file_parse_full_name:nN}
+% then do \cs{@@_file_subst_begin:nnn}\Arg{path}\Arg{name}\Arg{ext}.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@@_resolve_file_subst:w}{Replace files detect loops}%
+\ExplSyntaxOn
+\cs_new:Npn \@@_resolve_file_subst:w #1 \@nil
+ { \@@_file_parse_full_name:nN {#1} \@@_file_subst_begin:nnn }
+\cs_new:Npn \@@_normalize_file_name:w #1 \@nil
+ { \@@_file_parse_full_name:nN {#1} \@@_file_name_compose:nnn }
+\cs_new:Npn \@@_file_name_compose:nnn #1 #2 #3
+ { \tl_if_empty:nF {#1} { #1 / } #2#3 }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{flag @@_file_replaced}
+% \begin{macro}{\@@_if_file_replaced:TF}
+% Since the file replacement is done expandably in a \cs{csname}, use
+% a flag to remember if a substitution happened. We use this in
+% \cs{set@curr@file} to short-circuit some of it in case no
+% substitution happened (by far the most common case, so it's worth
+% optimising).
+% \begin{macrocode}
+\flag_new:n { @@_file_replaced }
+\cs_new:Npn \@@_if_file_replaced:TF #1 #2
+ { \flag_if_raised:nTF { @@_file_replaced } {#1} {#2} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_file_subst_begin:nnn}
+% First off, start by checking if the current file ($\meta{name} +
+% \meta{ext}$) has a declared substitution. If not, then just put
+% that as the name (including a possible \meta{path} in this case):
+% this is the default case with no substitutions, so it's the first to
+% be checked. The auxiliary \cs{@@_file_subst_tortoise_hare:nn} sees
+% that there's no replacement for |#2#3| and does nothing else.
+% \begin{macrocode}
+\cs_new:Npn \@@_file_subst_begin:nnn #1 #2 #3
+ {
+ \@@_file_subst_tortoise_hare:nn { #2#3 } { #2#3 }
+ { \@@_file_name_compose:nnn {#1} {#2} {#3} }
+ }
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \subsubsection{The Tortoise and Hare algorithm}
+%
+% \begin{macro}{\@@_file_subst_tortoise_hare:nn}
+% \begin{macro}{\@@_file_subst_loop:NN,\@@_file_subst_loop:cc}
+% If there is a substitution (\meta{true} in the first
+% \cs{cs_if_exist:cTF} below), then first check if there is no
+% substitution down the line: this should be the second most common
+% case, of one file replaced by another. In that case just leave the
+% substitution there and the job is done. If any substitution
+% happens, then the \cs{flag @@_file_replaced} is raised
+% (conditionally, because checking if a flag is raised is much faster
+% than raising it over and over again).
+%
+% If, however there are more substitutions, then we need to check for
+% a possible loop in the substitutions, which would otherwise put
+% \TeX{} in an infinite loop if just an exhaustive expansion was used.
+%
+% To detect a loop, the \emph{Tortoise and Hare} algorithm is used.
+% The name of the algorithm is an analogy to Aesop's fable, in which
+% the Hare outruns a Tortoise. The two pointers here are the csnames
+% which contains each file replacement, both of which start at the
+% position zero, which is the file requested. In the inner part of
+% the macro below, \cs{@@_file_subst_loop:cc} is called with
+% \cs[no-index]{@file-subst@\meta{file}} and
+% \cs[no-index]{@file-subst@\cs[no-index]{@file-subst@\meta{file}}};
+% that is, the substitution of \meta{file} and the substution of that
+% substution: the Tortoise walks one step while the Hare walks two.
+%
+% Within \cs{@@_file_subst_loop:NN} the two substitutions are
+% compared, and if they lead to the same file it means that there is
+% a loop in the substitutions. If there's no loop,
+% \cs{@@_file_subst_tortoise_hare:nn} is called again with the
+% Tortoise at position~1 and the hare at~2. Again, the substitutions
+% are checked ahead of the Hare pointer to check that it won't run too
+% far; in case there is no loop in the declarations, eventually one
+% of the \cs{cs_if_exist:cTF} below will go \meta{false} and the
+% algorithm will end; otherwise it will run until the Hare reaches
+% the same spot as the tortoise and a loop is detected.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@@_file_subst_tortoise_hare:nn}{Tortoise and Hare}%
+\ExplSyntaxOn
+\cs_new:Npn \@@_file_subst_tortoise_hare:nn #1 #2 #3
+ {
+ \cs_if_exist:cTF { @file-subst@ #2 }
+ {
+ \flag_if_raised:nF { @@_file_replaced }
+ { \flag_raise:n { @@_file_replaced } }
+ \cs_if_exist:cTF { @file-subst@ \use:c { @file-subst@ #2 } }
+ {
+ \@@_file_subst_loop:cc
+ { @file-subst@ #1 }
+ { @file-subst@ \use:c { @file-subst@ #2 } }
+ }
+ { \use:c { @file-subst@ #2 } }
+ }
+ { #3 }
+ }
+% \end{macrocode}
+% This is just an auxiliary to check if a loop was found, and continue
+% the algorithm otherwise. If a loop is found, the |.tex| file is
+% used as fallback and \cs{@@_file_subst_cycle_error:cN} is called to
+% report the error.
+% \begin{macrocode}
+\cs_new:Npn \@@_file_subst_loop:NN #1 #2
+ {
+ \token_if_eq_meaning:NNTF #1 #2
+ {
+ .tex
+ \@@_file_subst_cycle_error:cN { @file-subst@ #1 } #1
+ }
+ { \@@_file_subst_tortoise_hare:nn {#1} {#2} {#2} }
+ }
+\cs_generate_variant:Nn \@@_file_subst_loop:NN { cc }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{
+% \@@_file_subst_cycle_error:NN,
+% \@@_file_subst_cycle_error:cN,
+% }
+% Showing this type of error expandably is tricky, as we have a very
+% limited amount of characters to show and a potentially large list.
+% As a work around, several errors are printed, each showing one step
+% of the loop, until all the error messages combined show the loop.
+% \begin{macrocode}
+\cs_new:Npn \@@_file_subst_cycle_error:NN #1 #2
+ {
+ \__kernel_msg_expandable_error:nnff { kernel } { file-cycle }
+ {#1} { \use:c { @file-subst@ #1 } }
+ \token_if_eq_meaning:NNF #1 #2
+ { \@@_file_subst_cycle_error:cN { @file-subst@ #1 } #2 }
+ }
+\cs_generate_variant:Nn \@@_file_subst_cycle_error:NN { c }
+% \end{macrocode}
+%
+% And the error message:
+% \begin{macrocode}
+\__kernel_msg_new:nnn { kernel } { file-cycle }
+ { File~loop!~#1~replaced~by~#2... }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+%
+% \subsection{Preventing a package from loading}
+%
+% We support the use case of preventing a package from loading but not
+% any other type of files (e.g., classes).
+%
+% \begin{macro}{\disable@package@load}
+% \begin{macro}{\reenable@package@load}
+% \begin{macro}{\@disable@packageload@do}
+% \cs{disable@package@load} defines
+% \cs[no-index]{@pkg-disable@\meta{package}} to expand to some code |#2|
+% instead of loading the package.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\disable@package@load}{Disable packages}%
+\def\disable@package@load#1#2{%
+ \global\@namedef{@pkg-disable@#1.\@pkgextension}{#2}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\def\@disable@packageload@do#1#2{%
+ \@ifundefined{@pkg-disable@#1}{#2}%
+ {\@nameuse{@pkg-disable@#1}}}
+% \end{macrocode}
+%
+% \cs{reenable@package@load} undefines
+% \cs[no-index]{@pkg-disable@\meta{package}} to reallow loading a package.
+% \begin{macrocode}
+\def\reenable@package@load#1{%
+ \global\expandafter\let
+ \csname @pkg-disable@#1.\@pkgextension \endcsname \@undefined}
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\disable@package@load}{Disable packages}%
+%<latexrelease>
+%<latexrelease>\let\disable@package@load \@undefined
+%<latexrelease>\let\@disable@packageload@do\@undefined
+%<latexrelease>\let\reenable@package@load \@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
+%
+% \subsection{High-level interfaces for \LaTeX{}}
+%
+% None so far and the general feeling for now is that the hooks are
+% enough. Packages like \pkg{filehook}, etc., may use them to set
+% up their interfaces (samples are given below) but for the now the
+% kernel will not provide any.
+%
+%
+%
+% \subsection{Internal commands needed elsewhere}
+%
+% Here we set up a few horrible (but consistent) \LaTeXe{} names to
+% allow for internal commands to be used outside this module (and
+% in parts that still use \LaTeXe{} syntax. We have to unset the
+% \texttt{@\/@} since we want double ``at'' sign in place of double
+% underscores.
+%
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@expl@@@filehook@if@no@extension@@nTF}{2e tmp interfaces}%
+\ExplSyntaxOn
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@filehook@if@no@extension@@nTF
+ \__filehook_if_no_extension:nTF
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@filehook@set@curr@file@@N
+ \__filehook_set_curr_file:N
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@filehook@resolve@file@subst@@w
+ \__filehook_resolve_file_subst:w
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@filehook@normalize@file@name@@w
+ \__filehook_normalize_file_name:w
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@filehook@if@file@replaced@@TF
+ \__filehook_if_file_replaced:TF
+
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@filehook@drop@extension@@N
+ \__filehook_drop_extension:N
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@filehook@file@push@@
+ \__filehook_file_push:
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@filehook@file@pop@@
+ \__filehook_file_pop:
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@filehook@file@pop@assign@@nnnn
+ \__filehook_file_pop_assign:nnnn
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% This ends the kernel code in this file.
+% \begin{macrocode}
+%</2ekernel>
+% \end{macrocode}
+%
+%
+%
+% \section{A sample package for structuring the log output}
+%
+% \begin{macrocode}
+%<*structuredlog>
+%<@@=filehook>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ProvidesExplPackage
+ {structuredlog}{\ltfilehookdate}{\ltfilehookversion}
+ {Structuring the TeX transcript file}
+% \end{macrocode}
+%
+% \begin{macro}{\g_@@_nesting_level_int}
+% Stores the current package nesting level.
+% \begin{macrocode}
+\int_new:N \g_@@_nesting_level_int
+% \end{macrocode}
+% Initialise the counter with the number of files in the
+% \cs{@currnamestack} (the number of items divided by $3$) minus one,
+% because this package is skipped when printing to the log.
+% \begin{macrocode}
+\int_gset:Nn \g_@@_nesting_level_int
+ { ( \tl_count:N \@currnamestack ) / 3 - 1 }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_log_file_record:n}
+% This macro is responsible for increasing and decresing the file
+% nesting level, as well as printing to the log. The argument is
+% either |STOPTART| or |STOP| and the action it takes on the nesting
+% integer depends on that.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_log_file_record:n #1
+ {
+ \str_if_eq:nnT {#1} {START} { \int_gincr:N \g_@@_nesting_level_int }
+ \iow_term:x
+ {
+ \prg_replicate:nn { \g_@@_nesting_level_int } { = } ~
+ ( LEVEL ~ \int_use:N \g_@@_nesting_level_int \c_space_tl #1 ) ~
+ \CurrentFileUsed
+% \end{macrocode}
+% If there was a file replacement, show that as well:
+% \begin{macrocode}
+ \str_if_eq:NNF \CurrentFileUsed \CurrentFile
+ { ~ ( \CurrentFile \c_space_tl requested ) }
+ \iow_newline:
+ }
+ \str_if_eq:nnT {#1} {STOP} { \int_gdecr:N \g_@@_nesting_level_int }
+ }
+% \end{macrocode}
+%
+% Now just hook the macro above in the generic |file/before|\ldots
+% \begin{macrocode}
+\AddToHook{file/before}{ \@@_log_file_record:n { START } }
+% \end{macrocode}
+% \ldots and |file/after| hooks.
+% We don't want to install the \hook{file/after} hook immediately,
+% because that would mean it is the first time executed when the
+% package finishes. We therefore put the declaration inside
+% \cs{AddToHookNext} so that it gets only installed when we have
+% left this package.
+% \begin{macrocode}
+\AddToHookNext{file/after}
+ { \AddToHook{file/after}{ \@@_log_file_record:n { STOP } } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%<@@=>
+%</structuredlog>
+% \end{macrocode}
+%
+%
+%
+%
+%
+%
+% \section{Package emulations}
+%
+%
+% \subsection{Package \pkg{atveryend} emulation}
+%
+% With the new hook management and the hooks in \cs{enddocument}
+% all of \pkg{atveryend} is taken care of.
+% We can make an emulation only here after the substitution
+% functionality is available:
+% \begin{macrocode}
+%<*2ekernel>
+\declare@file@substitution{atveryend.sty}{atveryend-ltx.sty}
+%</2ekernel>
+% \end{macrocode}
+%
+% Here is the package file we point to:
+% \begin{macrocode}
+%<*atveryend-ltx>
+\ProvidesPackage{atveryend-ltx}
+ [2020/08/19 v1.0a
+ Emulation of the original atvery package^^Jwith kernel methods]
+% \end{macrocode}
+%
+%
+% Here are new definitions for its interfaces now pointing to the
+% hooks in \cs{enddocument}
+% \begin{macrocode}
+\newcommand\AfterLastShipout {\AddToHook{enddocument/afterlastpage}}
+\newcommand\AtVeryEndDocument {\AddToHook{enddocument/afteraux}}
+% \end{macrocode}
+% Next one is a bit of a fake, but the result should normally be as
+% expected. If not, one needs to add a rule to sort the code chunks
+% in \hook{enddocument/info}.
+% \begin{macrocode}
+\newcommand\AtEndAfterFileList{\AddToHook{enddocument/info}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\newcommand\AtVeryVeryEnd {\AddToHook{enddocument/end}}
+% \end{macrocode}
+%
+% \begin{macro}{\BeforeClearDocument}
+% This one is the only one we don't implement or rather don't have
+% a dedicated hook in the code.
+% \begin{macrocode}
+\ExplSyntaxOn
+\newcommand\BeforeClearDocument[1]
+ { \AtEndDocument{#1}
+ \atveryend@DEPRECATED{BeforeClearDocument \tl_to_str:n{#1}}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Npn\atveryend@DEPRECATED #1
+ {\iow_term:x{======~DEPRECATED~USAGE~#1~==========}}
+\ExplSyntaxOff
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+%</atveryend-ltx>
+% \end{macrocode}
+%
+%
+%
+% \Finale
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\endinput
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+
diff --git a/Master/texmf-dist/source/latex/base/ltfiles.dtx b/Master/texmf-dist/source/latex/base/ltfiles.dtx
index 33594a7b912..835f600e323 100644
--- a/Master/texmf-dist/source/latex/base/ltfiles.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfiles.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfiles.dtx}
- [2019/11/11 v1.2f LaTeX Kernel (File Handling)]
+ [2020/08/21 v1.2i LaTeX Kernel (File Handling)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfiles.dtx}
@@ -47,6 +47,8 @@
Chris Rowley\and
Rainer Sch\"opf}
+\providecommand\pkg[1]{\texttt{#1}}
+
\begin{document}
\MaintainedByLaTeXTeam{latex}
\maketitle
@@ -55,6 +57,8 @@
%</driver>
% \fi
%
+% \providecommand\hook[1]{\texttt{#1}}
+%
%
% \changes{v1.0h}{1994/05/21}{Use new error commands}
% \changes{v1.0n}{1994/11/17}
@@ -62,6 +66,7 @@
% \changes{v1.0u}{1995/07/13}{Updates to docu}
% \changes{v1.1m}{2015/02/21}
% {Removed autoload support}
+% \changes{v1.2i}{2020/08/21}{Integration of new hook management interface}
%
% \section{File Handling}
%
@@ -234,18 +239,28 @@
% \changes{v0.9e}{1993/12/09}{Hook added}
% \begin{macrocode}
%</2ekernel>
-%<latexrelease>\IncludeInRelease{2017/04/15}%
-%<latexrelease> {\document}{Save language for hyphenation}%
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\document}{Added hook to load l3backend code}%
%<*2ekernel|latexrelease>
+\def\document{%
% \end{macrocode}
-% Cancel the |\begingroup| from |\begin|.
+% We do cancel the grouping as part of the \cs{begin} handling
+% (this is now done inside \cs{begin} instead) so that the
+% \hook{env/\meta{env}/begin} hook is not hidden inside \cs{begingroup}
+% \texttt{...} \cs{endgroup}.
% \begin{macrocode}
-\def\document{\endgroup
+% \endgroup
% \end{macrocode}
-% If some options on |\documentclass| haven't been used by any
-% package we will now give a warning since this is most certainly a
-% misspelling.
+%
% \begin{macrocode}
+ \UseOneTimeHook{begindocument/before}%
+ \@kernel@after@begindocument@before
+% \end{macrocode}
+%
+% Added hook to load \textsf{l3backend} code:
+% \changes{v1.2h}{2020/06/05}{Added hook to load \textsf{l3backend} code}
+% \begin{macrocode}
+ \@expl@sys@load@backend@@
\ifx\@unusedoptionlist\@empty\else
\@latex@warning@no@line{Unused global option(s):^^J%
\@spaces[\@unusedoptionlist]}%
@@ -348,9 +363,11 @@
% \changes{v1.1e}{1996/04/24}
% {(DPC) Reset \cs{AtBeginDocument} eg for latex/1297}
% \begin{macrocode}
- \let\AtBeginDocument\@firstofone
- \@begindocumenthook
+ \@kernel@before@begindocument
+ \UseOneTimeHook{begindocument}%
+ \@kernel@after@begindocument
% \end{macrocode}
+%
% Most of the following assignments will be done globally in case
% the user adds something like |\begin{multicols}| to the document
% hook, i.e. starts are group in |\begin{document}|.
@@ -399,13 +416,128 @@
% \begin{macrocode}
\global\let\do\noexpand
% \end{macrocode}
+%
+% \begin{macrocode}
+ \UseOneTimeHook{begindocument/end}%
+% \end{macrocode}
% \changes{v1.1c}{1995/12/05}{\cs{ignorespaces} added for latex/1933}
-% Use of |\AtBeginDocument| hook might mean that we are already in
+% Use of the hook might mean that we are already in
% horizontal mode, so ignore the space after |\begin{document}|.
% \begin{macrocode}
\ignorespaces}
+% \end{macrocode}
+%
+% The \hook{begindocument} hook already existed in the kernel since
+% 1994 under the name \cs{atbegindocumenthook} the
+% additional ones are originally from the \pkg{etoolbox}
+% package under the names \cs{@endpreamblehook} \cs{afterpreamble}.
+% \begin{macrocode}
+\NewHook{begindocument}
+\NewHook{begindocument/before}
+\NewHook{begindocument/end}
+% \end{macrocode}
+
+
+
+% \begin{macro}{\@kernel@after@begindocument@before,
+% \@kernel@before@begindocument,
+% \@kernel@after@begindocument}
+%
+% Above we used two kernel only hooks to be run after the public
+% \hook{begindocument/before} and after \hook{begindocument}
+% hooks.
+%
+% In \cs{@kernel@after@begindocument@before} we already place one
+% action: drop the fast execution code for the
+% \hook{env/document/begin} hook. That hook marks the end of the
+% preamble and should therefore only be run once. In a normal
+% document that is anyway the case (so the code would just sit
+% there taking up space afterwards, which these days is rather
+% harmless), however, in more complicated scenarios where several
+% full documents are combined to a single document it might get
+% applied several times with harmful effects. We therefore
+% explicitly drop it at this point. the coing is somewhat obscure
+% due to the name of the macro which requires constructing.
+% \begin{macrocode}
+\edef \@kernel@after@begindocument@before {%
+ \let\expandafter\noexpand\csname
+ __hook env/document/begin\endcsname
+ \noexpand\@empty}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\let \@kernel@before@begindocument \@empty
+\let \@kernel@after@begindocument \@empty
+% \end{macrocode}
+%
+% \end{macro}
+%
+
+%
+% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2017/04/15}%
+%<latexrelease> {\document}{Save language for hyphenation}%
+%<latexrelease>
+%<latexrelease>\def\document{\endgroup
+%<latexrelease> \ifx\@unusedoptionlist\@empty\else
+%<latexrelease> \@latex@warning@no@line{Unused global option(s):^^J%
+%<latexrelease> \@spaces[\@unusedoptionlist]}%
+%<latexrelease> \fi
+%<latexrelease> \@colht\textheight
+%<latexrelease> \@colroom\textheight \vsize\textheight
+%<latexrelease> \columnwidth\textwidth
+%<latexrelease> \@clubpenalty\clubpenalty
+%<latexrelease> \if@twocolumn
+%<latexrelease> \advance\columnwidth -\columnsep
+%<latexrelease> \divide\columnwidth\tw@ \hsize\columnwidth \@firstcolumntrue
+%<latexrelease> \fi
+%<latexrelease> \hsize\columnwidth \linewidth\hsize
+%<latexrelease> \begingroup\@floatplacement\@dblfloatplacement
+%<latexrelease> \makeatletter\let\@writefile\@gobbletwo
+%<latexrelease> \global \let \@multiplelabels \relax
+%<latexrelease> \@input{\jobname.aux}%
+%<latexrelease> \endgroup
+%<latexrelease> \if@filesw
+%<latexrelease> \immediate\openout\@mainaux\jobname.aux
+%<latexrelease> \immediate\write\@mainaux{\relax}%
+%<latexrelease> \fi
+%<latexrelease> \process@table
+%<latexrelease> \let\glb@currsize\@empty % Force math initialization.
+%<latexrelease> \normalsize
+%<latexrelease> \everypar{}%
+%<latexrelease> \ifx\normalsfcodes\@empty
+%<latexrelease> \ifnum\sfcode`\.=\@m
+%<latexrelease> \let\normalsfcodes\frenchspacing
+%<latexrelease> \else
+%<latexrelease> \let\normalsfcodes\nonfrenchspacing
+%<latexrelease> \fi
+%<latexrelease> \fi
+%<latexrelease> \ifx\document@default@language\m@ne
+%<latexrelease> \chardef\document@default@language\language
+%<latexrelease> \fi
+%<latexrelease> \@noskipsecfalse
+%<latexrelease> \let \@refundefined \relax
+%<latexrelease> \let\AtBeginDocument\@firstofone
+%<latexrelease> \@begindocumenthook
+%<latexrelease> \ifdim\topskip<1sp\global\topskip 1sp\relax\fi
+%<latexrelease> \global\@maxdepth\maxdepth
+%<latexrelease> \global\let\@begindocumenthook\@undefined
+%<latexrelease> \ifx\@listfiles\@undefined
+%<latexrelease> \global\let\@filelist\relax
+%<latexrelease> \global\let\@addtofilelist\@gobble
+%<latexrelease> \fi
+%<latexrelease> \gdef\do##1{\global\let ##1\@notprerr}%
+%<latexrelease> \@preamblecmds
+%<latexrelease> \global\let \@nodocument \relax
+%<latexrelease> \global\let\do\noexpand
+%<latexrelease> \ignorespaces}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\document}{Save language for hyphenation}
%<latexrelease>\def\document{\endgroup
@@ -539,26 +671,14 @@
% \end{macrocode}
%
%
-% \begin{macro}{\includeonly}
+% \begin{macro}{\include,\includeonly}
+% \changes{v0.9p}{1994/01/18}
+% {Use \cs{@input@} so include files are listed.}
% \changes{v1.0p}{1995/04/22}{Allow blanks in argument}
% \changes{v1.2a}{2019/07/01}{Support UTF-8}
-% \begin{macrocode}
-%</2ekernel>
-%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2019/10/01}%
-%<latexrelease> {\includeonly}{Spaces in file names}%
-\def\includeonly#1{%
- \@partswtrue
- \set@curr@file{\zap@space#1 \@empty}%
- \let\@partlist\@curr@file
- }
-\@onlypreamble\includeonly
-% \end{macrocode}
-% \end{macro}
+% \changes{v1.2g}{2020/05/02}{Improved support for spaces in filenames
+% (gh/217)}
%
-% \begin{macro}{\include}
-% \changes{v0.9p}{1994/01/18}
-% {Use \cs{@input@} so include files are listed.}
% In the definition of |\include|, |\def\reserved@b| changed to
% |\edef\reserved@b| to be consistent with the |\edef| in
% |\includeonly|.
@@ -572,21 +692,113 @@
%
% Made |\include| check for being used inside an |\include|'d file, as
% this will not work and cause surprising results.
+% \changes{v1.2g}{2020/05/02}{Get rid of leading and trailing spaces
+% from the filename (gh/217)}
+% \changes{v1.2g}{2020-05-02}{Pass the filename to \cs{@include} by
+% value instead of by reference (gh/217)}
+%
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\includeonly}{Spaces in file names}%
+% \end{macrocode}
+%
% \begin{macrocode}
\def\include#1{\relax
\ifnum\@auxout=\@partaux
\@latex@error{\string\include\space cannot be nested}\@eha
\else
- \set@curr@file{#1 }%
- \expandafter\@include\@curr@file
+% \end{macrocode}
+% Here the normalisation will add |.tex| for all files, (it uses the
+% the same normalisation as the hooks), so we need to remove that
+% manually. \cs{@strip@tex@ext} does that.
+% \begin{macrocode}
+ \set@curr@file{#1}%
+ \edef\@curr@file{\@strip@tex@ext\@curr@file}%
+% \end{macrocode}
+% For historical reasons \cs{@include} expects an argument
+% delimited by a space. This is kept (though uncessary now) to avoid
+% errors in other packages that use \cs{@include} directly.
+% \begin{macrocode}
+ \expandafter\@include\expandafter{\@curr@file} % deliberate space
\fi}
% \end{macrocode}
-% \end{macro}
%
+% Here in \cs{includeonly} we also need to strip |.tex| after
+% normalisation:
+% \begin{macrocode}
+\def\includeonly#1{%
+ \@partswtrue
+% \end{macrocode}
+% Because the argument to |\includeonly| is a comma-separated list
+% of filenames where there may be comma's precedeing some of the
+% filenames or trailing them. Therefore we need to take the list
+% apart, remove the unwanted spaces while leaving the spaces
+% \emph{in} the filenames intact.
+% \begin{macrocode}
+ \let\@partlist\@empty
+ \@for\reserved@a:=#1 \do
+ {%
+ \expandafter\set@curr@file\expandafter{\reserved@a}%
+ \ifx\@partlist\@empty
+ \edef\@partlist{\@strip@tex@ext\@curr@file}%
+ \else
+ \edef\@partlist{\@partlist,\@strip@tex@ext\@curr@file}%
+ \fi
+ }%
+ }
+\@onlypreamble\includeonly
+% \end{macrocode}
+% \end{macro}
%
+% \begin{macro}{\@strip@tex@ext,\@strip@tex@ext@aux}
+% These macros take a (\cs{detokenize}d file name and remove any
+% |.tex| extension). Extra care is taken to not remove the string
+% |.tex| from the middle of a file name: it is only removed if it's
+% the very last thing in the file name.
% \begin{macrocode}
+\def\reserved@a#1{%
+\def\@strip@tex@ext##1{%
+ \expandafter\@strip@tex@ext@aux
+ ##1\@nil\@nil
+ #1\@nil\relax\@nnil}
+\def\@strip@tex@ext@aux##1#1\@nil##2\@nnil{%
+ \ifx\relax##2\@empty
+ \expandafter\@cdr\expandafter\@empty\@cdr{}##1%
+ \else##1\fi}}%
+\expandafter\reserved@a
+\expandafter{\detokenize{.tex}}
%</2ekernel|latexrelease>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\includeonly}{Spaces in file names}%
+%<latexrelease>
+%<latexrelease>\def\includeonly#1{%
+%<latexrelease> \@partswtrue
+%<latexrelease> \set@curr@file{\zap@space#1 \@empty}%
+%<latexrelease> \let\@partlist\@curr@file
+%<latexrelease> }
+%<latexrelease>
+%<latexrelease>\def\include#1{\relax
+%<latexrelease> \ifnum\@auxout=\@partaux
+%<latexrelease> \@latex@error{\string\include\space cannot be nested}\@eha
+%<latexrelease> \else
+%<latexrelease> \set@curr@file{#1 }%
+%<latexrelease> \expandafter\@include\@curr@file
+%<latexrelease> \fi}
+%<latexrelease>
+%<latexrelease>\let\@strip@tex@ext\@undefined
+%<latexrelease>\let\@strip@tex@ext@aux\@undefined
+%<latexrelease>
%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\includeonly}{Spaces in file names}%
%<latexrelease>\def\includeonly#1{%
@@ -601,14 +813,22 @@
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
-
%
% \begin{macro}{\@include}
+% \changes{v1.2g}{2020/05/02}{Support spaces in filenames by enclosing
+% the names of \texttt{.aux}-files in quotes (gh/217)}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@include}{Spaces in file names and hooks}%
+% \end{macrocode}
+%
% \begin{macrocode}
\def\@include#1 {%
\clearpage
\if@filesw
- \immediate\write\@mainaux{\string\@input{#1.aux}}%
+ \immediate\write\@mainaux{\string\@input{"#1.aux"}}%
\fi
\@tempswatrue
\if@partsw
@@ -620,11 +840,41 @@
\if@tempswa
\let\@auxout\@partaux
\if@filesw
- \immediate\openout\@partaux #1.aux
+ \immediate\openout\@partaux "#1.aux"
\immediate\write\@partaux{\relax}%
\fi
+% \end{macrocode}
+% Now before going to the hooks we need to set \cs{CurrentFile}:
+% \begin{macrocode}
+%-----------------------------------------
+ \@filehook@set@CurrentFile
+% \end{macrocode}
+% Execute the \texttt{before} hooks just after we switched the
+% \texttt{.aux} file \ldots
+% \begin{macrocode}
+ \UseHook{include/before}%
+ \UseHook{include/before/#1}%
+%-----------------------------------------
\@input@{#1.tex}%
+%-----------------------------------------
+% \end{macrocode}
+% \ldots{} then \texttt{end} hooks \ldots
+% \begin{macrocode}
+ \UseHook{include/end/#1}%
+ \UseHook{include/end}%
+%-----------------------------------------
\clearpage
+%-----------------------------------------
+% \end{macrocode}
+% \ldots{} and after the \cs{clearpage} the \texttt{after} hooks
+% followed by another \cs{clearpage} just in case new material got
+% added (after all we need to be in well defined state after the
+% \cs{include}).
+% \begin{macrocode}
+ \UseHook{include/after/#1}%
+ \UseHook{include/after}%
+ \clearpage
+%-----------------------------------------
\@writeckpt{#1}%
\if@filesw
\immediate\closeout\@partaux
@@ -640,6 +890,45 @@
\@nameuse{cp@#1}%
\fi
\let\@auxout\@mainaux}
+%<latexrelease>\EndIncludeInRelease
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@include}{Spaces in file names}%
+%<latexrelease>\def\@include#1 {%
+%<latexrelease> \clearpage
+%<latexrelease> \if@filesw
+%<latexrelease> \immediate\write\@mainaux{\string\@input{#1.aux}}%
+%<latexrelease> \fi
+%<latexrelease> \@tempswatrue
+%<latexrelease> \if@partsw
+%<latexrelease> \@tempswafalse
+%<latexrelease> \edef\reserved@b{#1}%
+%<latexrelease> \@for\reserved@a:=\@partlist\do
+%<latexrelease> {\ifx\reserved@a\reserved@b\@tempswatrue\fi}%
+%<latexrelease> \fi
+%<latexrelease> \if@tempswa
+%<latexrelease> \let\@auxout\@partaux
+%<latexrelease> \if@filesw
+%<latexrelease> \immediate\openout\@partaux #1.aux
+%<latexrelease> \immediate\write\@partaux{\relax}%
+%<latexrelease> \fi
+%<latexrelease> \@input@{#1.tex}%
+%<latexrelease> \clearpage
+%<latexrelease> \@writeckpt{#1}%
+%<latexrelease> \if@filesw
+%<latexrelease> \immediate\closeout\@partaux
+%<latexrelease> \fi
+%<latexrelease> \else
+%<latexrelease> \deadcycles\z@
+%<latexrelease> \@nameuse{cp@#1}%
+%<latexrelease> \fi
+%<latexrelease> \let\@auxout\@mainaux}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -688,7 +977,6 @@
%
%
%
-
% \begin{macro}{\@curr@file}
% \begin{macro}{\set@curr@file}
%
@@ -698,8 +986,8 @@
% the code in \texttt{utf8.def}). By setting \cs{escapchar} to
% \texttt{-1} we ensure that we don't get a backslash in front. As a
% result we end up with all characters as catcode 12 (plus
-% spaces). We then sometimes add quotes around the contruct
-% (removing any existing inner quotes. Somes we only remove the
+% spaces). We then sometimes add quotes around the construct
+% (removing any existing inner quotes. Sometimes we only remove the
% quotes if they have been supplied by the user. There is clearly
% some room for improvement.
%
@@ -716,11 +1004,11 @@
% \changes{v1.2c}{2019/10/11}{Remove one brace group}
% \changes{v1.2d}{2019/10/26}{remove quotes}
% \changes{v1.2e}{2019/11/09}{expand and \cs{string} before removing quotes}
+%
+% The definition below is from 2019 and only used during kernel
+% bootstrapping, later on in \texttt{ltfilehook.dtx} it will get
+% overwritten.
% \begin{macrocode}
-%</2ekernel>
-%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2019/10/01}%
-%<latexrelease> {\set@curr@file}{Quote file names}%
\def\set@curr@file#1{%
\begingroup
\escapechar\m@ne
@@ -747,6 +1035,10 @@
% -> ""
%\end{verbatim}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\quote@name}{Quote file names}%
\def\quote@name#1{"\quote@@name#1\@gobble""}
\def\quote@@name#1"{#1\quote@@name}
% \end{macrocode}
@@ -828,12 +1120,11 @@
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\set@curr@file}{Quote file names}%
+%<latexrelease> {\quote@name}{Quote file names}%
%<latexrelease>
%<latexrelease>\let\quote@name\@undefined
%<latexrelease>\let\quote@@name\@undefined
%<latexrelease>\let\unquote@name\@undefined
-%<latexrelease>\let\set@curr@file\@undefined
%<latexrelease>
%<latexrelease>\let\IfFileExists@\@undefined
%<latexrelease>
@@ -873,25 +1164,14 @@
%
%
% \begin{macro}{\InputIfFileExists}
-% \changes{v0.9b}
-% {1993/12/04}{Macro added}
-% \changes{v0.9p}
-% {1994/01/18}{New Definition}
-% \changes{v0.3b}{1994/03/13}
-% {Use new cmd \cs{@addtofilelist}}
-% Now define |\InputIfFileExists| to input |#1| if it seems to exist.
-% Immediately prior to the input, |#2| is executed.
-% If the file |#1| does not exist, execute `|#3|'.
-% \changes{v1.0t}{1995/05/25}
-% {(CAR) added \cs{long}}
-% \changes{v1.1o}{2019/02/07}{Expand \cs{@filef@und} before executing
-% second argument (github/109)}
-% \changes{v1.2b}{2019/08/27}{Make command robust}
-% \begin{macrocode}
-%</2ekernel>
-%<latexrelease>\IncludeInRelease{2019/10/01}%
-%<latexrelease> {\InputIfFileExists}{Don't lose the file name}%
-%<*2ekernel|latexrelease>
+%
+% Now define |\InputIfFileExists| to input |#1| if it seems to exist.
+% Immediately prior to the input, |#2| is executed.
+% If the file |#1| does not exist, execute `|#3|'.
+%
+% This here is a temporary definition for the kernel. The real one
+% comes somewhat later in the file \texttt{ltfilehook.dtx}.
+%
% \begin{macrocode}
\DeclareRobustCommand \InputIfFileExists[2]{%
\IfFileExists{#1}%
@@ -908,25 +1188,23 @@
% Swap two arguments and return them unbraced (like
% \cs{@firstoftwo} etc).
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\@swaptwoargs}{Don't lose the file name}%
\long\def\@swaptwoargs#1#2{#2#1}
% \end{macrocode}
-% \end{macro}
-%
%
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\InputIfFileExists}{Don't lose the file name}%
-%<latexrelease>\long\def \InputIfFileExists#1#2{%
-%<latexrelease> \IfFileExists{#1}%
-%<latexrelease> {#2\@addtofilelist{#1}\@@input \@filef@und}}
-%<latexrelease>
+%<latexrelease> {\@swaptwoargs}{Don't lose the file name}%
%<latexrelease>\let\@swaptwoargs\@undefined
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
-%
+% \end{macro}
%
%
% \begin{macro}{\input}
@@ -943,20 +1221,51 @@
% Define |\@iinput| (i.e., |\input|) in terms of
% |\InputIfIfileExists|.
% \changes{v0.9b}{1993/12/04}{Macro reimplemented}
+%
+% Changes to \cs{@iinput}: adapt to the changes to
+% \cs{@missingfileerror}.
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2019/10/01}%
-%<latexrelease> {\@iinput}{Quote file names}%
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@iinput}{Change in file error handling}%
\def\@iinput#1{%
\InputIfFileExists{#1}{}%
{\filename@parse\@curr@file
\edef\reserved@a{\noexpand\@missingfileerror
{\filename@area\filename@base}%
{\ifx\filename@ext\relax tex\else\filename@ext\fi}}%
+% \end{macrocode}
+% This line now just sets \cs[no-index]{@missingfile@\meta{part}}:
+% \begin{macrocode}
+ \reserved@a
+% \end{macrocode}
+% Now here we have to use it. The file here is guaranteed to exist,
+% because \cs{@missingfileerror} ensures so, but we have to use
+% \cs{InputIfFileExists} because it executes the file hooks.
+% \begin{macrocode}
+ \edef\reserved@a{\noexpand\@iinput{%
+ \@missingfile@area\@missingfile@base.\@missingfile@ext}}%
\reserved@a}}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\@iinput}{Quote file names}%
+%<latexrelease>
+%<latexrelease>\def\@iinput#1{%
+%<latexrelease> \InputIfFileExists{#1}{}%
+%<latexrelease> {\filename@parse\@curr@file
+%<latexrelease> \edef\reserved@a{\noexpand\@missingfileerror
+%<latexrelease> {\filename@area\filename@base}%
+%<latexrelease> {\ifx\filename@ext\relax tex\else\filename@ext\fi}}%
+%<latexrelease> \reserved@a}}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\@iinput}{Quote file names}%
%<latexrelease>\def\@iinput#1{%
@@ -1001,6 +1310,11 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
+%
+%
% \begin{macro}{\@missingfileerror}
% This `error' command avoids \TeX's primitive missing file loop.
%
@@ -1018,7 +1332,16 @@
% {Move here from ltclass}
% \changes{v1.0w}{1995/10/06}
% {Autoload error}
+%
+% Changes to \cs{@missingfileerror}: rather than trying to input the
+% file by force, now \cs{@missingfileerror} just returns three
+% \cs[no-index]{@missingfile@\meta{part}} and the caller macro is
+% responsible for doing the right thing with it.
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@missingfileerror}{Do not load missing file immediately}%
\gdef\@missingfileerror#1#2{%
\typeout{^^J! LaTeX Error: File `#1.#2' not found.^^J^^J%
Type X to quit or <RETURN> to proceed,^^J%
@@ -1027,20 +1350,74 @@
{\endlinechar\m@ne
\global\read\m@ne to\@gtempa}%
\ifx\@gtempa\@empty
+% \end{macrocode}
+% If the user answers with \meta{return}, fallback to the |.tex| file
+% (previously it did nothing).
+% \begin{macrocode}
+ \let\@missingfile@area\@empty
+ \let\@missingfile@base\@empty
+ \def\@missingfile@ext{tex}%
\else
- \def\reserved@a{x}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
- \def\reserved@a{X}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
+% \end{macrocode}
+% Use \cs{batchmode}\cs{read}|-1 to |\meta{tl} to end the \TeX{} run,
+% same as \pkg{expl3} does (it was \cs{batchmode}\cs{@@end} before).
+% \begin{macrocode}
+ \def\reserved@b{\batchmode\read-1 to \reserved@a}%
+ \def\reserved@a{x}\ifx\reserved@a\@gtempa\reserved@b\fi
+ \def\reserved@a{X}\ifx\reserved@a\@gtempa\reserved@b\fi
\filename@parse\@gtempa
\edef\filename@ext{%
\ifx\filename@ext\relax#2\else\filename@ext\fi}%
\edef\reserved@a{%
- \noexpand\InputIfFileExists
+% \end{macrocode}
+% Only check \cs{IfFileExists} (it was \cs{InputIfFileExists}).
+% \begin{macrocode}
+ \noexpand\IfFileExists
{\filename@area\filename@base.\filename@ext}%
- {}%
+% \end{macrocode}
+% If the file exists, define \cs[no-index]{@missingfile@\meta{part}}.
+% \begin{macrocode}
+ {\def\noexpand\@missingfile@area{\filename@area}%
+ \def\noexpand\@missingfile@base{\filename@base}%
+ \def\noexpand\@missingfile@ext {\filename@ext}}%
{\noexpand\@missingfileerror
{\filename@area\filename@base}{\filename@ext}}}%
\reserved@a
- \fi}
+ \fi
+}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@missingfileerror}{Do not load missing file immediately}%
+%<latexrelease>
+%<latexrelease>\gdef\@missingfileerror#1#2{%
+%<latexrelease> \typeout{^^J! LaTeX Error: File `#1.#2' not found.^^J^^J%
+%<latexrelease> Type X to quit or <RETURN> to proceed,^^J%
+%<latexrelease> or enter new name. (Default extension: #2)^^J}%
+%<latexrelease> \message{Enter file name: }%
+%<latexrelease> {\endlinechar\m@ne
+%<latexrelease> \global\read\m@ne to\@gtempa}%
+%<latexrelease> \ifx\@gtempa\@empty
+%<latexrelease> \else
+%<latexrelease> \def\reserved@a{x}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
+%<latexrelease> \def\reserved@a{X}\ifx\reserved@a\@gtempa\batchmode\@@end\fi
+%<latexrelease> \filename@parse\@gtempa
+%<latexrelease> \edef\filename@ext{%
+%<latexrelease> \ifx\filename@ext\relax#2\else\filename@ext\fi}%
+%<latexrelease> \edef\reserved@a{%
+%<latexrelease> \noexpand\InputIfFileExists
+%<latexrelease> {\filename@area\filename@base.\filename@ext}%
+%<latexrelease> {}%
+%<latexrelease> {\noexpand\@missingfileerror
+%<latexrelease> {\filename@area\filename@base}{\filename@ext}}}%
+%<latexrelease> \reserved@a
+%<latexrelease> \fi}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/base/ltfinal.dtx b/Master/texmf-dist/source/latex/base/ltfinal.dtx
index 56549507624..aa4219723af 100644
--- a/Master/texmf-dist/source/latex/base/ltfinal.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfinal.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltfinal.dtx}
- [2019-10-02 v2.2 LaTeX Kernel (Final Settings)]
+ [2020-09-26 v2.2j LaTeX Kernel (Final Settings)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfinal.dtx}
@@ -88,6 +88,7 @@
% argument.}
% \changes{v2.0r}{2016/10/15}{Require e\TeX{}}
% \changes{v2.0s}{2016/10/15}{Tidy up status of char 127}
+% \changes{v2.2i}{2020/08/21}{Integration of new hook management interface}
%
% \subsection{Debugging}
%
@@ -460,6 +461,14 @@
\fi
% \end{macrocode}
%
+% \changes{v2.2b}{2020/07/08}
+% {Add a last-minute hook for \textsf{expl3}}
+% At this stage, we can install any last-minute \textsf{expl3} set-up.
+% \begin{macrocode}
+\@expl@finalise@setup@@
+\def\@expl@finalise@setup@@{}
+% \end{macrocode}
+%
% This is as good a place as any to active a few Xe\TeX{}-specific
% settings
% \begin{macrocode}
@@ -582,7 +591,7 @@
% Skip this section in Unicode TeX, or if MLTeX and EncTeX are enabled.
% \begin{macrocode}
\ifnum0%
- \ifx\Umathchar\@undefined\else 1\fi
+ \ifx\Umathcode\@undefined\else 1\fi
\ifx\mubyte\@undefined\else 1\fi
\ifx\charsubdef\@undefined\else 1\fi
=\z@
@@ -1044,13 +1053,8 @@
% }{}
% \end{macrocode}
%
-% \subsection{Loading further extensions}
-%
% \changes{v2.2}{2019-10-02}{Load \textsf{ltexpl}}
-% Simply load further code: it's deliberately separate
-% \begin{macrocode}
-\input{ltexpl.ltx}
-% \end{macrocode}
+% \changes{v2.2a}{2020-06-04}{Load \textsf{ltexpl} in \texttt{ltdefns}}
%
% \subsection{Freeing Memory}
%
@@ -1124,14 +1128,6 @@
% \end{macro}
% \end{macro}
%
-% \subsection{Some last minute initializations \ldots}
-%
-% This initializes the 2020/02/02 extensions to NFSS after any changes
-% in the preamble.
-% \begin{macrocode}
-\AtBeginDocument{\reinstall@nfss@defs\init@series@setup}
-% \end{macrocode}
-%
%
%
% \subsection{Do some temporary work for pre-release}
@@ -1139,9 +1135,18 @@
% This is a good place to load code that hasn't yet been
% integrated into the other files \ldots
% \begin{macrocode}
-%\input ...
% \end{macrocode}
%
+% \subsection{Some last minute initializations \ldots}
+%
+% Load the first aid set of definitions for external packages that await updates.
+% \changes{v2.2j}{2020/09/26}
+% {Load first aid file if existing}
+% \begin{macrocode}
+\@input{latex2e-first-aid-for-external-files.ltx}
+% \end{macrocode}
+%
+%
% \subsection{Dumping the format}
% Finally we make |@| into a letter, ensure the format will
% be in the `normal' error mode, and dump everything into the
diff --git a/Master/texmf-dist/source/latex/base/ltfloat.dtx b/Master/texmf-dist/source/latex/base/ltfloat.dtx
index 23c3f464d3f..dee9a10197e 100644
--- a/Master/texmf-dist/source/latex/base/ltfloat.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfloat.dtx
@@ -31,7 +31,7 @@
%
%<*driver>
% \fi
-\ProvidesFile{ltfloat.dtx}[2015/02/21 v1.2c LaTeX Kernel (Floats)]
+\ProvidesFile{ltfloat.dtx}[2020/04/09 v1.2d LaTeX Kernel (Floats)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltfloat.dtx}
@@ -1327,13 +1327,36 @@
% always start with a font selection command, to activate the font
% size switch.
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@textsuperscript}{superscript baseline}%
\def\@textsuperscript#1{%
- {\m@th\ensuremath{^{\mbox{\fontsize\sf@size\z@#1}}}}}
+ {\m@th\ensuremath{^{\mbox{\fontsize\sf@size\sf@size#1}}}}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@textsuperscript}{superscript baseline}%
+%<latexrelease>
+%<latexrelease>\def\@textsuperscript#1{%
+%<latexrelease> {\m@th\ensuremath{^{\mbox{\fontsize\sf@size\z@#1}}}}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
+%
+%
+%
+%
+%
+%
% \begin{macro}{\textsubscript}
% \changes{v1.2a}{2014/12/30}{Command added (latexrelease)}
+% \changes{v1.2d}{2020/04/09}{Set non-zero baseline (gh/249)}
% \begin{macrocode}
%</2ekernel>
%<latexrelease>\IncludeInRelease{2015/01/01}%
@@ -1345,27 +1368,54 @@
\DeclareRobustCommand*\textsubscript[1]{%
\@textsubscript{\selectfont#1}}%
% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\textsubscript}{\textsubscript}%
+%<latexrelease>\let\textsubscript\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
% \end{macro}
%
+%
+%
+%
% \begin{macro}{\@textsubscript}
% \changes{v1.2a}{2014/12/30}{Command added (latexrelease)}
-%
+% \changes{v1.2d}{2020/04/09}{Set non-zero baseline (gh/249)}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@textsubscript}{subscript baseline}%
\def\@textsubscript#1{%
- {\m@th\ensuremath{_{\mbox{\fontsize\sf@size\z@#1}}}}}
+ {\m@th\ensuremath{_{\mbox{\fontsize\sf@size\sf@size#1}}}}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2015/01/01}%
+%<latexrelease> {\@textsubscript}{subscript baseline}%
+%<latexrelease>
+%<latexrelease>\def\@textsubscript#1{%
+%<latexrelease> {\m@th\ensuremath{_{\mbox{\fontsize\sf@size\z@#1}}}}}
% \end{macrocode}
-% \end{macro}
%
% \begin{macrocode}
-%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\textsubscript}{\textsubscript}%
-%<latexrelease>\let\textsubscript\@undefined
+%<latexrelease> {\@textsubscript}{subscript baseline}%
%<latexrelease>\let\@textsubscript\@undefined
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
+% \end{macro}
+%
+%
%
% \begin{macro}{\footnotesep}
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltfssaxes.dtx b/Master/texmf-dist/source/latex/base/ltfssaxes.dtx
index 02a49a3122d..d8e4286b786 100644
--- a/Master/texmf-dist/source/latex/base/ltfssaxes.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssaxes.dtx
@@ -35,7 +35,7 @@
%
%
\ProvidesFile{ltfssaxes.dtx}
- [2020/02/27 v1.0d LaTeX Kernel (NFSS Axes handing)]
+ [2020/08/21 v1.0g LaTeX Kernel (NFSS Axes handing)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -695,7 +695,7 @@
%
% \begin{macro}{\fontseriesforce}
% To change unconditionally to a new series you can use
-% \cs{fontseriesforce}. If course, if the series doesn't exist for
+% \cs{fontseriesforce}. Of course, if the series doesn't exist for
% the current family substitution still happens, but there is not
% dependency on the current series.
% \changes{v1.0c}{2020/02/10}{Switch \cs{if@forced@series} added}
@@ -849,7 +849,7 @@
% \changes{v1.0d}{2020/02/27}{Drop ``m'' only in a specific set of values (gh/293)}
% \begin{macrocode}
\edef\f@series{#1}%
- \expandafter\series@maybe@drop@one@m\expandafter{\f@series}\f@series
+ \series@maybe@drop@one@m\f@series\f@series
}
% \end{macrocode}
% \end{macro}
@@ -865,7 +865,13 @@
% \changes{v1.0d}{2020/02/27}{Drop ``m'' in certain values from a
% fixed list (gh/293)}
% \begin{macrocode}
-\def\series@maybe@drop@one@m#1#2{%
+\def\series@maybe@drop@one@m#1{%
+ \expandafter\series@maybe@drop@one@m@x\expandafter{#1}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+
+\def\series@maybe@drop@one@m@x#1#2{%
% \end{macrocode}
% The code below is an inline version of the \cs{in@} macro without
% the group, so that it works in \cs{accent}.
@@ -875,7 +881,16 @@
,ulm,elm,lm,slm,mm,sbm,bm,ebm,ubm,muc,mec,mc,msc,msx,mx,mex,mux,{}{},#1,}%
\edef\in@@{\the\series@check@toks}%
\ifx\in@@\@empty
- \def#2{#1}%
+% \end{macrocode}
+% The default definition for \cs{bfdefault} etc is actually
+% \texttt{b\cs{@empty}} so that we can detect if the user has
+% changed the default. However that means a) the above test will
+% definitely fail (maybe something to change) and b) we better use
+% \cs{edef} on the next line to get rid of it as otherwise the test
+% against \verb=#2= (e.g. \cs{bfdef@ult}) will fail in other places.
+% \changes{v1.0e}{2020/05/19}{Need to use \cs{edef} (gh/336)}
+% \begin{macrocode}
+ \edef#2{#1}%
\else
\edef#2{\expandafter\series@drop@one@m #1m\series@drop@one@m}%
\fi
@@ -891,7 +906,7 @@
% \begin{macro}{\series@drop@one@m}
% Drop up to two \texttt{m}s but keep one if that makes the series
% value empty. Actually, with the current implementation we know
-% that there is at least one in the series value istelf and we
+% that there is at least one in the series value itself and we
% added one after it, so all we have to do is now returning
% \verb=#1#2= and dropping the rest.
% \begin{macrocode}
@@ -949,6 +964,7 @@
\DeclareRobustCommand\ulcshape
{\not@math@alphabet\ulcshape\relax
\fontshape\ulcdefault\selectfont}
+\let\ulcdefault\@undefined % for rollback
\newcommand\ulcdefault{ulc}
% \end{macrocode}
% \end{macro}
@@ -969,6 +985,7 @@
\DeclareRobustCommand\swshape
{\not@math@alphabet\swshape\relax
\fontshape\swdefault\selectfont}
+\let\swdefault\@undefined % for rollback
\newcommand\swdefault{sw}
% \end{macrocode}
% \end{macro}
@@ -992,6 +1009,7 @@
\DeclareRobustCommand\sscshape
{\not@math@alphabet\sscshape\relax
\fontshape\sscdefault\selectfont}
+\let\sscdefault\@undefined % for rollback
\newcommand\sscdefault{ssc}
% \end{macrocode}
% \end{macro}
@@ -1276,6 +1294,35 @@
%<latexrelease>\let\reinstall@nfss@defs\relax
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
+% \end{macrocode}
+%
+% This initializes the 2020/02/02 extensions to NFSS after any changes
+% in the preamble.
+% \changes{v1.0g}{2020/08/21}{Integration of new hook management interface}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\reinstall@nfss@defs}{NFSS series init}%
+\g@addto@macro\@kernel@after@begindocument@before
+ {\reinstall@nfss@defs\init@series@setup}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% The initialization was introduced in 2020/02/02 but
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\reinstall@nfss@defs}{NFSS series init}%
+%<latexrelease>\AtBeginDocument{\reinstall@nfss@defs\init@series@setup}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\reinstall@nfss@defs}{NFSS series init}%
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
%</2ekernel>
% \end{macrocode}
%
diff --git a/Master/texmf-dist/source/latex/base/ltfssbas.dtx b/Master/texmf-dist/source/latex/base/ltfssbas.dtx
index f51d742d466..4a6afca3ace 100644
--- a/Master/texmf-dist/source/latex/base/ltfssbas.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssbas.dtx
@@ -282,7 +282,7 @@
% \cs{reservedb} so we use that and also issue a warning.
% \begin{macrocode}
\edef\reserved@a{#3}%
- \expandafter\series@maybe@drop@one@m\expandafter{#3}\reserved@b
+ \series@maybe@drop@one@m\reserved@a\reserved@b
\ifx\reserved@a\reserved@b\else
\@latex@warning{Font shape declaration has incorrect series
value `#3'.\MessageBreak It should not contain an `m'!
@@ -1850,7 +1850,7 @@
% Finally, it is not possible to simply call the new definition
% since we
% have an argument (the third argument of |\use@mathgroup|
-% or more exactly the argument od |\math@egroup| if the {\ttfamily
+% or more exactly the argument of |\math@egroup| if the {\ttfamily
% margid} option is in force)
% which would swallow our closing |\fi|. So
% we use the |\expandafter| technique to remove the |\fi|
diff --git a/Master/texmf-dist/source/latex/base/ltfssdcl.dtx b/Master/texmf-dist/source/latex/base/ltfssdcl.dtx
index 951c6de2e5a..291cd1368f2 100644
--- a/Master/texmf-dist/source/latex/base/ltfssdcl.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssdcl.dtx
@@ -36,7 +36,7 @@
%
%
\ProvidesFile{ltfssdcl.dtx}
- [2020/01/20 v3.0t LaTeX Kernel (NFSS Declarative Interface)]
+ [2020/03/19 v3.0v LaTeX Kernel (NFSS Declarative Interface)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -465,7 +465,7 @@
% \changes{v3.0q}{2015/03/18}{Introduce \cs{e@mathgroup@top}}
% \begin{macrocode}
%</2ekernel>
-%<latexrelease>\IncludeInRelease{2015/01/01}
+%<latexrelease>\IncludeInRelease{2020/10/01}
%<latexrelease> {\document@select@group}{\document@select@group}%
%<*2ekernel|latexrelease>
\def\document@select@group#1#2#3#4{%
@@ -491,13 +491,54 @@
\@eha
\fi
\else \expandafter\non@alpherr\fi
- #1{#4}%
+% \end{macrocode}
+% If the legacy interface is used, e.g., \verb=$\sf -1$= the math
+% alphabet \verb=#1= does not take an argument so we better do not
+% surround \verb=#4= with braces, because then we get
+% \verb={\relax}= into the formula and introduce an extra Ord
+% atom. The two different cases can be distinguished by looking at
+% the current value of \cs{math@bgroup}.
+% \changes{v3.0u}{2020/03/19}{fix for (gnats/3357)}
+% \begin{macrocode}
+ \expandafter#1\ifx\math@bgroup\bgroup{#4}\else#4\fi
}%
}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2015/01/01}
+%<latexrelease> {\document@select@group}{\document@select@group}%
+%<latexrelease>
+%<latexrelease>\def\document@select@group#1#2#3#4{%
+%<latexrelease> \ifx\math@bgroup\bgroup\else\relax\expandafter\@firstofone\fi
+%<latexrelease> {%
+%<latexrelease> \ifmmode
+%<latexrelease> \ifnum\csname c@mv@\math@version\endcsname<\e@mathgroup@top
+%<latexrelease> \begingroup
+%<latexrelease> \escapechar\m@ne
+%<latexrelease> \getanddefine@fonts{\csname c@mv@\math@version\endcsname}#3%
+%<latexrelease> \globaldefs\@ne \math@fonts
+%<latexrelease> \endgroup
+%<latexrelease> \expandafter\extract@alph@from@version
+%<latexrelease> \csname mv@\math@version\expandafter\endcsname
+%<latexrelease> \expandafter{\number\csname
+%<latexrelease> c@mv@\math@version\endcsname}%
+%<latexrelease> #1%
+%<latexrelease> \global\advance\csname c@mv@\math@version\endcsname\@ne
+%<latexrelease> \else
+%<latexrelease> \let#1\relax
+%<latexrelease> \@latex@error{Too many math alphabets used
+%<latexrelease> in version \math@version}%
+%<latexrelease> \@eha
+%<latexrelease> \fi
+%<latexrelease> \else \expandafter\non@alpherr\fi
+%<latexrelease> #1{#4}%
+%<latexrelease> }%
+%<latexrelease>}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
%<latexrelease>\IncludeInRelease{0000/00/00}
%<latexrelease> {\document@select@group}{\document@select@group}%
+%<latexrelease>
%<latexrelease>\def\document@select@group#1#2#3#4{%
%<latexrelease> \ifx\math@bgroup\bgroup\else\relax\expandafter\@firstofone\fi
%<latexrelease> {%
@@ -582,17 +623,19 @@
% \begin{macrocode}
\let\select@group\document@select@group
% \end{macrocode}
-% Install the default font attributes they are currently pointing
-% to error font shape.
+% Install the default font attributes as they are currently pointing
+% to error font face. We can speed up the process by just using
+% \cs{edef}, thereby avoiding all kind of extra processing.
% Don't use |\reset@font| since that would trigger |\selectfont|.
+% \changes{v3.0v}{2020/04/13}{Small update for speed.}
% \begin{macrocode}
- \fontencoding{\encodingdefault}%
- \fontfamily{\familydefault}%
- \fontseries{\seriesdefault}%
- \fontshape{\shapedefault}%
+ \fontencoding\encodingdefault
+ \edef\f@family{\familydefault}%
+ \edef\f@series{\seriesdefault}%
+ \edef\f@shape{\shapedefault}%
% \end{macrocode}
-% kill all macros not longer needed.
-% we need to add many more!!!!!!
+% Drop stuff not longer needed.
+% We need to add many more!!!!!!
% \begin{macrocode}
\everyjob{}%
}
diff --git a/Master/texmf-dist/source/latex/base/ltfssini.dtx b/Master/texmf-dist/source/latex/base/ltfssini.dtx
index 98f465ae9b9..10f3dc5863b 100644
--- a/Master/texmf-dist/source/latex/base/ltfssini.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfssini.dtx
@@ -36,7 +36,7 @@
%
%
\ProvidesFile{ltfssini.dtx}
- [2020/02/18 v3.1i LaTeX Kernel (NFSS Initialisation)]
+ [2020/09/30 v3.2d LaTeX Kernel (NFSS Initialisation)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -244,7 +244,7 @@
% \DescribeMacro\DeclareFontSeriesDefault
% We now support this concept directly from within \LaTeX{} and for
% use in font packages (or the document preamble) we offer
-% \cs{DeclareSeriesDefault}. This declaration takes three
+% \cs{DeclareFontSeriesDefault}. This declaration takes three
% arguments:
% \begin{description}
% \item[document family interface:] Can either be \texttt{rm},
@@ -278,6 +278,7 @@
% The command to declare font series defaults for the ``rm'', ``sf'' or
% ``tt'' family.
% \begin{macrocode}
+\let\DeclareFontSeriesDefault\@undefined % for rollback
\newcommand\DeclareFontSeriesDefault[3][]{%
\def\reserved@a{#1}%
% \end{macrocode}
@@ -287,11 +288,19 @@
\ifx\reserved@a\@empty
\ifcsname #2series\endcsname % supported are
% \[md/bf]default
+% \end{macrocode}
+% Adding \cs{@empty} allows us to detect if the default gets
+% redefined with \cs{renewcommand} or \cs{def} by the user.
+% \changes{v3.1k}{2020/03/19}{Support legacy use of \cs{bfdefault}
+% and \cs{mddefault} (gh/306)}
+% \begin{macrocode}
+ \expandafter\def
+ \csname #2default\endcsname{#3\@empty}%
\expandafter\def
- \csname #2default\endcsname{#3}%
+ \csname #2default@previous\endcsname{#3\@empty}%
\else
% \end{macrocode}
-%
+%
% \changes{v3.1g}{2020/02/05}{Clarrified error text}
% \begin{macrocode}
\@latex@error{Wrong syntax for \string\DeclareFontSeriesDefault}%
@@ -379,243 +388,6 @@
-% \begin{macro}{\expand@font@defaults}
-%
-% The family specific defaults are fully expanded, i.e., they are
-% defined via \cs{edef} inside \cs{DeclareFontSeriesDefault}.
-% However, the overall defaults, e.g., \cs{bfdefault} may have been
-% redefined by the user and thus may not be fully expanded. So to
-% enable reliable comparison we make expanded versions of
-% them. That we rerun each time. The alternative would be to only
-% allow for changes before begin document.
-% \begin{macrocode}
-\def\expand@font@defaults{%
- \edef\rmdef@ult{\rmdefault}%
- \edef\sfdef@ult{\sfdefault}%
- \edef\ttdef@ult{\ttdefault}%
- \edef\bfdef@ult{\bfdefault}%
- \edef\mddef@ult{\mddefault}%
- \edef\famdef@ult{\familydefault}%
-}
-% \end{macrocode}
-%
-% \end{macro}
-
-
-
-% \begin{macro}{\bfseries}
-% This document command switches to the bold series.
-% \begin{macrocode}
-\DeclareRobustCommand\bfseries{%
- \not@math@alphabet\bfseries\mathbf
-% \end{macrocode}
-% In the original NFSS definition it then called \cs{fontseries}
-% with the value \cs{bfdefault}. In the new scheme we have more
-% alternatives and therefore check if the current family
-% (\cs{f@family}) is the current \cs{rmdef@ult}, \cs{sfdef@ult} or
-% \cs{ttdef@ult} and the select the correct family default in that case.
-% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside
-% of \cs{fontseries} argument so that it is not done several times}
-% \begin{macrocode}
- \expand@font@defaults
- \ifx\f@family\rmdef@ult \fontseries\bfseries@rm
- \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf
- \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt
-% \end{macrocode}
-% If not \cs{bfdefault} is used.
-% \begin{macrocode}
- \else \fontseries\bfdefault
- \fi\fi\fi
- \selectfont
-}
-% \end{macrocode}
-% \end{macro}
-
-
-
-% \begin{macro}{\mdseries}
-% This document command switches to the medium series.
-% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside
-% of \cs{fontseries} argument so that it is not done several times}
-% \begin{macrocode}
-\DeclareRobustCommand\mdseries{%
- \not@math@alphabet\mdseries\relax
- \expand@font@defaults
- \ifx\f@family\rmdef@ult \fontseries\mdseries@rm
- \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf
- \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt
- \else \fontseries\mddefault
- \fi\fi\fi
- \selectfont
-}
-% \end{macrocode}
-% \end{macro}
-
-
-% \begin{macro}{\rmfamily}
-% Here are the document level commands for changing the main font
-% families, or rather, here is a documented outline of the code,
-% the actual code is then streamlined and somewhat generalized.
-%\begin{verbatim}
-%\DeclareRobustCommand\rmfamily{%
-% \not@math@alphabet\rmfamily\mathrm
-%\end{verbatim}
-% If families are changed then we have to do a bit more work.
-% In the original NFSS implementation
-% a family change kept encoding, series shape and size unchanged
-% but now we can't any
-% longer simply reuse the current series value. Instead we may have
-% to change it from one family default to the next.
-%\begin{verbatim}
-% \expand@font@defaults
-%\end{verbatim}
-% We have to do the testing while the current family is still
-% unchanged but we have to do the adjustment of the series after it
-% got changed (because the new family might has different sets
-% ofshapes available and we certainly don't want to see
-% substituation going on. So we use \cs{target@series@value} to
-% hold the target series (if any).
-%\begin{verbatim}
-% \let\target@series@value\@empty
-%\end{verbatim}
-% Thus, if the current family is the sans family
-%\begin{verbatim}
-% \ifx\f@family\sfdef@ult
-%\end{verbatim}
-% and if we using the medium series of the sans family
-%\begin{verbatim}
-% \ifx\f@series\mdseries@sf
-%\end{verbatim}
-% then lets switch to the medium series for the serif family
-%\begin{verbatim}
-% \let\target@series@value\mdseries@rm
-%\end{verbatim}
-% and if we use the bold series of the sans family switch to the
-% bold default of the serif family:
-%\begin{verbatim}
-% \else\ifx\f@series\bfseries@sf \let\target@series@value\bfseries@rm
-%\end{verbatim}
-% However, the sans family may not have any specific defaults set,
-% so we also compare with the overall defaults.
-%\begin{verbatim}
-% \else\ifx\f@series\mddef@ult \let\target@series@value\mdseries@rm
-% \else\ifx\f@series\bfdef@ult \let\target@series@value\bfseries@rm
-%\end{verbatim}
-% If neither test was true we leave the series alone. This way a
-% special manual setting such as \verb=\fontseries{lc}= is not
-% undone if the family changes (of course there may not be any
-% support for it in the new family but then the NFSS
-% substitution kicks in and sorts it out).
-%\begin{verbatim}
-% \fi\fi\fi\fi
-%
-%\end{verbatim}
-% We need to do the same if the current family is the typewriter family:
-%\begin{verbatim}
-% \else\ifx\f@family\ttdef@ult
-% \ifx\f@series\mdseries@tt \let\target@series@value\mdseries@rm
-% \else\ifx\f@series\bfseries@tt \let\target@series@value\bfseries@rm
-% \else\ifx\f@series\mddef@ult \let\target@series@value\mdseries@rm
-% \else\ifx\f@series\bfdef@ult \let\target@series@value\bfseries@rm
-% \fi\fi\fi\fi
-% \fi\fi
-%\end{verbatim}
-% With these preparations for series out of the way we can now
-% change the font family to \cs{rmdefault}.
-%\begin{verbatim}
-% \fontfamily\rmdefault
-%\end{verbatim}
-%
-% If \cs{target@series@value} is still empty there is nothing more
-% to do other than selecting the new family. However, if not then
-% we should update the font series now as well. But there is one
-% further subtle issue. We may not have loaded an \texttt{.fd} file
-% for our target font family yet. In the past that was done in
-% \cs{selectfont} if necessary but since we are now doing all the
-% comparisons in \cs{fontseries} we need to make sure that the font
-% family specifications are already loaded prior to calling
-% \cs{fontseries}.
-%\begin{verbatim}
-% \ifx\target@series@value\@empty \else
-% \maybe@load@fontshape
-%\end{verbatim}
-% Updating the series in this case means directly changing
-% \cs{f@series} to the target value. We don't want to go through
-% \cs{fontseries} because that would apply the mappings and then
-% \texttt{bx + b} would keep \texttt{bx} instead of changing to
-% \texttt{b} as desired.
-% as
-%\begin{verbatim}
-% \let\f@series\target@series@value
-% \fi
-% \selectfont}
-%\end{verbatim}
-%
-% So now for the real definition: most of the code above gets
-% delegated to a helper command \cs{prepare@family@series@update}
-% so that the definition becomes again fairly short. In addition we
-% add a hook, mainly for our Japanese friends so that the code can
-% be extended prior to the call to \cs{selectfont}.
-%
-% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook}
-% \begin{macrocode}
-\DeclareRobustCommand\rmfamily{%
- \not@math@alphabet\rmfamily\mathrm
-% \end{macrocode}
-% This holds all the code discussed above, first argument is the
-% meta family, i.e., \texttt{rm} in this case, and second argument
-% is the default family name, e.g., \texttt{cmr} indirectly
-% accessed via \cs{rmdefault}. This is calling \cs{fontfamily} and
-% if necessary \cs{fontseries} as outline above.
-% \begin{macrocode}
- \prepare@family@series@update{rm}\rmdefault
-% \end{macrocode}
-% Then comes the hook code (by default a no-op) and finally the call
-% to \cs{selectfont}.
-% \begin{macrocode}
- \@rmfamilyhook
- \selectfont}
-% \end{macrocode}
-%
-% \begin{macro}{\sffamily}
-% \begin{macro}{\ttfamily}
-% The definitions for \cs{sffamily} and \cs{ttfamily} are similar,
-% the differences are only in what font families get checked.
-% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook}
-% \begin{macrocode}
-\DeclareRobustCommand\sffamily{%
- \not@math@alphabet\sffamily\mathsf
- \prepare@family@series@update{sf}\sfdefault
- \@sffamilyhook
- \selectfont}
-% \end{macrocode}
-%
-% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook}
-% \begin{macrocode}
-\DeclareRobustCommand\ttfamily{%
- \not@math@alphabet\ttfamily\mathtt
- \prepare@family@series@update{tt}\ttdefault
- \@ttfamilyhook
- \selectfont}
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
-%
-% \begin{macro}{\@rmfamilyhook}
-% \begin{macro}{\@sffamilyhook}
-% \begin{macro}{\@ttfamilyhook}
-% By default the hooks do nothing.
-% \begin{macrocode}
-\let\@rmfamilyhook\@empty
-\let\@sffamilyhook\@empty
-\let\@ttfamilyhook\@empty
-% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
-%
%
%
%
@@ -675,7 +447,7 @@
% \begin{itemize}
% \item \cs{bfseries} is called for a family using \texttt{bx}
% (e.g., CMR)
-% \item Switch to a font family that is none of the the meta
+% \item Switch to a font family that is none of the meta
% families, e.g., via \verb=\fontfamily{ptm}\selectfont=
% \item Then none of the real meta families, match but the final
% \verb=\@elt{??}= will.
@@ -718,7 +490,16 @@
\maybe@load@fontshape
%<+debug> \series@change@debug{Target series:
%<+debug> \f@series \space -> \target@series@value}%
- \let\f@series\target@series@value
+% \end{macrocode}
+% The \cs{target@series@value} may contain something like
+% \texttt{cm} (coming from a default) and so we can't directly
+% asign it to \cs{f@series} be have to drop any surplus \texttt{m}
+% first.
+% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from
+% \cs{target@series@value} (gh/291)}
+% \begin{macrocode}
+% \let\f@series\target@series@value
+ \series@maybe@drop@one@m\target@series@value\f@series
\fi
\fi
\fi
@@ -776,10 +557,30 @@
% \cs{rmfamily}. This is now covered by looping and stopping the
% loop when a match was found.
% \begin{macrocode}
- \expandafter\ifx\csname mdseries@#1\endcsname\f@series
+% \end{macrocode}
+% We have to sanitize the default value first because it may
+% contain something like \texttt{mc} and that would never match
+% \cs{f@series} because there it would be called \texttt{c} with
+% the \texttt{m} dropped. It would be probably better to do that
+% differently these days, but it is hard to adjust without causing
+% a lot of issues, so we do the dropping in various places instead.
+% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from \cs{reserved@d}
+% (gh/291)}
+% \begin{macrocode}
+ \expandafter\series@maybe@drop@one@m
+ \csname mdseries@#1\endcsname\reserved@d
+ \ifx\reserved@d\f@series
%<+debug> \series@change@debug{mdseries@#1 matched -> \reserved@b}%
\let\target@series@value\reserved@b
- \else\expandafter\ifx\csname bfseries@#1\endcsname\f@series
+ \else
+% \end{macrocode}
+% Again do some sanitizing.
+% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from \cs{reserved@d}
+% (gh/291)}
+% \begin{macrocode}
+ \expandafter\series@maybe@drop@one@m
+ \csname bfseries@#1\endcsname\reserved@d
+ \ifx\reserved@d\f@series
%<+debug> \series@change@debug{bfseries@#1 matched -> \reserved@c}%
\let\target@series@value\reserved@c
\else\ifx\f@series\mddef@ult \let\target@series@value\reserved@b
@@ -823,37 +624,59 @@
% \cs{DeclareFontSeriesDefault} interface.
% \begin{macrocode}
\ifx\bfseries@rm@kernel\bfseries@rm
- \expandafter\in@\expandafter{\rmdefault}{cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}%
+ \expandafter\in@\expandafter{\rmdefault}%
+ {cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}%
\ifin@ \else \def\bfseries@rm{b}\fi\fi
% \end{macrocode}
% Same approach for \cs{bfseries@sf} and \cs{bfseries@tt}:
% \begin{macrocode}
\ifx\bfseries@sf@kernel\bfseries@sf
- \expandafter\in@\expandafter{\sfdefault}{cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}%
+ \expandafter\in@\expandafter{\sfdefault}%
+ {cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}%
\ifin@ \else \def\bfseries@sf{b}\fi\fi
\ifx\bfseries@tt@kernel\bfseries@tt
- \expandafter\in@\expandafter{\ttdefault}{cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}%
+ \expandafter\in@\expandafter{\ttdefault}%
+ {cmr,cmss,cmtt,lcmss,lcmtt,lmr,lmss,lmtt}%
\ifin@ \else \def\bfseries@tt{b}\fi\fi
% \end{macrocode}
%
% If the document preamble has changed the \cs{familydefault} or if
-% the if the \cs{rmdefault} contains a new font family, we have to
+% the if the \cs{rmdefault} contains a new font family, we may have to
% adjust the series defaults accordingly, before starting
% typesetting.
-%
-% On the other hand if we still typeset in CM or LM then
-% \cs{bfdefault} is wrong since it is now saying \texttt{b} and not
-% \texttt{bx}.
-
-% To fix this we run \cs{rmfamily}, \cs{sffamily} or
-% \cs{ttfamily} depending on the situation and this will correct
-% the setup for us.
-% \begin{macrocode}
- \expand@font@defaults
- \ifx\famdef@ult\rmdef@ult \rmfamily
- \else\ifx\famdef@ult\sfdef@ult \sffamily
- \else\ifx\famdef@ult\ttdef@ult \ttfamily
- \fi\fi\fi
+%
+% Similarly, if the user has changed the \cs{mddefault} or the
+% medium series for the family selected as document font we may
+% also have to adjust the \cs{seriesdefault}.
+%
+% On the other hand if the document font is still CM or LM then
+% \cs{bfdefault} is wrong, because it is now saying \texttt{b} and not
+% \texttt{bx} as it should for such fonts.
+%
+% To fix all this we first run \cs{reset@font} (the internal kernel
+% name for \cs{normalfont}). This will set up the document encoding,
+% family, series and shape based on the current values of
+% \cs{encodingdefault}, \cs{familydefault}, \cs{seriesdefault} and
+% \cs{shapedefault}.
+% However, if the family (from \cs{familydefault}) has special medium
+% default we should switch to that (and not use what is current
+% value from \cs{seriesdefault}). This can be achieved by afterwards
+% calling \cs{mediumseries} and then changing \cs{seriesdefault} to
+% the now current series value (in \cs{f@series}).
+%
+% But what should happen if \cs{seriesdefault} got explicitly
+% changed? In that case the explicit change should surive and we
+% should not alter \cs{seriesdefault}. This is solved by comparing
+% the current value of \cs{seriesdefault} with a kernel version
+% saved in the format and if they differ we do not call
+% \cs{mdseries} or change \cs{seriesdefault}.
+% \changes{v3.1n}{2020/04/13}{Handling \cs{seriesdefault} changes (gh/315)}
+% \begin{macrocode}
+ \reset@font
+ \ifx\seriesdefault\seriesdefault@kernel
+ \mdseries
+ \let\seriesdefault\f@series
+ \fi
}%
% \end{macrocode}
% \end{macro}
@@ -893,9 +716,435 @@
%<latexrelease>\let\mdseries@rm\@undefined
%<latexrelease>\let\mdseries@sf\@undefined
%<latexrelease>\let\mdseries@tt\@undefined
-%<latexrelease>\let\expand@font@defaults\@undefined
%<latexrelease>\expandafter\let\csname ver@mweights.sty\endcsname\@undefined
%<latexrelease>
+%<latexrelease>\let\@meta@family@list\@undefined
+%<latexrelease>\let\prepare@family@series@update\@undefined
+%<latexrelease>\let\update@series@target@value\@undefined
+%<latexrelease>
+% \end{macrocode}
+% This is always called in \cs{document} so don't make it undefined.
+% \begin{macrocode}
+%<latexrelease>\let\init@series@setup\relax
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\bfseries}{Custom series with hooks}%
+% \end{macrocode}
+
+
+% \begin{macro}{\expand@font@defaults}
+% \begin{macro}{\rm@def@ult}
+% \begin{macro}{\sf@def@ult}
+% \begin{macro}{\tt@def@ult}
+% \begin{macro}{\md@def@ult}
+% \begin{macro}{\bf@def@ult}
+%
+% The family specific defaults are fully expanded, i.e., they are
+% defined via \cs{edef} inside \cs{DeclareFontSeriesDefault}.
+% However, the overall defaults, e.g., \cs{bfdefault} may have been
+% redefined by the user and thus may not be fully expanded. So to
+% enable reliable comparison we make expanded versions of
+% them. That we rerun each time. The alternative would be to only
+% allow for changes before begin document.
+% \begin{macrocode}
+\def\expand@font@defaults{%
+ \edef\rmdef@ult{\rmdefault}%
+ \edef\sfdef@ult{\sfdefault}%
+ \edef\ttdef@ult{\ttdefault}%
+% \end{macrocode}
+% The series defaults may contain some surplus \texttt{m} that we
+% need to drop here.
+% \changes{v3.1j}{2020/02/25}{Drop surplus ``m'' from \cs{bfdef@ult}
+% and \cs{mddef@ult} (gh/291)}
+% \begin{macrocode}
+ \series@maybe@drop@one@m\bfdefault\bfdef@ult
+ \series@maybe@drop@one@m\mddefault\mddef@ult
+% \end{macrocode}
+% Formats that set up parallel fonts, e.g., for Japanese, can use
+% this hook to add additional code here.
+% \changes{v3.1m}{2020/04/06}{Hook added (gh/306)}
+% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
+% \begin{macrocode}
+ \UseHook{expand@font@defaults}%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+
+
+% \begin{macro}{\bfseries}
+% This document command switches to the bold series.
+% \begin{macrocode}
+\DeclareRobustCommand\bfseries{%
+ \not@math@alphabet\bfseries\mathbf
+% \end{macrocode}
+% In the original NFSS definition it then called \cs{fontseries}
+% with the value \cs{bfdefault}. In the new scheme we have more
+% alternatives and therefore check if the current family
+% (\cs{f@family}) is the current \cs{rmdef@ult}, \cs{sfdef@ult} or
+% \cs{ttdef@ult} and the select the correct family default in that case.
+% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside
+% of \cs{fontseries} argument so that it is not done several times}
+% \begin{macrocode}
+ \expand@font@defaults
+% \end{macrocode}
+% If \cs{bfdefault} and \cs{bfdefault@previous} are different then
+% the default got changed directly through the legacy interface
+% (i.e., via \cs{def} or \cs{renewcommand}. In that case we reset
+% all meta family defaults so that the document behaves like it was
+% the case before the new mechanism was introduced.
+% \changes{v3.1k}{2020/03/19}{Support legacy use of \cs{bfdefault}
+% and \cs{mddefault} (gh/306)}
+% \begin{macrocode}
+ \ifx\bfdefault\bfdefault@previous\else
+% \end{macrocode}
+% We add \cs{@empty} and then let \cs{bfdefault@previous} to
+% \cs{bfdefault} so that we can detect any further change.
+% \changes{v3.2d}{2020/09/30}{\cs{bfdefault@previous} not \cs{bfseries@previous}
+% (gh/395)}
+% \begin{macrocode}
+ \expandafter\def\expandafter\bfdefault
+ \expandafter{\bfdefault\@empty}%
+ \let\bfdefault@previous\bfdefault
+% \end{macrocode}
+% And we reset the meta family defaults (\cs{bfdef@ult} is an
+% expanded version of \cs{bfdefault}.
+% \begin{macrocode}
+ \let\bfseries@rm\bfdef@ult
+ \let\bfseries@sf\bfdef@ult
+ \let\bfseries@tt\bfdef@ult
+% \end{macrocode}
+%
+% Formats that set up parallel fonts, e.g., for Japanese, can use
+% this hook to add resets here. Not that this hook is only run when
+% resets are necessary.
+% \changes{v3.1m}{2020/04/06}{Hook added (gh/306)}
+% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
+% \begin{macrocode}
+ \UseHook{bfseries/defaults}%
+ \fi
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \ifx\f@family\rmdef@ult \fontseries\bfseries@rm
+ \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf
+ \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt
+% \end{macrocode}
+% If not \cs{bfdefault} is used.
+% \begin{macrocode}
+ \else \fontseries\bfdefault
+ \fi\fi\fi
+% \end{macrocode}
+% This hook in contrast is always executed.
+% \begin{macrocode}
+ \UseHook{bfseries}%
+ \selectfont
+}
+% \end{macrocode}
+% \end{macro}
+
+
+
+% \begin{macro}{\mdseries}
+% This document command switches to the medium series.
+% \changes{v3.1i}{2020/02/18}{Make the \cs{ifx} selection outside
+% of \cs{fontseries} argument so that it is not done several times}
+% \changes{v3.1k}{2020/03/19}{Support legacy use of \cs{bfdefault}
+% and \cs{mddefault} (gh/306)}
+% \changes{v3.2d}{2020/09/30}{\cs{mddefault@previous} not \cs{mdseries@previous}
+% (gh/395)}
+% \begin{macrocode}
+\DeclareRobustCommand\mdseries{%
+ \not@math@alphabet\mdseries\relax
+ \expand@font@defaults
+ \ifx\mddefault\mddefault@previous\else
+ \expandafter\def\expandafter\mddefault\expandafter{\mddefault\@empty}%
+ \let\mddefault@previous\mddefault
+ \let\mdseries@rm\mddef@ult
+ \let\mdseries@sf\mddef@ult
+ \let\mdseries@tt\mddef@ult
+% \end{macrocode}
+%
+% Formats that set up parallel fonts, e.g., for Japanese, can use
+% this hook to add resets here.
+% \changes{v3.1m}{2020/04/06}{Hook added (gh/306)}
+% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
+% \begin{macrocode}
+ \UseHook{mdseries/defaults}%
+ \fi
+ \ifx\f@family\rmdef@ult \fontseries\mdseries@rm
+ \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf
+ \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt
+ \else \fontseries\mddefault
+ \fi\fi\fi
+ \UseHook{mdseries}%
+ \selectfont
+}
+% \end{macrocode}
+% \end{macro}
+
+
+% \begin{macro}{\rmfamily}
+% Here are the document level commands for changing the main font
+% families, or rather, here is a documented outline of the code,
+% the actual code is then streamlined and somewhat generalized.
+%\begin{verbatim}
+%\DeclareRobustCommand\rmfamily{%
+% \not@math@alphabet\rmfamily\mathrm
+%\end{verbatim}
+% If families are changed then we have to do a bit more work.
+% In the original NFSS implementation
+% a family change kept encoding, series shape and size unchanged
+% but now we can't any
+% longer simply reuse the current series value. Instead we may have
+% to change it from one family default to the next.
+%\begin{verbatim}
+% \expand@font@defaults
+%\end{verbatim}
+% We have to do the testing while the current family is still
+% unchanged but we have to do the adjustment of the series after it
+% got changed (because the new family might has different sets
+% ofshapes available and we certainly don't want to see
+% substituation going on. So we use \cs{target@series@value} to
+% hold the target series (if any).
+%\begin{verbatim}
+% \let\target@series@value\@empty
+%\end{verbatim}
+% Thus, if the current family is the sans family
+%\begin{verbatim}
+% \ifx\f@family\sfdef@ult
+%\end{verbatim}
+% and if we using the medium series of the sans family
+%\begin{verbatim}
+% \ifx\f@series\mdseries@sf
+%\end{verbatim}
+% then lets switch to the medium series for the serif family
+%\begin{verbatim}
+% \let\target@series@value\mdseries@rm
+%\end{verbatim}
+% and if we use the bold series of the sans family switch to the
+% bold default of the serif family:
+%\begin{verbatim}
+% \else\ifx\f@series\bfseries@sf \let\target@series@value\bfseries@rm
+%\end{verbatim}
+% However, the sans family may not have any specific defaults set,
+% so we also compare with the overall defaults.
+%\begin{verbatim}
+% \else\ifx\f@series\mddef@ult \let\target@series@value\mdseries@rm
+% \else\ifx\f@series\bfdef@ult \let\target@series@value\bfseries@rm
+%\end{verbatim}
+% If neither test was true we leave the series alone. This way a
+% special manual setting such as \verb=\fontseries{lc}= is not
+% undone if the family changes (of course there may not be any
+% support for it in the new family but then the NFSS
+% substitution kicks in and sorts it out).
+%\begin{verbatim}
+% \fi\fi\fi\fi
+%
+%\end{verbatim}
+% We need to do the same if the current family is the typewriter family:
+%\begin{verbatim}
+% \else\ifx\f@family\ttdef@ult
+% \ifx\f@series\mdseries@tt \let\target@series@value\mdseries@rm
+% \else\ifx\f@series\bfseries@tt \let\target@series@value\bfseries@rm
+% \else\ifx\f@series\mddef@ult \let\target@series@value\mdseries@rm
+% \else\ifx\f@series\bfdef@ult \let\target@series@value\bfseries@rm
+% \fi\fi\fi\fi
+% \fi\fi
+%\end{verbatim}
+% With these preparations for series out of the way we can now
+% change the font family to \cs{rmdefault}.
+%\begin{verbatim}
+% \fontfamily\rmdefault
+%\end{verbatim}
+%
+% If \cs{target@series@value} is still empty there is nothing more
+% to do other than selecting the new family. However, if not then
+% we should update the font series now as well. But there is one
+% further subtle issue. We may not have loaded an \texttt{.fd} file
+% for our target font family yet. In the past that was done in
+% \cs{selectfont} if necessary but since we are now doing all the
+% comparisons in \cs{fontseries} we need to make sure that the font
+% family specifications are already loaded prior to calling
+% \cs{fontseries}.
+%\begin{verbatim}
+% \ifx\target@series@value\@empty \else
+% \maybe@load@fontshape
+%\end{verbatim}
+% Updating the series in this case means directly changing
+% \cs{f@series} to the target value. We don't want to go through
+% \cs{fontseries} because that would apply the mappings and then
+% \texttt{bx + b} would keep \texttt{bx} instead of changing to
+% \texttt{b} as desired.
+% as
+%\begin{verbatim}
+% \let\f@series\target@series@value
+% \fi
+% \selectfont}
+%\end{verbatim}
+%
+% So now for the real definition: most of the code above gets
+% delegated to a helper command \cs{prepare@family@series@update}
+% so that the definition becomes again fairly short. In addition we
+% add a hook, mainly for our Japanese friends so that the code can
+% be extended prior to the call to \cs{selectfont}.
+%
+% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook}
+% \begin{macrocode}
+\DeclareRobustCommand\rmfamily{%
+ \not@math@alphabet\rmfamily\mathrm
+% \end{macrocode}
+% This holds all the code discussed above, first argument is the
+% meta family, i.e., \texttt{rm} in this case, and second argument
+% is the default family name, e.g., \texttt{cmr} indirectly
+% accessed via \cs{rmdefault}. This is calling \cs{fontfamily} and
+% if necessary \cs{fontseries} as outline above.
+% \begin{macrocode}
+ \prepare@family@series@update{rm}\rmdefault
+% \end{macrocode}
+% Then comes the hook code (by default a no-op) and finally the call
+% to \cs{selectfont}.
+% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
+% \begin{macrocode}
+ \UseHook{rmfamily}%
+ \selectfont}
+% \end{macrocode}
+%
+% \begin{macro}{\sffamily}
+% \begin{macro}{\ttfamily}
+% The definitions for \cs{sffamily} and \cs{ttfamily} are similar,
+% the differences are only in what font families get checked.
+% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook}
+% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
+% \begin{macrocode}
+\DeclareRobustCommand\sffamily{%
+ \not@math@alphabet\sffamily\mathsf
+ \prepare@family@series@update{sf}\sfdefault
+ \UseHook{sffamily}%
+ \selectfont}
+% \end{macrocode}
+%
+% \changes{v3.1f}{2020/01/11}{Streamlined implementation with hook}
+% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
+% \begin{macrocode}
+\DeclareRobustCommand\ttfamily{%
+ \not@math@alphabet\ttfamily\mathtt
+ \prepare@family@series@update{tt}\ttdefault
+ \UseHook{ttfamily}%
+ \selectfont}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+% \begin{macro}{rmfamily,sffamily,ttfamily,normalfont,expand@font@defaults,
+% bfseries,bfseries/defaults,mdseries,mdseries/defaults}
+% Declare the hooks used above.
+% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
+% \begin{macrocode}
+\NewHook{rmfamily}
+\NewHook{sffamily}
+\NewHook{ttfamily}
+\NewHook{normalfont}
+\NewHook{expand@font@defaults}
+\NewHook{bfseries}
+\NewHook{bfseries/defaults}
+\NewHook{mdseries}
+\NewHook{mdseries/defaults}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@rmfamilyhook}
+% \begin{macro}{\@sffamilyhook}
+% \begin{macro}{\@ttfamilyhook}
+% These four hooks have legacy versions used in 2020/02/02 so we
+% should support them until they aren't any longer used.
+% \begin{macrocode}
+\let\@rmfamilyhook\@empty
+\let\@sffamilyhook\@empty
+\let\@ttfamilyhook\@empty
+\let\@defaulfamilyhook\@empty
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2020/02/02}%
+%<latexrelease> {\bfseries}{Custom series with hooks}%
+%<latexrelease>
+%<latexrelease>\def\expand@font@defaults{%
+%<latexrelease> \edef\rmdef@ult{\rmdefault}%
+%<latexrelease> \edef\sfdef@ult{\sfdefault}%
+%<latexrelease> \edef\ttdef@ult{\ttdefault}%
+%<latexrelease> \edef\bfdef@ult{\bfdefault}%
+%<latexrelease> \edef\mddef@ult{\mddefault}%
+%<latexrelease> \edef\famdef@ult{\familydefault}%
+%<latexrelease>}
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\bfseries{%
+%<latexrelease> \not@math@alphabet\bfseries\mathbf
+%<latexrelease> \expand@font@defaults
+%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\bfseries@rm
+%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\bfseries@sf
+%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\bfseries@tt
+%<latexrelease> \else \fontseries\bfdefault
+%<latexrelease> \fi\fi\fi
+%<latexrelease> \selectfont
+%<latexrelease>}
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\mdseries{%
+%<latexrelease> \not@math@alphabet\mdseries\relax
+%<latexrelease> \expand@font@defaults
+%<latexrelease> \ifx\f@family\rmdef@ult \fontseries\mdseries@rm
+%<latexrelease> \else\ifx\f@family\sfdef@ult \fontseries\mdseries@sf
+%<latexrelease> \else\ifx\f@family\ttdef@ult \fontseries\mdseries@tt
+%<latexrelease> \else \fontseries\mddefault
+%<latexrelease> \fi\fi\fi
+%<latexrelease> \selectfont
+%<latexrelease>}
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\rmfamily{%
+%<latexrelease> \not@math@alphabet\rmfamily\mathrm
+%<latexrelease> \prepare@family@series@update{rm}\rmdefault
+%<latexrelease> \@rmfamilyhook
+%<latexrelease> \selectfont}
+%<latexrelease>\DeclareRobustCommand\sffamily{%
+%<latexrelease> \not@math@alphabet\sffamily\mathsf
+%<latexrelease> \prepare@family@series@update{sf}\sfdefault
+%<latexrelease> \@sffamilyhook
+%<latexrelease> \selectfont}
+%<latexrelease>\DeclareRobustCommand\ttfamily{%
+%<latexrelease> \not@math@alphabet\ttfamily\mathtt
+%<latexrelease> \prepare@family@series@update{tt}\ttdefault
+%<latexrelease> \@ttfamilyhook
+%<latexrelease> \selectfont}
+%<latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\bfseries}{Custom series with hooks}%
+%<latexrelease>
+%<latexrelease>\let\expand@font@defaults\@undefined
+%<latexrelease>
%<latexrelease>\DeclareRobustCommand\bfseries
%<latexrelease> {\not@math@alphabet\bfseries\mathbf
%<latexrelease> \fontseries\bfdefault\selectfont}
@@ -915,21 +1164,173 @@
%<latexrelease>\let\@rmfamilyhook\@undefined
%<latexrelease>\let\@sffamilyhook\@undefined
%<latexrelease>\let\@ttfamilyhook\@undefined
-%<latexrelease>\let\@meta@family@list\@undefined
-%<latexrelease>\let\prepare@family@series@update\@undefined
-%<latexrelease>\let\update@series@target@value\@undefined
%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
-% This is always called in \cs{document} so don't make it undefined.
+%
+%
+%
+% \begin{macro}{\IfFontSeriesContextTF}
+%
+% With the ability for \cs{bfseries} or \cs{mdseries} to be mapped
+% to different NFSS axis values it becomes important to have the
+% ability to determine the current context as we can no longer look
+% at \cs{f@series} to answer a question such as ``am I currently
+% typsetting in a bold typeface?''
+%
+% This is provided by the test \cs{IfFontSeriesContextTF}. It takes
+% three arguments:
+% \begin{itemize}
+% \item
+% The context we try to check (either \texttt{bf} for bold or
+% \texttt{md} for medium, i.e., the same that can go into the
+% first mandatory argument of \cs{DeclareFontSeriesDefault}),
+%
+% \item
+% what to do if we are in this context (true case) and
+%
+% \item
+% what to do if we are not (false case).
+% \end{itemize}
+% This allows you to define commands like \cs{IfBold}, e.g.,
+%\begin{verbatim}
+% \newcommand\IfBold[2]{\IfSeriesContextTF{bf}{#1}{#2}}
+%\end{verbatim}
+% and then do
+%\begin{verbatim}
+% This is \IfBold{bold}{non-bold} text.
+%\end{verbatim}
+% and get the appropriate result.
+%
+% \changes{v3.2a}{2020/05/19}{Macros added (gh/335)}
% \begin{macrocode}
-%<latexrelease>\let\init@series@setup\relax
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\IfFontSeriesContextTF}{Font series context}%
+% \end{macrocode}
+%
+% \begin{macrocode}
+\DeclareRobustCommand\IfFontSeriesContextTF[1]{%
+ \expand@font@defaults
+% \end{macrocode}
+% In the beginning we haven't found the context we are loking for.
+% \begin{macrocode}
+ \@font@series@contextfalse
+% \end{macrocode}
+% We store the requested context away for use in the tests.
+% \begin{macrocode}
+ \def\requested@test@context{#1}%
+% \end{macrocode}
+% The next definition is there to ensure that get a final match
+% during testing
+% even if the current family is non of the meta families
+% (\texttt{rm}, \texttt{sf} or \texttt{tt}). This will then
+% basically tests if the current font family matches the overall default.
+% \begin{macrocode}
+ \expandafter\edef\csname ??def@ult\endcsname{\f@family}%
+% \end{macrocode}
+% Then we run through the meta family list (currently containing
+% just the three values) followed by the artifical meta family
+% \texttt{??} and test each of them in turn using
+% \cs{test@font@series@context} as the testing command.
+% \begin{macrocode}
+ \let\@elt\test@font@series@context
+ \@meta@family@list
+ \@elt{??}%
+ \let\@elt\relax
+% \end{macrocode}
+% Following that we evaluate the status of
+% \cs{if@font@series@context} to determine which of the remaining
+% arguments (true/false case) we have to execute.
+% \begin{macrocode}
+ \if@font@series@context
+ \expandafter\@firstoftwo
+ \else
+ \expandafter\@secondoftwo
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+
+
+
+% \begin{macro}{\test@font@series@context}
+% This tests the context (stored in \cs{requested@test@context})
+% and updates the bookean if the right context is found.
+% \begin{macrocode}
+\def\test@font@series@context#1{%
+% \end{macrocode}
+% First task is to figure out whether the current family matches
+% \cs{rmfamily}, \cs{sffamily}, etc.\ so in \cs{reserved@a} we
+% store the value of \cs{rmdef@ult} (or whatever the given meta
+% family is) and compare that to \cs{f@family}.
+% \begin{macrocode}
+ \edef\reserved@a{\csname #1def@ult\endcsname}%
+ \ifx\f@family\reserved@a
+% \end{macrocode}
+% If they match we have found the right meta family so we don't
+% need to test any of the remaining meta family and therefore
+% change \cs{@elt} to \cs{@gobble}.
+% \begin{macrocode}
+ \let\@elt\@gobble
+% \end{macrocode}
+% Now we have to test if \cs{f@series} matches the requested
+% context (e.g., whether \cs{bfseries@rm} has that value if the
+% current meta family is \texttt{rm} and we are looking for the
+% \texttt{bf} context).
+% \begin{macrocode}
+ \expandafter\ifx
+ \csname\requested@test@context series@#1\endcsname\f@series
+% \end{macrocode}
+% If yes we change the boolean and are done.
+% \begin{macrocode}
+ \@font@series@contexttrue
+% \end{macrocode}
+% If not then maybe the reason is that nothing special was set up
+% for that meta family so we also check now check if \cs{f@series}
+% matches the overall default (e.g., \cs{bfdef@ult} if we are
+% looking for the bold context). If that matches we change the boolean.
+% \begin{macrocode}
+ \else
+ \expandafter\ifx
+ \csname\requested@test@context def@ult\endcsname\f@series
+ \@font@series@contexttrue
+ \fi\fi\fi
+}
+% \end{macrocode}
+% \end{macro}
+
+
+% \begin{macro}{\if@font@series@context}
+% The boolean to signal if we found the requested font series context.
+% \begin{macrocode}
+\newif\if@font@series@context
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\IfFontSeriesContextTF}{Font series context}%
%<latexrelease>
+%<latexrelease>\let\IfFontSeriesContextTF\@undefined
+%<latexrelease>\let\test@font@series@context\@undefined
+%<latexrelease>\let\if@font@series@context\@undefined
+%<latexrelease>\let\@font@series@contexttrue\@undefined
+%<latexrelease>\let\@font@series@contextfalse\@undefined
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
-%
-%
+
+
%
% \section{Supporting nested emphasis}
%
@@ -1201,26 +1602,50 @@
\def\math@version{normal}
% \end{macrocode}
%
-% \subsection{Miscellaneous}
+% \subsection{Legacy}
%
-% \begin{macro}{\newfont}
-% \changes{v1.2g}{1991/03/30}{Definition added.}
-% \changes{v2.2e}{1995/05/23}{Font assignment made local again.}
-% \begin{macro}{\symbol}
-% \changes{v1.2g}{1991/03/30}{Definition added.}
% We start by defining a few macros that are part of
% standard \LaTeX's user interface. The use of these functions is
% not encouraged, but they will allow to process older documents
% without changes to the source.
+%
+% \begin{macro}{\newfont}
+% \changes{v1.2g}{1991/03/30}{Definition added.}
+% \changes{v2.2e}{1995/05/23}{Font assignment made local again.}
% \begin{macrocode}
\def\newfont#1#2{\@ifdefinable#1{\font#1=#2\relax}}
% \end{macrocode}
+% \end{macro}
%
+% \begin{macro}{\symbol}
+% \changes{v1.2g}{1991/03/30}{Definition added.}
+% \changes{v3.1h}{2020/02/07}{XeTeX-specific version to avoid bug in maths mode.}
% \begin{macrocode}
-\DeclareRobustCommand\symbol[1]{\char #1\relax}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\symbol}{XeTeX change for math}%
+\ifdefined\XeTeXversion
+ \DeclareRobustCommand\symbol[1]{\Ucharcat#1 12\relax}
+\else
+ \DeclareRobustCommand\symbol[1]{\char#1\relax}
+\fi
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\symbol}{XeTeX change for math}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\symbol[1]{\char#1\relax}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
-% \end{macro}
+%
+% \subsection{Miscellaneous}
%
% \begin{macro}{\@setfontsize}
% \begin{macro}{\@setsize}
@@ -1344,8 +1769,14 @@
\edef\f@shape{\shapedefault}%
% \end{macrocode}
%
+% \changes{v3.2b}{2020/08/21}{Integration of new hook management interface}
% \begin{macrocode}
- \@defaultfamilyhook
+ \UseHook{normalfont}%
+% \end{macrocode}
+% This is the old name for the hook introduced in 2020/02/02.
+% It will be removed in one of the future releases!
+% \begin{macrocode}
+ \@defaultfamilyhook % hookname from 2020/02 will vanish
\selectfont}
% \end{macrocode}
%
@@ -1360,7 +1791,7 @@
% By default the hooks do nothing.
% \changes{v3.1h}{2020/02/10}{Add \cs{@defaultfamilyhook} to \cs{normalfont} (gh/269)}
% \begin{macrocode}
-\let\@defaultfamilyhook\@empty
+\let\@defaultfamilyhook\@empty %FMi sort out
% \end{macrocode}
% \end{macro}
%
@@ -1505,6 +1936,26 @@
% \end{macrocode}
%
%
+%
+% \begin{macro}{\seriesdefault}
+% \begin{macro}{\seriesdefault@kernel}
+% After \cs{seriesdefault} got defined inside \texttt{fonttext.ltx}
+% or a \texttt{.cfg} file overwriting it, we alter its value by
+% appending \cs{@empty} to it. This will vanish if expanded but
+% allows us to check if the default gets altered (even to the same
+% value) in the document preamble. All we have to do is to save the
+% current value somewhere and later compare the two. For this we
+% use \cs{seriesdefault@kernel}.
+% \changes{v3.1n}{2020/04/13}{Handling \cs{seriesdefault} changes (gh/315)}
+% \begin{macrocode}
+\expandafter\def\expandafter\seriesdefault\expandafter{\seriesdefault\@empty}
+\let\seriesdefault@kernel\seriesdefault
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
% \begin{macro}{\@acci}
% \begin{macro}{\@accii}
% \begin{macro}{\@acciii}
diff --git a/Master/texmf-dist/source/latex/base/ltfsstrc.dtx b/Master/texmf-dist/source/latex/base/ltfsstrc.dtx
index e997e5be552..055f408ceb3 100644
--- a/Master/texmf-dist/source/latex/base/ltfsstrc.dtx
+++ b/Master/texmf-dist/source/latex/base/ltfsstrc.dtx
@@ -37,7 +37,7 @@
%<package> [2019/10/11 v3.0l Standard LaTeX package (font tracing)]
% \fi
% \ProvidesFile{ltfsstrc.dtx}
-% [2019/10/11 v3.0l LaTeX Kernel (NFSS tracing)]
+% [2020/02/03 v3.0l LaTeX Kernel (NFSS tracing)]
%
% \iffalse
%<+checkmem>\CHECKMEM
@@ -1731,7 +1731,7 @@
% the optional argument (if present) is ignored. The font encoding
% scheme cannot be changed. Therefore, the first thing we do is to
% prepend the encoding scheme.
-% {documentation fixes}
+% \changes{v2.0b}{1992/07/26}{documentation fixes}
% \begin{macrocode}
\DeclareSizeFunction{sub}{\sub@sfcnt\@font@warning}
\DeclareSizeFunction{ssub}{\sub@sfcnt\@font@info}
@@ -1803,7 +1803,7 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2020/02/01}%
+%<latexrelease>\IncludeInRelease{2020/02/02}%
%<latexrelease> {\@font@aliasinfo}{alias size function}%
\DeclareSizeFunction{alias}{\sub@sfcnt\@font@aliasinfo}
\def\@font@aliasinfo#1{%
diff --git a/Master/texmf-dist/source/latex/base/lthooks.dtx b/Master/texmf-dist/source/latex/base/lthooks.dtx
new file mode 100644
index 00000000000..cb48570a0d8
--- /dev/null
+++ b/Master/texmf-dist/source/latex/base/lthooks.dtx
@@ -0,0 +1,4012 @@
+% \iffalse meta-comment
+%%
+%% File: lthooks.dtx (C) Copyright 2020 Frank Mittelbach,
+%% Phelype Oleinik & LaTeX Team
+%
+% This file is part of the LaTeX base system.
+% -------------------------------------------
+%
+% It may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% https://www.latex-project.org/lppl.txt
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008 or later.
+%
+% This file has the LPPL maintenance status "maintained".
+%
+% The list of all files belonging to the LaTeX base distribution is
+% given in the file `manifest.txt'. See also `legal.txt' for additional
+% information.
+%
+% The list of derived (unpacked) files belonging to the distribution
+% and covered by LPPL is defined by the unpacking scripts (with
+% extension .ins) which are part of the distribution.
+%
+% \fi
+%
+% \iffalse
+%
+%%% From File: lthooks.dtx
+%
+% \begin{macrocode}
+\def\lthooksversion{v1.0b}
+\def\lthooksdate{2020/09/21}
+% \end{macrocode}
+%
+%<*driver>
+\documentclass{l3doc}
+
+% bug fix fo l3doc.cls
+\ExplSyntaxOn
+\cs_set_protected:Npn \__codedoc_macro_typeset_one:nN #1#2
+ {
+ \vbox_set:Nn \l__codedoc_macro_box
+ {
+ \vbox_unpack_drop:N \l__codedoc_macro_box
+ \hbox { \llap { \__codedoc_print_macroname:nN {#1} #2
+ \MacroFont % <----- without it the \ is in lmr10 if a link is made
+ \
+ } }
+ }
+ \int_incr:N \l__codedoc_macro_int
+ }
+\ExplSyntaxOff
+
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{lthooks.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+%
+% \long\def\fmi#1{\begin{quote}\itshape FMi: #1\end{quote}}
+% \long\def\pho#1{\begin{quote}\itshape PhO: #1\end{quote}}
+%
+% \newcommand\hook[1]{\texttt{#1}}
+%
+%
+% \title{The \texttt{lthooks} package\thanks{This package has version
+% \lthooksversion\ dated \lthooksdate, \copyright\ \LaTeX\
+% Project.}}
+%
+% \author{Frank Mittelbach\thanks{Code improvements for speed and other goodies by Phelype Oleinik}}
+%
+% \maketitle
+%
+%
+% \tableofcontents
+%
+% \section{Introduction}
+%
+% Hooks are points in the code of commands or environments where it
+% is possible to add processing code into existing commands. This
+% can be done by different packages that do not know about each
+% other and to allow for hopefully safe processing it is necessary
+% to sort different chunks of code added by different packages into
+% a suitable processing order.
+%
+% This is done by the packages adding chunks of code (via
+% \cs{AddToHook}) and labeling their code with some label by
+% default using the package name as a label.
+%
+% At \verb=\begin{document}= all code for a hook is then sorted
+% according to some rules (given by \cs{DeclareHookRule}) for fast
+% execution without processing overhead. If the hook code is
+% modified afterwards (or the rules are changed),
+% a new version for fast processing is generated.
+%
+% Some hooks are used already in the preamble of the document. If
+% that happens then the hook is prepared for execution (and sorted)
+% already at that point.
+%
+%
+% \section{Package writer interface}
+%
+% The hook management system is offered as a set of CamelCase
+% commands for traditional \LaTeXe{} packages (and for use in the
+% document preamble if needed) as well as \texttt{expl3} commands
+% for modern packages, that use the L3 programming layer of
+% \LaTeX{}. Behind the scenes, a single set of data structures is
+% accessed so that packages from both worlds can coexist and access
+% hooks in other packages.
+%
+%
+%
+% \subsection{\LaTeXe\ interfaces}
+%
+% \subsubsection{Declaring hooks and using them in code}
+%
+% With two exceptions, hooks have to be declared before they can be
+% used. The exceptions are hooks in environments (i.e., executed at
+% \cs{begin} and \cs{end}) and hooks run when loading files,
+% e.g. before and after a package is loaded, etc. Their hook names
+% depend on the environment or the file name and so declaring them
+% beforehand is difficult.
+%
+%
+% \begin{function}{\NewHook}
+% \begin{syntax}
+% \cs{NewHook} \Arg{hook}
+% \end{syntax}
+% Creates a new \meta{hook}.
+% If this is a hook provided as part of a package it is suggested
+% that the \meta{hook} name is always structured as follows:
+% \meta{package-name}\texttt{/}\meta{hook-name}. If necessary you
+% can further subdivide the name by adding more \texttt{/} parts.
+% If a hook name is already taken, an error is raised and the hook
+% is not created.
+%
+% The \meta{hook} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% \end{function}
+%
+% \begin{function}{\NewReversedHook}
+% \begin{syntax}
+% \cs{NewReversedHook} \Arg{hook}
+% \end{syntax}
+% Like \cs{NewHook} declares a new \meta{hook}.
+% the difference is that the code chunks for this hook are in
+% reverse order by default (those added last are executed first).
+% Any rules for the hook are applied after the default ordering.
+% See sections~\ref{sec:order} and \ref{sec:reversed-order}
+% for further details.
+%
+% The \meta{hook} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% \end{function}
+%
+%
+% \begin{function}{\NewMirroredHookPair}
+% \begin{syntax}
+% \cs{NewMirroredHookPair} \Arg{hook-1} \Arg{hook-2}
+% \end{syntax}
+% A shorthand for
+% \cs{NewHook}\Arg{hook-1}\cs{NewReversedHook}\Arg{hook-2}.
+%
+% The \meta{hooks} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% \end{function}
+%
+%
+%
+%
+% \begin{function}{\UseHook}
+% \begin{syntax}
+% \cs{UseHook} \Arg{hook}
+% \end{syntax}
+% Execute the hook code inside a command or environment.
+%
+% Before \verb=\begin{document}= the fast execution code for a hook
+% is not set up, so in order to use a hook there it is explicitly
+% initialized first. As that involves assignments using a hook at
+% those times is not 100\% the same as using it after
+% \verb=\begin{document}=.
+%
+% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
+% A leading |.| is treated literally.
+% \end{function}
+%
+% \begin{function}{\UseOneTimeHook}
+% \begin{syntax}
+% \cs{UseOneTimeHook} \Arg{hook}
+% \end{syntax}
+% Some hooks are only used (and can be only used) in one place, for
+% example, those in \verb=\begin{document}= or
+% \verb=\end{document}=. Once we have passed that point adding to
+% the hook through a defined \cs{\meta{addto-cmd}} command (e.g.,
+% \cs{AddToHook} or \cs{AtBeginDocument}, etc.\@) would have no
+% effect (as would the use of such a command inside the hook code
+% itself). It is therefore customary to redefine
+% \cs{\meta{addto-cmd}} to simply process its argument, i.e.,
+% essentially make it behave like \cs{@firstofone}.
+%
+% \cs{UseOneTimeHook} does that: it records that the hook has been
+% consumed and any further attempt to add to it will result in
+% executing the code to be added immediately.
+%
+% \fmi{Maybe add an error version as well?}
+%
+% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
+% A leading |.| is treated literally.
+% \end{function}
+%
+%
+% \subsubsection{Updating code for hooks}
+%
+% \begin{function}{\AddToHook}
+% \begin{syntax}
+% \cs{AddToHook} \Arg{hook}\oarg{label}\Arg{code}
+% \end{syntax}
+% Adds \meta{code} to the \meta{hook} labeled by \meta{label}. If
+% the optional argument \meta{label} is not provided, if \cs{AddToHook}
+% is used in a package/class, then the current
+% package/class name is used, otherwise \hook{top-level} is
+% used~(see section~\ref{sec:default-label}).
+%
+% If there already exists code under the \meta{label} then the new
+% \meta{code} is appended to the existing one (even if this is a reversed hook).
+% If you want to replace existing code under the
+% \meta{label}, first apply \cs{RemoveFromHook}.
+%
+% The hook doesn't have to exist for code to be added to
+% it. However, if it is not declared later then obviously the
+% added \meta{code} will never be executed. This
+% allows for hooks to work regardless of package loading order and
+% enables packages to add to hook of other packages without
+% worrying whether they are actually used in the current document.
+% See section~\ref{sec:querying}.
+%
+% The \meta{hook} and \meta{label} can be specified using the
+% dot-syntax to denote the current package name.
+% See section~\ref{sec:default-label}.
+% \end{function}
+%
+% \begin{function}{\RemoveFromHook}
+% \begin{syntax}
+% \cs{RemoveFromHook} \Arg{hook}\oarg{label}
+% \end{syntax}
+% Removes any code labeled by \meta{label} from the \meta{hook}.
+% If the optional
+% argument \meta{label} is not provided, if \cs{AddToHook}
+% is used in a package/class, then the current
+% package/class name is used, otherwise \hook{top-level} is used.
+%
+% If the optional argument is \texttt{*}, then all code chunks are
+% removed. This is rather dangerous as it drops code from other
+% packages one may not know about!
+%
+% The \meta{hook} and \meta{label} can be specified using the
+% dot-syntax to denote the current package name.
+% See section~\ref{sec:default-label}.
+% \end{function}
+%
+% \medskip
+%
+% In contrast to the \texttt{voids} relationship between two labels
+% in a \cs{DeclareHookrule} this is a destructive operation as the
+% labeled code is removed from the hook data structure, whereas the
+% relationship setting can be undone by providing a different
+% relationship later.
+%
+% A useful application for this declaration inside the document body
+% is when one wants to temporarily add code to hooks and later remove
+% it again, e.g.,
+%\begin{verbatim}
+% \AddToHook{env/quote/before}{\small}
+% \begin{quote}
+% A quote set in a smaller typeface
+% \end{quote}
+% ...
+% \RemoveFromHook{env/quote/before}
+% ... now back to normal for further quotes
+%\end{verbatim}
+% Note that you can't cancel the setting with
+%\begin{verbatim}
+% \AddToHook{env/quote/before}{}
+%\end{verbatim}
+% because that only \enquote{adds} a further empty chunk of code to
+% the hook. Adding \cs{normalsize} would work but that means the hook
+% then contained \cs{small}\cs{normalsize} which means to font size
+% changes for no good reason.
+%
+% The above is only needed if one wants to typeset several quotes in a
+% smaller typeface. If the hook is only needed once then
+% \cs{AddToHookNext} is simpler, because it resets itself after one use.
+%
+%
+% \begin{function}{\AddToHookNext}
+% \begin{syntax}
+% \cs{AddToHookNext} \Arg{hook}\Arg{code}
+% \end{syntax}
+% Adds \meta{code} to the next invocation of the \meta{hook}.
+% The code is executed after the normal hook code has finished and
+% it is executed only once, i.e. it is deleted after it was used.
+%
+% Using the declaration is a global operation, i.e., the code is
+% not lost, even if the declaration is used inside a group and the
+% next invocation happens after the group. If the declaration is
+% used several times before the hook is executed then all code is
+% executed in the order in which it was declared.\footnotemark
+%
+% It is possible to nest declarations using the same hook (or
+% different hooks), e.g.,
+% \begin{quote}
+% \cs{AddToHookNext}\Arg{hook}\verb={=\meta{code-1}^^A
+% \cs{AddToHookNext}\Arg{hook}\Arg{code-2}\verb=}=
+% \end{quote}
+% will execute \meta{code-1} next time the \meta{hook} is used and at
+% that point puts \meta{code-2} into the \meta{hook} so that it gets
+% executed on following time the hook is run.
+%
+% A hook doesn't have to exist for code to be added to it. This
+% allows for hooks to work regardless of package loading
+% order.
+% See section~\ref{sec:querying}.
+%
+% The \meta{hook} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% \end{function}\footnotetext{There is
+% no mechanism to reorder such code chunks (or delete them).}
+%
+% \subsubsection{Hook names and default labels}
+% \label{sec:default-label}
+%
+% It is best practice to use \cs{AddToHook} in packages or classes
+% \emph{without specifying a \meta{label}} because then the package
+% or class name is automatically used, which is helpful if rules are
+% needed, and avoids mistyping the \meta{label}.
+%
+% Using an explicit \meta{label} is only necessary in very specific
+% situations, e.g., if you want to add several chunks of code into a
+% single hook and have them placed in different parts of the hook
+% (by providing some rules).
+%
+% The other case is when you develop a larger package with several
+% sub-packages. In that case you may want to use the same
+% \meta{label} throughout the sub-packages in order to avoid
+% that the labels change if you internally reorganize your code.
+%
+% Except for \cs{UseHook}, \cs{UseOneTimeHook}, \cs{IfHookEmptyTF}, and
+% \cs{IfHookExistsTF} (and their \pkg{expl3} interfaces \cs{hook_use:n},
+% \cs{hook_use_once:n}, \cs{hook_if_empty:nTF}, and
+% \cs{hook_if_exist:nTF}), all \meta{hook}
+% and \meta{label} arguments are processed in the same way: first,
+% spaces are trimmed around the argument, then it is fully expanded
+% until only character tokens remain. If the full expansion of the
+% \meta{hook} or \meta{label} contains a non-expandable non-character
+% token, a low-level \TeX{} error is raised (namely, the \meta{hook} is
+% expanded using \TeX's \cs{csname}\ldots\cs{endcsname}, as such,
+% Unicode characters are allowed in \meta{hook} and \meta{label}
+% arguments). The arguments of \cs{UseHook} and \cs{UseOneTimeHook} are
+% processed much in the same way except that spaces are not trimmed
+% around the argument, for better performance.
+%
+% It is not enforced, but highly recommended that the hooks defined by
+% a package, and the \meta{labels} used to add code to other hooks
+% contain the package name to easily identify the source of the code
+% chunk and to prevent clashes. This should be the standard practice,
+% so this hook management code provides a shortcut to refer to the
+% current package in the name of a \meta{hook} and in a \meta{label}.
+% If \meta{hook} name or \meta{label} consist just of a single dot
+% (|.|), or starts with a dot followed by a slash (|./|) then the dot
+% denotes the \meta{default label} (usually the current package or class
+% name---see~\cs{DeclareDefaultHookLabel}).
+% A \enquote{|.|} or \enquote{|./|} anywhere else in a \meta{hook} or in
+% \meta{label} is treated literally and is not replaced.
+%
+% For example,
+% inside the package \texttt{mypackage.sty}, the default label is
+% \texttt{mypackage}, so the instructions:
+% \begin{verbatim}
+% \NewHook {./hook}
+% \AddToHook {./hook}[.]{code} % Same as \AddToHook{./hook}{code}
+% \AddToHook {./hook}[./sub]{code}
+% \DeclareHookRule{begindocument}{.}{before}{babel}
+% \AddToHook {file/after/foo.tex}{code}
+% \end{verbatim}
+% are equivalent to:
+% \begin{verbatim}
+% \NewHook {mypackage/hook}
+% \AddToHook {mypackage/hook}[mypackage]{code}
+% \AddToHook {mypackage/hook}[mypackage/sub]{code}
+% \DeclareHookRule{begindocument}{mypackage}{before}{babel}
+% \AddToHook {file/after/foo.tex}{code} % unchanged
+% \end{verbatim}
+%
+% The \meta{default label} is automatically set to the name of the
+% current package or class (using \cs{@currname}). If \cs{@currname}
+% is not set (because the hook command is used outside of a package, or
+% the current file wasn't loaded with \cs{usepackage} or
+% \cs{documentclass}), then the \texttt{top-level} is used as the
+% \meta{default label}.
+%
+% This syntax is available in all \meta{label} arguments and most
+% \meta{hook}, both in the \LaTeXe{} interface, and the \LaTeX3
+% interface described in section~\ref{sec:l3hook-interface}.
+%
+% Note, however, that the replacement of |.| by the \meta{default label}
+% takes place when the hook command is executed, so actions that are
+% somehow executed after the package ends will have the wrong
+% \meta{default label} if the dot-syntax is used. For that reason,
+% this syntax is not available in \cs{UseHook} (and \cs{hook_use:n})
+% because the hook is most of the time used outside of the package file
+% in which it was defined. This syntax is also not available in the hook
+% conditionals \cs{IfHookEmptyTF} (and \cs{hook_if_empty:nTF}) and
+% \cs{IfHookExistsTF} (and \cs{hook_if_exist:nTF}) because these
+% conditionals are used in some performance-critical parts of the hook
+% management code, and because they are usually used to refer to other
+% package's hooks, so the dot-syntax doesn't make much sense.
+%
+% In some cases, for example in large packages, one may want to separate
+% it in logical parts, but still use the main package name as
+% \meta{label}, then the \meta{default label} can be set using
+% \cs{DeclareDefaultHookLabel}:
+%
+% \begin{function}{\DeclareDefaultHookLabel}
+% \begin{syntax}
+% \cs{DeclareDefaultHookLabel} \Arg{default label}
+% \end{syntax}
+% Sets the \meta{default label} to be used in \meta{label} arguments.
+% If \cs{DeclareDefaultHookLabel} is not used in the
+% current package, \cs{@currname} is used instead. If \cs{@currname}
+% is not set, the code is assumed to be in the main document, in which
+% case \texttt{top-level} is used.
+%
+% The effect of \cs{DeclareDefaultHookLabel} holds for the current
+% file, and is reset to the previous value when the file is closed.
+% \end{function}
+%
+%
+% \subsubsection{Defining relations between hook code}
+%
+% The default assumption is that code added to hooks by different
+% packages is independent and the order in which it is executed is
+% irrelevant. While this is true in many case it is obviously false
+% in many others.
+%
+% Before the hook management system was introduced
+% packages had to take elaborate precaution to determine of some other
+% package got loaded as well (before or after) and find some ways to
+% alter its behavior accordingly. In addition is was often the user's
+% responsibility to load packages in the right order so that code
+% added to hooks got added in the right order and some cases even
+% altering the loading order wouldn't resolve the conflicts.
+%
+% With the new hook management system it is now possible to define
+% rules (i.e., relationships) between code chunks added by different
+% packages and explicitly describe in which order they should be
+% processed.
+%
+% \begin{function}{\DeclareHookRule}
+% \begin{syntax}
+% \cs{DeclareHookRule} \Arg{hook}\Arg{label1}\Arg{relation}\Arg{label2}
+% \end{syntax}
+% Defines a relation between \meta{label1} and \meta{label2} for a
+% given \meta{hook}. If \meta{hook} is \texttt{??} this defines a default
+% relation for all hooks that use the two labels, i.e., that have
+% chunks of code labeled with \meta{label1} and \meta{label2}.
+% Rules specific to a given hook take precedence over default
+% rules that use \texttt{??} as the \meta{hook}.
+%
+% Currently, the supported relations are the following:
+% \begin{itemize}
+%
+% \item[\texttt{before} or \texttt{\string<}]
+%
+% Code for \meta{label1} comes before code for \meta{label2}.
+%
+% \item[\texttt{after} or \texttt{\string>}]
+% Code for \meta{label1} comes after code for \meta{label2}.
+%
+% \item[\texttt{incompatible-warning}]
+%
+% Only code for either \meta{label1} or \meta{label2} can appear
+% for that hook (a way to say that two packages---or parts of
+% them---are incompatible). A warning is raised if both labels
+% appear in the same hook.
+%
+% \item[\texttt{incompatible-error}]
+%
+% Like \texttt{incompatible-error} but instead of a warning a
+% \LaTeX{} error is raised, and the code for both labels are
+% dropped from that hook until the conflict is resolved.
+%
+% \item[\texttt{voids}]
+%
+% Code for \meta{label1} overwrites code for \meta{label2}. More
+% precisely, code for \meta{label2} is dropped for that
+% hook. This can be used, for example if one package is a
+% superset in functionality of another one and therefore wants to
+% undo code in some hook and replace it with its own version.
+%
+% \item[\texttt{unrelated}]
+%
+% The order of code for \meta{label1} and \meta{label2} is
+% irrelevant. This rule is there to undo an incorrect rule
+% specified earlier.
+%
+% \end{itemize}
+% There can only be a single relation between two labels for a
+% given hook,
+% i.e., a later \cs{DeclareHookrule} overwrites any previous
+% delcaration.
+%
+% The \meta{hook} and \meta{label} can be specified using the
+% dot-syntax to denote the current package name.
+% See section~\ref{sec:default-label}.
+%
+% \end{function}
+%
+%
+% \begin{function}{\ClearHookRule}
+% \begin{syntax}
+% \cs{ClearHookRule}\Arg{hook}\Arg{label1}\Arg{label2}
+% \end{syntax}
+% Syntactic sugar for saying that \meta{label1} and \meta{label2}
+% are unrelated for the given \meta{hook}.
+% \end{function}
+%
+%
+%
+% \begin{function}{\DeclareDefaultHookRule}
+% \begin{syntax}
+% \cs{DeclareDefaultHookRule}\Arg{label1}\Arg{relation}\Arg{label2}
+% \end{syntax}
+% This sets up a relation between \meta{label1} and \meta{label2}
+% for all hooks unless overwritten by a specific rule for a hook.
+% Useful for cases where one package has a specific relation to
+% some other package, e.g., is \texttt{incompatible} or always
+% needs a special ordering \texttt{before} or \texttt{after}.
+% (Technically it is just a shorthand for using \cs{DeclareHookRule}
+% with \texttt{??} as the hook name.)
+%
+% Declaring default rules is only supported in the document
+% preamble.\footnotemark{}
+%
+% The \meta{label} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% \end{function}\footnotetext{Trying to do so, e.g., via
+% \cs{DeclareHookRule} with \texttt{??} has bad side-effects and
+% is not supported (though not explicitly caught for performance
+% reasons).}
+%
+%
+%
+% \subsubsection{Querying hooks}
+% \label{sec:querying}
+%
+% Simpler data types, like token lists, have three possible states; they
+% can:
+% \begin{itemize}
+% \item exist and be empty;
+% \item exist and be non-empty; and
+% \item not exist (in which case emptiness doesn't apply);
+% \end{itemize}
+% Hooks are a bit more complicated: they have four possible states.
+% A hook may exist or not, and either way it may or may not be empty.
+% This means that even a hook that doesn't exist may be non-empty.
+%
+% This seemingly strange state may happen when, for example, package~$A$
+% defines hook \hook{A/foo}, and package $B$ adds some code to that
+% hook. However, a document may load package $B$ before package $A$, or
+% may not load package $A$ at all. In both cases some code is added to
+% hook \hook{A/foo} without that hook being defined yet, thus that
+% hook is said to be non-empty, whereas it doesn't exist. Therefore,
+% querying the existence of a hook doesn't imply its emptiness, neither
+% does the other way around.
+%
+% A hook is said to be empty when no code was added to it, either to
+% its permanent code pool, or to its ``next'' token list. The hook
+% doesn't need to be declared to have code added to its code pool.
+% A hook is said to exist when it was declared with \cs{NewHook} or
+% some variant thereof.
+%
+% \begin{function}[EXP]{\IfHookEmptyTF}
+% \begin{syntax}
+% \cs{IfHookEmptyTF} \Arg{hook} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the \meta{hook} is empty (\emph{i.e.}, no code was added to
+% it using either \cs{AddToHook} or \cs{AddToHookNext}), and
+% branches to either \meta{true code} or \meta{false code} depending
+% on the result.
+%
+% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
+% A leading |.| is treated literally.
+% \end{function}
+%
+% \begin{function}[EXP]{\IfHookExistsTF}
+% \begin{syntax}
+% \cs{IfHookExistsTF} \Arg{hook} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the \meta{hook} exists (if it was created with either
+% \cs{NewHook}, \cs{NewReversedHook}, or \cs{NewMirroredHookPair}), and
+% branches to either \meta{true code} or \meta{false code} depending
+% on the result.
+%
+% The existence of a hook usually doesn't mean much from the viewpoint
+% of code that tries to add/remove code from that hook, since package
+% loading order may vary, thus the creation of hooks is asynchronous
+% to adding and removing code from it, so this test should be used
+% sparingly.
+%
+% Generic hooks are declared at the time code is added to them, so the
+% result of \cs{hook_if_exist:n} will change once code is added to
+% said hook (unless the hook was previously declared).
+%
+% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
+% A leading |.| is treated literally.
+% \end{function}
+%
+% \fmi{Would be helpful if we provide some use cases}
+%
+% \subsubsection{Displaying hook code}
+%
+% If one has to adjust the code execution in a hook using a hook
+% rule it is helpful to get some information about the code
+% associated with a hook, its current order and the existing rules.
+%
+% \begin{function}{\ShowHook,\LogHook}
+% \begin{syntax}
+% \cs{ShowHook} \Arg{hook}
+% \end{syntax}
+% Displays information about the \meta{hook} such as
+% \begin{itemize}
+% \item
+% the code chunks (and their labels) added to it,
+% \item
+% any rules set up to order them,
+% \item
+% the computed order in which the chunks are executed,
+% \item
+% any code executed on the next invocation only.
+% \end{itemize}
+%
+% \cs{LogHook} prints the information to the |.log| file, and
+% \cs{ShowHook} prints them to the terminal/command window and starts
+% \TeX's prompt (only if \cs{errorstopmode}) to wait for user action.
+%
+% The \meta{hook} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% \end{function}
+%
+%
+% \subsubsection{Debugging hook code}
+%
+% \begin{function}{\DebugHooksOn,\DebugHooksOff}
+% \begin{syntax}
+% \cs{DebugHooksOn}
+% \end{syntax}
+% Turn the debugging of hook code on or off. This displays changes
+% made to the hook data structures. The output is rather coarse and
+% not really intended for normal use.
+% \end{function}
+%
+%
+% \subsection{L3 programming layer (\texttt{expl3}) interfaces}
+% \label{sec:l3hook-interface}
+%
+%
+% This is a quick summary of the \LaTeX3 programming interfaces for
+% use with packages written in \texttt{expl3}. In contrast to the
+% \LaTeXe{} interfaces they always use mandatory arguments only, e.g.,
+% you always have to specify the \meta{label} for a code chunk. We
+% therefore suggest to use the declarations discussed in the previous
+% section even in \texttt{expl3} packages, but the choice is yours.
+%
+%
+% \begin{function}
+% {\hook_new:n,\hook_new_reversed:n,\hook_new_pair:nn}
+% \begin{syntax}
+% \cs{hook_new:n}\Arg{hook}
+% \cs{hook_new_pair:nn}\Arg{hook-1}\Arg{hook-2}
+% \end{syntax}
+% Creates a new \meta{hook} with normal or reverse ordering of code
+% chunks. \cs{hook_new_pair:nn} creates a pair of such hooks with
+% \Arg{hook-2} being a reversed hook.
+% If a hook name is already taken, an error is raised and the hook
+% is not created.
+%
+% The \meta{hook} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% \end{function}
+%
+%
+%
+% \begin{function}{\hook_use:n}
+% \begin{syntax}
+% \cs{hook_use:n} \Arg{hook}
+% \end{syntax}
+% Executes the \Arg{hook} code followed (if set up) by the code for next
+% invocation only, then empties that next invocation code.
+%
+% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
+% A leading |.| is treated literally.
+% \end{function}
+%
+% \begin{function}{\hook_use_once:n}
+% \begin{syntax}
+% \cs{hook_use_once:n} \Arg{hook}
+% \end{syntax}
+% Changes the \Arg{hook} status so that from now on any addition to
+% the hook code is executed immediately. Then execute any
+% \Arg{hook} code already set up.
+% \fmi{better L3 name?}
+%
+% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
+% A leading |.| is treated literally.
+% \end{function}
+%
+% \begin{function}{\hook_gput_code:nnn}
+% \begin{syntax}
+% \cs{hook_gput_code:nnn} \Arg{hook} \Arg{label} \Arg{code}
+% \end{syntax}
+% Adds a chunk of \meta{code} to the \meta{hook} labeled
+% \meta{label}. If the label already exists the \meta{code} is
+% appended to the already existing code.
+%
+% If code is added to an external \meta{hook} (of the kernel or
+% another package) then the convention is to use the package name
+% as the \meta{label} not some internal module name or some other
+% arbitrary string.
+%
+% The \meta{hook} and \meta{label} can be specified using the
+% dot-syntax to denote the current package name.
+% See section~\ref{sec:default-label}.
+% \end{function}
+%
+% \begin{function}
+% {\hook_gput_next_code:nn}
+% \begin{syntax}
+% \cs{hook_gput_next_code:nn} \Arg{hook} \Arg{code}
+% \end{syntax}
+% Adds a chunk of \meta{code} for use only in the next invocation of the
+% \meta{hook}. Once used it is gone.
+%
+% This is simpler than \cs{hook_gput_code:nnn}, the code is simply
+% appended to the hook in the order of declaration at the very end,
+% i.e., after all standard code for the hook got executed.
+%
+% Thus if one needs to undo what the standard does one has to do
+% that as part of \meta{code}.
+%
+% The \meta{hook} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% \end{function}
+%
+%
+%
+% \begin{function}{\hook_gremove_code:nn}
+% \begin{syntax}
+% \cs{hook_gremove_code:nn} \Arg{hook} \Arg{label}
+% \end{syntax}
+% Removes any code for \meta{hook} labeled \meta{label}.
+%
+% If the code for that \meta{label} wasn't yet added to the
+% \meta{hook}, an order is set so that when some code attempts to add
+% that label, the removal order takes action and the code is not
+% added.
+%
+% If the second argument is \texttt{*}, then all code chunks are
+% removed. This is rather dangerous as it drops code from other
+% packages one may not know about, so think twice before using
+% that!
+%
+% The \meta{hook} and \meta{label} can be specified using the
+% dot-syntax to denote the current package name.
+% See section~\ref{sec:default-label}.
+% \end{function}
+%
+%
+% \begin{function}{\hook_gset_rule:nnnn}
+% \begin{syntax}
+% \cs{hook_gset_rule:nnnn} \Arg{hook} \Arg{label1} \Arg{relation} \Arg{label2}
+% \end{syntax}
+% Relate \meta{label1} with \meta{label2} when used in \meta{hook}.
+% See \cs{DeclareHookRule} for the allowed \meta{relation}s.
+% If \meta{hook} is \texttt{??} a default rule is specified.
+%
+% The \meta{hook} and \meta{label} can be specified using the
+% dot-syntax to denote the current package name.
+% See section~\ref{sec:default-label}.
+% The dot-syntax is parsed in both \meta{label} arguments, but it
+% usually makes sense to be used in only one of them.
+% \end{function}
+%
+% \begin{function}[pTF]{\hook_if_empty:n}
+% \begin{syntax}
+% \cs{hook_if_empty:nTF} \Arg{hook} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the \meta{hook} is empty (\emph{i.e.}, no code was added to
+% it using either \cs{AddToHook} or \cs{AddToHookNext}), and
+% branches to either \meta{true code} or \meta{false code} depending
+% on the result.
+%
+% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
+% A leading |.| is treated literally.
+% \end{function}
+%
+% \begin{function}[pTF]{\hook_if_exist:n}
+% \begin{syntax}
+% \cs{hook_if_exist:nTF} \Arg{hook} \Arg{true code} \Arg{false code}
+% \end{syntax}
+% Tests if the \meta{hook} exists (if it was created with either
+% \cs{NewHook}, \cs{NewReversedHook}, or \cs{NewMirroredHookPair}), and
+% branches to either \meta{true code} or \meta{false code} depending
+% on the result.
+%
+% The existence of a hook usually doesn't mean much from the viewpoint
+% of code that tries to add/remove code from that hook, since package
+% loading order may vary, thus the creation of hooks is asynchronous
+% to adding and removing code from it, so this test should be used
+% sparingly.
+%
+% Generic hooks are declared at the time code is added to them, so the
+% result of \cs{hook_if_exist:n} will change once code is added to
+% said hook (unless the hook was previously declared).
+%
+% The \meta{hook} \emph{cannot} be specified using the dot-syntax.
+% A leading |.| is treated literally.
+% \end{function}
+%
+% \begin{function}{\hook_show:n,\hook_log:n}
+% \begin{syntax}
+% \cs{hook_show:n} \Arg{hook}
+% \end{syntax}
+% Displays information about the \meta{hook} such as
+% \begin{itemize}
+% \item
+% the code chunks (and their labels) added to it,
+% \item
+% any rules set up to order them,
+% \item
+% the computed order in which the chunks are executed,
+% \item
+% any code executed on the next invocation only.
+% \end{itemize}
+%
+% \cs{hook_log:n} prints the information to the |.log| file, and
+% \cs{hook_show:n} prints them to the terminal/command window and starts
+% \TeX's prompt (only if \cs{errorstopmode}) to wait for user action.
+%
+% The \meta{hook} can be specified using the dot-syntax to denote
+% the current package name. See section~\ref{sec:default-label}.
+% \end{function}
+%
+% \begin{function}{\hook_debug_on:,\hook_debug_off:}
+% \begin{syntax}
+% \cs{hook_debug_on:}
+% \end{syntax}
+% Turns the debugging of hook code on or off. This displays changes
+% to the hook data.
+% \end{function}
+%
+%
+%
+% \subsection{On the order of hook code execution} \label{sec:order}
+%
+% Chunks of code for a \meta{hook} under different labels are supposed
+% to be independent if there are no special rules set up that
+% define a relation between the chunks. This means that you can't
+% make assumptions about the order of execution!
+%
+% Suppose you have the following declarations:
+%\begin{verbatim}
+% \NewHook{myhook}
+% \AddToHook{myhook}[packageA]{\typeout{A}}
+% \AddToHook{myhook}[packageB]{\typeout{B}}
+% \AddToHook{myhook}[packageC]{\typeout{C}}
+%\end{verbatim}
+% then executing the hook with \cs{UseHook} will produce the
+% typeout \texttt{A} \texttt{B} \texttt{C} in that order. In other
+% words, the execution order is computed to be \texttt{packageA},
+% \texttt{packageB}, \texttt{packageC} which you can verify with
+% \cs{ShowHook}\texttt{\{myhook\}}:
+%\begin{verbatim}
+% The hook 'myhook':
+% Code chunks:
+% packageA -> \typeout {A}
+% packageB -> \typeout {B}
+% packageC -> \typeout {C}
+% Extra code next invocation:
+% ---
+% Rules:
+% ---
+% Execution order:
+% packageA, packageB, packageC
+%\end{verbatim}
+% The reason is that the code chunks are internally saved in a property list
+% and the initial order of such a property list is the order in
+% which key-value pairs got added. However, that is only true if
+% nothing other than adding happens!
+%
+% Suppose, or example, you want to replace the code chunk for
+% \texttt{packageA}, e.g.,
+%\begin{verbatim}
+% \RemoveFromHook{myhook}[packageA]
+% \AddToHook{myhook}[packageA]{\typeout{A alt}}
+%\end{verbatim}
+% then your order becomes \texttt{packageB},
+% \texttt{packageC}, \texttt{packageA} because the label got removed
+% from the property list and then re-added (at its end).
+%
+% While that may not be too surprising, the execution order is
+% also sometimes altered if you add a redundant rule, e.g. if you specify
+%\begin{verbatim}
+% \DeclareHookRule{myhook}{packageA}{before}{packageB}
+%\end{verbatim}
+% instead of the previous lines we get
+%\begin{verbatim}
+% The hook 'myhook':
+% Code chunks:
+% packageA -> \typeout {A}
+% packageB -> \typeout {B}
+% packageC -> \typeout {C}
+% Extra code next invocation:
+% ---
+% Rules:
+% packageA|packageB with relation before
+% Execution order (after applying rules):
+% packageA, packageC, packageB
+%\end{verbatim}
+% As you can see the code chunks are still in the same order, but
+% in the execution order for the labels \texttt{packageB} and
+% \texttt{packageC} have
+% swapped places.
+% The reason is that, with the rule there are two orders that
+% satisfy it, and the algorithm for sorting happened to pick a
+% different one compared to the case without rules (where it
+% doesn't run at all as there is nothing to resolve).
+% Incidentally, if we had instead specified the redundant rule
+%\begin{verbatim}
+% \DeclareHookRule{myhook}{packageB}{before}{label-3}
+%\end{verbatim}
+% the execution order would not have changed.
+%
+% In summary: it is not possible to rely on the order of execution
+% unless there are rules that partially or fully define the order
+% (in which you can rely on them being fulfilled).
+%
+%
+% \subsection{The use of \enquote{reversed} hooks} \label{sec:reversed-order}
+%
+% You may have wondered why you can declare a \enquote{reversed} hook
+% with \cs{NewReversedHook} and what that does exactly.
+%
+% In short: the execution order of a reversed hook (without any
+% rules!) is exactly reversed to the order you would have gotten for
+% a hook declared with \cs{NewHook}.
+%
+% This is helpful if you have a pair of hooks where you expect to see
+% code added that involves grouping, e.g., starting an environment
+% in the first and closing that environment in the second hook.
+% To give a somewhat contrived example\footnote{there are simpler
+% ways to achieve the same effect.}, suppose there is a package
+% adding the following:
+%\begin{verbatim}
+% \AddToHook{env/quote/before}[package-1]{\begin{itshape}}
+% \AddToHook{env/quote/after} [package-1]{\end{itshape}}
+%\end{verbatim}
+% As a result, all quotes will be in italics.
+% Now suppose further that the user wants the quotes also in blue
+% and therefore adds:
+%\begin{verbatim}
+% \usepackage{color}
+% \AddToHook{env/quote/before}{\begin{color}{blue}}
+% \AddToHook{env/quote/after} {\end{color}}
+%\end{verbatim}
+% Now if the \hook{env/quote/after} hook would be a normal hook we
+% would get the same execution order in both hooks, namely:
+%\begin{verbatim}
+% package-1, top-level
+%\end{verbatim}
+% (or vice versa) and as a result, would get:
+%\begin{verbatim}
+% \begin{itshape}\begin{color}{blue} ...
+% \end{itshape}\end{color}
+%\end{verbatim}
+% and an error message that \verb=\begin{color}= ended by
+% \verb=\end{itshape}=.
+% With \hook{env/quote/after} declared as a reversed hook the
+% execution order is reversed and so all environments are closed in
+% the correct sequence and \cs{ShowHook} would give us the
+% following output:
+%\begin{verbatim}
+% The hook 'env/quote/after':
+% Code chunks:
+% package-1 -> \end {itshape}
+% top-level -> \end {color}
+% Extra code next invocation:
+% ---
+% Rules:
+% ---
+% Execution order (after reversal):
+% top-level, package-1
+%\end{verbatim}
+%
+% The reversal of the execution order happens before applying any
+% rules, so if you alter the order you will probably have to alter
+% it in both hooks, not just in one, but that depends on the use case.
+%
+%
+%
+%
+% \subsection{Difference between \enquote{normal} and
+% \enquote{one-time} hooks}
+%
+% When executing a hook a developer has the choice of using
+% either \cs{UseHook} or \cs{UseOneTimeHook} (or their \pkg{expl3}
+% equivalents \cs{hook_use:n} and \cs{hook_use_once:n}).
+% This choice affects how \cs{AddToHook} is handled after the hook
+% has been executed for the first time.
+%
+% With normal hooks adding code via \cs{AddToHook} means that the
+% code chunk is added to the hook data structure and then used each time
+% \cs{UseHook} is called.
+%
+% With one-time hooks it this is handled slightly differently:
+% After \cs{UseOneTimeHook} has been called, any further attempts to
+% add code to the hook via \cs{AddToHook} will simply execute the
+% \meta{code} immediately.
+%
+% This has some consequences one needs to be aware of:
+% \begin{itemize}
+% \item
+%
+% If \meta{code} is added to a normal hook after the hook was
+% executed and it is never executed again for one or the other
+% reason, then this new \meta{code} will never be executed.
+%
+% \item
+%
+% In contrast if that happens with a one-time hook the \meta{code} is
+% executed immediately.
+%
+% \end{itemize}
+% In particular this means that construct such as
+%\begin{quote}
+% \cs{AddToHook}\verb={myhook}=\\
+% \phantom{\cs{AddToHook}}\verb={= \meta{code-1}
+% \cs{AddToHook}\verb={myhook}=\Arg{code-2}
+% \meta{code-3} \verb=}=
+%\end{quote}
+% works for one-time hooks\footnote{This is sometimes used with
+% \cs{AtBeginDocument} which is why it is supported.} (all three
+% code chunks are executed one after another), but it makes little
+% sense with a normal hook, because with a normal hook the first time
+% \verb=\UseHook{myhook}= is executed it would
+% \begin{itemize}
+% \item
+% execute \meta{code-1},
+% \item
+% then execute \verb=\AddToHook{myhook}{code-2}= which adds the
+% code chunk \meta{code-2} to the hook for use on the next invocation,
+% \item
+% and finally execute \meta{code-3}.
+% \end{itemize}
+% The second time \cs{UseHook} is called it would execute the
+% above and in addition \meta{code-2} as that was added as a code
+% chunk to the hook in the meantime. So each time the hook is used
+% another copy of \meta{code-2} is added and so that code chunk
+% is executed $\meta{\# of invocations} -1$ times.
+%
+%
+%
+%
+%
+% \subsection{Private \LaTeX{} kernel hooks}
+%
+% There are a few places where it is absolutely essential for
+% \LaTeX{} to function correctly that code is executed in a precisely
+% defined order. Even that could have been implemented with the
+% hook management (by adding various rules to ensure the
+% appropriate ordering with respect to other code added by
+% packages). However, this makes every document unnecessary
+% slow, because there has to be sorting even through the result is
+% predetermined. Furthermore it forces package writers to
+% unnecessarily add such rules if they add further code to the hook
+% (or break \LaTeX{}).
+%
+% For that reason such code is not using the hook management, but
+% instead private kernel commands directly before or after a public
+% hook with the following naming
+% convention: \cs{@kernel@before@\meta{hookname}} or
+% \cs{@kernel@after@\meta{hookname}}. For example, in
+% \cs{enddocument} you find
+%\begin{verbatim}
+% \UseHook{enddocument}%
+% \@kernel@after@enddocument
+%\end{verbatim}
+% which means first the user/package-accessible \hook{enddocument}
+% hook is executed and then the internal kernel hook. As their name
+% indicates these kernel commands should not be altered by third-party
+% packages, so please refrain from that in the interest of
+% stability and instead use the public hook next to it.\footnote{As
+% with everything in \TeX{} there is not enforcement of this rule,
+% and by looking at the code it is easy to find out how the kernel
+% adds to them. The main reason of this section is therefore to say
+% \enquote{please don't do that, this is unconfigurable code!}}
+%
+%
+%
+% \subsection{Legacy \LaTeXe{} interfaces}
+%
+% \LaTeXe{} offered a small number of hooks together with commands to
+% add to them. They are listed here and are retained for backwards
+% compatibility.
+%
+% With the new hook management several additional hooks have been added
+% to \LaTeX\ and more will follow. See the next section for what
+% is already available.
+%
+%
+% \begin{function}{\AtBeginDocument}
+% \begin{syntax}
+% \cs{AtBeginDocument} \oarg{label} \Arg{code}
+% \end{syntax}
+% If used without the optional argument \meta{label}, it works essentially
+% like before, i.e., it is adding \meta{code} to the hook
+% \hook{begindocument}
+% (which is executed inside \verb=\begin{document}=).
+% However, all code added this way is labeled with the label
+% \hook{top-level} if done outside of a package or class or with the
+% package/class name if called inside such a file.
+%
+% This way one can add further code to the hook using
+% \cs{AddToHook} or \cs{AtBeginDocument} using a different label
+% and explicitly order the code chunks as necessary, e.g., run some
+% code before or after the \hook{top-level} code. When using the
+% optional argument the call is equivalent to running
+% \cs{AddToHook} \texttt{\{begindocument\}} \oarg{label}
+% \Arg{code}.
+%
+% For important packages with known order requirement we may over
+% time add rules to the kernel (or to those packages) so that they
+% work regardless of the loading-order in the document.
+% \end{function}
+%
+% \begin{function}{\AtEndDocument}
+% \begin{syntax}
+% \cs{AtEndDocument} \oarg{label} \Arg{code}
+% \end{syntax}
+% Like \cs{AtBeginDocument} but for the \hook{enddocument} hook.
+% \end{function}
+%
+%
+%
+% \begin{function}{\AtBeginDvi}
+% \begin{syntax}
+% \cs{AtBeginDvi} \oarg{label} \Arg{code}
+% \end{syntax}
+% This hook is discussed in conjunction with the shipout hooks.
+% \end{function}
+%
+% \bigskip
+%
+% The few hooks that existed previously in \LaTeXe{} used internally
+% commands such as \cs{@begindocumenthook} and packages sometimes
+% augemented them directly rather than working through
+% \cs{AtBeginDocumement}. For that reason there is currently support
+% for this, that is, if the system detects that such an internal
+% legacy hook command contains code it adds it to the new hook
+% system under the label \texttt{legacy} so that it doesn't get
+% lost.
+%
+% However, over time the remaining cases of direct usage need
+% updating because in one of the future release of \LaTeX{} we will
+% turn this legacy support off, as it does unnecessary slow down
+% the processing.
+%
+%
+% \subsection{\LaTeXe{} commands and environments augmented by
+% hooks}
+%
+% \emph{intro to be written}
+%
+% \subsubsection{Generic hooks for all environments}
+%
+% Every environment \meta{env} has now four associated hooks coming
+% with it:
+% \begin{description}
+% \item[\hook{env/\meta{env}/before}]
+%
+% This hook is executed as part of \cs{begin} as the very first
+% action, in particular prior to starting the environment group.
+% Its scope is therefore not restricted by the environment.
+%
+% \item[\hook{env/\meta{env}/begin}]
+%
+% This hook is executed as part of \cs{begin} directly in front
+% of the code specific to the environment start (e.g., the
+% second argument of \cs{newenvironment}). Its scope is the
+% environment body.
+%
+% \item[\hook{env/\meta{env}/end}]
+%
+% This hook is executed as part of \cs{end} directly in front of the
+% code specific to the end of the environment (e.g., the third
+% argument of \cs{newenvironment}).
+%
+% \item[\hook{env/\meta{env}/after}]
+%
+% This hook is executed as part of \cs{end} after the
+% code specific to the environment end and after the environment
+% group has ended.
+% Its scope is therefore not restricted by the environment.
+%
+% The hook is implemented as a reversed hook so if two packages
+% add code to \hook{env/\meta{env}/before} and to
+% \hook{env/\meta{env}/after} they can add surrounding
+% environments and the order of closing them happens in the
+% right sequence.
+%
+% \end{description}
+% Generic environment hooks are never one-time hooks even with
+% environments that are supposed to appear only once in a
+% document.\footnote{Thus if one adds code to such hooks after the
+% environment has been processed, it will only be executed if the
+% environment appears again and if that doesn't happen the code
+% will never get executed.} In contrast to other hooks there is
+% also no need to declare them using \cs{NewHook}.
+%
+% The hooks are only executed if \cs{begin}\Arg{env} and
+% \cs{end}\Arg{env} is used. If the environment code is executed
+% via low-level calls to \cs{\meta{env}} and \cs{end\meta{env}}
+% (e.g., to avoid the environment grouping) they are not
+% available. If you want them available in code using this method,
+% you would need to add them yourself, i.e., write something like
+%\begin{verbatim}
+% \UseHook{env/quote/before}\quote
+% ...
+% \endquote\UseHook{env/quote/after}
+%\end{verbatim}
+% to add the outer hooks, etc.
+%
+%
+% \begin{function}{\BeforeBeginEnvironment}
+% \begin{syntax}
+% \cs{BeforeBeginEnvironment} \oarg{label} \Arg{code}
+% \end{syntax}
+% This declaration adds to the \hook{env/\meta{env}/before} hook
+% using by default the current package or class name as a label or
+% \texttt{top-level} if used in the document directly.
+% \end{function}
+%
+% \begin{function}{\AtBeginEnvironment}
+% \begin{syntax}
+% \cs{AtBeginEnvironment} \oarg{label} \Arg{code}
+% \end{syntax}
+% Like \cs{BeforeBeginEnvironment} but adds to the \hook{env/\meta{env}/begin} hook.
+% \end{function}
+%
+% \begin{function}{\AtEndEnvironment}
+% \begin{syntax}
+% \cs{AtEndEnvironment} \oarg{label} \Arg{code}
+% \end{syntax}
+% Like \cs{BeforeBeginEnvironment} but adds to the \hook{env/\meta{env}/end} hook.
+% \end{function}
+%
+% \begin{function}{\AfterEndEnvironment}
+% \begin{syntax}
+% \cs{AfterEndEnvironment} \oarg{label} \Arg{code}
+% \end{syntax}
+% Like \cs{BeforeBeginEnvironment} but adds to the \hook{env/\meta{env}/after} hook.
+% \end{function}
+%
+%
+%
+%
+% \subsubsection{Hooks provided by \cs{begin}\texttt{\{document\}}}
+%
+% Until 2020 \cs{begin}\texttt{\{document\}} offered exactly one
+% hook that one could add to using
+% \cs{AtBeginDocument}. Experiences over the years have shown that
+% this single hook in one place was not enough and as part of
+% adding the general hook management system a number of additional
+% hooks have been added at this point. The places for these hooks have
+% been chosen to provide the same support as offered by external
+% packages, such as \pkg{etoolbox} and others that augmented
+% \cs{document} to gain better control.
+%
+% Supported are now the following hooks (all of them one-time hooks):
+% \begin{description}
+%
+%
+% \item[\hook{begindocument/before}]
+%
+% This hook is executed at the very start of \cs{document}, one can
+% think of it as a hook for code at the end of the preamble
+% section and this is how it is used by \pkg{etoolbox}'s
+% \cs{AtEndPreamble}.
+%
+%
+%
+% \item[\hook{begindocument}]
+%
+% This hook is added to when using \cs{AtBeginDocument} and it is executed
+% after the \texttt{.aux} file as be read in and most
+% initialization are done, so they can be altered and inspected by
+% the hook code. It is followed by a small number of further
+% initializations that shouldn't be altered and are therefore
+% coming later.
+%
+% The hook should not be used to add material for typesetting as
+% we are still in \LaTeX's initialization phase and not in the
+% document body. If such material needs to be added to the document
+% body use the next hook instead.
+%
+% \item[\hook{begindocument/end}]
+%
+% This hook is executed at the end of the \cs{document} code in
+% other words at the beginning of the document body. The only
+% command that follows it is \cs{ignorespaces}.
+%
+% \end{description}
+% The generic hooks executed by \cs{begin} also exist, i.e.,
+% \hook{env/document/before} and \hook{env/document/begin}, but
+% with this special environment it is better use the dedicated
+% one-time hooks above.
+%
+%
+%
+%
+% \subsubsection{Hooks provided by \cs{end}\texttt{\{document\}}}
+%
+% \LaTeXe{} always provided \cs{AtEndDocument} to add code to the
+% execution of \verb=\end{document}= just in front of the code that
+% is normally executed there. While this was a big improvement over
+% the situation in \LaTeX\,2.09 it was not flexible enough for a
+% number of use cases and so packages, such as \pkg{etoolbox},
+% \pkg{atveryend} and others patched \cs{enddocument} to add
+% additional points where code could be hooked into.
+%
+% Patching using packages is always problematical as leads to
+% conflicts (code availability, ordering of patches, incompatible
+% patches, etc.). For this reason a number of additional hooks
+% have been added to the \cs{enddocument} code to allow packages
+% to add code in various places in a controlled way without the
+% need for overwriting or patching the core code.
+%
+% Supported are now the following hooks (all of them one-time hooks):
+% \begin{description}
+%
+% \item[\hook{enddocument}]
+%
+% The hook associated with \cs{AtEndDocument}. It is immediately
+% called at the beginning of \cs{enddocument}.
+%
+% When this hook is executed there may be still unprocessed
+% material (e.g., floats on the deferlist) and the hook may add
+% further material to be typeset. After it, \cs{clearpage} is
+% called to ensure that all such material gets typeset. If there
+% is nothing waiting the \cs{clearpage} has no effect.
+%
+%
+% \item[\hook{enddocument/afterlastpage}]
+%
+% As the name indicates this hook should not receive code that
+% generates material for further pages. It is the right place to
+% do some final housekeeping and possibly write out some
+% information to the \texttt{.aux} file (which is still open at
+% this point to receive data). It is also the correct place to
+% set up any testing code to be run when the \texttt{.aux} file
+% is re-read in the next step.
+%
+%
+% After this hook has been executed the \texttt{.aux} file is
+% closed for writing and then read back in to do some tests
+% (e.g., looking for missing references or duplicated labels, etc.).
+%
+% \item[\hook{enddocument/afteraux}]
+%
+% At this point, the \texttt{.aux} file has been reprocessed and so
+% this is a possible place for final checks and display of
+% information to the user. However, for the latter you might
+% prefer the next hook, so that your information is displayed after the
+% (possibly longish) list of files if that got requested via \cs{listfiles}.
+%
+% \item[\hook{enddocument/info}]
+%
+% This hook is meant to receive code that write final information
+% messages to the terminal. It follows immediately after the
+% previous hook (so both could have been combined, but then
+% packages adding further code would always need to also supply
+% an explicit rule to specify where it should go.
+%
+% This hook already contains some code added by the kernel (under
+% the labels \texttt{kernel/filelist} and
+% \texttt{kernel/warnings}), namely the list of files when
+% \cs{listfiles} has been used and the warnings for duplicate
+% labels, missing references, font substitutions etc.
+%
+% \item[\hook{enddocument/end}]
+%
+% Finally, this hook is executed just in front of the final call
+% to \cs{@{}@end}.
+%
+% \end{description}
+%
+%
+% There is also the hook \hook{shipout/lastpage}. This hook is
+% executed as part of the last \cs{shipout} in the document to
+% allow package to add final \cs{special}'s to that page. Where
+% this hook is executed in relation to those from the above list
+% can vary from document to document. Furthermore to determine correctly
+% which of the \cs{shipout}s is the last one, \LaTeX{} needs to be run
+% several times, so initially it might get executed on the wrong
+% page. See section~\ref{sec:shipout} for where to find the details.
+%
+%
+% It is in also possible to use the generic \hook{env/document/end}
+% hook which is execuded by \cs{end}, i.e., just in front of the
+% first hook above. Note however that the other generic \cs{end}
+% environment hook, i.e., \hook{env/document/after} will never get
+% executed, because by that time \LaTeX{} has finished the document
+% processing.
+%
+%
+%
+%
+% \subsubsection{Hooks provided \cs{shipout} operations}
+% \label{sec:shipout}
+%
+% There are several hooks and mechanisms added to \LaTeX{}'s
+% process of generating pages. These are documented in
+% \texttt{ltshipout-doc.pdf} or with code in
+% \texttt{ltshipout-code.pdf}.
+%
+%
+% \subsubsection{Hooks provided by file loading operations}
+%
+% There are several hooks added to \LaTeX{}'s
+% process of loading file via its high-level interfaces such as
+% \cs{input}, \cs{include}, \cs{usepackage}, etc. These are documented in
+% \texttt{ltfilehook-doc.pdf} or with code in
+% \texttt{ltfilehook-code.pdf}.
+%
+%
+% \subsubsection{Hooks provided in NFSS commands}
+%
+% In languages that need to support for more than one script in
+% parallel (and thus several sets of fonts), e.g., Latin and
+% Japanese fonts, NFSS font commands, such as \cs{sffamily}, need
+% to switch both the Latin family to ``Sans Serif'' and in addition
+% alter a second set of fonts.
+%
+% To support this several NFSS have hooks in which such support can
+% be added.
+% \begin{description}
+%
+% \item[\hook{rmfamily}]
+%
+% After \cs{rmfamily} has done its initial checks and prepared a
+% any font series update this hook is executed and only
+% afterwards \cs{selectfont}.
+%
+% \item[\hook{sffamily}]
+%
+% Like the \hook{rmfamily} hook but for the \cs{sffamily} command.
+%
+% \item[\hook{ttfamily}]
+%
+% Like the \hook{rmfamily} hook but for the \cs{ttfamily} command.
+%
+% \item[\hook{normalfont}]
+%
+% The \cs{normalfont} command resets font encoding family series
+% and shape to their document defaults. It then executes this
+% hook and finally calls \cs{selectfont}.
+%
+% \item[\hook{expand@font@defaults}]
+%
+% The internal \cs{expand@font@defaults} command expands and
+% saves the current defaults for the meta families (rm/sf/tt) and
+% the meta series (bf/md). If the NFSS machinery has been
+% augmented, e.g., for Chinese or Japanese fonts, then further
+% defaults may need to be set at this point. This can be done in
+% this hook which is executed at the end of this macro.
+%
+% \item[\hook{bfseries/defaults}, \hook{bfseries}]
+%
+% If the \cs{bfdefault} was explicitly changed by the user its
+% new value is used to set the bf series defaults for the meta
+% families (rm/sf/tt) when \cs{bfseries} is called. In the
+% \hook{bfseries/defaults} hook further adjustments can be made
+% in this case. This hook is only executed if such a change is
+% detected. In contrast the \hook{bfseries} hook is always
+% executed just before \cs{selectfont} is called to change to the
+% new series.
+%
+%
+% \item[\hook{mdseries/defaults}, \hook{mdseries}]
+%
+% These two hooks are like the previous ones but used in
+% \cs{mdseries} command.
+%
+% \end{description}
+%
+%
+% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex }
+%
+%
+% \section{The Implementation}
+%
+%
+% \subsection{Loading further extensions}
+%
+% \begin{macrocode}
+%<@@=hook>
+% \end{macrocode}
+%
+%
+% At the moment the whole module rolls back in one go, but if we
+% make any modifications in later releases this will then need
+% splitting.
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\NewHook}{The hook management}%
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+% \end{macrocode}
+%
+%
+% \subsection{Debugging}
+%
+% \begin{macro}{\g_@@_debug_bool}
+% Holds the current debugging state.
+% \begin{macrocode}
+\bool_new:N \g_@@_debug_bool
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hook_debug_on:,\hook_debug_off:}
+% \begin{macro}{\@@_debug:n}
+% \begin{macro}{\@@_debug_gset:}
+% Turns debugging on and off by redefining \cs{@@_debug:n}.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_debug:n \use_none:n
+\cs_new_protected:Npn \hook_debug_on:
+ {
+ \bool_gset_true:N \g_@@_debug_bool
+ \@@_debug_gset:
+ }
+\cs_new_protected:Npn \hook_debug_off:
+ {
+ \bool_gset_false:N \g_@@_debug_bool
+ \@@_debug_gset:
+ }
+\cs_new_protected:Npn \@@_debug_gset:
+ {
+ \cs_gset_protected:Npx \@@_debug:n ##1
+ { \bool_if:NT \g_@@_debug_bool {##1} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+% \subsection{Borrowing from internals of other kernel modules}
+%
+%
+% \begin{macro}[EXP]{\@@_str_compare:nn}
+% Private copy of \cs{__str_if_eq:nn}
+% \begin{macrocode}
+\cs_new_eq:NN \@@_str_compare:nn \__str_if_eq:nn
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Declarations}
+%
+% \begin{macro}{\l_@@_tmpa_bool}
+% Scratch boolean used throughout the package.
+% \begin{macrocode}
+\bool_new:N \l_@@_tmpa_bool
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_@@_return_tl,\l_@@_tmpa_tl,\l_@@_tmpb_tl}
+% Scratch variables used throughout the package.
+% \begin{macrocode}
+\tl_new:N \l_@@_return_tl
+\tl_new:N \l_@@_tmpa_tl
+\tl_new:N \l_@@_tmpb_tl
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_all_seq}
+% In a few places we need a list of all hook names ever defined so
+% we keep track if them in this sequence.
+% \begin{macrocode}
+\seq_new:N \g_@@_all_seq
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_removal_list_prop}
+% A token list to hold delayed removals.
+% \begin{macrocode}
+\tl_new:N \g_@@_removal_list_tl
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_@@_cur_hook_tl}
+% Stores the name of the hook currently being sorted.
+% \begin{macrocode}
+\tl_new:N \l_@@_cur_hook_tl
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_@@_work_prop}
+% A property list holding a copy of the
+% \cs[no-index]{g_@@_\meta{hook}_code_prop} of the hook being sorted
+% to work on, so that changes don't act destructively on the hook data
+% structure.
+% \begin{macrocode}
+\prop_new:N \l_@@_work_prop
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_execute_immediately_prop}
+% List of hooks that from no on should not longer receive code.
+% \begin{macrocode}
+\prop_new:N \g_@@_execute_immediately_prop
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_used_prop}
+% All hooks that receive code (for use in debugging display).
+% \begin{macrocode}
+\prop_new:N \g_@@_used_prop
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_hook_curr_name_tl,\g_@@_name_stack_seq}
+% Default label used for hook commands, and a stack to keep track of
+% packages within packages.
+% \begin{macrocode}
+\tl_new:N \g_@@_hook_curr_name_tl
+\seq_new:N \g_@@_name_stack_seq
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_tmp:w}
+% Temporary macro for generic usage.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_tmp:w ?
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\tl_gremove_once:Nx,\tl_show:x,\tl_log:x}
+% Some variants of \pkg{expl3} functions. \fmi{should be moved to expl3}
+% \begin{macrocode}
+\cs_generate_variant:Nn \tl_gremove_once:Nn { Nx }
+\cs_generate_variant:Nn \tl_show:n { x }
+\cs_generate_variant:Nn \tl_log:n { x }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\s_@@_mark}
+% Scan mark used for delimited arguments.
+% \begin{macrocode}
+\scan_new:N \s_@@_mark
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Providing new hooks}
+%
+% \begin{macro}{\g_@@_..._code_prop,\@@~...,\@@_next~...}
+%
+% Hooks have a \meta{name} and for each hook we have to provide a number of
+% data structures. These are
+% \begin{description}
+% \item[\cs{g_@@_\meta{name}_code_prop}] A property list holding the code
+% for the hook in separate chunks. The keys are by default the
+% package names that add code to the hook, but it is possible
+% for packages to define other keys.
+%
+% \item[{\cs[no-index]{g_@@_\meta{name}_rule_\meta{label1}\string|\meta{label2}_tl}}]
+% A token list holding the relation between \meta{label1} and
+% \meta{label2} in the \meta{name}. The \meta{labels} are lexically
+% (reverse) sorted to ensure that two labels always point to the same
+% token list. For global rules, the \meta{name} is |??|.
+%
+% \item[\cs{@@~\meta{name}}] The code that is actually executed
+% when the hook is called in the document is stored in this token
+% list. It is constructed from the code chunks applying the
+% information.
+% This token list is named like that so that in case of an error
+% inside the hook, the reported token list in the error is shorter,
+% and to make it simpler to normalize hook names in
+% \cs{@@_make_name:n}.
+%
+% \item[\cs{g_@@_\meta{name}_reversed_tl}] Some hooks are
+% \enquote{reversed}. This token list stores a |-| for such hook
+% so that it can be identified. The |-| character is used because
+% $\meta{reversed}1$ is $+1$ for normal hooks and $-1$ for reversed
+% ones.
+%
+% \item[\cs{@@_next~\meta{name}}] Finally there is extra code
+% (normally empty) that is used on the next invocation of the hook
+% (and then deleted). This can be used to define some special
+% behavior for a single occasion from within the document. This token
+% list follows the same naming scheme than the main \cs{@@~\meta{name}}
+% token list. It is called \cs{@@_next~\meta{name}} rather than
+% \cs{@@~next_\meta{name}} because otherwise a hook whose name is
+% |next_|\meta{name} would clash with the next code-token list of the
+% hook called \meta{name}.
+%
+% \end{description}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\hook_new:n}
+% The \cs{hook_new:n} declaration declare a new hook and expects
+% the hook \meta{name} as its argument, e.g.,
+% \hook{begindocument}.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_new:n #1
+ { \@@_normalize_hook_args:Nn \@@_new:n {#1} }
+\cs_new_protected:Npn \@@_new:n #1
+ {
+% \end{macrocode}
+% We check for one of the internal data structures and if it
+% already exists we complain.
+% \begin{macrocode}
+ \hook_if_exist:nTF {#1}
+ { \msg_error:nnn { hooks } { exists } {#1} }
+% \end{macrocode}
+% Otherwise we add the hook name to the list of all hooks and
+% allocate the necessary data structures for the new hook.
+% \begin{macrocode}
+ {
+ \seq_gput_right:Nn \g_@@_all_seq {#1}
+% \end{macrocode}
+% This is only used by the actual code of the current hook, so
+% declare it normally:
+% \begin{macrocode}
+ \tl_new:c { @@~#1 }
+% \end{macrocode}
+% Now ensure that the base data structure for the hook exists:
+% \begin{macrocode}
+ \@@_declare:n {#1}
+% \end{macrocode}
+% The \cs{g_@@_\meta{hook}_labels_clist} holds the sorted list of
+% labels (once it got sorted). This is used only for debugging.
+% \begin{macrocode}
+ \clist_new:c {g_@@_#1_labels_clist}
+% \end{macrocode}
+% Some hooks should reverse the default order of code chunks. To
+% signal this we have a token list which is empty for normal hooks
+% and contains a \verb=-= for reversed hooks.
+% \begin{macrocode}
+ \tl_new:c { g_@@_#1_reversed_tl }
+% \end{macrocode}
+% The above is all in L3 convention, but we also provide an
+% interface to legacy \LaTeXe{} hooks of the form \cs{@...hook},
+% e.g., \cs{@begindocumenthook}.
+% there have been a few of them and they have been added to
+% using \cs{g@addto@macro}. If there exists such a macro matching
+% the name of the new hook, i.e.,
+% \verb+\@+\meta{hook-name}\texttt{hook} and it is not empty then
+% we add its contents as a code chunk under the label \texttt{legacy}.
+% \begin{quote}
+% \textbf{Warning: this support will vanish in future releases!}
+% \end{quote}
+%
+% \begin{macrocode}
+ \@@_include_legacy_code_chunk:n {#1}
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_declare:n}
+% This function declares the basic data structures for a hook without
+% actually declaring the hook itself. This is needed to allow adding
+% to undeclared hooks. Here it is unnecessary to check whether both
+% variables exist, since both are declared at the same time (either
+% both exist, or neither).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_declare:n #1
+ {
+ \@@_if_exist:nF {#1}
+ {
+ \prop_new:c { g_@@_#1_code_prop }
+ \tl_new:c { @@_next~#1 }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\hook_new_reversed:n,\@@_new_reversed:n}
+%
+% Declare a new hook. The default ordering of code chunks is
+% reversed, signaled by setting the token list to a minus sign.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_new_reversed:n #1
+ { \@@_normalize_hook_args:Nn \@@_new_reversed:n {#1} }
+\cs_new_protected:Npn \@@_new_reversed:n #1
+ {
+ \@@_new:n {#1}
+% \end{macrocode}
+% If the hook already exists the above will generate an error
+% message, so the next line should be executed (but it is --- too
+% bad).
+% \begin{macrocode}
+ \tl_gset:cn { g_@@_#1_reversed_tl } { - }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hook_new_pair:nn}
+% A shorthand for declaring a normal and a (matching) reversed hook in one go.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_new_pair:nn #1#2
+ { \hook_new:n {#1} \hook_new_reversed:n {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_include_legacy_code_chunk:n}
+% The \LaTeX{} legacy concept for hooks uses with hooks the
+% following naming scheme in the code: \cs{@...hook}.
+%
+% If this macro is not empty we add it under the label
+% \texttt{legacy} to the current hook and then empty it globally.
+% This way packages or classes directly manipulating commands such
+% as \cs{@begindocumenthook} still get their hook data added.
+% \begin{quote}
+% \textbf{Warning: this support will vanish in future releases!}
+% \end{quote}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_include_legacy_code_chunk:n #1
+ {
+% \end{macrocode}
+% If the \pkg{expl3} code is run with checking on then assigning or
+% using non L3 names such as \cs{@enddocumenthook} with \pkg{expl3}
+% functions will trigger warnings so we run this code with
+% debugging explicitly suspended.
+% \begin{macrocode}
+ \debug_suspend:
+% \end{macrocode}
+% If the macro doesn't exist (which is the usual case) then nothing
+% needs to be done.
+% \begin{macrocode}
+ \tl_if_exist:cT { @#1hook }
+% \end{macrocode}
+% Of course if the legacy hook exists but is empty, there is no need
+% to add anything under \texttt{legacy} the legacy label.
+% \begin{macrocode}
+ {
+ \tl_if_empty:cF { @#1hook }
+ {
+ \exp_args:Nnnv \@@_hook_gput_code_do:nnn {#1}
+ { legacy } { @#1hook }
+% \end{macrocode}
+% Once added to the hook, we need to clear it otherwise it might
+% get added again later if the hook data gets updated.
+% \begin{macrocode}
+ \tl_gclear:c { @#1hook }
+ }
+ }
+ \debug_resume:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \subsection{Parsing a label}
+%
+% \begin{macro}[EXP]{\@@_parse_label_default:n}
+% This macro checks if a label was given (not \cs{c_novalue_tl}), and
+% if so, tries to parse the label looking for a leading \verb|.| to
+% replace for \cs{@currname}. Otherwise \cs{@@_currname_or_default:n}
+% is used to pick \cs{@currname} or the fallback value.
+%
+% The default |top-level| is hard-coded here. It once was an
+% argument, but it's no longer needed. \pho{can't remember why}
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_label_default:n #1
+ {
+ \tl_if_novalue:nTF {#1}
+ { \@@_currname_or_default:n { top-level } }
+ {
+ \tl_trim_spaces_apply:nN {#1}
+ \@@_parse_dot_label:nn { top-level }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_parse_dot_label:nn}
+% \begin{macro}[EXP]{
+% \@@_parse_dot_label:nw,
+% \@@_parse_dot_label_cleanup:w,
+% \@@_parse_dot_label_aux:nw
+% }
+% Start by checking if the label is empty, which raises an error, and
+% uses the fallback value. If not,
+% split the label at a \verb|./|, if any, and check if no tokens are
+% before the \verb|./|, or if the only character is a \verb|.|.
+% If these requirements are fulfilled, the leading
+% \verb|.| is replaced with \cs{@@_currname_or_default:n}. Otherwise
+% the label is returned unchanged.
+% \begin{macrocode}
+\cs_new:Npn \@@_parse_dot_label:nn #1 #2
+ {
+ \tl_if_empty:nTF {#1}
+ {
+ \msg_expandable_error:nnn { hooks } { empty-label } {#2}
+ #2
+ }
+ {
+ \str_if_eq:nnTF {#1} { . }
+ { \@@_currname_or_default:n {#2} }
+ { \@@_parse_dot_label:nw {#2} #1 ./ \s_@@_mark }
+ }
+ }
+\cs_new:Npn \@@_parse_dot_label:nw #1 #2 ./ #3 \s_@@_mark
+ {
+ \tl_if_empty:nTF {#2}
+ { \@@_parse_dot_label_aux:nw {#1} #3 \s_@@_mark }
+ {
+ \tl_if_empty:nTF {#3}
+ { \@@_make_name:n {#2} }
+ { \@@_parse_dot_label_cleanup:w #2 ./ #3 \s_@@_mark }
+ }
+ }
+\cs_new:Npn \@@_parse_dot_label_cleanup:w #1 ./ \s_@@_mark {#1}
+\cs_new:Npn \@@_parse_dot_label_aux:nw #1 #2 ./ \s_@@_mark
+ { \@@_currname_or_default:n {#1} / \@@_make_name:n {#2} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_currname_or_default:n}
+% Uses \cs{g_@@_hook_curr_name_tl} if it is set, otherwise tries
+% \cs{@currname}. If neither is set, uses the fallback value
+% \verb|#1| (usually \texttt{top-level}).
+% \begin{macrocode}
+\cs_new:Npn \@@_currname_or_default:n #1
+ {
+ \tl_if_empty:NTF \g_@@_hook_curr_name_tl
+ {
+ \tl_if_empty:NTF \@currname
+ { \@@_make_name:n {#1} }
+ { \@currname }
+ }
+ { \g_@@_hook_curr_name_tl }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_make_name:n,\@@_make_name:w}
+% Provides a standard sanitisation of a hook's name.
+% It uses \cs{cs:w} to build a control sequence out of the hook name,
+% then uses \cs{cs_to_str:N} to get the string representation of that,
+% without the escape character. \cs{cs:w}-based expansion is used
+% instead of |e|-based because Unicode characters don't behave well
+% inside \cs{expanded}. The macro adds the \cs{@@~} prefix to the
+% hook name to reuse the hook's code token list to build the csname
+% and avoid leaving \enquote{public} control sequences defined
+% (as~\cs{relax}) in TeX's memory.
+% \begin{macrocode}
+\cs_new:Npn \@@_make_name:n #1
+ {
+ \exp_after:wN \exp_after:wN \exp_after:wN \@@_make_name:w
+ \exp_after:wN \token_to_str:N \cs:w @@~ #1 \cs_end:
+ }
+\exp_last_unbraced:NNNNo
+\cs_new:Npn \@@_make_name:w #1 \tl_to_str:n { @@~ } { }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_normalize_hook_args:Nn}
+% \begin{macro}{\@@_normalize_hook_args:Nnn}
+% \begin{macro}{\@@_normalize_hook_rule_args:Nnnnn}
+% \begin{macro}{\@@_normalize_hook_args_aux:Nn}
+% Standard route for normalising hook and label arguments. The main
+% macro does the entire operation within a group so that csnames made
+% by \cs{@@_make_name:n} are wiped off before continuing. This means
+% that this function cannot be used for \cs{hook_use:n}!
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_normalize_hook_args_aux:Nn #1 #2
+ {
+ \group_begin:
+ \use:e
+ {
+ \group_end:
+ \exp_not:N #1 #2
+ }
+ }
+\cs_new_protected:Npn \@@_normalize_hook_args:Nn #1 #2
+ {
+ \@@_normalize_hook_args_aux:Nn #1
+ { { \@@_parse_label_default:n {#2} } }
+ }
+\cs_new_protected:Npn \@@_normalize_hook_args:Nnn #1 #2 #3
+ {
+ \@@_normalize_hook_args_aux:Nn #1
+ {
+ { \@@_parse_label_default:n {#2} }
+ { \@@_parse_label_default:n {#3} }
+ }
+ }
+\cs_new_protected:Npn \@@_normalize_hook_rule_args:Nnnnn #1 #2 #3 #4 #5
+ {
+ \@@_normalize_hook_args_aux:Nn #1
+ {
+ { \@@_parse_label_default:n {#2} }
+ { \@@_parse_label_default:n {#3} }
+ { \tl_trim_spaces:n {#4} }
+ { \@@_parse_label_default:n {#5} }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+% \begin{macro}{\hook_gput_code:nnn}
+% \begin{macro}{\@@_gput_code:nnn,\@@_gput_code:nxv,\@@_hook_gput_code_do:nnn}
+%
+% With \cs{hook_gput_code:nnn}\Arg{hook}\Arg{label}\Arg{code} a
+% chunk of \meta{code} is added to an existing \meta{hook} labeled
+% with \meta{label}.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_gput_code:nnn #1 #2
+ { \@@_normalize_hook_args:Nnn \@@_gput_code:nnn {#1} {#2} }
+\cs_new_protected:Npn \@@_gput_code:nnn #1 #2 #3
+ {
+% \end{macrocode}
+% First check if the hook was used as a one-time hook:
+% \begin{macrocode}
+ \prop_if_in:NnTF \g_@@_execute_immediately_prop {#1}
+ {#3}
+ {
+% \end{macrocode}
+% Then check if the current \meta{hook}/\meta{label} pair was marked
+% for removal, in which case \cs{@@_unmark_removal:nn} is used to
+% remove that mark (once). This may happen when a package removes
+% code from another package which was not yet loaded: the removal
+% order is stored, and at this stage it is executed by not adding to
+% the hook.
+% \begin{macrocode}
+ \@@_if_marked_removal:nnTF {#1} {#2}
+ { \@@_unmark_removal:nn {#1} {#2} }
+ {
+% \end{macrocode}
+% If no removal is queued, we are free to add. Start by checking if
+% the hook exists.
+% \begin{macrocode}
+ \hook_if_exist:nTF {#1}
+% \end{macrocode}
+% If so we simply add (or append) the new code to the property list
+% holding different chunks for the hook. At \verb=\begin{document}=
+% this is then sorted into a token list for fast execution.
+% \begin{macrocode}
+ {
+ \@@_hook_gput_code_do:nnn {#1} {#2} {#3}
+% \end{macrocode}
+% However, if there is an update within the document we need to alter
+% this execution code which is done by
+% \cs{@@_update_hook_code:n}. In the preamble this does nothing.
+% \begin{macrocode}
+ \@@_update_hook_code:n {#1}
+ }
+% \end{macrocode}
+%
+% If the hook does not exist, however, before giving up try to
+% declare it as a generic hook, if its name matches one of the valid
+% patterns.
+% \begin{macrocode}
+ { \@@_try_declaring_generic_hook:nnn {#1} {#2} {#3} }
+ }
+ }
+ }
+\cs_generate_variant:Nn \@@_gput_code:nnn { nxv }
+% \end{macrocode}
+%
+% This macro will unconditionally add a chunk of code to the given hook.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_hook_gput_code_do:nnn #1 #2 #3
+ {
+% \end{macrocode}
+% However, first some debugging info if debugging is enabled:
+% \begin{macrocode}
+ \@@_debug:n{\iow_term:x{****~ Add~ to~
+ \hook_if_exist:nF {#1} { undeclared~ }
+ hook~ #1~ (#2)
+ \on@line\space <-~ \tl_to_str:n{#3}} }
+% \end{macrocode}
+% Then try to get the code chunk labeled \verb=#2= from the hook.
+% If there's code already there, then append \verb=#3= to that,
+% otherwise just put \verb=#3=.
+% \begin{macrocode}
+ \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl
+ {
+ \prop_gput:cno { g_@@_#1_code_prop } {#2}
+ { \l_@@_return_tl #3 }
+ }
+ { \prop_gput:cnn { g_@@_#1_code_prop } {#2} {#3} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_gput_undeclared_hook:nnn}
+% Often it may happen that a package $A$ defines a hook \verb=foo=,
+% but package $B$, that adds code to that hook, is loaded before $A$.
+% In such case we need to add code to the hook before its declared.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_gput_undeclared_hook:nnn #1 #2 #3
+ {
+ \@@_declare:n {#1}
+ \@@_hook_gput_code_do:nnn {#1} {#2} {#3}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_try_declaring_generic_hook:nnn}
+% \begin{macro}{\@@_try_declaring_generic_next_hook:nn}
+% These entry-level macros just pass the arguments along to the
+% common \cs{@@_try_declaring_generic_hook:nNNnn} with the right
+% functions to execute when some action is to be taken.
+%
+% The wrapper \cs{@@_try_declaring_generic_hook:nnn} then defers
+% \cs{hook_gput_code:nnn} if the generic hook was declared, or to
+% \cs{@@_gput_undeclared_hook:nnn} otherwise (the hook was tested for
+% existence before, so at this point if it isn't generic, it doesn't
+% exist).
+%
+% The wrapper \cs{@@_try_declaring_generic_next_hook:nn} for
+% next-execution hooks does the same: it defers the code to
+% \cs{hook_gput_next_code:nn} if the generic hook was declared, or
+% to \cs{@@_gput_next_do:nn} otherwise.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_try_declaring_generic_hook:nnn #1
+ {
+ \@@_try_declaring_generic_hook:nNNnn {#1}
+ \hook_gput_code:nnn \@@_gput_undeclared_hook:nnn
+ }
+\cs_new_protected:Npn \@@_try_declaring_generic_next_hook:nn #1
+ {
+ \@@_try_declaring_generic_hook:nNNnn {#1}
+ \hook_gput_next_code:nn \@@_gput_next_do:nn
+ }
+% \end{macrocode}
+%
+% \begin{macro}{
+% \@@_try_declaring_generic_hook:nNNnn,
+% \@@_try_declaring_generic_hook_split:nNNnn
+% }
+% \begin{macro}[TF]{\@@_try_declaring_generic_hook:wn}
+% \cs{@@_try_declaring_generic_hook:nNNnn} now splits the hook name
+% at the first \texttt{/} (if any) and first checks if it is a
+% file-specific hook (they require some normalization) using
+% \cs{@@_if_file_hook:wTF}. If not then check it is one of a
+% predefined set for generic names. We also split off the second
+% component to see if we have to make a reversed hook. In either case
+% the function returns \meta{true} for a generic hook and \meta{false}
+% in other cases.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_try_declaring_generic_hook:nNNnn #1
+ {
+ \@@_if_file_hook:wTF #1 / / \s_@@_mark
+ {
+ \exp_args:Ne \@@_try_declaring_generic_hook_split:nNNnn
+ { \exp_args:Ne \@@_file_hook_normalize:n {#1} }
+ }
+ { \@@_try_declaring_generic_hook_split:nNNnn {#1} }
+ }
+\cs_new_protected:Npn \@@_try_declaring_generic_hook_split:nNNnn #1 #2 #3
+ {
+ \@@_try_declaring_generic_hook:wnTF #1 / / / \scan_stop: {#1}
+ { #2 }
+ { #3 } {#1}
+ }
+\prg_new_protected_conditional:Npnn \@@_try_declaring_generic_hook:wn
+ #1 / #2 / #3 / #4 \scan_stop: #5 { TF }
+ {
+ \tl_if_empty:nTF {#2}
+ { \prg_return_false: }
+ {
+ \prop_if_in:NnTF \c_@@_generics_prop {#1}
+ {
+ \hook_if_exist:nF {#5} { \hook_new:n {#5} }
+% \end{macrocode}
+% After having declared the hook we check the second component (for
+% file hooks) or the third component for environment hooks) and
+% if it is on the list of components for which we should have declared
+% a reversed hook we alter the hook data structure accordingly.
+% \begin{macrocode}
+ \prop_if_in:NnTF \c_@@_generics_reversed_ii_prop {#2}
+ { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
+ {
+ \prop_if_in:NnT \c_@@_generics_reversed_iii_prop {#3}
+ { \tl_gset:cn { g_@@_#5_reversed_tl } { - } }
+ }
+% \end{macrocode}
+% Now that we know that the hook is declared we can add the code to it.
+% \begin{macrocode}
+ \prg_return_true:
+ }
+ { \prg_return_false: }
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_if_file_hook:w}
+% \cs{@@_if_file_hook:wTF} checks if the argument is a valid
+% file-specific hook (not, for example, |file/before|, but
+% |file/before/foo.tex|). If it is a file-specific hook, then it
+% executes the \meta{true} branch, otherwise \meta{false}.
+%
+% A file-specific hook is \texttt{file/\meta{position}/\meta{name}}.
+% If any of these parts don't exist, it is a general file hook or not
+% a file hook at all, so the conditional evaluates to \meta{false}.
+% Otherwise, it checks that the first part is |file| and that the
+% \meta{position} is in the \cs{c_@@_generics_file_prop}.
+%
+% A property list is used here to avoid having to worry with catcodes,
+% because \pkg{expl3}'s file name parsing turns all characters into
+% catcode-12 tokens, which might differ from hand-input letters.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_file_hook:w
+ #1 / #2 / #3 \s_@@_mark { TF }
+ {
+ \str_if_eq:nnTF {#1} { file }
+ {
+ \bool_lazy_or:nnTF
+ { \tl_if_empty_p:n {#3} }
+ { \str_if_eq_p:nn {#3} { / } }
+ { \prg_return_false: }
+ {
+ \prop_if_in:NnTF \c_@@_generics_file_prop {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ }
+ { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_file_hook_normalize:n}
+% \begin{macro}[EXP]{\@@_strip_double_slash:n,\@@_strip_double_slash:w}
+% When a file-specific hook is found, before being declared it is
+% lightly normalized by \cs{@@_file_hook_normalize:n}. The current
+% implementation just replaces two consecutive slashes (|//|) by a
+% single one, to cope with simple cases where the user did something
+% like \verb|\def\input@path{{./mypath/}}|, in which case a hook would
+% have to be \verb|\AddToHook{file/after/./mypath//file.tex}|.
+% \begin{macrocode}
+\cs_new:Npn \@@_file_hook_normalize:n #1
+ { \@@_strip_double_slash:n {#1} }
+\cs_new:Npn \@@_strip_double_slash:n #1
+ { \@@_strip_double_slash:w #1 // \s_@@_mark }
+\cs_new:Npn \@@_strip_double_slash:w #1 // #2 \s_@@_mark
+ {
+ \tl_if_empty:nTF {#2}
+ {#1}
+ { \@@_strip_double_slash:w #1 / #2 \s_@@_mark }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\c_@@_generics_prop}
+% Property list holding the generic names. We don't provide any user
+% interface to this as this is meant to be static.
+% \begin{description}
+% \item[\texttt{env}]
+% The generic hooks used in \cs{begin} and \cs{end}.
+% \item[\texttt{file}]
+% The generic hooks used when loading a file
+% \end{description}
+% \begin{macrocode}
+\prop_const_from_keyval:Nn \c_@@_generics_prop
+ {env=,file=,package=,class=,include=}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\c_@@_generics_reversed_ii_prop,
+% \c_@@_generics_reversed_iii_prop,
+% \c_@@_generics_file_prop}
+% Some of the generic hooks are supposed to use reverse ordering, these are
+% the following (only the second or third sub-component is checked):
+% \begin{macrocode}
+\prop_const_from_keyval:Nn \c_@@_generics_reversed_ii_prop {after=,end=}
+\prop_const_from_keyval:Nn \c_@@_generics_reversed_iii_prop {after=}
+\prop_const_from_keyval:Nn \c_@@_generics_file_prop {before=,after=}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\hook_gremove_code:nn}
+% \begin{macro}{\@@_gremove_code:nn}
+%
+% With \cs{hook_gremove_code:nn}\Arg{hook}\Arg{label} any code
+% for \meta{hook} stored under \meta{label} is removed.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_gremove_code:nn #1 #2
+ { \@@_normalize_hook_args:Nnn \@@_gremove_code:nn {#1} {#2} }
+\cs_new_protected:Npn \@@_gremove_code:nn #1 #2
+ {
+% \end{macrocode}
+% First check that the hook code pool exists. \cs{hook_if_exist:nTF}
+% isn't used here because it should be possible to remove code from a
+% hook before its defined (see section~\ref{sec:querying}).
+% \begin{macrocode}
+ \@@_if_exist:nTF {#1}
+% \end{macrocode}
+% Then remove the chunk and run \cs{@@_update_hook_code:n} so
+% that the execution token list reflects the change if we are after
+% \verb=\begin{document}=.
+% \begin{macrocode}
+ {
+ \str_if_eq:nnTF {#2} {*}
+ { \prop_gclear:c { g_@@_#1_code_prop } }
+ {
+% \end{macrocode}
+% Check if the label being removed exists in the code pool. If it does,
+% just call \cs{@@_gremove_code_do:nn} to do the removal, otherwise mark it
+% to be removed.
+% \begin{macrocode}
+ \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl
+ { \@@_gremove_code_do:nn }
+ { \@@_mark_removal:nn }
+ {#1} {#2}
+ }
+% \end{macrocode}
+% Finally update the code, if the hook exists.
+% \begin{macrocode}
+ \hook_if_exist:nT {#1}
+ { \@@_update_hook_code:n {#1} }
+ }
+% \end{macrocode}
+%
+% If the code pool for this hook doesn't exist it means that nothing
+% tried to add to it before, so we just queue this removal order for
+% later.
+% \begin{macrocode}
+ { \@@_mark_removal:nn {#1} {#2} }
+ }
+% \end{macrocode}
+%
+% \begin{macro}{\@@_gremove_code_do:nn}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_gremove_code_do:nn #1 #2
+ { \prop_gremove:cn { g_@@_#1_code_prop } {#2} }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_mark_removal:nn}
+% Marks \meta{label} (\verb=#2=) to be removed from \meta{hook}
+% (\verb=#1=). The number of removals should be fairly small, and
+% \cs{tl_gremove_once:Nx} is fairly efficient even for longer token
+% lists, so we use a single global token list, rather than one for
+% each hook.
+%
+% A hand-crafted token list is used here because property lists don't
+% hold repeated items, so multiple usages of \cs{@@_mark_removal:nn}
+% would be cancelled by a single \cs{@@_unmark_removal:nn}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_mark_removal:nn #1 #2
+ {
+ \tl_gput_right:Nx \g_@@_removal_list_tl
+ { \@@_removal_tl:nn {#1} {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_unmark_removal:nn}
+% Unmarks \meta{label} (\verb=#2=) to be removed from \meta{hook}
+% (\verb=#1=). \cs{tl_gremove_once:Nx} is used rather than
+% \cs{tl_gremove_all:Nx} so that two additions are needed to cancel
+% two marked removals, rather than only one.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_unmark_removal:nn #1 #2
+ {
+ \tl_gremove_once:Nx \g_@@_removal_list_tl
+ { \@@_removal_tl:nn {#1} {#2} }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[TF]{\@@_if_marked_removal:nn}
+% Checks if the \cs{g_@@_removal_list_tl} contains the current
+% \meta{label} (\verb=#2=) and \meta{hook} (\verb=#1=).
+% \begin{macrocode}
+\prg_new_protected_conditional:Npnn \@@_if_marked_removal:nn #1 #2 { TF }
+ {
+ \exp_args:NNx \tl_if_in:NnTF \g_@@_removal_list_tl
+ { \@@_removal_tl:nn {#1} {#2} }
+ { \prg_return_true: } { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[rEXP]{\@@_removal_tl:nn}
+% Builds a token list with \verb=#1= and \verb=#2= which can only be
+% matched by \verb=#1= and \verb=#2=. The |&|$_4$ anchors a removal,
+% so that \verb=#1= can't be mistaken by \verb=#2= and vice versa, and
+% the two |$|$_3$ delimit the two arguments
+% \begin{macrocode}
+\cs_new:Npn \@@_removal_tl:nn #1 #2
+ { & \tl_to_str:n {#2} $ \tl_to_str:n {#1} $ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{
+% \g_@@_??_code_prop,
+% \@@~??,
+% \g_@@_??_reversed_tl,
+% }
+%
+% Initially these variables simply used an empty ``label'' name (not
+% two question marks). This was a bit unfortunate, because then
+% \texttt{l3doc} complains about \verb=__= in the middle of a
+% command name when trying to typeset the documentation. However
+% using a ``normal'' name such as \texttt{default} has the
+% disadvantage of that being not really distinguishable from a real
+% hook name. I now have settled for \texttt{??} which needs some
+% gymnastics to get it into the csname, but since this is used a
+% lot things should be fast, so this is not done with \texttt{c}
+% expansion in the code later on.
+%
+% \cs{@@~??} isn't used, but it has to be defined to trick
+% the code into thinking that \verb=??= is actually a hook.
+% \begin{macrocode}
+\prop_new:c {g_@@_??_code_prop}
+\prop_new:c {@@~??}
+% \end{macrocode}
+%
+% Default rules are always given in normal ordering (never in
+% reversed ordering). If such a rule is applied to a reversed
+% hook it behaves as if the rule is reversed (e.g.,
+% \texttt{after} becomes \texttt{before})
+% because those rules are applied first and then the order is reversed.
+% \begin{macrocode}
+\tl_new:c {g_@@_??_reversed_tl}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Setting rules for hooks code}
+%
+% \begin{macro}{\hook_gset_rule:nnnn}
+% \begin{macro}{\@@_gset_rule:nnnn}
+%
+% \fmi{needs docu correction given new implementation}
+%
+% With
+% \cs{hook_gset_rule:nnnn}\Arg{hook}\Arg{label1}\Arg{relation}\Arg{label2}
+% a relation is defined between the two code labels for the given
+% \meta{hook}. The special hook \texttt{??} stands for \emph{any}
+% hook describing a default rule.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_gset_rule:nnnn #1#2#3#4
+ {
+ \@@_normalize_hook_rule_args:Nnnnn \@@_gset_rule:nnnn
+ {#1} {#2} {#3} {#4}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_gset_rule:nnnn #1#2#3#4
+ {
+% \end{macrocode}
+% First we ensure the basic data structure of the hook exists:
+% \begin{macrocode}
+ \@@_declare:n {#1}
+% \end{macrocode}
+% Then we clear any previous relationship between both labels.
+% \begin{macrocode}
+ \@@_rule_gclear:nnn {#1} {#2} {#4}
+% \end{macrocode}
+% Then we call the function to handle the given rule. Throw an error if the
+% rule is invalid.
+% \begin{macrocode}
+ \debug_suspend:
+ \cs_if_exist_use:cTF { @@_rule_#3_gset:nnn }
+ {
+ {#1} {#2} {#4}
+ \@@_update_hook_code:n {#1}
+ }
+ { \msg_error:nnnnnn { hooks } { unknown-rule }
+ {#1} {#2} {#3} {#4} }
+ \debug_resume:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_rule_before_gset:nnn, \@@_rule_after_gset:nnn,
+% \@@_rule_<_gset:nnn, \@@_rule_>_gset:nnn}
+% Then we add the new rule. We need to normalize the rules here to
+% allow for faster processing later. Given a pair of labels
+% $l_A$ and $l_B$, the rule $l_A>l_B$ is the same as $l_B<l_A$
+% only presented differently. But by normalizing the
+% forms of the rule to a single representation, say, $l_B<l_A$, reduces
+% the time spent looking for the rules later considerably.
+%
+% Here we do that normalization by using \cs[no-index]{(pdf)strcmp} to
+% lexically sort labels $l_A$ and $l_B$ to a fixed order. This order
+% is then enforced every time these two labels are used together.
+%
+% Here we use \cs{@@_label_pair:nn}~\Arg{hook}~\Arg{l_A}~\Arg{l_B}
+% to build a string \texttt{$l_B$\string|$l_A$} with a fixed order, and
+% use \cs{@@_label_ordered:nnTF} to apply the correct rule to the pair
+% of labels, depending if it was sorted or not.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rule_before_gset:nnn #1#2#3
+ {
+ \tl_gset:cx { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
+ { \@@_label_ordered:nnTF {#2} {#3} { < } { > } }
+ }
+\cs_new_eq:cN { @@_rule_<_gset:nnn } \@@_rule_before_gset:nnn
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rule_after_gset:nnn #1#2#3
+ {
+ \tl_gset:cx { g_@@_#1_rule_ \@@_label_pair:nn {#3} {#2} _tl }
+ { \@@_label_ordered:nnTF {#3} {#2} { < } { > } }
+ }
+\cs_new_eq:cN { @@_rule_>_gset:nnn } \@@_rule_after_gset:nnn
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_rule_voids_gset:nnn}
+% This rule removes (clears, actually) the code from label |#3| if
+% label |#2| is in the hook |#1|.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rule_voids_gset:nnn #1#2#3
+ {
+ \tl_gset:cx { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl }
+ { \@@_label_ordered:nnTF {#2} {#3} { -> } { <- } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \@@_rule_incompatible-error_gset:nnn,
+% \@@_rule_incompatible-warning_gset:nnn,
+% }
+% These relations make an error/warning if labels |#2| and |#3| appear
+% together in hook |#1|.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_rule_incompatible-error_gset:nnn } #1#2#3
+ { \tl_gset:cn { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl } { xE } }
+\cs_new_protected:cpn { @@_rule_incompatible-warning_gset:nnn } #1#2#3
+ { \tl_gset:cn { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl } { xW } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_rule_unrelated_gset:nnn, \@@_rule_gclear:nnn}
+% Undo a setting. \cs{@@_rule_unrelated_gset:nnn} doesn't need to do anything,
+% since we use \cs{@@_rule_gclear:nnn} before setting any rule.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_rule_unrelated_gset:nnn #1#2#3 { }
+\cs_new_protected:Npn \@@_rule_gclear:nnn #1#2#3
+ { \cs_undefine:c { g_@@_#1_rule_ \@@_label_pair:nn {#2} {#3} _tl } }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_label_pair:nn}
+% Ensure that the lexically greater label comes first.
+% \begin{macrocode}
+\cs_new:Npn \@@_label_pair:nn #1#2
+ {
+ \if_case:w \@@_str_compare:nn {#1} {#2} \exp_stop_f:
+ #1 | #1 % 0
+ \or: #1 | #2 % +1
+ \else: #2 | #1 % -1
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_label_ordered:nn}
+% Check that labels |#1| and |#2| are in the correct order (as
+% returned by \cs{@@_label_pair:nn}) and if so return true, else
+% return false.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_label_ordered:nn #1#2 { TF }
+ {
+ \if_int_compare:w \@@_str_compare:nn {#1} {#2} > 0 \exp_stop_f:
+ \prg_return_true:
+ \else
+ \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_if_label_case:nnnnn}
+% To avoid doing the string comparison twice in \cs{@@_initialize_single:NNNn}
+% (once with \cs{str_if_eq:nn} and again with \cs{@@_label_ordered:nn}),
+% we use a three-way branching macro that will compare |#1| and |#2|
+% and expand to \cs{use_i:nnn} if they are equal, \cs{use_ii:nn} if
+% |#1| is lexically greater, and \cs{use_iii:nn} otherwise.
+% \begin{macrocode}
+\cs_new:Npn \@@_if_label_case:nnnnn #1#2
+ {
+ \cs:w use_
+ \if_case:w \@@_str_compare:nn {#1} {#2}
+ i \or: ii \else: iii \fi: :nnn
+ \cs_end:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_update_hook_code:n}
+% Before \verb=\begin{document}= this does nothing, in the body it
+% reinitializes the hook code using the altered data.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_update_hook_code:n \use_none:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_initialize_all:}
+% Initialize all known hooks (at \verb=\begin{document}=), i.e.,
+% update the fast execution token lists to hold the necessary code
+% in the right order.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_initialize_all: {
+% \end{macrocode}
+% First we change \cs{@@_update_hook_code:n} which so far was a
+% no-op to now initialize one hook. This way any later updates to
+% the hook will run that code and also update the execution token
+% list.
+% \begin{macrocode}
+ \cs_gset_eq:NN \@@_update_hook_code:n \@@_initialize_hook_code:n
+% \end{macrocode}
+% Now we loop over all hooks that have been defined and update each
+% of them.
+% \begin{macrocode}
+ \@@_debug:n { \prop_gclear:N \g_@@_used_prop }
+ \seq_map_inline:Nn \g_@@_all_seq
+ {
+ \@@_update_hook_code:n {##1}
+ }
+% \end{macrocode}
+% If we are debugging we show results hook by hook for all hooks
+% that have data.
+% \begin{macrocode}
+ \@@_debug:n
+ { \iow_term:x{^^JAll~ initialized~ (non-empty)~ hooks:}
+ \prop_map_inline:Nn \g_@@_used_prop
+ { \iow_term:x{^^J~ ##1~ ->~
+ \exp_not:v {@@~##1}~ }
+ }
+ }
+% \end{macrocode}
+% After all hooks are initialized we change the ``use'' to just
+% call the hook code and not initialize it (as it was done in the
+% preamble.
+% \begin{macrocode}
+ \cs_gset_eq:NN \hook_use:n \@@_use_initialized:n
+ \cs_gset_eq:NN \@@_preamble_hook:n \use_none:n
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_initialize_hook_code:n}
+% Initializing or reinitializing the fast execution hook code. In
+% the preamble this is selectively done in case a hook gets used
+% and at \verb=\begin{document}= this is done for all hooks and
+% afterwards only if the hook code changes.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_initialize_hook_code:n #1
+ {
+ \debug_suspend:
+ \@@_debug:n{ \iow_term:x{^^JUpdate~ code~ for~ hook~
+ '#1' \on@line :^^J} }
+% \end{macrocode}
+% This does the sorting and the updates.
+% First thing we do is to check if a legacy hook macro exists and
+% if so we add it to the hook under the label \texttt{legacy}. This
+% might make the hook non-empty so we have to do this before
+% the then following test.
+% \begin{macrocode}
+ \@@_include_legacy_code_chunk:n {#1}
+% \end{macrocode}
+% If there aren't any code
+% chunks for the current hook, there is no point in even starting
+% the sorting routine so we make a quick test for that and in that
+% case just update \cs{@@~\meta{hook}} to hold the next
+% code. If there are code chunks we call
+% \cs{@@_initialize_single:NNNn} and pass to it ready made csnames
+% as they are needed several times inside. This way we save a bit
+% on processing time if we do that up front.
+% \begin{macrocode}
+ \hook_if_exist:nT {#1}
+ {
+ \prop_if_empty:cTF {g_@@_#1_code_prop}
+ { \tl_gset:co { @@~#1 }
+ { \cs:w @@_next~#1 \cs_end: } }
+ {
+% \end{macrocode}
+% By default the algorithm sorts the code chunks and then saves the
+% result in a token list for fast execution by adding the code one
+% after another using \cs{tl_gput_right:NV}. When we sort code for
+% a reversed hook, all we have to do is to add the code chunks in
+% the opposite order into the token list. So all we have to do
+% in preparation is to change two definitions used later on.
+% \begin{macrocode}
+ \@@_if_reversed:nTF {#1}
+ { \cs_set_eq:NN \@@_tl_gput:NV \tl_gput_left:NV
+ \cs_set_eq:NN \@@_clist_gput:NV \clist_gput_left:NV }
+ { \cs_set_eq:NN \@@_tl_gput:NV \tl_gput_right:NV
+ \cs_set_eq:NN \@@_clist_gput:NV \clist_gput_right:NV }
+% \end{macrocode}
+%
+% When sorting, some relations (namely \verb|voids|) need to
+% act destructively on the code property lists to remove code that
+% shouldn't appear in the sorted hook token list, so we temporarily
+% save the old code property list so that it can be restored later.
+% \begin{macrocode}
+ \prop_set_eq:Nc \l_@@_work_prop { g_@@_#1_code_prop }
+ \@@_initialize_single:cccn
+ { @@~#1 } { @@_next~#1 }
+ { g_@@_#1_labels_clist } {#1}
+% \end{macrocode}
+% For debug display we want to keep track of those hooks that
+% actually got code added to them, so we record that in plist. We
+% use a plist to ensure that we record each hook name only once,
+% i.e., we are only interested in storing the keys and the value is
+% arbitrary.
+% \begin{macrocode}
+ \@@_debug:n{ \exp_args:NNx \prop_gput:Nnn
+ \g_@@_used_prop {#1}{} }
+ }
+ }
+ \debug_resume:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}[EXP]{\@@_tl_csname:n,\@@_seq_csname:n}
+% It is faster to pass a single token and expand it when necessary
+% than to pass a bunch of character tokens around.
+% \fmi{note to myself: verify}
+% \begin{macrocode}
+\cs_new:Npn \@@_tl_csname:n #1 { l_@@_label_#1_tl }
+\cs_new:Npn \@@_seq_csname:n #1 { l_@@_label_#1_seq }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\l_@@_labels_seq,\l_@@_labels_int,\l_@@_front_tl,
+% \l_@@_rear_tl,\l_@@_label_0_tl}
+%
+% For the sorting I am basically implementing Knuth's algorithm for
+% topological sorting as given in TAOCP volume 1 pages 263--266.
+% For this algorithm we need a number of local variables:
+% \begin{itemize}
+% \item
+% List of labels used in the current hook to label code chunks:
+% \begin{macrocode}
+\seq_new:N \l_@@_labels_seq
+% \end{macrocode}
+% \item
+% Number of labels used in the current hook. In Knuth's algorithm
+% this is called $N$:
+% \begin{macrocode}
+\int_new:N \l_@@_labels_int
+% \end{macrocode}
+% \item
+% The sorted code list to be build is managed using two pointers
+% one to the front of the queue and one to the rear. We model this
+% using token list pointers. Knuth calls them $F$ and $R$:
+% \begin{macrocode}
+\tl_new:N \l_@@_front_tl
+\tl_new:N \l_@@_rear_tl
+% \end{macrocode}
+% \item
+% The data for the start of the queue is kept in this token list,
+% it corresponds to what Don calls \texttt{QLINK[0]} but since we
+% aren't manipulating individual words in memory it is slightly
+% differently done:
+% \begin{macrocode}
+\tl_new:c { \@@_tl_csname:n { 0 } }
+% \end{macrocode}
+%
+% \end{itemize}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_initialize_single:NNNn,\@@_initialize_single:cccn}
+%
+% \cs{@@_initialize_single:NNNn} implements the sorting of the code
+% chunks for a hook and saves the result in the token list for fast
+% execution (\verb=#3=). The arguments are \meta{hook-code-plist},
+% \meta{hook-code-tl}, \meta{hook-next-code-tl},
+% \meta{hook-ordered-labels-clist} and \meta{hook-name} (the latter
+% is only used for debugging---the \meta{hook-rule-plist} is accessed
+% using the \meta{hook-name}).
+%
+% The additional complexity compared to Don's algorithm is that we
+% do not use simple positive integers but have arbitrary
+% alphanumeric labels. As usual Don's data structures are chosen in
+% a way that one can omit a lot of tests and I have mimicked that as
+% far as possible. The result is a restriction I do not test for at
+% the moment: a label can't be equal to the number 0! \fmi{Needs
+% checking for, just in case}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_initialize_single:NNNn #1#2#3#4
+ {
+% \end{macrocode}
+% Step T1: Initialize the data structure \ldots
+% \begin{macrocode}
+ \seq_clear:N \l_@@_labels_seq
+ \int_zero:N \l_@@_labels_int
+% \end{macrocode}
+%
+% Store the name of the hook:
+% \begin{macrocode}
+ \tl_set:Nn \l_@@_cur_hook_tl {#4}
+% \end{macrocode}
+%
+% We loop over the property list holding the code and record all
+% labels listed there. Only rules for those labels are of interest
+% to us. While we are at it we count them (which gives us the $N$
+% in Knuth's algorithm. The prefix |label_| is added to the variables
+% to ensure that labels named |front|, |rear|, |labels|, or |return|
+% don't interact with our code.
+% \begin{macrocode}
+ \prop_map_inline:Nn \l_@@_work_prop
+ {
+ \int_incr:N \l_@@_labels_int
+ \seq_put_right:Nn \l_@@_labels_seq {##1}
+ \tl_set:cn { \@@_tl_csname:n {##1} }{0}
+ \seq_clear_new:c { \@@_seq_csname:n {##1} }
+ }
+% \end{macrocode}
+% Steps T2 and T3: Sort the relevant rules into the data structure\ldots
+%
+% This loop constitutes a square matrix of the labels in
+% \cs{l_@@_work_prop} in the
+% vertical and the horizontal directions. However since the rule
+% $l_A\meta{rel}l_B$ is the same as $l_B\meta{rel}^{-1}l_A$ we can cut
+% the loop short at the diagonal of the matrix (\emph{i.e.}, when
+% both labels are equal), saving a good amount of time. The way the
+% rules were set up (see the implementation of \cs{@@_rule_before_gset:nnn}
+% above) ensures that we have no rule in the ignored side of the
+% matrix, and all rules are seen. The rules are applied in
+% \cs{@@_apply_label_pair:nnn}, which takes the properly-ordered pair
+% of labels as argument.
+% \begin{macrocode}
+ \prop_map_inline:Nn \l_@@_work_prop
+ {
+ \prop_map_inline:Nn \l_@@_work_prop
+ {
+ \@@_if_label_case:nnnnn {##1} {####1}
+ { \prop_map_break: }
+ { \@@_apply_label_pair:nnn {##1} {####1} }
+ { \@@_apply_label_pair:nnn {####1} {##1} }
+ {#4}
+ }
+ }
+% \end{macrocode}
+% Take a breath and take a look at the data structures that have
+% been set up:
+% \begin{macrocode}
+ \@@_debug:n { \@@_debug_label_data:N \l_@@_work_prop }
+% \end{macrocode}
+%
+%
+% Step T4:
+% \begin{macrocode}
+ \tl_set:Nn \l_@@_rear_tl { 0 }
+ \tl_set:cn { \@@_tl_csname:n { 0 } } { 0 }
+ \seq_map_inline:Nn \l_@@_labels_seq
+ {
+ \int_compare:nNnT { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0
+ {
+ \tl_set:cn { \@@_tl_csname:n { \l_@@_rear_tl } }{##1}
+ \tl_set:Nn \l_@@_rear_tl {##1}
+ }
+ }
+ \tl_set_eq:Nc \l_@@_front_tl { \@@_tl_csname:n { 0 } }
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \tl_gclear:N #1
+ \clist_gclear:N #3
+% \end{macrocode}
+%
+% The whole loop combines steps T5--T7:
+% \begin{macrocode}
+ \bool_while_do:nn { ! \str_if_eq_p:Vn \l_@@_front_tl { 0 } }
+ {
+% \end{macrocode}
+% This part is step T5:
+% \begin{macrocode}
+ \int_decr:N \l_@@_labels_int
+ \prop_get:NVN \l_@@_work_prop \l_@@_front_tl \l_@@_return_tl
+ \@@_tl_gput:NV #1 \l_@@_return_tl
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \@@_clist_gput:NV #3 \l_@@_front_tl
+ \@@_debug:n{ \iow_term:x{Handled~ code~ for~ \l_@@_front_tl} }
+% \end{macrocode}
+%
+% This is step T6 except that we don't use a pointer $P$ to move
+% through the successors, but instead use \verb=##1= of the mapping
+% function.
+% \begin{macrocode}
+ \seq_map_inline:cn { \@@_seq_csname:n { \l_@@_front_tl } }
+ {
+ \tl_set:cx { \@@_tl_csname:n {##1} }
+ { \int_eval:n
+ { \cs:w \@@_tl_csname:n {##1} \cs_end: - 1 }
+ }
+ \int_compare:nNnT
+ { \cs:w \@@_tl_csname:n {##1} \cs_end: } = 0
+ {
+ \tl_set:cn { \@@_tl_csname:n { \l_@@_rear_tl } } {##1}
+ \tl_set:Nn \l_@@_rear_tl {##1}
+ }
+ }
+% \end{macrocode}
+% and step T7:
+% \begin{macrocode}
+ \tl_set_eq:Nc \l_@@_front_tl
+ { \@@_tl_csname:n { \l_@@_front_tl } }
+% \end{macrocode}
+%
+% This is step T8: If we haven't moved the code for all labels
+% (i.e., if \cs{l_@@_labels_int} is still greater than zero) we
+% have a loop and our partial order can't be flattened out.
+% \begin{macrocode}
+ }
+ \int_compare:nNnF \l_@@_labels_int = 0
+ {
+ \iow_term:x{====================}
+ \iow_term:x{Error:~ label~ rules~ are~ incompatible:}
+% \end{macrocode}
+%
+% This is not really the information one needs in the error case
+% but will do for now \ldots \fmi{fix}
+% \begin{macrocode}
+ \@@_debug_label_data:N \l_@@_work_prop
+ \iow_term:x{====================}
+ }
+% \end{macrocode}
+% After we have added all hook code to \verb=#1= we finish it off
+% with adding extra code for a one time execution. That is stored
+% in \verb=#2= but is normally empty.
+% \begin{macrocode}
+ \tl_gput_right:Nn #1 {#2}
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_generate_variant:Nn \@@_initialize_single:NNNn {ccc}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_tl_gput:NV,\@@_clist_gput:NV}
+% These append either on the right (normal hook) or on the left
+% (reversed hook). This is setup up in
+% \cs{@@_initialize_hook_code:n}, elsewhere their behavior is undefined.
+% \begin{macrocode}
+\cs_new:Npn \@@_tl_gput:NV {\ERROR}
+\cs_new:Npn \@@_clist_gput:NV {\ERROR}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_apply_label_pair:nnn,\@@_label_if_exist_apply:nnnF}
+%
+% This is the payload of steps T2 and T3 executed in the loop described
+% above. This macro assumes |#1| and |#2| are ordered, which means that
+% any rule pertaining the pair |#1| and |#2| is
+% \cs{g_@@_\meta{hook}_rule_\#1\string|\#2_tl}, and not
+% \cs{g_@@_\meta{hook}_rule_\#2\string|\#1_tl}. This also saves a great deal
+% of time since we only need to check the order of the labels once.
+%
+% The arguments here are \meta{label1}, \meta{label2}, \meta{hook}, and
+% \meta{hook-code-plist}. We are about to apply the next rule and
+% enter it into the data structure. \cs{@@_apply_label_pair:nnn} will
+% just call \cs{@@_label_if_exist_apply:nnnF} for the \meta{hook}, and
+% if no rule is found, also try the \meta{hook} name \verb=??=
+% denoting a default hook rule.
+%
+% \cs{@@_label_if_exist_apply:nnnF} will check if the rule exists for
+% the given hook, and if so call \cs{@@_apply_rule:nnn}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_apply_label_pair:nnn #1#2#3
+ {
+% \end{macrocode}
+% Extra complication: as we use default rules and local hook specific
+% rules we first have to check if there is a local rule and if that
+% exist use it. Otherwise check if there is a default rule and use
+% that.
+% \begin{macrocode}
+ \@@_label_if_exist_apply:nnnF {#1} {#2} {#3}
+ {
+% \end{macrocode}
+% If there is no hook-specific rule we check for a default one and
+% use that if it exists.
+% \begin{macrocode}
+ \@@_label_if_exist_apply:nnnF {#1} {#2} { ?? } { }
+ }
+ }
+\cs_new_protected:Npn \@@_label_if_exist_apply:nnnF #1#2#3
+ {
+ \if_cs_exist:w g_@@_ #3 _rule_ #1 | #2 _tl \cs_end:
+% \end{macrocode}
+% What to do precisely depends on the type of rule we have
+% encountered. If it is a \texttt{before} rule it will be handled by the
+% algorithm but other types need to be managed differently. All
+% this is done in \cs{@@_apply_rule:nnnN}.
+% \begin{macrocode}
+ \@@_apply_rule:nnn {#1} {#2} {#3}
+ \exp_after:wN \use_none:n
+ \else:
+ \use:nn
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\@@_apply_rule:nnn}
+% This is the code executed in steps T2 and T3 while looping through
+% the matrix This is part of step T3. We are about to apply the next
+% rule and enter it into the data structure. The arguments are
+% \meta{label1}, \meta{label2}, \meta{hook-name}, and \meta{hook-code-plist}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_apply_rule:nnn #1#2#3
+ {
+ \cs:w @@_apply_
+ \cs:w g_@@_#3_reversed_tl \cs_end: rule_
+ \cs:w g_@@_ #3 _rule_ #1 | #2 _tl \cs_end: :nnn \cs_end:
+ {#1} {#2} {#3}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_apply_rule_<:nnn,\@@_apply_rule_>:nnn}
+% The most common cases are \texttt{\string<} and \texttt{\string>} so we handle
+% that first. They are relations $\prec$ and $\succ$ in TAOCP, and
+% they dictate sorting.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_apply_rule_<:nnn } #1#2#3
+ {
+ \@@_debug:n { \@@_msg_pair_found:nnn {#1} {#2} {#3} }
+ \tl_set:cx { \@@_tl_csname:n {#2} }
+ { \int_eval:n{ \cs:w \@@_tl_csname:n {#2} \cs_end: + 1 } }
+ \seq_put_right:cn{ \@@_seq_csname:n {#1} }{#2}
+ }
+\cs_new_protected:cpn { @@_apply_rule_>:nnn } #1#2#3
+ {
+ \@@_debug:n { \@@_msg_pair_found:nnn {#1} {#2} {#3} }
+ \tl_set:cx { \@@_tl_csname:n {#1} }
+ { \int_eval:n{ \cs:w \@@_tl_csname:n {#1} \cs_end: + 1 } }
+ \seq_put_right:cn{ \@@_seq_csname:n {#2} }{#1}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_apply_rule_xE:nnn,\@@_apply_rule_xW:nnn}
+% These relations make two labels incompatible within a hook.
+% |xE| makes raises an error if the labels are found in the same
+% hook, and |xW| makes it a warning.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_apply_rule_xE:nnn } #1#2#3
+ {
+ \@@_debug:n { \@@_msg_pair_found:nnn {#1} {#2} {#3} }
+ \msg_error:nnnnnn { hooks } { labels-incompatible }
+ {#1} {#2} {#3} { 1 }
+ \use:c { @@_apply_rule_->:nnn } {#1} {#2} {#3}
+ \use:c { @@_apply_rule_<-:nnn } {#1} {#2} {#3}
+ }
+\cs_new_protected:cpn { @@_apply_rule_xW:nnn } #1#2#3
+ {
+ \@@_debug:n { \@@_msg_pair_found:nnn {#1} {#2} {#3} }
+ \msg_warning:nnnnnn { hooks } { labels-incompatible }
+ {#1} {#2} {#3} { 0 }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_apply_rule_->:nnn,\@@_apply_rule_<-:nnn}
+% If we see \texttt{\detokenize{->}} we have to drop code for label
+% \verb=#3= and carry on. We could do a little better and drop
+% everything for that label since it doesn't matter where we sort
+% in the empty code. However that would complicate the algorithm a
+% lot with little gain.\footnote{This also hase the advantage that
+% the result of the sorting doesn't change which might otherwise
+% (for unrelated chunks) if we aren't careful.} So we still
+% unnecessarily try to sort it in and depending on the rules that
+% might result in a loop that is otherwise resolved. If that turns
+% out to be a real issue, we can improve the code.
+%
+% Here the code is removed from \cs{l_@@_cur_hook_tl} rather than
+% \verb=#3= because the latter may be \verb=??=, and the default
+% hook doesn't store any code. Removing from \cs{l_@@_cur_hook_tl}
+% makes default rules \verb=->= and \verb=<-= work properly.
+% \begin{macrocode}
+\cs_new_protected:cpn { @@_apply_rule_->:nnn } #1#2#3
+ {
+ \@@_debug:n
+ {
+ \@@_msg_pair_found:nnn {#1} {#2} {#3}
+ \iow_term:x{--->~ Drop~ '#2'~ code~ from~
+ \iow_char:N \\ g_@@_ \l_@@_cur_hook_tl _code_prop ~
+ because~ of~ '#1' }
+ }
+ \prop_put:Nnn \l_@@_work_prop {#2} { }
+ }
+\cs_new_protected:cpn { @@_apply_rule_<-:nnn } #1#2#3
+ {
+ \@@_debug:n
+ {
+ \@@_msg_pair_found:nnn {#1} {#2} {#3}
+ \iow_term:x{--->~ Drop~ '#1'~ code~ from~
+ \iow_char:N \\ g_@@_ \l_@@_cur_hook_tl _code_prop ~
+ because~ of~ '#2' }
+ }
+ \prop_put:Nnn \l_@@_work_prop {#1} { }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{
+% \@@_apply_-rule_<:nnn,
+% \@@_apply_-rule_>:nnn,
+% \@@_apply_-rule_<-:nnn,
+% \@@_apply_-rule_->:nnn,
+% \@@_apply_-rule_x:nnn,
+% }
+% Reversed rules.
+% \begin{macrocode}
+\cs_new_eq:cc { @@_apply_-rule_<:nnn } { @@_apply_rule_>:nnn }
+\cs_new_eq:cc { @@_apply_-rule_>:nnn } { @@_apply_rule_<:nnn }
+\cs_new_eq:cc { @@_apply_-rule_<-:nnn } { @@_apply_rule_<-:nnn }
+\cs_new_eq:cc { @@_apply_-rule_->:nnn } { @@_apply_rule_->:nnn }
+\cs_new_eq:cc { @@_apply_-rule_xE:nnn } { @@_apply_rule_xE:nnn }
+\cs_new_eq:cc { @@_apply_-rule_xW:nnn } { @@_apply_rule_xW:nnn }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_msg_pair_found:nnn}
+% A macro to avoid moving this many tokens around.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_msg_pair_found:nnn #1#2#3
+ {
+ \iow_term:x{~ \str_if_eq:nnTF {#3} {??} {default} {~normal} ~
+ rule~ \@@_label_pair:nn {#1} {#2}:~
+ \use:c { g_@@_#3_rule_ \@@_label_pair:nn {#1} {#2} _tl } ~
+ found}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_debug_label_data:N}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_debug_label_data:N #1 {
+ \iow_term:x{Code~ labels~ for~ sorting:}
+ \iow_term:x{~ \seq_use:Nnnn\l_@@_labels_seq {~and~}{,~}{~and~} }
+ \iow_term:x{^^J Data~ structure~ for~ label~ rules:}
+ \prop_map_inline:Nn #1
+ {
+ \iow_term:x{~ ##1~ =~ \tl_use:c{ \@@_tl_csname:n {##1} }~ ->~
+ \seq_use:cnnn{ \@@_seq_csname:n {##1} }{~->~}{~->~}{~->~}
+ }
+ }
+ \iow_term:x{}
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\hook_show:n,\hook_log:n}
+% \begin{macro}{\@@_log_line:x,\@@_log_line_indent:x}
+% \begin{macro}{\@@_log:nN}
+% This writes out information about the hook given in its argument
+% onto the \texttt{.log} file and the terminal, if \cs{show_hook:n} is
+% used. Internally both share the same structure, except that at the
+% end, \cs{hook_show:n} triggers \TeX's prompt.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_log:n #1
+ {
+ \cs_set_eq:NN \@@_log_cmd:x \iow_log:x
+ \@@_normalize_hook_args:Nn \@@_log:nN {#1} \tl_log:x
+ }
+\cs_new_protected:Npn \hook_show:n #1
+ {
+ \cs_set_eq:NN \@@_log_cmd:x \iow_term:x
+ \@@_normalize_hook_args:Nn \@@_log:nN {#1} \tl_show:x
+ }
+\cs_new_protected:Npn \@@_log_line:x #1
+ { \@@_log_cmd:x { >~#1 } }
+\cs_new_protected:Npn \@@_log_line_indent:x #1
+ { \@@_log_cmd:x { >~\@spaces #1 } }
+\cs_new_protected:Npn \@@_log:nN #1 #2
+ {
+ \@@_preamble_hook:n {#1}
+ \iow_term:x { ^^J ->~The~hook~'#1': }
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \hook_if_exist:nF {#1}
+ { \@@_log_line:x { is~not~declared! } }
+ \@@_if_exist:nTF {#1}
+ {
+ \@@_log_line:x { Code~chunks: }
+ \prop_if_empty:cTF { g_@@_#1_code_prop }
+ { \@@_log_line_indent:x { --- } }
+ {
+ \prop_map_inline:cn { g_@@_#1_code_prop }
+ { \@@_log_line_indent:x { ##1~->~\tl_to_str:n {##2} } }
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \@@_log_line:x { Extra~code~for~next~invocation:}
+ \@@_log_line_indent:x
+ {
+ \tl_if_empty:cTF { @@_next~#1 }
+ { --- }
+% \end{macrocode}
+%
+% If the token list is not empty we want to display it but without
+% the first tokens (the code to clear itself) so we call a helper
+% command to get rid of them.
+% \begin{macrocode}
+ { ->~ \exp_args:Nv \@@_log_next_code:n { @@_next~#1 } }
+ }
+% \end{macrocode}
+%
+% Loop through the rules in a hook and for every rule found, print it.
+% If no rule is there, print |---|. The boolean \cs{l_@@_tmpa_bool}
+% here indicates if the hook has no rules.
+% \begin{macrocode}
+ \@@_log_line:x { Rules: }
+ \bool_set_true:N \l_@@_tmpa_bool
+ \@@_list_rules:nn {#1}
+ {
+ \bool_set_false:N \l_@@_tmpa_bool
+ \@@_log_line_indent:x
+ {
+ ##2~ with~
+ \str_if_eq:nnT {##3} {??} { default~ }
+ relation~ ##1
+ }
+ }
+ \bool_if:NT \l_@@_tmpa_bool
+ { \@@_log_line_indent:x { --- } }
+% \end{macrocode}
+%
+% When the hook is declared (that is, the sorting algorithm is applied
+% to that hook) and not empty
+% \begin{macrocode}
+ \bool_lazy_and:nnTF
+ { \hook_if_exist_p:n {#1} }
+ { ! \hook_if_empty_p:n {#1} }
+ {
+ \@@_log_line:x
+ {
+ Execution~order
+ \bool_if:NTF \l_@@_tmpa_bool
+ { \@@_if_reversed:nT {#1} { ~(after~reversal) } }
+ { ~(after~
+ \@@_if_reversed:nT {#1} { reversal~and~ }
+ applying~rules)
+ } :
+ }
+ #2 % \tl_show:n
+ {
+ \@spaces
+ \clist_if_empty:cTF { g_@@_#1_labels_clist }
+ { --- }
+ { \clist_use:cn {g_@@_#1_labels_clist} { ,~ } }
+ }
+ }
+ {
+ #2
+ {
+ Hook~ \hook_if_exist:nTF {#1}
+ {code~pool~empty} {not~declared}
+ }
+ }
+ }
+ { #2 { The~hook~is~empty. } }
+ }
+% \end{macrocode}
+%
+% \begin{macro}{\@@_log_next_code:n}
+% To display the code for next invocation only (i.e., from
+% \cs{AddToHookNext} we have to remove the first two tokens at the
+% front which are \cs{tl_gclear:N} and the token list to clear.
+% \begin{macrocode}
+\cs_new:Npn \@@_log_next_code:n #1
+ { \exp_args:No \tl_to_str:n { \use_none:nn #1 } }
+% \end{macrocode}
+% \end{macro}
+%
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_list_rules:nn}
+% \begin{macro}{\@@_list_one_rule:nnn,\@@_list_if_rule_exists:nnnF}
+% This macro takes a \meta{hook} and an \meta{inline function} and
+% loops through each pair of \meta{labels} in the \meta{hook}, and if
+% there is a relation between this pair of \meta{labels}, the
+% \meta{inline function} is executed with |#1|${}={}$\meta{relation},
+% |#2|${}={}$\meta{label_1}\verb=|=\meta{label_2},
+% and |#3|${}={}$\meta{hook} (the latter may be the argument |#1| to
+% \cs{@@_list_rules:nn}, or |??| if it is a default rule).
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_list_rules:nn #1 #2
+ {
+ \cs_set_protected:Npn \@@_tmp:w ##1 ##2 ##3 {#2}
+ \prop_map_inline:cn { g_@@_#1_code_prop }
+ {
+ \prop_map_inline:cn { g_@@_#1_code_prop }
+ {
+ \@@_if_label_case:nnnnn {##1} {####1}
+ { \prop_map_break: }
+ { \@@_list_one_rule:nnn {##1} {####1} }
+ { \@@_list_one_rule:nnn {####1} {##1} }
+ {#1}
+ }
+ }
+ }
+% \end{macrocode}
+%
+% These two are quite similar to \cs{@@_apply_label_pair:nnn} and
+% \cs{@@_label_if_exist_apply:nnnF}, respectively, but rather than
+% applying the rule, they pass it to the \meta{inline function}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_list_one_rule:nnn #1#2#3
+ {
+ \@@_list_if_rule_exists:nnnF {#1} {#2} {#3} { }
+ { \@@_list_if_rule_exists:nnnF {#1} {#2} { ?? } { } }
+ }
+\cs_new_protected:Npn \@@_list_if_rule_exists:nnnF #1#2#3
+ {
+ \if_cs_exist:w g_@@_ #3 _rule_ #1 | #2 _tl \cs_end:
+ \exp_args:Nv \@@_tmp:w
+ { g_@@_ #3 _rule_ #1 | #2 _tl } { #1 | #2 } {#3}
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_debug_print_rules:n}
+% A shorthand for debugging that prints similar to \cs{prop_show:N}.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_debug_print_rules:n #1
+ {
+ \iow_term:n { The~hook~#1~contains~the~rules: }
+ \cs_set_protected:Npn \@@_tmp:w ##1
+ {
+ \@@_list_rules:nn {#1}
+ {
+ \iow_term:x
+ {
+ > ##1 {####2} ##1 => ##1 {####1}
+ \str_if_eq:nnT {####3} {??} { ~(default) }
+ }
+ }
+ }
+ \exp_args:No \@@_tmp:w { \use:nn { ~ } { ~ } }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Specifying code for next invocation}
+%
+% \begin{macro}{\hook_gput_next_code:nn}
+% \begin{macro}{%
+% \@@_gput_next_code:nn,
+% \@@_gput_next_do:nn,
+% \@@_gput_next_do:Nnn,
+% \@@_clear_next:n
+% }
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_gput_next_code:nn #1
+ { \@@_normalize_hook_args:Nn \@@_gput_next_code:nn {#1} }
+\cs_new_protected:Npn \@@_gput_next_code:nn #1 #2
+ {
+ \debug_suspend:
+ \@@_declare:n {#1}
+ \hook_if_exist:nTF {#1}
+ { \@@_gput_next_do:nn {#1} {#2} }
+ { \@@_try_declaring_generic_next_hook:nn {#1} {#2} }
+ \debug_resume:
+ }
+\cs_new_protected:Npn \@@_gput_next_do:nn #1
+ {
+ \exp_args:Nc \@@_gput_next_do:Nnn
+ { @@_next~#1 } {#1}
+ }
+% \end{macrocode}
+% First check if the ``next code'' token list is empty: if so we need
+% to add a \cs{tl_gclear:c} to clear it, so the code lasts for one
+% usage only. The token list is cleared early so that nested usages
+% don't get lost. \cs{tl_gclear:c} is used instead of
+% \cs{tl_gclear:N} in case the hook is used in an expansion-only
+% context, so the token list doesn't expand before \cs{tl_gclear:N}:
+% that would make an infinite loop. Also in case the main code token
+% list is empty, the hook code has to be updated to add the next
+% execution token list.
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_gput_next_do:Nnn #1 #2
+ {
+ \tl_if_empty:cT { @@~#2 }
+ { \@@_update_hook_code:n {#2} }
+ \tl_if_empty:NT #1
+ { \tl_gset:Nn #1 { \@@_clear_next:n {#2} } }
+ \tl_gput_right:Nn #1
+ }
+\cs_new_protected:Npn \@@_clear_next:n #1
+ { \cs_gset_eq:cN { @@_next~#1 } \c_empty_tl }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \subsection{Using the hook}
+%
+% \begin{macro}{\hook_use:n}
+% \begin{macro}[EXP]{\@@_use_initialized:n}
+% \begin{macro}{\@@_use_undefined:w,\@@_use_end:}
+% \begin{macro}{\@@_preamble_hook:n}
+% \cs{hook_use:n} as defined here is used in the preamble, where
+% hooks aren't initialized by default. \cs{@@_use_initialized:n} is
+% also defined, which is the non-\tn{protected} version for use within
+% the document. Their definition is identical, except for the
+% \cs{@@_preamble_hook:n} (which wouldn't hurt in the expandable
+% version, but it would be an unnecessary extra expansion).
+%
+% \cs{@@_use_initialized:n} holds the expandable definition while in
+% the preamble. \cs{@@_preamble_hook:n} initializes the hook in the
+% preamble, and is redefined to \cs{use_none:n} at |\begin{document}|.
+%
+% Both versions do the same internally: check if the hook exist as
+% given, and if so use it as quickly as possible. If it doesn't
+% exist, the a call to \cs{@@_use:wn} checks for file hooks.
+%
+% At |\begin{document}|, all hooks are initialized, and any change in
+% them causes an update, so \cs{hook_use:n} can be made expandable.
+% This one is better not protected so that it can expand into nothing
+% if containing no code. Also important in case of generic hooks that
+% we do not generate a \cs{relax} as a side effect of checking for a
+% csname. In contrast to the \TeX{} low-level
+% \verb=\csname ...\endcsname= construct \cs{tl_if_exist:c} is
+% careful to avoid this.
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_use:n #1
+ {
+ \tl_if_exist:cTF { @@~#1 }
+ {
+ \@@_preamble_hook:n {#1}
+ \cs:w @@~#1 \cs_end:
+ }
+ { \@@_use:wn #1 / \s_@@_mark {#1} }
+ }
+\cs_new:Npn \@@_use_initialized:n #1
+ {
+ \if_cs_exist:w @@~#1 \cs_end:
+ \else:
+ \@@_use_undefined:w
+ \fi:
+ \cs:w @@~#1 \@@_use_end:
+ }
+\cs_new:Npn \@@_use_undefined:w #1 #2 @@~#3 \@@_use_end:
+ {
+ #1 % fi
+ \@@_use:wn #3 / \s_@@_mark {#3}
+ }
+\cs_new_protected:Npn \@@_preamble_hook:n #1
+ { \@@_initialize_hook_code:n {#1} }
+\cs_new_eq:NN \@@_use_end: \cs_end:
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_use:wn}
+% \begin{macro}{\@@_try_file_hook:n,\@@_if_exist_use:n}
+% \cs{@@_use:wn} does a quick check to test if the current hook is a
+% file hook: those need a special treatment. If it is not, the hook
+% does not exist. If it is, then \cs{@@_try_file_hook:n} is called,
+% and checks that the current hook is a file-specific hook using
+% \cs{@@_if_file_hook:wTF}. If it's not, then it's a generic |file/|
+% hook and is used if it exist.
+%
+% If it is a file-specific hook, it passes through the same
+% normalization as during declaration, and then it is used if defined.
+% \cs{@@_if_exist_use:n} checks if the hook exist, and calls
+% \cs{@@_preamble_hook:n} if so, then uses the hook.
+% \begin{macrocode}
+\cs_new:Npn \@@_use:wn #1 / #2 \s_@@_mark #3
+ {
+ \str_if_eq:nnTF {#1} { file }
+ { \@@_try_file_hook:n {#3} }
+ { } % Hook doesn't exist
+ }
+\cs_new_protected:Npn \@@_try_file_hook:n #1
+ {
+ \@@_if_file_hook:wTF #1 / / \s_@@_mark
+ {
+ \exp_args:Ne \@@_if_exist_use:n
+ { \exp_args:Ne \@@_file_hook_normalize:n {#1} }
+ }
+ { \@@_if_exist_use:n {#1} } % file/ generic hook (e.g. file/before)
+ }
+\cs_new_protected:Npn \@@_if_exist_use:n #1
+ {
+ \tl_if_exist:cT { @@~#1 }
+ {
+ \@@_preamble_hook:n {#1}
+ \cs:w @@~#1 \cs_end:
+ }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\hook_use_once:n}
+% For hooks that can and should be used only once we have a special
+% use command that remembers the hook name in
+% \cs{g_@@_execute_immediately_prop}. This has the effect that any
+% further code added to the hook is executed immediately rather
+% than stored in the hook.
+%
+% The code needs some gymnastics to prevent space trimming from the
+% hook name, since \cs{hook_use:n} and \cs{hook_use_once:n} are
+% documented to not trim spaces.
+%
+% \pho{Should this raise an error if the hook doesn't exist?}
+% \begin{macrocode}
+\cs_new_protected:Npn \hook_use_once:n #1
+ {
+ \tl_if_exist:cT { @@~#1 }
+ {
+ \tl_set:Nn \l_@@_return_tl {#1}
+ \@@_normalize_hook_args:Nn \@@_use_once_store:n
+ { \l_@@_return_tl }
+ \hook_use:n {#1}
+ }
+ }
+\cs_new_protected:Npn \@@_use_once_store:n #1
+ { \prop_gput:Nnn \g_@@_execute_immediately_prop {#1} { } }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Querying a hook}
+%
+% Simpler data types, like token lists, have three possible states; they
+% can exist and be empty, exist and be non-empty, and they may not
+% exist, in which case emptiness doesn't apply (though
+% \cs{tl_if_empty:N} returns false in this case).
+%
+% Hooks are a bit more complicated: they have four possible states.
+% A hook may exist or not, and either way it may or may not be empty
+% (even a hook that doesn't exist may be non-empty).
+%
+% A hook is said to be empty when no code was added to it, either to
+% its permanent code pool, or to its ``next'' token list. The hook
+% doesn't need to be declared to have code added to its code pool
+% (it may happen that a package $A$ defines a hook \hook{foo}, but
+% it's loaded after package $B$, which adds some code to that hook.
+% In this case it is important that the code added by package $B$ is
+% remembered until package $A$ is loaded).
+%
+% A hook is said to exist when it was declared with \cs{hook_new:n} or
+% some variant thereof.
+%
+% \begin{macro}[pTF]{\hook_if_empty:n}
+% Test if a hook is empty (that is, no code was added to that hook).
+% A hook being empty means that \emph{both} its
+% \cs[no-index]{g_@@_\meta{hook}_code_prop} and its
+% \cs[no-index]{@@_next~\meta{hook}} are empty.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \hook_if_empty:n #1 { p , T , F , TF }
+ {
+ \@@_if_exist:nTF {#1}
+ {
+ \bool_lazy_and:nnTF
+ { \prop_if_empty_p:c { g_@@_#1_code_prop } }
+ { \tl_if_empty_p:c { @@_next~#1 } }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ { \prg_return_true: }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\hook_if_exist:n}
+% A canonical way to test if a hook exists. A hook exists if the
+% token list that stores the sorted code for that hook,
+% \cs[no-index]{@@~\meta{hook}}, exists. The property list
+% \cs[no-index]{g_@@_\meta{hook}_code_prop} cannot be used here
+% because often it is necessary to add code to a hook without knowing
+% if such hook was already declared, or even if it will ever be
+% (for example, in case the package that defines it isn't loaded).
+% \begin{macrocode}
+\prg_new_conditional:Npnn \hook_if_exist:n #1 { p , T , F , TF }
+ {
+ \tl_if_exist:cTF { @@~#1 }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_if_exist:n}
+% An internal check if the hook has already been declared with
+% \cs{@@_declare:n}. This means that the hook was already used somehow
+% (a code chunk or rule was added to it), but it still wasn't declared
+% with \cs{hook_new:n}.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_exist:n #1 { p , T , F , TF }
+ {
+ \prop_if_exist:cTF { g_@@_#1_code_prop }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_if_reversed:n}
+% An internal conditional that checks if a hook is reversed.
+% \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_reversed:n #1 { p , T , F , TF }
+ {
+ \if_int_compare:w \cs:w g_@@_#1_reversed_tl \cs_end: 1 < 0 \exp_stop_f:
+ \prg_return_true:
+ \else:
+ \prg_return_false:
+ \fi:
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Messages}
+%
+% \begin{macrocode}
+\msg_new:nnnn { hooks } { labels-incompatible }
+ {
+ Labels~`#1'~and~`#2'~are~incompatible
+ \str_if_eq:nnF {#3} {??} { ~in~hook~`#3' } .~
+ \int_compare:nNnTF {#4} = { 1 }
+ { The~ code~ for~ both~ labels~ will~ be~ dropped. }
+ { You~ may~ see~ errors~ later. }
+ }
+ { LaTeX~found~two~incompatible~labels~in~the~same~hook.~
+ This~indicates~an~incompatibility~between~packages. }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnnn { hooks } { exists }
+ { Hook~`#1'~ has~ already~ been~ declared. }
+ { There~ already~ exists~ a~ hook~ declaration~ with~ this~
+ name.\\
+ Please~ use~ a~ different~ name~ for~ your~ hook.}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnn { hooks } { empty-label }
+ { Empty~code~label~\msg_line_context:.~Using~`#1'~instead. }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnnn { hooks } { unknown-rule }
+ { Unknown~ relationship~ `#3'~
+ between~ labels~ `#2'~ and~ `#4'~
+ \str_if_eq:nnF {#1} {??} { ~in~hook~`#1' }. ~
+ Perhaps~ a~ missspelling?
+ }
+ {
+ The~ relation~ used~ not~ known~ to~ the~ system.~ Allowed~ values~ are~
+ `before'~ or~ `<',~
+ `after'~ or~ `>',~
+ `incompatible-warning',~
+ `incompatible-error',~
+ `voids'~ or~
+ `unrelated'.
+ }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\msg_new:nnn { hooks } { should-not-happen }
+ {
+ ERROR!~This~should~not~happen.~#1 \\
+ Please~report~at~https://github.com/latex3/latex2e.
+ }
+% \end{macrocode}
+%
+% \subsection{\LaTeXe{} package interface commands}
+%
+%
+%
+% \begin{macro}{\NewHook,\NewReversedHook,\NewMirroredHookPair}
+% Declaring new hooks \ldots
+% \begin{macrocode}
+\NewDocumentCommand \NewHook { m }{ \hook_new:n {#1} }
+\NewDocumentCommand \NewReversedHook { m }{ \hook_new_reversed:n {#1} }
+\NewDocumentCommand \NewMirroredHookPair { mm }{ \hook_new_pair:nn {#1}{#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\AddToHook}
+%
+% \begin{macrocode}
+\NewDocumentCommand \AddToHook { m o +m }
+ { \hook_gput_code:nnn {#1} {#2} {#3} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\AddToHookNext}
+%
+% \begin{macrocode}
+\NewDocumentCommand \AddToHookNext { m +m }
+ { \hook_gput_next_code:nn {#1} {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\RemoveFromHook}
+%
+% \begin{macrocode}
+\NewDocumentCommand \RemoveFromHook { m o }
+ { \hook_gremove_code:nn {#1} {#2} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\DeclareDefaultHookLabel}
+% \begin{macro}{\@@_curr_name_push:n,\@@_curr_name_pop:}
+% The token list \cs{g_@@_hook_curr_name_tl} stores the name of the
+% current package/file to be used as label for hooks.
+% Providing a consistent interface is tricky, because packages can
+% be loaded within packages, and some packages may not use
+% \cs{DeclareDefaultHookLabel} to change the default label (in which case
+% \cs{@currname} is used, if set).
+%
+% To pull that off, we keep a stack that contains the default label
+% for each level of input. The bottom of the stack contains the
+% default label for the top-level. Since the string \verb|top-level|
+% is hardcoded, here this item of the stack is empty. Also, since
+% we're in an input level, add \verb|lthooks| to the stack as well.
+% This stack should never go empty. An empty entry is added to the
+% stack to account for the \verb|top-level|. The item is empty so
+% that the hard-coded default is used, but a call to
+% \cs{DeclareDefaultHookLabel} will change it if needed.
+% \begin{macrocode}
+\seq_gpush:Nn \g_@@_name_stack_seq { }
+% \end{macrocode}
+%
+%
+% Two commands keep track of the stack: when a file is input,
+% \cs{@@_curr_name_push:n} pushes an (empty by default) label to the
+% stack:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_curr_name_push:n #1
+ {
+ \seq_gpush:Nn \g_@@_name_stack_seq {#1}
+ \tl_gset:Nn \g_@@_hook_curr_name_tl {#1}
+ }
+%
+% \end{macrocode}
+% and when an input is over, the topmost item of the stack is popped,
+% since the label will not be used again, and \cs{g_@@_hook_curr_name_tl}
+% is updated to the now topmost item of the stack:
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_curr_name_pop:
+ {
+ \seq_gpop:NN \g_@@_name_stack_seq \l_@@_return_tl
+ \seq_get:NNTF \g_@@_name_stack_seq \l_@@_return_tl
+ { \tl_gset_eq:NN \g_@@_hook_curr_name_tl \l_@@_return_tl }
+ {
+ \msg_error:nnn { hooks } { should-not-happen }
+ { Tried~to~pop~from~an~empty~default~label~stack. }
+ }
+ }
+% \end{macrocode}
+%
+% The token list \cs{g_@@_hook_curr_name_tl} is but a mirror of the top
+% of the stack.
+%
+% Now define a wrapper that replaces the top of the stack with the
+% argument, and updates \cs{g_@@_hook_curr_name_tl} accordingly.
+% \begin{macrocode}
+\NewDocumentCommand \DeclareDefaultHookLabel { m }
+ {
+ \seq_gpop:NN \g_@@_name_stack_seq \l_@@_return_tl
+ \@@_curr_name_push:n {#1}
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\UseHook,\UseOneTimeHook}
+% Avoid the overhead of \pkg{xparse} and its protection that we
+% don't want here (since the hook should vanish without trace if empty)!
+% \begin{macrocode}
+\cs_new:Npn \UseHook { \hook_use:n }
+\cs_new:Npn \UseOneTimeHook { \hook_use_once:n }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\ShowHook,\LogHook}
+% \begin{macrocode}
+\cs_new_protected:Npn \ShowHook { \hook_show:n }
+\cs_new_protected:Npn \LogHook { \hook_log:n }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\DebugHooksOn,\DebugHooksOff}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \DebugHooksOn { \hook_debug_on: }
+\cs_new_protected:Npn \DebugHooksOff { \hook_debug_off: }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\DeclareHookRule}
+%
+% \begin{macrocode}
+\NewDocumentCommand \DeclareHookRule { m m m m }
+ { \hook_gset_rule:nnnn {#1}{#2}{#3}{#4} }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\DeclareDefaultHookRule}
+% This declaration is only supported before \verb=\begin{document}=.
+% \begin{macrocode}
+\NewDocumentCommand \DeclareDefaultHookRule { m m m }
+ { \hook_gset_rule:nnnn {??}{#1}{#2}{#3} }
+\@onlypreamble\DeclareDefaultHookRule
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ClearHookRule}
+% A special setup rule that removes an existing relation.
+% Basically {@@_rule_gclear:nnn} plus fixing the property list for debugging.
+% \fmi{Need an L3 interface, or maybe it should get dropped?}
+% \begin{macrocode}
+\NewDocumentCommand \ClearHookRule { m m m }
+{ \hook_gset_rule:nnnn {#1}{#2}{unrelated}{#3} }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}[EXP]{\IfHookExistsTF,\IfHookEmptyTF}
+% Here we avoid the overhead of \pkg{xparse}, since \cs{IfHookEmptyTF}
+% is used in \cs{end} (that is, every \LaTeX{} environment). As a
+% further optimisation, use \cs{let} rather than \cs{def} to avoid one
+% expansion step.
+% \begin{macrocode}
+\cs_new_eq:NN \IfHookExistsTF \hook_if_exist:nTF
+\cs_new_eq:NN \IfHookEmptyTF \hook_if_empty:nTF
+% \end{macrocode}
+% \end{macro}
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
+%
+% \subsection{Internal commands needed elsewhere}
+%
+% Here we set up a few horrible (but consistent) \LaTeXe{} names to
+% allow for internal commands to be used outside this module. We
+% have to unset the \texttt{@\/@} since we want double ``at'' sign
+% in place of double underscores.
+%
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+% \begin{macro}{\@expl@@@initialize@all@@,
+% \@expl@@@hook@curr@name@push@@n,
+% \@expl@@@hook@curr@name@pop@@}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@initialize@all@@
+ \__hook_initialize_all:
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@hook@curr@name@push@@n
+ \__hook_curr_name_push:n
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \@expl@@@hook@curr@name@pop@@
+ \__hook_curr_name_pop:
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+% \end{macrocode}
+%
+%
+% Rolling back here doesn't undefine the interface commands as they
+% may be used in packages without rollback functionality. So we
+% just make them do nothing which may or may not work depending on
+% the code usage.
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\NewHook}{The hook management}%
+%<latexrelease>
+%<latexrelease>\def \NewHook#1{}
+%<latexrelease>\def \NewReversedHook#1{}
+%<latexrelease>\def \NewMirroredHookPair#1#2{}
+%<latexrelease>
+%<latexrelease>\long\def \AddToHook#1#2{}
+%<latexrelease>
+%<latexrelease>\def \AddToHookNext#1{\@gobble@AddToHook@args}
+%<latexrelease>\providecommand\@gobble@AddToHook@args[2][]{}
+%<latexrelease>
+%<latexrelease>\def\RemoveFromHook#1{\@gobble@RemoveFromHook@arg}
+%<latexrelease>\providecommand\@gobble@RemoveFromHook@arg[1][]{}
+%<latexrelease>
+%<latexrelease>\def \UseHook #1{}
+%<latexrelease>\def \UseOneTimeHook #1{}
+%<latexrelease>\def \ShowHook #1{}
+%<latexrelease>\let \DebugHooksOn \@empty
+%<latexrelease>\let \DebugHooksOff\@empty
+%<latexrelease>
+%<latexrelease>\def \DeclareHookRul#1#2#3#4{}
+%<latexrelease>\def \DeclareDefaultHookRule #1#2#3{}
+%<latexrelease>\def \ClearHookRule#1#2#3{}
+% \end{macrocode}
+% If the hook management is not provided we make the test for existence
+% false and the test for empty true in the hope that this is most
+% of the time reasonable. If not a package would need to guard
+% against running in an old kernel.
+% \begin{macrocode}
+%<latexrelease>\def \IfHookExistTF #1#2#3{#3}
+%<latexrelease>\def \IfHookEmptyTF #1#2#3{#2}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+%
+% \Finale
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\endinput
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/Master/texmf-dist/source/latex/base/ltlists.dtx b/Master/texmf-dist/source/latex/base/ltlists.dtx
index e8c9ebc16bd..653e4e2edd2 100644
--- a/Master/texmf-dist/source/latex/base/ltlists.dtx
+++ b/Master/texmf-dist/source/latex/base/ltlists.dtx
@@ -31,7 +31,7 @@
%<*driver>
% \fi
\ProvidesFile{ltlists.dtx}
- [2015/05/10 v1.0t LaTeX Kernel (List Environments)]
+ [2020/04/24 v1.0t LaTeX Kernel (List Environments)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltlists.dtx}
@@ -546,6 +546,7 @@
% \end{macrocode}
% \end{macro}\end{macro}\end{macro}
%
+% \begin{environment}{list}
% \begin{macro}{\list}
% \begin{macrocode}
\def\list#1#2{%
@@ -572,6 +573,7 @@
\ignorespaces}
% \end{macrocode}
% \end{macro}
+% \end{environment}
%
% \begin{macro}{\par@deathcycles}
% \begin{macrocode}
@@ -626,8 +628,9 @@
% \end{macrocode}
% \end{macro}
%
-% \changes{0.0}{1992/03/18}{RmS: added \cs{@nmbrlistfalse}}
+% \begin{environment}{trivlist}
% \begin{macro}{\trivlist}
+% \changes{0.0}{1992/03/18}{RmS: added \cs{@nmbrlistfalse}}
% \begin{macrocode}
\def\trivlist{%
\parsep\parskip
@@ -647,6 +650,7 @@
\def\makelabel##1{##1}}
% \end{macrocode}
% \end{macro}
+% \end{environment}
%
% \begin{macro}{\endlist}
% \begin{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltluatex.dtx b/Master/texmf-dist/source/latex/base/ltluatex.dtx
index 1f9ab8d1332..8573b3e6ca6 100644
--- a/Master/texmf-dist/source/latex/base/ltluatex.dtx
+++ b/Master/texmf-dist/source/latex/base/ltluatex.dtx
@@ -23,12 +23,12 @@
%<tex> \ProvidesFile\undefined\begingroup\def\ProvidesFile
%<tex> #1#2[#3]{\endgroup\immediate\write-1{File: #1 #3}}
%<tex>\fi
-%<plain>\ProvidesFile{ltluatex.tex}
+%<plain>\ProvidesFile{ltluatex.tex}%
%<*driver>
\ProvidesFile{ltluatex.dtx}
%</driver>
%<*tex>
-[2020/02/02 v1.1l
+[2020/09/25 v1.1s
%</tex>
%<plain> LuaTeX support for plain TeX (core)
%<*tex>
@@ -406,6 +406,14 @@
\fi
% \end{macrocode}
%
+% \changes{v1.1n}{2020/06/10}{Define \cs{@gobble}/\cs{@firstofone} even for \LaTeX\ to allow early loading.}
+% Two simple \LaTeX\ macros from |ltdefns.dtx| have to be defined here
+% because ltdefns.dtx is not loaded yet when ltluatex.dtx is executed.
+% \begin{macrocode}
+\long\def\@gobble#1{}
+\long\def\@firstofone#1{#1}
+% \end{macrocode}
+%
% \subsection{Older \LaTeX{}/Plain \TeX\ setup}
%
% \begin{macrocode}
@@ -451,7 +459,7 @@
% \end{macrocode}
% luatex/xetex also allow more math fam.
% \begin{macrocode}
-\edef \et@xmaxfam {\ifx\Umathchar\@undefined\sixt@@n\else\@cclvi\fi}
+\edef \et@xmaxfam {\ifx\Umathcode\@undefined\sixt@@n\else\@cclvi\fi}
% \end{macrocode}
%
% \begin{macrocode}
@@ -521,12 +529,6 @@
\fi}%
% \end{macrocode}
%
-% Two simple \LaTeX\ macros used in |ltlatex.sty|.
-% \begin{macrocode}
-\long\def\@gobble#1{}
-\long\def\@firstofone#1{#1}
-% \end{macrocode}
-%
% Fix up allocations not to clash with |etex.src|.
%
% \begin{macrocode}
@@ -544,23 +546,23 @@
%</tex>
% \end{macrocode}
%
-%
% \subsection{Attributes}
%
% \begin{macro}{\newattribute}
% \changes{v1.0a}{2015/09/24}{Macro added}
+% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional}
% As is generally the case for the Lua\TeX{} registers we start here
% from~$1$. Notably, some code assumes that |\attribute0| is never used so
% this is important in this case.
% \begin{macrocode}
\ifx\e@alloc@attribute@count\@undefined
\countdef\e@alloc@attribute@count=258
+ \e@alloc@attribute@count=\z@
\fi
\def\newattribute#1{%
\e@alloc\attribute\attributedef
\e@alloc@attribute@count\m@ne\e@alloc@top#1%
}
-\e@alloc@attribute@count=\z@
% \end{macrocode}
% \end{macro}
%
@@ -585,13 +587,13 @@
% \begin{macrocode}
\ifx\e@alloc@ccodetable@count\@undefined
\countdef\e@alloc@ccodetable@count=259
+ \e@alloc@ccodetable@count=\z@
\fi
\def\newcatcodetable#1{%
\e@alloc\catcodetable\chardef
\e@alloc@ccodetable@count\m@ne{"8000}#1%
\initcatcodetable\allocationnumber
}
-\e@alloc@ccodetable@count=\z@
% \end{macrocode}
% \end{macro}
%
@@ -698,18 +700,19 @@
%
% \begin{macro}{\newluafunction}
% \changes{v1.0a}{2015/09/24}{Macro added}
+% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional}
% Much the same story for allocating Lua\TeX{} functions except here they are
% just numbers so they are allocated in the same way as boxes.
% Lua indexes from~$1$ so once again slot~$0$ is skipped.
% \begin{macrocode}
\ifx\e@alloc@luafunction@count\@undefined
\countdef\e@alloc@luafunction@count=260
+ \e@alloc@luafunction@count=\z@
\fi
\def\newluafunction{%
\e@alloc\luafunction\e@alloc@chardef
\e@alloc@luafunction@count\m@ne\e@alloc@top
}
-\e@alloc@luafunction@count=\z@
% \end{macrocode}
% \end{macro}
%
@@ -717,17 +720,18 @@
%
% \begin{macro}{\newwhatsit}
% \changes{v1.0a}{2015/09/24}{Macro added}
+% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional}
% These are only settable from Lua but for consistency are definable
% here.
% \begin{macrocode}
\ifx\e@alloc@whatsit@count\@undefined
\countdef\e@alloc@whatsit@count=261
+ \e@alloc@whatsit@count=\z@
\fi
\def\newwhatsit#1{%
\e@alloc\whatsit\e@alloc@chardef
\e@alloc@whatsit@count\m@ne\e@alloc@top#1%
}
-\e@alloc@whatsit@count=\z@
% \end{macrocode}
% \end{macro}
%
@@ -735,17 +739,18 @@
%
% \begin{macro}{\newluabytecode}
% \changes{v1.0a}{2015/09/24}{Macro added}
+% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional}
% These are only settable from Lua but for consistency are definable
% here.
% \begin{macrocode}
\ifx\e@alloc@bytecode@count\@undefined
\countdef\e@alloc@bytecode@count=262
+ \e@alloc@bytecode@count=\z@
\fi
\def\newluabytecode#1{%
\e@alloc\luabytecode\e@alloc@chardef
\e@alloc@bytecode@count\m@ne\e@alloc@top#1%
}
-\e@alloc@bytecode@count=\z@
% \end{macrocode}
% \end{macro}
%
@@ -753,12 +758,14 @@
% \begin{macro}{\newluachunkname}
% \changes{v1.0a}{2015/09/24}{Macro added}
+% \changes{v1.1q}{2020/08/02}{Move reset to $0$ inside conditional}
% As for bytecode registers, but in addition we need to add a string
% to the \verb|lua.name| table to use in stack tracing. We use the
% name of the command passed to the allocator, with no backslash.
% \begin{macrocode}
\ifx\e@alloc@luachunk@count\@undefined
\countdef\e@alloc@luachunk@count=263
+ \e@alloc@luachunk@count=\z@
\fi
\def\newluachunkname#1{%
\e@alloc\luachunk\e@alloc@chardef
@@ -766,19 +773,31 @@
{\escapechar\m@ne
\directlua{lua.name[\the\allocationnumber]="\string#1"}}%
}
-\e@alloc@luachunk@count=\z@
% \end{macrocode}
% \end{macro}
%
% \subsection{Lua loader}
+% \changes{v1.1r}{2020/08/10}{Load ltluatex Lua module during format building}
+%
+% Lua code loaded in the format often has to to be loaded again at the
+% beginning of every job, so we define a helper whch allows us to avoid
+% duplicated code:
+%
+% \begin{macrocode}
+\def\now@and@everyjob#1{%
+ \everyjob\expandafter{\the\everyjob
+ #1%
+ }%
+ #1%
+}
+% \end{macrocode}
%
% Load the Lua code at the start of every job.
% For the conversion of \TeX{} into numbers at the Lua side we need some
% known registers: for convenience we use a set of systematic names, which
% means using a group around the Lua loader.
% \begin{macrocode}
-%<2ekernel>\everyjob\expandafter{%
-%<2ekernel> \the\everyjob
+%<2ekernel>\now@and@everyjob{%
\begingroup
\attributedef\attributezero=0 %
\chardef \charzero =0 %
@@ -1321,6 +1340,7 @@ local callbacktypes = callbacktypes or {
% \changes{v1.1k}{2019/10/02}{process\_rule is \texttt{exclusive}}
% \changes{v1.1k}{2019/10/02}{mlist\_to\_hlist is \texttt{exclusive}}
% \changes{v1.1l}{2020/02/02}{post\_linebreak\_filter is \texttt{reverselist}}
+% \changes{v1.1p}{2020/08/01}{new\_graf is \texttt{exclusive}}
% \begin{macrocode}
contribute_filter = simple,
buildpage_filter = simple,
@@ -1342,7 +1362,7 @@ local callbacktypes = callbacktypes or {
pre_mlist_to_hlist_filter = list,
mlist_to_hlist = exclusive,
post_mlist_to_hlist_filter = reverselist,
- new_graf = simple,
+ new_graf = exclusive,
% \end{macrocode}
% Section 8.5: information reporting callbacks.
% \changes{v1.0m}{2016/02/11}{show\_warning\_message added}
@@ -1481,6 +1501,7 @@ end
% \end{macrocode}
% Handler for |list| callbacks.
% \changes{v1.0k}{2015/12/02}{resolve name and i.description (PHG)}
+% \changes{v1.1s}{2020/12/02}{Fix return value of list callbacks}
% \begin{macrocode}
local function list_handler(name)
return function(head, ...)
@@ -1493,7 +1514,7 @@ local function list_handler(name)
"Function `" .. i.description .. "' returned false\n"
.. "in callback `" .. name .."'"
)
- break
+ return false
end
if ret ~= true then
alltrue = false
@@ -1526,7 +1547,7 @@ local function reverselist_handler(name)
"Function `" .. cb.description .. "' returned false\n"
.. "in callback `" .. name .."'"
)
- break
+ return false
end
if ret ~= true then
alltrue = false
@@ -1716,6 +1737,7 @@ luatexbase.add_to_callback = add_to_callback
% \changes{v1.0a}{2015/09/24}{Function added}
% \changes{v1.0k}{2015/12/02}{adjust initialisation of cb local (PHG)}
% \changes{v1.0k}{2015/12/02}{Give more specific error messages (PHG)}
+% \changes{v1.1m}{2020/03/07}{Do not call callback.register for user-defined callbacks}
% Remove a function from a callback. First check arguments.
% \begin{macrocode}
local function remove_from_callback(name, description)
@@ -1761,7 +1783,9 @@ local function remove_from_callback(name, description)
)
if #l == 0 then
callbacklist[name] = nil
- callback_register(name, nil)
+ if user_callbacks_defaults[name] == nil then
+ callback_register(name, nil)
+ end
end
return cb.func,cb.description
end
diff --git a/Master/texmf-dist/source/latex/base/ltmath.dtx b/Master/texmf-dist/source/latex/base/ltmath.dtx
index 18688068b04..36b8bb7ec46 100644
--- a/Master/texmf-dist/source/latex/base/ltmath.dtx
+++ b/Master/texmf-dist/source/latex/base/ltmath.dtx
@@ -38,7 +38,7 @@
%<*driver>
% \fi
\ProvidesFile{ltmath.dtx}
- [2019/08/27 v1.2c LaTeX Kernel (Math Setup)]
+ [2020/07/27 v1.2g LaTeX Kernel (Math Setup)]
% \iffalse
%</driver>
%
@@ -407,15 +407,17 @@
% \begin{macro}{\cases}
% \changes{LaTeX2.09}{1991/08/14}
% {(RmS) inserted extra braces around entry for NFSS}
+% \changes{v1.2g}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
% \begin{macrocode}
-\DeclareRobustCommand\cases[1]{\left\{\,\vcenter{\normalbaselines\m@th
+\DeclareRobustCommand*\cases[1]{\left\{\,\vcenter{\normalbaselines\m@th
\ialign{$##\hfil$&\quad{##}\hfil\crcr#1\crcr}}\right.}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\matrix}
+% \changes{v1.2g}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
% \begin{macrocode}
-\DeclareRobustCommand\matrix[1]{\null\,\vcenter{\normalbaselines\m@th
+\DeclareRobustCommand*\matrix[1]{\null\,\vcenter{\normalbaselines\m@th
\ialign{\hfil$##$\hfil&&\quad\hfil$##$\hfil\crcr
\mathstrut\crcr\noalign{\kern-\baselineskip}
#1\crcr\mathstrut\crcr\noalign{\kern-\baselineskip}}}\,}
@@ -423,8 +425,9 @@
% \end{macro}
%
% \begin{macro}{\pmatrix}
+% \changes{v1.2g}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
% \begin{macrocode}
-\DeclareRobustCommand\pmatrix[1]{\left(\matrix{#1}\right)}
+\DeclareRobustCommand*\pmatrix[1]{\left(\matrix{#1}\right)}
% \end{macrocode}
% \end{macro}
%
@@ -509,18 +512,103 @@
% \end{macro}
% \end{macro}
%
-% \begin{macro}{\>}
-% \begin{macro}{\;}
-% \begin{macro}{\!}
+
+
+%
+% \begin{macro}{\tmspace}
+% \begin{macro}{\,}
+% \begin{macro}{\thinspace}
+% \begin{macro}{\!}
+% \begin{macro}{\negthinspace}
+% \begin{macro}{\:}
+% \begin{macro}{\medspace}
+% \begin{macro}{\negmedspace}
+% \begin{macro}{\;}
+% \begin{macro}{\thickspace}
+% \begin{macro}{\negthickspace}
+%
+% Originally \LaTeX{} only provided a small set of spacing commands
+% for use in text and math, some of the commands like \cs{;} were
+% only supported in manth mode. \texttt{amsmath} normalized and
+% provided all of them in text and math. This code has now been
+% moved to the kernel so that it is generally available.
+%
+%
% \begin{macrocode}
-%\def\,{\mskip\thinmuskip} % already defined in ltspace
-\def\>{\mskip\medmuskip}
-\def\;{\mskip\thickmuskip}
-\def\!{\mskip-\thinmuskip}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\tmspace}{amsmath spacing commands}%
+% \end{macrocode}
+% \cs{tmspace} is really meant to be an internal command so it
+% doesn't necessarily has to be robust but it was robust in
+% \texttt{amsmath} so we leave it like that.
+% \changes{v1.2e}{2020/03/07}{Add \texttt{amsmath} math/text spacing
+% commands to the kernel (gh/303)}
+% \begin{macrocode}
+\DeclareRobustCommand\tmspace[3]{%
+ \ifmmode\mskip#1#2\else\leavevmode@ifvmode\kern#1#3\fi\relax}
+% \end{macrocode}
+% In \texttt{amsmath} the text kern is \texttt{.1667em}. For
+% compatibility reasons we keep the longer one.
+% \begin{macrocode}
+\DeclareRobustCommand\,{\tmspace+\thinmuskip{.16667em}}
+\let\thinspace\,
% \end{macrocode}
-% \end{macro}
-% \end{macro}
-% \end{macro}
+%
+% \begin{macrocode}
+\DeclareRobustCommand\!{\tmspace-\thinmuskip{.16667em}}
+\let\negthinspace\!
+% \end{macrocode}
+%
+% \begin{macrocode}
+\DeclareRobustCommand\:{\tmspace+\medmuskip{.2222em}}
+\let\medspace\:
+% \end{macrocode}
+% \LaTeX{} has a second name for this in its manual:
+% \begin{macrocode}
+\let\>=\:
+\DeclareRobustCommand\negmedspace{\tmspace-\medmuskip{.2222em}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\DeclareRobustCommand\;{\tmspace+\thickmuskip{.2777em}}
+\let\thickspace\;
+\DeclareRobustCommand\negthickspace{\tmspace-\thickmuskip{.2777em}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\tmspace}{amsmath spacing commands}%
+%<latexrelease>
+%<latexrelease>\let\tmspace\@undefined
+%<latexrelease>\DeclareRobustCommand{\,}{%
+%<latexrelease> \relax\ifmmode\mskip\thinmuskip\else\thinspace\fi}
+%<latexrelease>\DeclareRobustCommand\thinspace{\leavevmode@ifvmode\kern .16667em }
+%<latexrelease>\DeclareRobustCommand\negthinspace{\leavevmode@ifvmode\kern-.16667em }
+%<latexrelease>\def\>{\mskip\medmuskip}
+%<latexrelease>\let\:=\>
+%<latexrelease>\def\;{\mskip\thickmuskip}
+%<latexrelease>\def\!{\mskip-\thinmuskip}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
%
% \begin{macro}{\*}
% \begin{macrocode}
@@ -532,7 +620,7 @@
% Nickname for the medium space since |\>| is not available inside
% \texttt{tabbing}.
% \begin{macrocode}
-\let\:=\>
+%\let\:=\>
% \end{macrocode}
% \end{macro}
%
@@ -884,12 +972,32 @@
\def\@yeqncr{\@testopt\@xeqncr\z@skip}
% \end{macrocode}
%
+% \changes{v1.2f}{2020/04/21}{Support calc syntax (gh/152)}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@xeqncr}{eqnarray support calc syntax}%
\def\@xeqncr[#1]{%
\ifnum0=`{\fi}%
\@@eqncr
- \noalign{\penalty\@eqpen\vskip\jot\vskip #1\relax}%
+ \noalign{\penalty\@eqpen\vskip\jot\@vspace@calcify{#1}}%
}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@xeqncr}{eqnarray support calc syntax}%
+%<latexrelease>
+%<latexrelease>\def\@xeqncr[#1]{%
+%<latexrelease> \ifnum0=`{\fi}%
+%<latexrelease> \@@eqncr
+%<latexrelease> \noalign{\penalty\@eqpen\vskip\jot\vskip #1\relax}%
+%<latexrelease>}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
%
% \end{macro}
@@ -1009,9 +1117,11 @@
%
% \begin{macro}{\mathindent}
% The amount of indentation of the equations is stored in a register.
+% \changes{v1.2d}{2020/02/18}{Make \cs{mathindent} a skip register to match
+% amsmath (gh/252)}
% \begin{macrocode}
%<*fleqn>
-\newdimen\mathindent
+\newskip\mathindent
% \end{macrocode}
% The setting of |\mathindent| has to be deferred until the class
% file has been processed, because |\leftmargini| is still 0pt
@@ -1097,7 +1207,13 @@
\hb@xt@\linewidth\bgroup $\m@th% $
\displaystyle
\hskip\mathindent}%
- {$\hfil % $
+% \end{macrocode}
+% Ensure that there is at least a space between formula and
+% equation number so that they don't bump in each other.
+% \changes{v1.2d}{2020/02/18}{Separate formula and eqn number by at
+% least a space in fleqn option}
+% \begin{macrocode}
+ {$\hskip .3em minus.3em\hfil % $
\displaywidth\linewidth\hbox{\@eqnnum}%
\egroup
\endtrivlist}
diff --git a/Master/texmf-dist/source/latex/base/ltmiscen.dtx b/Master/texmf-dist/source/latex/base/ltmiscen.dtx
index 97b1f4a572b..0c115d3be1b 100644
--- a/Master/texmf-dist/source/latex/base/ltmiscen.dtx
+++ b/Master/texmf-dist/source/latex/base/ltmiscen.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltmiscen.dtx}
- [2019/11/02 v1.1s LaTeX Kernel (Misc. Environments)]
+ [2020/08/21 v1.1v LaTeX Kernel (Misc. Environments)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltmiscen.dtx}
@@ -73,6 +73,7 @@
% \cs{@noligs}.}
% \changes{v1.1g}{1998/08/17}{(RmS) Minor documentation fixes.}
% \changes{v1.1p}{2019/08/27}{Make various commands robust}
+% \changes{v1.1v}{2020/08/21}{Integration of new hook management interface}
%
% \section{Miscellaneous Environments}
% This section implements the basic environment mechanism, and also
@@ -182,6 +183,7 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{environment}{document}
% \begin{macro}{\enddocument}
% \changes{LaTeX2.09}{1993/08/03}
% {Changed redefinition of \cs{global} to redefinition
@@ -190,6 +192,10 @@
% {Added warning in case of undefined references.}%
% \changes{v0.9e}{1993/12/09}{Hook added}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\enddocument}{Use Hooks}%
\def\enddocument{%
% \end{macrocode}
% The |\end{document}| hook is executed first. If necessary it can
@@ -208,10 +214,15 @@
% \changes{v1.1i}{2000/05/19}
% {Reset \cs{AtEndDocument} for latex/3060}
% \begin{macrocode}
- \let\AtEndDocument\@firstofone
- \@enddocumenthook
+ \UseOneTimeHook{enddocument}%
+ \@kernel@after@enddocument
+% \end{macrocode}
+%
+% \begin{macrocode}
\@checkend{document}%
\clearpage
+ \UseOneTimeHook{enddocument/afterlastpage}%
+ \@kernel@after@enddocument@afterlastpage
\begingroup
\if@filesw
\immediate\closeout\@mainaux
@@ -234,11 +245,52 @@
\@tempswafalse
\makeatletter \@@input\jobname.aux
\fi
+ \UseHook{enddocument/afteraux}%
% \end{macrocode}
-% \changes{v1.0w}{1994/11/30}
-% {(DPC) Use \cs{@dofilelist}}
+% Next hook is expect to contain only code for writing info
+% messages on the terminal.
+% \begin{macrocode}
+ \UseOneTimeHook{enddocument/info}%
+ \endgroup
+ \UseOneTimeHook{enddocument/end}%
+ \deadcycles\z@\@@end}
+% \end{macrocode}
+%
+% The public hooks used in \cs{enddocument}:
+% \begin{macrocode}
+\NewHook{enddocument}
+\NewHook{enddocument/afterlastpage}
+\NewHook{enddocument/afteraux}
+\NewHook{enddocument/info}
+\NewHook{enddocument/end}
+% \end{macrocode}
+%
+% This is one of the few places where we already add data and rules
+% to a hook already in the kernel.
+% \changes{v1.0w}{1994/11/30}{(DPC) Use \cs{@dofilelist}}
+% \begin{macrocode}
+\AddToHook{enddocument/info}[kernel/filelist]{\@dofilelist}
+\AddToHook{enddocument/info}[kernel/warnings]{\@enddocument@kernel@warnings}
+\DeclareHookRule{enddocument/info}{kernel/filelist}{before}{kernel/warnings}
+% \end{macrocode}
+% \end{macro}
+% \end{environment}
+%
+%
+% \begin{macro}{\@kernel@after@enddocument,
+% \@kernel@after@enddocument@afterlastpage}
+%
+% The two kernel hooks above are used by the shipout code.
+% \begin{macrocode}
+\let\@kernel@after@enddocument\@empty
+\let\@kernel@after@enddocument@afterlastpage\@empty
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@enddocument@kernel@warnings}
+%
% \begin{macrocode}
- \@dofilelist
+\def\@enddocument@kernel@warnings{%
% \end{macrocode}
% First we check for font size substitution bigger than
% |\fontsubfuzz|. The |\relax| is necessary because this is a macro
@@ -246,29 +298,29 @@
% \changes{v1.0w}{1994/11/30}
% {(DPC) Do warnings even for \cs{nofiles}}
% \begin{macrocode}
- \ifdim \font@submax >\fontsubfuzz\relax
+ \ifdim \font@submax >\fontsubfuzz\relax
% \end{macrocode}
% In case you wonder about the |\@gobbletwo| inside the message
% below, this is a horrible hack to remove the tokens |\on@line.|
% that are added by |\@font@warning| at the end.
% \changes{v1.1j}{2000/07/11}{Fix typo in warning}
% \begin{macrocode}
- \@font@warning{Size substitutions with differences\MessageBreak
- up to \font@submax\space have occurred.\@gobbletwo}%
- \fi
+ \@font@warning{Size substitutions with differences\MessageBreak
+ up to \font@submax\space have occurred.\@gobbletwo}%
+ \fi
% \end{macrocode}
% The macro |\@defaultsubs| is initially |\relax| but gets redefined
% to produce
% a warning if there have been some default font substitutions.
% \changes{v1.0z}{1995/07/13}{Use \cs{@defaultsubs} instead of switch}
% \begin{macrocode}
- \@defaultsubs
+ \@defaultsubs
% \end{macrocode}
% The macro |\@refundefined| is initially |\relax| but gets redefined
% to produce a warning if there are undefined refs.
% \changes{v1.1b}{1995/10/24}{Use \cs{@refundefined} instead of switch}
% \begin{macrocode}
- \@refundefined
+ \@refundefined
% \end{macrocode}
% If a label is defined more than once, |\@tempswa| will always be
% true and thus produce a ``Label(s) may \ldots'' warning. But
@@ -280,21 +332,78 @@
% \changes{v1.1b}{1995/10/24}{Changed logic for producing
% warning messages and removed switch}
% \begin{macrocode}
- \if@filesw
- \ifx \@multiplelabels \relax
- \if@tempswa
- \@latex@warning@no@line{Label(s) may have changed.
- Rerun to get cross-references right}%
- \fi
- \else
- \@multiplelabels
+ \if@filesw
+ \ifx \@multiplelabels \relax
+ \if@tempswa
+ \@latex@warning@no@line{Label(s) may have changed.
+ Rerun to get cross-references right}%
\fi
+ \else
+ \@multiplelabels
+ \fi
+ \ifx \@extra@page@added \relax
+ \@latex@warning@no@line{Temporary extra page added at the end.
+ Rerun to get it removed}%
\fi
- \endgroup
- \deadcycles\z@\@@end}
+% \end{macrocode}
+% We could think of adding a warning that nothing can be corrected
+% while \cs{nofiles} is in force. In the past the warnings related
+% to the \texttt{aux} file are simply suppressed in this case.
+% \begin{macrocode}
+ \fi
+}
% \end{macrocode}
% \end{macro}
%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\enddocument}{Use Hooks}%
+%<latexrelease>
+%<latexrelease>\def\enddocument{%
+%<latexrelease> \let\AtEndDocument\@firstofone
+%<latexrelease> \@enddocumenthook
+%<latexrelease> \@checkend{document}%
+%<latexrelease> \clearpage
+%<latexrelease> \begingroup
+%<latexrelease> \if@filesw
+%<latexrelease> \immediate\closeout\@mainaux
+%<latexrelease> \let\@setckpt\@gobbletwo
+%<latexrelease> \let\@newl@bel\@testdef
+%<latexrelease> \@tempswafalse
+%<latexrelease> \makeatletter \@@input\jobname.aux
+%<latexrelease> \fi
+%<latexrelease> \@dofilelist
+%<latexrelease> \ifdim \font@submax >\fontsubfuzz\relax
+%<latexrelease> \@font@warning{Size substitutions with differences\MessageBreak
+%<latexrelease> up to \font@submax\space have occurred.\@gobbletwo}%
+%<latexrelease> \fi
+%<latexrelease> \@defaultsubs
+%<latexrelease> \@refundefined
+%<latexrelease> \if@filesw
+%<latexrelease> \ifx \@multiplelabels \relax
+%<latexrelease> \if@tempswa
+%<latexrelease> \@latex@warning@no@line{Label(s) may have changed.
+%<latexrelease> Rerun to get cross-references right}%
+%<latexrelease> \fi
+%<latexrelease> \else
+%<latexrelease> \@multiplelabels
+%<latexrelease> \fi
+%<latexrelease> \fi
+%<latexrelease> \endgroup
+%<latexrelease> \deadcycles\z@\@@end}
+%<latexrelease>
+%<latexrelease>\let\@kernel@after@enddocument\@undefined
+%<latexrelease>\let\@kernel@after@enddocument@afterlastpage\@undefined
+%<latexrelease>\let\@enddocument@kernel@warnings\@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+%
+%
% \begin{macro}{\@testdef}
% \begin{macrocode}
\def\@testdef #1#2#3{%
@@ -523,17 +632,107 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2019/10/01}%
-%<latexrelease> {\begin}{Making \begin/\end robust}%
-\DeclareRobustCommand\begin[1]{%
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\begin}{Use hook system}%
+\DeclareRobustCommand*\begin[1]{%
+ \UseHook{env/#1/before}%
\@ifundefined{#1}%
{\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}%
{\def\reserved@a{\def\@currenvir{#1}%
- \edef\@currenvline{\on@line}%
- \csname #1\endcsname}}%
+ \edef\@currenvline{\on@line}%
+ \@execute@begin@hook{#1}%
+ \csname #1\endcsname}}%
\@ignorefalse
\begingroup\@endpefalse\reserved@a}
% \end{macrocode}
+%
+% Before the \cs{document} code is executed we have to first undo
+% the \cs{endgroup} as there should be none for this environment to
+% avoid that changes on top-level unnecessarily go to \TeX's
+% savestack, and we have to initialize all hooks in the hook system.
+% So we need to test for this environment name. But once it has be
+% found all this testing is no longer needed and so we redefine
+% \cs{@execute@begin@hook} to simply use the hook.
+% \begin{macrocode}
+\def\@execute@begin@hook #1{%
+ \expandafter\ifx\csname #1\endcsname\document
+ \endgroup
+ \gdef\@execute@begin@hook##1{\UseHook{env/##1/begin}}%
+ \@expl@@@initialize@all@@
+ \fi
+% \end{macrocode}
+% If this is an environment before \verb=\begin{document}= we just
+% run the hook so this can be outside the test.
+% \begin{macrocode}
+ \UseHook{env/#1/begin}%
+}
+% \end{macrocode}
+%
+% The top level definition for \cs{end}. for an explanation see
+% below (this is the same as the 2019 version where it was
+% introduced, but for rollback we have to repeat it).
+% \begin{macrocode}
+\edef\end
+ {\unexpanded{%
+ \romannumeral
+ \ifx\protect\@typeset@protect
+ \expandafter %1
+ \expandafter %2
+ \expandafter %1
+ \expandafter %3 expands the \csname inside \end<space>
+ \expandafter %1
+ \expandafter %2 expands \end<space>
+ \expandafter %1 expands the \else
+ \z@
+ \else
+ \expandafter\z@\expandafter\protect
+ \fi
+ }%
+ \expandafter\noexpand\csname end \endcsname
+ }
+% \end{macrocode}
+% Version that adds hooks (so different from the 2019 version). It
+% fixes tlb3722 but the change should perhaps be made in
+% \texttt{tabularx} instead.
+% \begin{macrocode}
+\@namedef{end }#1{%
+ \romannumeral
+ \IfHookEmptyTF{env/#1/end}%
+ {\expandafter\z@}%
+ {\z@\UseHook{env/#1/end}}%
+ \csname end#1\endcsname\@checkend{#1}%
+ \expandafter\endgroup\if@endpe\@doendpe\fi
+ \UseHook{env/#1/after}%
+ \if@ignore\@ignorefalse\ignorespaces\fi
+}
+% \end{macrocode}
+% Version without the fix for tlb3722 for the record:
+% \begin{macrocode}
+%\@namedef{end }#1{%
+% \UseHook{env/#1/end}%
+% \csname end#1\endcsname\@checkend{#1}%
+% \expandafter\endgroup\if@endpe\@doendpe\fi
+% \UseHook{env/#1/after}%
+% \if@ignore\@ignorefalse\ignorespaces\fi}%
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\begin}{Making \begin/\end robust}%
+%<latexrelease>\DeclareRobustCommand\begin[1]{%
+%<latexrelease> \@ifundefined{#1}%
+%<latexrelease> {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}%
+%<latexrelease> {\def\reserved@a{\def\@currenvir{#1}%
+%<latexrelease> \edef\@currenvline{\on@line}%
+%<latexrelease> \csname #1\endcsname}}%
+%<latexrelease> \@ignorefalse
+%<latexrelease> \begingroup\@endpefalse\reserved@a}
+% \end{macrocode}
% A version that doesn't start out with \cs{relax} when in
% typesetting mode would be the following, but since \cs{begin}
% issues a \cs{begingroup} it wouldn't help much with respect to
@@ -606,41 +805,50 @@
% \changes{v1.1p}{2019/08/27}{Make command robust}
%
% \begin{macrocode}
-\edef\end
- {\unexpanded{%
- \romannumeral
- \ifx\protect\@typeset@protect
- \expandafter %1
- \expandafter %2
- \expandafter %1
- \expandafter %3 expands the \csname inside \end<space>
- \expandafter %1
- \expandafter %2 expands \end<space>
- \expandafter %1 expands the \else
- \z@
- \else
- \expandafter\z@\expandafter\protect
- \fi
- }%
- \expandafter\noexpand\csname end \endcsname
- }
+%<latexrelease>\edef\end
+%<latexrelease> {\unexpanded{%
+%<latexrelease> \romannumeral
+%<latexrelease> \ifx\protect\@typeset@protect
+%<latexrelease> \expandafter %1
+%<latexrelease> \expandafter %2
+%<latexrelease> \expandafter %1
+%<latexrelease> \expandafter %3 expands the \csname inside \end<space>
+%<latexrelease> \expandafter %1
+%<latexrelease> \expandafter %2 expands \end<space>
+%<latexrelease> \expandafter %1 expands the \else
+%<latexrelease> \z@
+%<latexrelease> \else
+%<latexrelease> \expandafter\z@\expandafter\protect
+%<latexrelease> \fi
+%<latexrelease> }%
+%<latexrelease> \expandafter\noexpand\csname end \endcsname
+%<latexrelease> }
% \end{macrocode}
% And here is the original definition of \cs{end} the way it was in
% \LaTeX{} for several decades now hidden in \verb*=\end =.
% \begin{macrocode}
-\@namedef{end }#1{%
- \csname end#1\endcsname\@checkend{#1}%
- \expandafter\endgroup\if@endpe\@doendpe\fi
- \if@ignore\@ignorefalse\ignorespaces\fi}
-%</2ekernel|latexrelease>
+%<latexrelease>\@namedef{end }#1{%
+%<latexrelease> \csname end#1\endcsname\@checkend{#1}%
+%<latexrelease> \expandafter\endgroup\if@endpe\@doendpe\fi
+%<latexrelease> \if@ignore\@ignorefalse\ignorespaces\fi}
%<latexrelease>\EndIncludeInRelease
% \end{macrocode}
% An here the rollback in case that is ever needed.
% \begin{macrocode}
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\begin}{Making \begin/\end robust}%
-%<latexrelease>\kernel@make@fragile\begin
-%<latexrelease>\kernel@make@fragile\end
+%<latexrelease>\def\begin#1{%
+%<latexrelease> \@ifundefined{#1}%
+%<latexrelease> {\def\reserved@a{\@latex@error{Environment #1 undefined}\@eha}}%
+%<latexrelease> {\def\reserved@a{\def\@currenvir{#1}%
+%<latexrelease> \edef\@currenvline{\on@line}%
+%<latexrelease> \csname #1\endcsname}}%
+%<latexrelease> \@ignorefalse
+%<latexrelease> \begingroup\@endpefalse\reserved@a}
+%<latexrelease>\def\end#1{%
+%<latexrelease> \csname end#1\endcsname\@checkend{#1}%
+%<latexrelease> \expandafter\endgroup\if@endpe\@doendpe\fi
+%<latexrelease> \if@ignore\@ignorefalse\ignorespaces\fi}
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
@@ -672,6 +880,47 @@
% \end{macro}
%
%
+%
+% \begin{macro}{\AtBeginEnvironment,\AtEndEnvironment,
+% \BeforeBeginEnvironment,\AfterEndEnvironment}
+%
+% We provide 4 high-level hook interfaces directly, the others only when
+% etoolbox is loaded
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\AtBeginEnvironment}{Hooks for environments}%
+% \end{macrocode}
+%
+% \begin{macrocode}
+\newcommand\AtBeginEnvironment[2][.] {\AddToHook{env/#2/begin}[#1]}
+\newcommand\AtEndEnvironment[2][.] {\AddToHook{env/#2/end}[#1]}
+\newcommand\BeforeBeginEnvironment[2][.]{\AddToHook{env/#2/before}[#1]}
+\newcommand\AfterEndEnvironment[2][.] {\AddToHook{env/#2/after}[#1]}
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\AtBeginEnvironment}{Hooks for environments}%
+%<latexrelease>
+%<latexrelease>\let\AtBeginEnvironment\@undefined
+%<latexrelease>\let\AtEndEnvironment\@undefined
+%<latexrelease>\let\BeforeBeginEnvironment\@undefined
+%<latexrelease>\let\AfterEndEnvironment\@undefined
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
% \subsection{Center, Flushright, Flushleft}
%
% \begin{macrocode}
@@ -738,10 +987,25 @@
% \end{macro}
%
% \begin{macro}{\@icentercr}
+% \changes{v1.1t}{2020/04/21}{Support calc syntax (gh/152)}
% \begin{macrocode}
-\def\@icentercr[#1]{\vskip #1\ignorespaces}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@icentercr}{centering, etc support calc}%
+\def\@icentercr[#1]{\@vspace@calcify{#1}\ignorespaces}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@icentercr}{centering, etc support calc}%
+%<latexrelease>
+%<latexrelease>\def\@icentercr[#1]{\vskip #1\ignorespaces}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
-%
% \end{macro}
%
%
@@ -763,33 +1027,39 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2019/10/01}%
-%<latexrelease> {\centering}{Make commands robust}%
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\centering}{Set finaldhypendemerits}%
% \end{macrocode}
%
% \begin{macro}{\centering}
+% \changes{v1.1u}{2020/05/31}{Added \cs{finalhyphendemerits} setting (gh/247)}
% \begin{macrocode}
\DeclareRobustCommand\centering{%
\let\\\@centercr
\rightskip\@flushglue\leftskip\@flushglue
+ \finalhyphendemerits=\z@
\parindent\z@\parfillskip\z@skip}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\raggedright}
+% \changes{v1.1u}{2020/05/31}{Added \cs{finalhyphendemerits} setting (gh/247)}
% \begin{macrocode}
\DeclareRobustCommand\raggedright{%
\let\\\@centercr\@rightskip\@flushglue \rightskip\@rightskip
+ \finalhyphendemerits=\z@
\leftskip\z@skip
\parindent\z@}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\raggedleft}
+% \changes{v1.1u}{2020/05/31}{Added \cs{finalhyphendemerits} setting (gh/247)}
% \begin{macrocode}
\DeclareRobustCommand\raggedleft{%
\let\\\@centercr
\rightskip\z@skip\leftskip\@flushglue
+ \finalhyphendemerits=\z@
\parindent\z@\parfillskip\z@skip}
% \end{macrocode}
% \end{macro}
@@ -797,6 +1067,23 @@
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\centering}{Make commands robust}%
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand\centering{%
+%<latexrelease> \let\\\@centercr
+%<latexrelease> \rightskip\@flushglue\leftskip\@flushglue
+%<latexrelease> \parindent\z@\parfillskip\z@skip}
+%<latexrelease>\DeclareRobustCommand\raggedright{%
+%<latexrelease> \let\\\@centercr\@rightskip\@flushglue \rightskip\@rightskip
+%<latexrelease> \leftskip\z@skip
+%<latexrelease> \parindent\z@}
+%<latexrelease>\DeclareRobustCommand\raggedleft{%
+%<latexrelease> \let\\\@centercr
+%<latexrelease> \rightskip\z@skip\leftskip\@flushglue
+%<latexrelease> \parindent\z@\parfillskip\z@skip}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\centering}{Make commands robust}%
%<latexrelease>
@@ -983,6 +1270,7 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{environment}{verbatim}
% \begin{macro}{\verbatim}
% \begin{macro}{\endverbatim}
% (RmS 93/09/19) Protected against `missing item' error message
@@ -993,6 +1281,7 @@
% \end{macrocode}
% \end{macro}
% \end{macro}
+% \end{environment}
%
% \begin{macro}{\verbatim@font}
% \changes{v0.9a}{1993/11/21}{Macro added}
@@ -1010,7 +1299,7 @@
%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2018/12/01}%
-%<latexrelease> {\verbvisiblespace}{Setup visible space for verb}%
+%<latexrelease> {\verbvisiblespace}{Setup visible space for \verb}%
% \end{macrocode}
%
%
@@ -1092,15 +1381,71 @@
% \end{macrocode}
% \end{macro}
%
+%^^A \@sverb was here
+%
+% \begin{environment}{verbatim*}
+% For \texttt{verbatim*} we also set up the correct visible space
+% character definition and then run |\@vobeyspaces|. As this code
+% is not called as part of the normal verbatim environment (the
+% method is done the other way around this time) we don't have to
+% check if space is already active---it shouldn't be.
+% \changes{v1.1o}{2018/10/11}
+% {Provide visible space in \cs{verb*} also for XeTeX and LuaTeX (github/69)}
+% \begin{macrocode}
+\@namedef{verbatim*}{\@verbatim
+ \@setupverbvisiblespace
+ \frenchspacing\@vobeyspaces\@sxverbatim}
+\expandafter\let\csname endverbatim*\endcsname =\endverbatim
+% \end{macrocode}
+% \end{environment}
+%
+%
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\verbvisiblespace}{Setup visible space for \verb}%
+%<latexrelease>
+%<latexrelease>\@namedef{verbatim*}{\@verbatim\@sxverbatim}
+%<latexrelease>
+%<latexrelease>\let\asciispace \@undefined
+%<latexrelease>\let\verbvisiblespace \@undefined
+%<latexrelease>\let\@setupverbvisiblespace\@undefined
+%<latexrelease>\let\@verbvisiblespacebox \@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+%
%
% \begin{macro}{\@sverb}
+% \begin{macro}{\@@sverb}
% \changes{v1.0j}{1994/05/10}{Slight change in error message text.}
% Definitions of |\@sverb| and |\@verb| changed so |\verb+ foo+|
% does not lose leading blanks when it comes at the beginning of a line.
% Change made 24 May 89. Suggested by Frank Mittelbach and Rainer
% Sch\"opf.
% \begin{macrocode}
-\def\@sverb#1{%
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@sverb}{Drop spaces before \verb delimiter}%
+% \end{macrocode}
+%
+% If the users types \verb=\verb !~! foo= then surprisingly we would
+% get the space as the delimiter and thus
+% ``\verb=!~!foo='' in the output.
+% To avoid this scenario we check if \verb=#1= has the character
+% code of a space, if so we recurse otherwise we call \cs{@@sverb}
+% (which is the original definition of \cs{@sverb}.
+% \changes{v1.1u}{2020/04/22}{Drop spaces before \cs{verb} delimiter (gh/327)}
+% \begin{macrocode}
+\def\@sverb#1{\if\noexpand#1 \expandafter\@sverb\else\@@sverb{#1}\fi}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\def\@@sverb#1{%
\catcode`#1\active
\lccode`\~`#1%
\gdef\verb@balance@group{\verb@egroup
@@ -1120,39 +1465,28 @@
\else \@setupverbvisiblespace \@vobeyspaces \fi
}
% \end{macrocode}
-% \end{macro}
-%
-% \begin{environment}{verbatim*}
-% For \texttt{verbatim*} we also set up the correct visible space
-% character definition and then run |\@vobeyspaces|. As this code
-% is not called as part of the normal verbatim environment (the
-% method is done the other way around this time) we don't have to
-% check if space is already active---it shouldn't be.
-% \changes{v1.1o}{2018/10/11}
-% {Provide visible space in \cs{verb*} also for XeTeX and LuaTeX (github/69)}
-% \begin{macrocode}
-\@namedef{verbatim*}{\@verbatim
- \@setupverbvisiblespace
- \frenchspacing\@vobeyspaces\@sxverbatim}
-\expandafter\let\csname endverbatim*\endcsname =\endverbatim
-% \end{macrocode}
-% \end{environment}
-%
-%
-%
+%
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
-%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\verbvisiblespace}{Setup visible space for verb}%
-%<latexrelease>
-%<latexrelease>\@namedef{verbatim*}{\@verbatim\@sxverbatim}
+%<latexrelease>\IncludeInRelease{2018/12/01}%
+%<latexrelease> {\@sverb}{Setup visible space for \verb}%
%<latexrelease>
-%<latexrelease>\let\asciispace \@undefined
-%<latexrelease>\let\verbvisiblespace \@undefined
-%<latexrelease>\let\@setupverbvisiblespace\@undefined
-%<latexrelease>\let\@verbvisiblespacebox \@undefined
+%<latexrelease>\def\@sverb#1{%
+%<latexrelease> \catcode`#1\active
+%<latexrelease> \lccode`\~`#1%
+%<latexrelease> \gdef\verb@balance@group{\verb@egroup
+%<latexrelease> \@latex@error{\noexpand\verb illegal in command argument}\@ehc}%
+%<latexrelease> \aftergroup\verb@balance@group
+%<latexrelease> \lowercase{\let~\verb@egroup}%
+%<latexrelease> \ifnum\catcode`\ =\active
+%<latexrelease> \else \@setupverbvisiblespace \@vobeyspaces \fi
+%<latexrelease>}
+%<latexrelease>\let\@@sverb\@undefined
+%<latexrelease>\EndIncludeInRelease
%<latexrelease>
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@sverb}{Setup visible space for \verb}%
%<latexrelease>\def\@sverb#1{%
%<latexrelease> \catcode`#1\active
%<latexrelease> \lccode`\~`#1%
@@ -1164,8 +1498,8 @@
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
-%
-%
+% \end{macro}
+% \end{macro}
%
%
% \begin{macro}{\@makeother}
diff --git a/Master/texmf-dist/source/latex/base/ltoutenc.dtx b/Master/texmf-dist/source/latex/base/ltoutenc.dtx
index f3c19000edf..c6bfc149b7c 100644
--- a/Master/texmf-dist/source/latex/base/ltoutenc.dtx
+++ b/Master/texmf-dist/source/latex/base/ltoutenc.dtx
@@ -37,14 +37,14 @@
%<TS1>\ProvidesFile{ts1enc.def}[2001/06/05 v3.0e (jk/car/fm)
%<TU>\ProvidesFile{tuenc.def}
%<package>\ProvidesPackage{fontenc}
-%<OT1|T1|OMS|OML|OT4|TU|package> [2020/02/11 v2.0o
+%<OT1|T1|OMS|OML|OT4|TU|package> [2020/08/10 v2.0s
%<OT1|T1|OMS|OML|OT4|TS1|TU> Standard LaTeX file]
%<package> Standard LaTeX package]
%
%<*driver>
% \fi
\ProvidesFile{ltoutenc.dtx}
- [2020/02/11 v2.0o LaTeX Kernel (font encodings)]
+ [2020/08/10 v2.0s LaTeX Kernel (font encodings)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltoutenc.dtx}
@@ -188,6 +188,8 @@
% like.}
% \changes{v1.99m}{2015/02/21}
% {Removed autoload code}
+% \changes{v2.0p}{2020/04/22}
+% {corrected \=y unicode value in tuenc.def}
%
%
% \section{Font encodings}
@@ -1080,8 +1082,9 @@
% deficiencies, see pr/3160.
% \task{?}{Improve this and document its problems, see pr/3160}
% \changes{v1.9z}{2000/01/30}{Macro reimplemented (pr/3160)}
+% \changes{v2.0r}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
% \begin{macrocode}
-\DeclareRobustCommand\UseTextAccent[3]{%
+\DeclareRobustCommand*\UseTextAccent[3]{%
\hmode@start@before@group
{%
% \end{macrocode}
@@ -1096,8 +1099,9 @@
% \end{macrocode}
%
% \changes{v1.9z}{2000/01/30}{Macro reimplemented (pr/3160)}
+% \changes{v2.0r}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
% \begin{macrocode}
-\DeclareRobustCommand\UseTextSymbol[2]{%
+\DeclareRobustCommand*\UseTextSymbol[2]{%
\hmode@start@before@group
{%
\def\@wrong@font@char{\MessageBreak
@@ -2867,28 +2871,64 @@
% \end{macrocode}
%
% LuaTeX.
+% For Lua\TeX~1.10+, define a Lua function to disable any handing by the font code.
+% Otherwise we reload the font without TeX ligatures.
+% \changes{v2.0q}{2020/07/04}{%
+% Implement \cs{remove@tlig} in Lua\TeX without font reloading}
% \begin{macrocode}
\def\UnicodeFontTeXLigatures{+tlig;}
-% \end{macrocode}
-%
-% \begin{macrocode}
- \def\reserved@a#1{%
- \def\@remove@tlig##1{\@remove@tlig@##1\@nil#1\@nil\relax}
- \def\@remove@tlig@##1#1{\@remove@tlig@@##1}}
- \edef\reserved@b{\detokenize{+tlig;}}
- \expandafter\reserved@a\expandafter{\reserved@b}
- \def\@remove@tlig@@#1\@nil#2\relax{#1}
-% \end{macrocode}
-%
-% \begin{macrocode}
- \def\remove@tlig#1{%
- \begingroup
- \font\remove@tlig
- \expandafter\@remove@tlig\expandafter{\fontname\font}%
- \remove@tlig
- \char#1\relax
- \endgroup
- }
+ \ifnum\luatexversion<110
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \def\reserved@a#1{%
+ \def\@remove@tlig##1{\@remove@tlig@##1\@nil#1\@nil\relax}
+ \def\@remove@tlig@##1#1{\@remove@tlig@@##1}}
+ \edef\reserved@b{\detokenize{+tlig;}}
+ \expandafter\reserved@a\expandafter{\reserved@b}
+ \def\@remove@tlig@@#1\@nil#2\relax{#1}
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \def\remove@tlig#1{%
+ \begingroup
+ \font\remove@tlig
+ \expandafter\@remove@tlig\expandafter{\fontname\font}%
+ \remove@tlig
+ \char#1\relax
+ \endgroup
+ }
+ \else
+ \newluafunction\@remove@tlig@@@@
+% \end{macrocode}
+% Now we can define the function. Mostly we just have to insert a protected glyph
+% node, which is a glyph node with subtype 256. But we have to keep track of the
+% current mode to avoid inserting the glyph into a vlist.
+% \begin{macrocode}
+ \now@and@everyjob{\directlua{
+ local rawchar_func = token.create'@remove@tlig@@@@'.index
+ local forcehmode = tex.forcehmode
+ local put_next = token.put_next
+ local glyph_id = node.id'glyph'
+ local rawchar_token = token.new(rawchar_func, token.command_id'lua_call')
+ lua.get_functions_table()[rawchar_func] = function()
+ local mode = tex.nest.top.mode
+ if mode == 1 or mode == -1 then
+ put_next(rawchar_token)
+ return forcehmode(true)
+ end
+ local n = node.new(glyph_id, 256)
+ n.font = font.current()
+ n.char = token.scan_int()
+ return node.write(n)
+ end
+ token.set_lua('@remove@tlig@@@', rawchar_func, 'global', 'protected')
+ }}
+% \end{macrocode}
+% Now \verb+\remove@tlig+ can be implemented almost as in XeTeX.
+% \begin{macrocode}
+ \def\remove@tlig#1{\@remove@tlig@@@#1\relax}
+ \fi
% \end{macrocode}
%
% \begin{macrocode}
@@ -3370,7 +3410,7 @@
\DeclareUnicodeComposite{\textcommabelow}{T}{"021A}
\DeclareUnicodeComposite{\textcommabelow}{t}{"021B}
\DeclareUnicodeComposite{\=} {Y}{"0232}
-\DeclareUnicodeComposite{\=} {y}{"0232}
+\DeclareUnicodeComposite{\=} {y}{"0233}
\DeclareUnicodeComposite{\.} {B}{"1E02}
\DeclareUnicodeComposite{\.} {b}{"1E03}
\DeclareUnicodeComposite{\d} {B}{"1E04}
@@ -3601,7 +3641,7 @@
\xdef\@fontenc@load@list{\@fontenc@load@list
\@elt{\csname opt@fontenc.sty\endcsname}}
% \end{macrocode}
-%
+%
% \begin{macrocode}
\global\expandafter\let\csname ver@fontenc.sty\endcsname\relax
\global\expandafter\let\csname opt@fontenc.sty\endcsname\relax
diff --git a/Master/texmf-dist/source/latex/base/ltoutput.dtx b/Master/texmf-dist/source/latex/base/ltoutput.dtx
index c3b27baf42d..35d049b9590 100644
--- a/Master/texmf-dist/source/latex/base/ltoutput.dtx
+++ b/Master/texmf-dist/source/latex/base/ltoutput.dtx
@@ -37,7 +37,7 @@
%<*driver>
% \fi
\ProvidesFile{ltoutput.dtx}
- [2019/08/27 v1.4e LaTeX Kernel (Output Routine)]
+ [2020/08/21 v1.4f LaTeX Kernel (Output Routine)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltoutput.dtx}
@@ -791,12 +791,17 @@
%
% The stuff in the box should not add any typeset material to the
% page when it is unboxed.
+%
+% This interface is no longer used. Instead a new one is inside
+% \texttt{ltshipout.dtx}. We only keep the box in case some old
+% code refers to it directly (or we do some rollback).
+% \changes{v1.4f}{2020/08/21}{Integration of new hook management interface}
% \begin{macrocode}
\newbox\@begindvibox
-\DeclareRobustCommand \AtBeginDvi [1]{%
- \global \setbox \@begindvibox
- \vbox{\unvbox \@begindvibox #1}%
-}
+%\DeclareRobustCommand \AtBeginDvi [1]{%
+% \global \setbox \@begindvibox
+% \vbox{\unvbox \@begindvibox #1}%
+%}
% \end{macrocode}
% \end{macro}
% \end{macro}
diff --git a/Master/texmf-dist/source/latex/base/ltpage.dtx b/Master/texmf-dist/source/latex/base/ltpage.dtx
index f926f330605..8c7aac0a7b8 100644
--- a/Master/texmf-dist/source/latex/base/ltpage.dtx
+++ b/Master/texmf-dist/source/latex/base/ltpage.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltpage.dtx}
- [2019/08/27 v1.0l LaTeX Kernel (page style setup)]
+ [2020/07/27 v1.0m LaTeX Kernel (page style setup)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltpage.dtx}
@@ -201,8 +201,9 @@
% expansion, CAR}
% \changes{v1.0j}{2000/05/26}{Reimplementation to fix expansion
% error (pr/3203).}
+% \changes{v1.0m}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
% \begin{macrocode}
-\DeclareRobustCommand\markboth[2]{%
+\DeclareRobustCommand*\markboth[2]{%
\begingroup
\let\label\relax \let\index\relax \let\glossary\relax
\unrestored@protected@xdef\@themark {{#1}{#2}}%
@@ -212,8 +213,9 @@
\if@nobreak\ifvmode\nobreak\fi\fi}
% \end{macrocode}
%
+% \changes{v1.0m}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
% \begin{macrocode}
-\DeclareRobustCommand\markright[1]{%
+\DeclareRobustCommand*\markright[1]{%
\begingroup
\let\label\relax \let\index\relax \let\glossary\relax
% \end{macrocode}
diff --git a/Master/texmf-dist/source/latex/base/ltpictur.dtx b/Master/texmf-dist/source/latex/base/ltpictur.dtx
index 9440fc783ad..5bef40375cd 100644
--- a/Master/texmf-dist/source/latex/base/ltpictur.dtx
+++ b/Master/texmf-dist/source/latex/base/ltpictur.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltpictur.dtx}
- [2019/08/27 v1.1m LaTeX Kernel (Picture Mode)]
+ [2020/08/14 v1.2a LaTeX Kernel (Picture Mode)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltpictur.dtx}
@@ -191,6 +191,46 @@
% \end{macro}
% \end{macro}
%
+% \begin{macro}{\@defaultunitsset}
+% \changes{v1.2a}{2020/08/15}{Macro added}
+% Set a length register, |#1|,
+% accepting number or an etex length expression, |#2|,
+% with default unit, |#3|.
+%
+% The register name in |#1| can be prefixed by |\advance| so that
+% the register is incremented by the supplied value.
+%
+% |\@defaultunitsset{\advance\@vxx}{\textwidth-15pt}\unitlength|
+%
+% |#3| can be a literal unit such as |cm| or a length register such
+% as |\unitlength|.
+%
+% This is used in all |picture| commands that take picture coordinates.
+% So |\put(2,2)| as previously but now |\put(\textwidth-5cm,0.4\texteight)|
+% Note that you can only use expressions with lengths, |\put(1+2,0)| is not
+% supported.
+%
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@defaultunitsset}{default units}%
+\def\@defaultunitsset#1#2#3{%
+ \@defaultunits#1\dimexpr#2#3\relax\relax\@nnil}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@defaultunitsset}{default units}%
+%<latexrelease>\let\@defaultunitsset\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{environment}{picture}
% \begin{macro}{\picture}
% \changes{v0.1c}{1994/04/28}{(DPC) Ignore spaces before (}
% |#1| should be white space.
@@ -207,12 +247,34 @@
%
% \begin{macro}{\@picture}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@picture}{default units}%
\def\@picture(#1,#2)(#3,#4){%
- \@picht#2\unitlength
- \setbox\@picbox\hb@xt@#1\unitlength\bgroup
- \hskip -#3\unitlength
- \lower #4\unitlength\hbox\bgroup
+ \@defaultunitsset\@picht{#2}\unitlength
+ \@defaultunitsset\@tempdimc{#1}\unitlength
+ \setbox\@picbox\hb@xt@\@tempdimc\bgroup
+ \@defaultunitsset\@tempdimc{#3}\unitlength
+ \hskip -\@tempdimc
+ \@defaultunitsset\@tempdimc{#4}\unitlength
+ \lower\@tempdimc\hbox\bgroup
\ignorespaces}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@picture}{default units}%
+%<latexrelease>\def\@picture(#1,#2)(#3,#4){%
+%<latexrelease> \@picht#2\unitlength
+%<latexrelease> \setbox\@picbox\hb@xt@#1\unitlength\bgroup
+%<latexrelease> \hskip -#3\unitlength
+%<latexrelease> \lower #4\unitlength\hbox\bgroup
+%<latexrelease> \ignorespaces}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -229,16 +291,41 @@
\mbox{\box\@picbox}}
% \end{macrocode}
% \end{macro}
+% \end{environment}
%
% In the definitions of |\put| and |\multiput|, |\hskip| was replaced by
% |\kern| just in case arg |#3| = ``plus''. (Bug detected by Don Knuth.
% changed 20 Jul 87).
%
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\put}{default units}%
+%<latexrelease>\expandafter\let\csname put \endcsname\@undefind
\long\def\put(#1,#2)#3{%
- \@killglue\raise#2\unitlength
- \hb@xt@\z@{\kern#1\unitlength #3\hss}%
+ \@killglue
+ \@defaultunitsset\@tempdimc{#2}\unitlength
+ \raise\@tempdimc
+ \hb@xt@\z@{%
+ \@defaultunitsset\@tempdimc{#1}\unitlength
+ \kern\@tempdimc
+ #3\hss}%
\ignorespaces}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\put}{default units}%
+%<latexrelease>\expandafter\let\csname put \endcsname\@undefind
+%<latexrelease>\long\def\put(#1,#2)#3{%
+%<latexrelease> \@killglue\raise#2\unitlength
+%<latexrelease> \hb@xt@\z@{\kern#1\unitlength #3\hss}%
+%<latexrelease> \ignorespaces}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
%
%
@@ -246,23 +333,63 @@
% \changes{v0.1c}{1994/04/28}{(DPC) Ignore spaces between )(}
% |#3| had better be a |(|.
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\multiput}{default units}%
+%<latexrelease>\expandafter\let\csname multiput \endcsname\@undefind
\def\multiput(#1,#2)#3{%
- \@xdim #1\unitlength
- \@ydim #2\unitlength
+ \@defaultunitsset\@xdim{#1}\unitlength
+ \@defaultunitsset\@ydim{#2}\unitlength
\@multiput(}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\multiput}{default units}%
+%<latexrelease>\expandafter\let\csname multiput \endcsname\@undefind
+%<latexrelease>\def\multiput(#1,#2)#3{%
+%<latexrelease> \@xdim #1\unitlength
+%<latexrelease> \@ydim #2\unitlength
+%<latexrelease> \@multiput(}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
-% \begin{macro}{\multiput}
+% \begin{macro}{\@multiput}
% \changes{v0.1c}{1994/04/28}{(DPC) Macro added}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@multiput}{default units}%
\long\def\@multiput(#1,#2)#3#4{%
\@killglue\@multicnt #3\relax
\@whilenum \@multicnt >\z@\do
{\raise\@ydim\hb@xt@\z@{\kern\@xdim #4\hss}%
\advance\@multicnt\m@ne
- \advance\@xdim#1\unitlength\advance\@ydim#2\unitlength}%
+ \@defaultunitsset{\advance\@xdim}{#1}\unitlength
+ \@defaultunitsset{\advance\@ydim}{#2}\unitlength}%
\ignorespaces}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@multiput}{default units}%
+%<latexrelease>\long\def\@multiput(#1,#2)#3#4{%
+%<latexrelease> \@killglue\@multicnt #3\relax
+%<latexrelease> \@whilenum \@multicnt >\z@\do
+%<latexrelease> {\raise\@ydim\hb@xt@\z@{\kern\@xdim #4\hss}%
+%<latexrelease> \advance\@multicnt\m@ne
+%<latexrelease> \advance\@xdim#1\unitlength\advance\@ydim#2\unitlength}%
+%<latexrelease> \ignorespaces}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -275,18 +402,22 @@
% \begin{macro}{\thinlines}
% \begin{macro}{\thicklines}
% \begin{macrocode}
-\DeclareRobustCommand\thinlines{\let\@linefnt\tenln \let\@circlefnt\tencirc
+\DeclareRobustCommand\thinlines{\let\@linefnt\tenln
+ \let\@circlefnt\tencirc
\@wholewidth\fontdimen8\tenln \@halfwidth .5\@wholewidth}
-\DeclareRobustCommand\thicklines{\let\@linefnt\tenlnw \let\@circlefnt\tencircw
+\DeclareRobustCommand\thicklines{\let\@linefnt\tenlnw
+ \let\@circlefnt\tencircw
\@wholewidth\fontdimen8\tenlnw \@halfwidth .5\@wholewidth}
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\linethickness}
+% \changes{v1.1n}{2020/02/14}{Suppress spaces following the declaration (gh/274)}
+% \changes{v1.1p}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
% \begin{macrocode}
-\DeclareRobustCommand\linethickness[1]
- {\@wholewidth #1\relax \@halfwidth .5\@wholewidth}
+\DeclareRobustCommand*\linethickness[1]
+ {\@wholewidth #1\relax \@halfwidth .5\@wholewidth \ignorespaces}
% \end{macrocode}
% \end{macro}
%
@@ -332,8 +463,24 @@
% \end{macro}
%
% \begin{macro}{\@istackcr}
+% \changes{v1.1o}{2020/04/21}{Support calc syntax (gh/152)}
% \begin{macrocode}
-\def\@istackcr[#1]{\cr\noalign{\vskip #1}\ignorespaces}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@istackcr}{\shortstack calc support}%
+\def\@istackcr[#1]{\cr\noalign{\@vspace@calcify{#1}}\ignorespaces}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@istackcr}{\shortstack calc support}%
+%<latexrelease>
+%<latexrelease>\def\@istackcr[#1]{\cr\noalign{\vskip #1}\ignorespaces}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -510,13 +657,35 @@
%
% \begin{macro}{\line}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\line}{default units}%
+%<latexrelease>\expandafter\let\csname line \endcsname\@undefind
\def\line(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax
- \@linelen #3\unitlength
+ \@defaultunitsset\@linelen{#3}\unitlength
\ifdim\@linelen<\z@\@badlinearg\else
\ifnum\@xarg =\z@ \@vline
\else \ifnum\@yarg =\z@ \@hline \else \@sline\fi
\fi
\fi}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\line}{default units}%
+%<latexrelease>\expandafter\let\csname line \endcsname\@undefind
+%<latexrelease>\def\line(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax
+%<latexrelease> \@linelen #3\unitlength
+%<latexrelease> \ifdim\@linelen<\z@\@badlinearg\else
+%<latexrelease> \ifnum\@xarg =\z@ \@vline
+%<latexrelease> \else \ifnum\@yarg =\z@ \@hline \else \@sline\fi
+%<latexrelease> \fi
+%<latexrelease> \fi}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -600,16 +769,41 @@
%
% \begin{macro}{\vector}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\vector}{default units}%
+%<latexrelease>\expandafter\let\csname vector \endcsname\@undefind
\def\vector(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax
\@tempcnta \ifnum\@xarg<\z@ -\@xarg\else\@xarg\fi
\ifnum\@tempcnta<5\relax
- \@linelen #3\unitlength
+ \@defaultunitsset\@linelen{#3}\unitlength
\ifdim\@linelen<\z@\@badlinearg\else
\ifnum\@xarg =\z@ \@vvector
\else \ifnum\@yarg =\z@ \@hvector \else \@svector\fi
\fi
\fi
\else\@badlinearg\fi}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\vector}{default units}%
+%<latexrelease>\expandafter\let\csname vector \endcsname\@undefind
+%<latexrelease>\def\vector(#1,#2)#3{\@xarg #1\relax \@yarg #2\relax
+%<latexrelease> \@tempcnta \ifnum\@xarg<\z@ -\@xarg\else\@xarg\fi
+%<latexrelease> \ifnum\@tempcnta<5\relax
+%<latexrelease> \@linelen #3\unitlength
+%<latexrelease> \ifdim\@linelen<\z@\@badlinearg\else
+%<latexrelease> \ifnum\@xarg =\z@ \@vvector
+%<latexrelease> \else \ifnum\@yarg =\z@ \@hvector \else \@svector\fi
+%<latexrelease> \fi
+%<latexrelease> \fi
+%<latexrelease> \else\@badlinearg\fi}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -803,11 +997,17 @@
%
% \begin{macro}{\dashbox}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\dashbox}{default units}%
+%<latexrelease>\expandafter\let\csname dashbox \endcsname\@undefind
\def\dashbox#1(#2,#3){\leavevmode\hb@xt@\z@{\baselineskip \z@skip
\lineskip \z@skip
-\@dashdim #2\unitlength
+\@defaultunitsset\@dashdim{#2}\unitlength
\@dashcnt \@dashdim \advance\@dashcnt 200
-\@dashdim #1\unitlength\divide\@dashcnt \@dashdim
+\@defaultunitsset\@dashdim{#1}\unitlength
+\divide\@dashcnt \@dashdim
\ifodd\@dashcnt\@dashdim \z@
\advance\@dashcnt \@ne \divide\@dashcnt \tw@
\else \divide\@dashdim \tw@ \divide\@dashcnt \tw@
@@ -819,15 +1019,19 @@
\put(#2,#3){\hskip-\@dashdim\box\@dashbox}%
\multiply\@dashdim \thr@@
\fi
-\setbox\@dashbox \hbox{\vrule \@height \@halfwidth \@depth \@halfwidth
-\@width #1\unitlength\hskip #1\unitlength}\@tempcnta\z@
+\setbox\@dashbox \hbox{%
+ \@defaultunitsset\@tempdimc{#1}\unitlength
+ \vrule \@height \@halfwidth \@depth \@halfwidth \@width \@tempdimc
+ \hskip\@tempdimc}%
+\@tempcnta\z@
\put(0,0){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt
\do{\copy\@dashbox\advance\@tempcnta \@ne }}\@tempcnta\z@
\put(0,#3){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt
\do{\copy\@dashbox\advance\@tempcnta \@ne }}%
-\@dashdim #3\unitlength
+\@defaultunitsset\@dashdim{#3}\unitlength
\@dashcnt \@dashdim \advance\@dashcnt 200
-\@dashdim #1\unitlength\divide\@dashcnt \@dashdim
+\@defaultunitsset\@dashdim{#1}\unitlength
+\divide\@dashcnt \@dashdim
\ifodd\@dashcnt \@dashdim \z@
\advance\@dashcnt \@ne \divide\@dashcnt \tw@
\else
@@ -841,14 +1045,79 @@
\put(#2,#3){\lower\@dashdim\copy\@dashbox}%
\multiply\@dashdim \thr@@
\fi
-\setbox\@dashbox\hbox{\vrule \@width \@wholewidth
-\@height #1\unitlength}\@tempcnta\z@
+\@defaultunitsset\@tempdimb{#1}\unitlength
+\setbox\@dashbox\hbox{%
+ \vrule \@width \@wholewidth \@height\@tempdimb}%
+\@tempcnta\z@
\put(0,0){\hskip -\@halfwidth \vbox{\@whilenum \@tempcnta <\@dashcnt
-\do{\vskip #1\unitlength\copy\@dashbox\advance\@tempcnta \@ne }%
+\do{\vskip\@tempdimb\copy\@dashbox\advance\@tempcnta \@ne }%
\vskip\@dashdim}}\@tempcnta\z@
\put(#2,0){\hskip -\@halfwidth \vbox{\@whilenum \@tempcnta<\@dashcnt
-\do{\vskip #1\unitlength\copy\@dashbox\advance\@tempcnta \@ne }%
+\do{\vskip\@tempdimb\copy\@dashbox\advance\@tempcnta \@ne }%
\vskip\@dashdim}}}\@makepicbox(#2,#3)}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\dashbox}{default units}%
+%<latexrelease>\expandafter\let\csname dashbox \endcsname\@undefind
+%<latexrelease>\def\dashbox#1(#2,#3){%
+%<latexrelease>\leavevmode\hb@xt@\z@{\baselineskip \z@skip
+%<latexrelease>\lineskip \z@skip
+%<latexrelease>\@dashdim #2\unitlength
+%<latexrelease>\@dashcnt \@dashdim \advance\@dashcnt 200
+%<latexrelease>\@dashdim #1\unitlength\divide\@dashcnt \@dashdim
+%<latexrelease>\ifodd\@dashcnt\@dashdim \z@
+%<latexrelease>\advance\@dashcnt \@ne \divide\@dashcnt \tw@
+%<latexrelease>\else \divide\@dashdim \tw@ \divide\@dashcnt \tw@
+%<latexrelease>\advance\@dashcnt \m@ne
+%<latexrelease>\setbox\@dashbox \hbox{%
+%<latexrelease> \vrule \@height \@halfwidth \@depth \@halfwidth
+%<latexrelease> \@width \@dashdim}\put(0,0){\copy\@dashbox}%
+%<latexrelease>\put(0,#3){\copy\@dashbox}%
+%<latexrelease>\put(#2,0){\hskip-\@dashdim\copy\@dashbox}%
+%<latexrelease>\put(#2,#3){\hskip-\@dashdim\box\@dashbox}%
+%<latexrelease>\multiply\@dashdim \thr@@
+%<latexrelease>\fi
+%<latexrelease>\setbox\@dashbox \hbox{%
+%<latexrelease> \vrule \@height \@halfwidth \@depth \@halfwidth
+%<latexrelease> \@width #1\unitlength\hskip #1\unitlength}\@tempcnta\z@
+%<latexrelease>\put(0,0){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt
+%<latexrelease>\do{\copy\@dashbox\advance\@tempcnta \@ne }}\@tempcnta\z@
+%<latexrelease>\put(0,#3){\hskip\@dashdim \@whilenum \@tempcnta <\@dashcnt
+%<latexrelease>\do{\copy\@dashbox\advance\@tempcnta \@ne }}%
+%<latexrelease>\@dashdim #3\unitlength
+%<latexrelease>\@dashcnt \@dashdim \advance\@dashcnt 200
+%<latexrelease>\@dashdim #1\unitlength\divide\@dashcnt \@dashdim
+%<latexrelease>\ifodd\@dashcnt \@dashdim \z@
+%<latexrelease>\advance\@dashcnt \@ne \divide\@dashcnt \tw@
+%<latexrelease>\else
+%<latexrelease>\divide\@dashdim \tw@ \divide\@dashcnt \tw@
+%<latexrelease>\advance\@dashcnt \m@ne
+%<latexrelease>\setbox\@dashbox\hbox{\hskip -\@halfwidth
+%<latexrelease>\vrule \@width \@wholewidth
+%<latexrelease>\@height \@dashdim}\put(0,0){\copy\@dashbox}%
+%<latexrelease>\put(#2,0){\copy\@dashbox}%
+%<latexrelease>\put(0,#3){\lower\@dashdim\copy\@dashbox}%
+%<latexrelease>\put(#2,#3){\lower\@dashdim\copy\@dashbox}%
+%<latexrelease>\multiply\@dashdim \thr@@
+%<latexrelease>\fi
+%<latexrelease>\setbox\@dashbox\hbox{\vrule \@width \@wholewidth
+%<latexrelease>\@height #1\unitlength}\@tempcnta\z@
+%<latexrelease>\put(0,0){%
+%<latexrelease> \hskip -\@halfwidth \vbox{\@whilenum \@tempcnta <\@dashcnt
+%<latexrelease> \do{\vskip #1\unitlength\copy\@dashbox
+%<latexrelease> \advance\@tempcnta\@ne }%
+%<latexrelease> \vskip\@dashdim}}\@tempcnta\z@
+%<latexrelease>\put(#2,0){%
+%<latexrelease> \hskip -\@halfwidth \vbox{\@whilenum \@tempcnta<\@dashcnt
+%<latexrelease> \do{\vskip #1\unitlength\copy\@dashbox
+%<latexrelease> \advance\@tempcnta \@ne }%
+%<latexrelease> \vskip\@dashdim}}}\@makepicbox(#2,#3)}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -1143,12 +1412,26 @@
% \begin{macrocode}
\newif\if@ovvline \@ovvlinetrue
\newif\if@ovhline \@ovhlinetrue
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@ovhlinetrue}%
+%<latexrelease> {Avoid almost zero length leaders}%
+%<latexrelease>\let\if@ovvline\@undefined
+%<latexrelease>\let\if@ovhline\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@oval}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@oval}{default units}%
\def\@oval(#1,#2)[#3]{\begingroup\boxmaxdepth \maxdimen
\@ovttrue \@ovbtrue \@ovltrue \@ovrtrue
% \end{macrocode}
@@ -1157,9 +1440,10 @@
\@ovvlinefalse \@ovhlinefalse
% \end{macrocode}
% \begin{macrocode}
- \@tfor\reserved@a :=#3\do{\csname @ov\reserved@a false\endcsname}%
- \@ovxx #1\unitlength
- \@ovyy #2\unitlength
+ \@tfor\reserved@a :=#3\do{%
+ \csname @ov\reserved@a false\endcsname}%
+ \@defaultunitsset\@ovxx{#1}\unitlength
+ \@defaultunitsset\@ovyy{#2}\unitlength
% \end{macrocode}
% \changes{v1.1l}{2016/03/29}{add setting of line tests}
% \begin{macrocode}
@@ -1187,11 +1471,79 @@
\advance\@ovdy\@ovro \ht\@tempboxa\z@ \dp\@tempboxa\z@
\@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}%
\endgroup}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2016/03/31}%
+%<latexrelease> {\@oval}{default units}%
+%<latexrelease>\def\@oval(#1,#2)[#3]{\begingroup\boxmaxdepth \maxdimen
+%<latexrelease> \@ovttrue \@ovbtrue \@ovltrue \@ovrtrue
+%<latexrelease> \@ovvlinefalse \@ovhlinefalse
+%<latexrelease> \@tfor\reserved@a :=#3\do{%
+%<latexrelease> \csname @ov\reserved@a false\endcsname}%
+%<latexrelease> \@ovxx #1\unitlength
+%<latexrelease> \@ovyy #2\unitlength
+%<latexrelease> \@tempdimb \ifdim \@ovyy >\@ovxx \@ovxx \@ovvlinetrue
+%<latexrelease> \else \@ovyy \ifdim \@ovyy =\@ovxx \else \@ovhlinetrue
+%<latexrelease> \fi\fi
+%<latexrelease> \advance \@tempdimb -2\p@
+%<latexrelease> \@getcirc \@tempdimb
+%<latexrelease> \@ovro \ht\@tempboxa \@ovri \dp\@tempboxa
+%<latexrelease> \@ovdx\@ovxx \advance\@ovdx -\@tempdima \divide\@ovdx \tw@
+%<latexrelease> \@ovdy\@ovyy \advance\@ovdy -\@tempdima \divide\@ovdy \tw@
+%<latexrelease> \ifdim \@ovdx >\z@ \@ovhlinetrue \fi
+%<latexrelease> \ifdim \@ovdy >\z@ \@ovvlinetrue \fi
+%<latexrelease> \@circlefnt \setbox\@tempboxa
+%<latexrelease> \hbox{\if@ovr \@ovvert32\kern -\@tempdima \fi
+%<latexrelease> \if@ovl
+%<latexrelease> \kern \@ovxx \@ovvert01\kern -\@tempdima \kern -\@ovxx
+%<latexrelease> \fi
+%<latexrelease> \if@ovt \@ovhorz \kern -\@ovxx \fi
+%<latexrelease> \if@ovb \raise \@ovyy \@ovhorz \fi}\advance\@ovdx\@ovro
+%<latexrelease> \advance\@ovdy\@ovro \ht\@tempboxa\z@ \dp\@tempboxa\z@
+%<latexrelease> \@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}%
+%<latexrelease> \endgroup}
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@oval}{default units}%
+%<latexrelease>\def\@oval(#1,#2)[#3]{\begingroup\boxmaxdepth \maxdimen
+%<latexrelease> \@ovttrue \@ovbtrue \@ovltrue \@ovrtrue
+%<latexrelease> \@tfor\reserved@a :=#3\do
+%<latexrelease> {\csname @ov\reserved@a false\endcsname}%
+%<latexrelease> \@ovxx #1\unitlength
+%<latexrelease> \@ovyy #2\unitlength
+%<latexrelease> \@tempdimb \ifdim \@ovyy >\@ovxx \@ovxx\else \@ovyy \fi
+%<latexrelease> \advance \@tempdimb -2\p@
+%<latexrelease> \@getcirc \@tempdimb
+%<latexrelease> \@ovro \ht\@tempboxa \@ovri \dp\@tempboxa
+%<latexrelease> \@ovdx\@ovxx \advance\@ovdx -\@tempdima \divide\@ovdx \tw@
+%<latexrelease> \@ovdy\@ovyy \advance\@ovdy -\@tempdima \divide\@ovdy \tw@
+%<latexrelease> \@circlefnt \setbox\@tempboxa
+%<latexrelease> \hbox{\if@ovr \@ovvert32\kern -\@tempdima \fi
+%<latexrelease> \if@ovl
+%<latexrelease> \kern \@ovxx \@ovvert01\kern -\@tempdima \kern -\@ovxx
+%<latexrelease> \fi
+%<latexrelease> \if@ovt \@ovhorz \kern -\@ovxx \fi
+%<latexrelease> \if@ovb \raise \@ovyy \@ovhorz \fi}\advance\@ovdx\@ovro
+%<latexrelease> \advance\@ovdy\@ovro \ht\@tempboxa\z@ \dp\@tempboxa\z@
+%<latexrelease> \@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}%
+%<latexrelease> \endgroup}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@ovvert}
% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2016/03/31}%
+%<latexrelease> {\@ovvert}{Avoid almost zero length leaders}%
+%<*2ekernel|latexrelease>
\def\@ovvert#1#2{\vbox to\@ovyy{%
\if@ovb \@tempcntb \@tempcnta \advance \@tempcntb #1\relax
\kern -\@ovro \hbox{\char \@tempcntb}\nointerlineskip
@@ -1207,11 +1559,32 @@
\if@ovt \@tempcntb \@tempcnta \advance \@tempcntb #2\relax
\hbox{\char \@tempcntb}%
\else \kern \@ovdy \kern \@ovro \fi}}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@ovvert}{Avoid almost zero length leaders}%
+%<latexrelease>\def\@ovvert#1#2{\vbox to\@ovyy{%
+%<latexrelease> \if@ovb \@tempcntb \@tempcnta \advance \@tempcntb #1\relax
+%<latexrelease> \kern -\@ovro \hbox{\char \@tempcntb}\nointerlineskip
+%<latexrelease> \else \kern \@ovri \kern \@ovdy \fi
+%<latexrelease> \leaders\vrule \@width \@wholewidth\vfil \nointerlineskip
+%<latexrelease> \if@ovt \@tempcntb \@tempcnta \advance \@tempcntb #2\relax
+%<latexrelease> \hbox{\char \@tempcntb}%
+%<latexrelease> \else \kern \@ovdy \kern \@ovro \fi}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@ovhorz}
% \begin{macrocode}
+%</2ekernel>
+%<latexrelease>\IncludeInRelease{2016/03/31}%
+%<latexrelease> {\@ovhorz}{Avoid almost zero length leaders}%
+%<*2ekernel|latexrelease>
\def\@ovhorz{\hb@xt@\@ovxx{\kern \@ovro
\if@ovr \else \kern \@ovdx \fi
% \end{macrocode}
@@ -1220,51 +1593,18 @@
% \begin{macrocode}
\if@ovhline \leaders \hrule \@height \@wholewidth \fi
% \end{macrocode}
+%
% \begin{macrocode}
\hfil
\if@ovl \else \kern \@ovdx \fi
\kern \@ovri}}
+%</2ekernel|latexrelease>
% \end{macrocode}
-% \end{macro}
-%
+%
% \begin{macrocode}
-%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
-%<latexrelease> {\@ovhlinetrue}%
-%<latexrelease> {Avoid almost zero length leaders}%
-%<latexrelease>\let\if@ovvline\@undefined
-%<latexrelease>\let\if@ovhline\@undefined
-%<latexrelease>\def\@oval(#1,#2)[#3]{\begingroup\boxmaxdepth \maxdimen
-%<latexrelease> \@ovttrue \@ovbtrue \@ovltrue \@ovrtrue
-%<latexrelease> \@tfor\reserved@a :=#3\do
-%<latexrelease> {\csname @ov\reserved@a false\endcsname}%
-%<latexrelease> \@ovxx #1\unitlength
-%<latexrelease> \@ovyy #2\unitlength
-%<latexrelease> \@tempdimb \ifdim \@ovyy >\@ovxx \@ovxx\else \@ovyy \fi
-%<latexrelease> \advance \@tempdimb -2\p@
-%<latexrelease> \@getcirc \@tempdimb
-%<latexrelease> \@ovro \ht\@tempboxa \@ovri \dp\@tempboxa
-%<latexrelease> \@ovdx\@ovxx \advance\@ovdx -\@tempdima \divide\@ovdx \tw@
-%<latexrelease> \@ovdy\@ovyy \advance\@ovdy -\@tempdima \divide\@ovdy \tw@
-%<latexrelease> \@circlefnt \setbox\@tempboxa
-%<latexrelease> \hbox{\if@ovr \@ovvert32\kern -\@tempdima \fi
-%<latexrelease> \if@ovl
-%<latexrelease> \kern \@ovxx \@ovvert01\kern -\@tempdima \kern -\@ovxx
-%<latexrelease> \fi
-%<latexrelease> \if@ovt \@ovhorz \kern -\@ovxx \fi
-%<latexrelease> \if@ovb \raise \@ovyy \@ovhorz \fi}\advance\@ovdx\@ovro
-%<latexrelease> \advance\@ovdy\@ovro \ht\@tempboxa\z@ \dp\@tempboxa\z@
-%<latexrelease> \@put{-\@ovdx}{-\@ovdy}{\box\@tempboxa}%
-%<latexrelease> \endgroup}
-%<latexrelease>\def\@ovvert#1#2{\vbox to\@ovyy{%
-%<latexrelease> \if@ovb \@tempcntb \@tempcnta \advance \@tempcntb #1\relax
-%<latexrelease> \kern -\@ovro \hbox{\char \@tempcntb}\nointerlineskip
-%<latexrelease> \else \kern \@ovri \kern \@ovdy \fi
-%<latexrelease> \leaders\vrule \@width \@wholewidth\vfil \nointerlineskip
-%<latexrelease> \if@ovt \@tempcntb \@tempcnta \advance \@tempcntb #2\relax
-%<latexrelease> \hbox{\char \@tempcntb}%
-%<latexrelease> \else \kern \@ovdy \kern \@ovro \fi}}
+%<latexrelease> {\@ovhorz}{Avoid almost zero length leaders}%
%<latexrelease>\def\@ovhorz{\hb@xt@\@ovxx{\kern \@ovro
%<latexrelease> \if@ovr \else \kern \@ovdx \fi
%<latexrelease> \leaders \hrule \@height \@wholewidth \hfil
@@ -1273,6 +1613,7 @@
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
+% \end{macro}
%
% \begin{macro}{\circle}
% \changes{LaTeX2.09}{1993/08/05}
@@ -1284,8 +1625,13 @@
%
% \begin{macro}{\@circle}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@circle}{default units}%
\def\@circle#1{%
- \begingroup \boxmaxdepth \maxdimen \@tempdimb #1\unitlength
+ \begingroup \boxmaxdepth \maxdimen
+ \@defaultunitsset\@tempdimb{#1}\unitlength
\ifdim \@tempdimb >15.5\p@ \@getcirc\@tempdimb
\@ovro\ht\@tempboxa
\setbox\@tempboxa\hbox{\@circlefnt
@@ -1296,13 +1642,52 @@
\box\@tempboxa}\ht\@tempboxa\z@ \dp\@tempboxa\z@
\@put{-\@ovro}{-\@ovro}{\box\@tempboxa}%
\else \@circ\@tempdimb{96}\fi\endgroup}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@circle}{default units}%
+%<latexrelease>\def\@circle#1{%
+%<latexrelease> \begingroup \boxmaxdepth \maxdimen \@tempdimb #1\unitlength
+%<latexrelease> \ifdim \@tempdimb >15.5\p@ \@getcirc\@tempdimb
+%<latexrelease> \@ovro\ht\@tempboxa
+%<latexrelease> \setbox\@tempboxa\hbox{\@circlefnt
+%<latexrelease> \advance\@tempcnta\tw@ \char \@tempcnta
+%<latexrelease> \advance\@tempcnta\m@ne \char \@tempcnta
+%<latexrelease> \kern -2\@tempdima
+%<latexrelease> \advance\@tempcnta\tw@
+%<latexrelease> \raise \@tempdima \hbox{\char\@tempcnta}%
+%<latexrelease> \raise \@tempdima
+%<latexrelease> \box\@tempboxa}\ht\@tempboxa\z@ \dp\@tempboxa\z@
+%<latexrelease> \@put{-\@ovro}{-\@ovro}{\box\@tempboxa}%
+%<latexrelease> \else \@circ\@tempdimb{96}\fi\endgroup}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@dot}
% Internal form of |\circle*|.
% \begin{macrocode}
-\def\@dot#1{\@tempdimb #1\unitlength \@circ\@tempdimb{112}}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@dot}{default units}%
+\def\@dot#1{%
+ \@defaultunitsset\@tempdimb{#1}\unitlength
+ \@circ\@tempdimb{112}}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@dot}{default units}%
+%<latexrelease>\def\@dot#1{\@tempdimb #1\unitlength \@circ\@tempdimb{112}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -1340,7 +1725,7 @@
% \end{macro}
%
% \begin{macro}{\@xdim}
-% \begin{macro}{\yxdim}
+% \begin{macro}{\@ydim}
% Length registers.
% \begin{macrocode}
\newdimen\@xdim
@@ -1482,35 +1867,45 @@
%
% \begin{macro}{\@bezier}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@bezier}{default units}%
\def\@bezier#1(#2,#3)(#4,#5)(#6,#7){%
\ifnum #1=\z@
- \@ovxx #4\unitlength
- \advance\@ovxx -#2\unitlength
+ \@defaultunitsset\@ovxx{#4}\unitlength
+ \@defaultunitsset{\advance\@ovxx}{-#2}\unitlength
\ifdim \@ovxx<\z@ \@ovxx -\@ovxx \fi
- \@ovdx #6\unitlength
- \advance\@ovdx -#4\unitlength
+ \@defaultunitsset\@ovdx{#6}\unitlength
+ \@defaultunitsset{\advance\@ovdx}{-#4}\unitlength
\ifdim \@ovdx<\z@ \@ovdx -\@ovdx \fi
\ifdim \@ovxx<\@ovdx \@ovxx \@ovdx \fi
- \@ovyy #5\unitlength
- \advance\@ovyy -#3\unitlength
+ \@defaultunitsset\@ovyy{#5}\unitlength
+ \@defaultunitsset{\advance\@ovyy}{-#3}\unitlength
\ifdim \@ovyy<\z@ \@ovyy -\@ovyy \fi
- \@ovdy #7\unitlength
- \advance\@ovdy -#5\unitlength
+ \@defaultunitsset\@ovdy{#7}\unitlength
+ \@defaultunitsset{\advance\@ovdy}{-#5}\unitlength
\ifdim \@ovdy<\z@ \@ovdy -\@ovdy \fi
\ifdim \@ovyy<\@ovdy \@ovyy \@ovdy \fi
\@multicnt
\ifdim \@ovxx>\@ovyy \@ovxx \else \@ovyy \fi
\@ovxx .5\@halfwidth \divide\@multicnt\@ovxx
- \ifnum \qbeziermax<\@multicnt \@multicnt\qbeziermax\relax \fi
+ \ifnum \qbeziermax<\@multicnt
+ \@multicnt\qbeziermax\relax
+ \fi
\else \@multicnt#1\relax \fi
\@tempcnta\@multicnt \advance\@tempcnta\@ne
- \@ovdx #4\unitlength \advance\@ovdx -#2\unitlength
+ \@defaultunitsset\@ovdx{#4}\unitlength
+ \@defaultunitsset{\advance\@ovdx}{-#2}\unitlength
\multiply\@ovdx \tw@
- \@ovxx #6\unitlength \advance\@ovxx -#2\unitlength
+ \@defaultunitsset\@ovxx{#6}\unitlength
+ \@defaultunitsset{\advance\@ovxx}{-#2}\unitlength
\advance\@ovxx -\@ovdx \divide\@ovxx\@multicnt
- \@ovdy #5\unitlength \advance\@ovdy -#3\unitlength
+ \@defaultunitsset\@ovdy{#5}\unitlength
+ \@defaultunitsset{\advance\@ovdy}{-#3}\unitlength
\multiply\@ovdy \tw@
- \@ovyy #7\unitlength \advance\@ovyy -#3\unitlength
+ \@defaultunitsset\@ovyy{#7}\unitlength
+ \@defaultunitsset{\advance\@ovyy}{-#3}\unitlength
\advance\@ovyy -\@ovdy \divide\@ovyy\@multicnt
% \end{macrocode}
%
@@ -1536,6 +1931,67 @@
\hb@xt@\z@{\kern\@xdim
\unhcopy\@tempboxa\hss}%
\advance\count@\@ne}}}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@bezier}{default units}%
+%<latexrelease>\def\@bezier#1(#2,#3)(#4,#5)(#6,#7){%
+%<latexrelease> \ifnum #1=\z@
+%<latexrelease> \@ovxx #4\unitlength
+%<latexrelease> \advance\@ovxx -#2\unitlength
+%<latexrelease> \ifdim \@ovxx<\z@ \@ovxx -\@ovxx \fi
+%<latexrelease> \@ovdx #6\unitlength
+%<latexrelease> \advance\@ovdx -#4\unitlength
+%<latexrelease> \ifdim \@ovdx<\z@ \@ovdx -\@ovdx \fi
+%<latexrelease> \ifdim \@ovxx<\@ovdx \@ovxx \@ovdx \fi
+%<latexrelease> \@ovyy #5\unitlength
+%<latexrelease> \advance\@ovyy -#3\unitlength
+%<latexrelease> \ifdim \@ovyy<\z@ \@ovyy -\@ovyy \fi
+%<latexrelease> \@ovdy #7\unitlength
+%<latexrelease> \advance\@ovdy -#5\unitlength
+%<latexrelease> \ifdim \@ovdy<\z@ \@ovdy -\@ovdy \fi
+%<latexrelease> \ifdim \@ovyy<\@ovdy \@ovyy \@ovdy \fi
+%<latexrelease> \@multicnt
+%<latexrelease> \ifdim \@ovxx>\@ovyy \@ovxx \else \@ovyy \fi
+%<latexrelease> \@ovxx .5\@halfwidth \divide\@multicnt\@ovxx
+%<latexrelease> \ifnum
+%<latexrelease> \qbeziermax<\@multicnt \@multicnt\qbeziermax\relax
+%<latexrelease> \fi
+%<latexrelease> \else \@multicnt#1\relax \fi
+%<latexrelease> \@tempcnta\@multicnt \advance\@tempcnta\@ne
+%<latexrelease> \@ovdx #4\unitlength \advance\@ovdx -#2\unitlength
+%<latexrelease> \multiply\@ovdx \tw@
+%<latexrelease> \@ovxx #6\unitlength \advance\@ovxx -#2\unitlength
+%<latexrelease> \advance\@ovxx -\@ovdx \divide\@ovxx\@multicnt
+%<latexrelease> \@ovdy #5\unitlength \advance\@ovdy -#3\unitlength
+%<latexrelease> \multiply\@ovdy \tw@
+%<latexrelease> \@ovyy #7\unitlength \advance\@ovyy -#3\unitlength
+%<latexrelease> \advance\@ovyy -\@ovdy \divide\@ovyy\@multicnt
+%<latexrelease> \setbox\@tempboxa\hbox{%
+%<latexrelease> \hskip -\@halfwidth
+%<latexrelease> \vrule \@height\@halfwidth
+%<latexrelease> \@depth \@halfwidth
+%<latexrelease> \@width \@wholewidth}%
+%<latexrelease> \put(#2,#3){%
+%<latexrelease> \count@\z@
+%<latexrelease> \@whilenum{\count@<\@tempcnta}\do
+%<latexrelease> {\@xdim\count@\@ovxx
+%<latexrelease> \advance\@xdim\@ovdx
+%<latexrelease> \divide\@xdim\@multicnt
+%<latexrelease> \multiply\@xdim\count@
+%<latexrelease> \@ydim\count@\@ovyy
+%<latexrelease> \advance\@ydim\@ovdy
+%<latexrelease> \divide\@ydim\@multicnt
+%<latexrelease> \multiply\@ydim\count@
+%<latexrelease> \raise \@ydim
+%<latexrelease> \hb@xt@\z@{\kern\@xdim
+%<latexrelease> \unhcopy\@tempboxa\hss}%
+%<latexrelease> \advance\count@\@ne}}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
% \end{macro}
diff --git a/Master/texmf-dist/source/latex/base/ltplain.dtx b/Master/texmf-dist/source/latex/base/ltplain.dtx
index 06602780664..7949b836d46 100644
--- a/Master/texmf-dist/source/latex/base/ltplain.dtx
+++ b/Master/texmf-dist/source/latex/base/ltplain.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltplain.dtx}
- [2017/04/10 v2.3c LaTeX Kernel (Plain TeX)]
+ [2020/08/20 v2.3d LaTeX Kernel (Plain TeX)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltplain.dtx}
@@ -691,12 +691,32 @@
% \end{macro}
%
% \begin{macro}{\alloc@}
+% \changes{v2.3d}{2020/08/20}
+% {Define \cs{alloc@} in terms of \cs{e@alloc}}
+% Since |\e@alloc| was added in 2015, |\@alloc| has not been used,
+% but was left as some legacy code calls it. However the original
+% defnition gives spurious errors once the ``classic'' registers
+% run out, so it is now defined to call |\e@alloc| internally.
% \begin{macrocode}
-\def\alloc@#1#2#3#4#5{\global\advance\count1#1\@ne
- \ch@ck#1#4#2%
- \allocationnumber\count1#1%
- \global#3#5\allocationnumber
- \wlog{\string#5=\string#2\the\allocationnumber}}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}
+%<latexrelease> {\alloc@}{emulate alloc@}%
+\def\alloc@#1#2#3#4{\e@alloc#2#3{\count1#1}#4\float@count}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\alloc@}{emulate alloc@}%
+%<latexrelease>\def\alloc@#1#2#3#4#5{\global\advance\count1#1\@ne
+%<latexrelease> \ch@ck#1#4#2%
+%<latexrelease> \allocationnumber\count1#1%
+%<latexrelease> \global#3#5\allocationnumber
+%<latexrelease> \wlog{\string#5=\string#2\the\allocationnumber}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/base/ltsect.dtx b/Master/texmf-dist/source/latex/base/ltsect.dtx
index 9ccd042fb4e..359b445f453 100644
--- a/Master/texmf-dist/source/latex/base/ltsect.dtx
+++ b/Master/texmf-dist/source/latex/base/ltsect.dtx
@@ -31,7 +31,7 @@
%%% From File: ltsect.dtx
%<*driver>
% \fi
-\ProvidesFile{ltsect.dtx}[2019/08/27 v1.1d LaTeX Kernel (Sectioning)]
+\ProvidesFile{ltsect.dtx}[2020/07/27 v1.1e LaTeX Kernel (Sectioning)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltsect.dtx}
@@ -137,20 +137,22 @@
%
% \begin{macro}{\author}
% \changes{LaTeX2e}{1993/12/11}{Added default}
+% \changes{v1.1e}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
%
% |\author| for use in |\maketitle|. If not given |\maketitle| will
% produce a warning message.
%
% \begin{macrocode}
-\DeclareRobustCommand\author[1]{\gdef\@author{#1}}
+\DeclareRobustCommand*\author[1]{\gdef\@author{#1}}
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\date}
% |\date| for use in |\maketitle|. If not given |\maketitle| will
% produce |\today| as the default.
+% \changes{v1.1e}{2020/07/27}{Don't make the command \cs{long} (gh/354)}
% \begin{macrocode}
-\DeclareRobustCommand\date[1]{\gdef\@date{#1}}
+\DeclareRobustCommand*\date[1]{\gdef\@date{#1}}
% \end{macrocode}
% \end{macro}
%
@@ -776,20 +778,33 @@
% \cs{addcontentsline}. ASAJ.}
% \changes{v1.1c}{2018/09/26}{Sometimes mask the endline char when
% writing to files (github/73)}
+% \changes{v1.1e}{2020/10/01}{add a fourth argument for better
+% hyperref compability}
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\addcontentsline}{fourth argument}%
+\def\addcontentsline#1#2#3{%
+% \end{macrocode}
+% We add an empty brace pair at the end of \cs{contentsline}
+% so that the number of argument is identical in documents
+% with and without hyperref.
+% \begin{macrocode}
+ \addtocontents{#1}{\protect\contentsline{#2}{#3}{\thepage}{}%
+ \protected@file@percent}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2018/12/01}%
%<latexrelease> {\addcontentsline}{Mask line endings}%
-\def\addcontentsline#1#2#3{%
- \addtocontents{#1}{\protect\contentsline{#2}{#3}{\thepage}%
+%<latexrelease> \def\addcontentsline#1#2#3{%
+%<latexrelease> \addtocontents{#1}{\protect\contentsline{#2}{#3}{\thepage}%
% \end{macrocode}
% We add \cs{protected@file@percent} at the end which is turned inside
% \cs{@writefile} into a percent character to mask the newline after
% the closing argument brace.
% \begin{macrocode}
- \protected@file@percent}}
-%</2ekernel|latexrelease>
+%<latexrelease> \protected@file@percent}}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\addcontentsline}{Mask line endings}%
diff --git a/Master/texmf-dist/source/latex/base/ltshipout.dtx b/Master/texmf-dist/source/latex/base/ltshipout.dtx
new file mode 100644
index 00000000000..8f0422c887b
--- /dev/null
+++ b/Master/texmf-dist/source/latex/base/ltshipout.dtx
@@ -0,0 +1,1739 @@
+% \iffalse meta-comment
+%%
+%% File: ltshipout.dtx (C) Copyright 2020 Frank Mittelbach, LaTeX Team
+%%
+%
+% This file is part of the LaTeX base system.
+% -------------------------------------------
+%
+% It may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
+% of this license or (at your option) any later version.
+% The latest version of this license is in
+% https://www.latex-project.org/lppl.txt
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008 or later.
+%
+% This file has the LPPL maintenance status "maintained".
+%
+% The list of all files belonging to the LaTeX base distribution is
+% given in the file `manifest.txt'. See also `legal.txt' for additional
+% information.
+%
+% The list of derived (unpacked) files belonging to the distribution
+% and covered by LPPL is defined by the unpacking scripts (with
+% extension .ins) which are part of the distribution.
+%
+% \fi
+%
+% \iffalse
+%
+%%% From File: ltshipout.dtx
+%
+% \begin{macrocode}
+\providecommand\ltshipoutversion{v1.0c}
+\providecommand\ltshipoutdate{2020/09/27}
+% \end{macrocode}
+%
+%<*driver>
+
+\documentclass{l3doc}
+
+% bug fix fo l3doc.cls
+\ExplSyntaxOn
+\cs_set_protected:Npn \__codedoc_macro_typeset_one:nN #1#2
+ {
+ \vbox_set:Nn \l__codedoc_macro_box
+ {
+ \vbox_unpack_drop:N \l__codedoc_macro_box
+ \hbox { \llap { \__codedoc_print_macroname:nN {#1} #2
+ \MacroFont % <----- without it the \ is in lmr10 if a link is made
+ \
+ } }
+ }
+ \int_incr:N \l__codedoc_macro_int
+ }
+\ExplSyntaxOff
+
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+ \DocInput{ltshipout.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+%
+% \long\def\fmi#1{\begin{quote}\itshape Todo: #1\end{quote}}
+%
+% \providecommand\hook[1]{\texttt{#1}}
+% \providecommand\pkg[1]{\texttt{#1}}
+%
+%
+% \title{The \texttt{ltshipout} package\thanks{This package has version
+% \ltshipoutversion\ dated \ltshipoutdate, \copyright\ \LaTeX\
+% Project.}}
+%
+% \author{Frank Mittelbach}
+%
+% \maketitle
+%
+%
+% \tableofcontents
+%
+% \section{Introduction}
+%
+% The code provides an interface to the \cs{shipout} primitive of
+% \TeX{} which is called when a finished pages is finally
+% \enquote{shipped out} to the target output file, e.g., the
+% \texttt{.dvi} or \texttt{.pdf} file.
+% A good portion of the code is based on ideas by Heiko Oberdiek
+% implemented in his packages \pkg{atbegshi} and \pkg{atenddvi}
+% even though the interfaces are somewhat
+% different.\footnote{Heiko's interfaces are emulated by the kernel
+% code, if a document requests his packages, so older documents
+% will continue to work.}
+%
+% \subsection{Overloading the \cs{shipout} primitive}
+%
+%
+% \begin{function}{\shipout}
+% With this implementation \TeX's shipout primitive is no longer
+% available for direct use. Instead \cs{shipout} is running some
+% (complicated) code that picks up the box to be shipped out
+% regardless of how that is done, i.e., as a constructed \cs{vbox}
+% or \cs{hbox} or as a box register.
+%
+% It then stores it in a named box register. This box can then be
+% manipulated through a set of hooks after which it is shipped out
+% for real.
+% \end{function}
+%
+% \begin{variable}{\ShipoutBox,\l_shipout_box}
+% This box register is called \cs{ShipoutBox} (alternatively available via the
+% L3 name \cs{l_shipout_box}).
+% \end{variable}
+%
+%
+% \begin{variable}{\l_shipout_box_ht_dim,
+% \l_shipout_box_dp_dim,\l_shipout_box_wd_dim,
+% \l_shipout_box_ht_plus_dp_dim}
+% The shipout box dimensions are available in the L3 registers
+% \cs{l_shipout_box_ht_dim}, etc.\ (there are no \LaTeXe{}
+% names).\footnotemark{} These variables can be used
+% inside the hook code for \hook{shipout/before},
+% \hook{shipout/foreground} and \hook{shipout/background} if needed.
+% \end{variable}
+% \footnotetext{Might need changing, but HO's version as strings
+% is not really helpful I think).}
+%
+%
+%
+%
+% \subsection{Provided hooks}
+%
+% \begin{variable}{shipout/before,
+% shipout/foreground,shipout/background,
+% shipout/firstpage,
+% shipout/lastpage}
+% The code offers a number of hooks into which packages (or the
+% user) can add code to support different use cases.
+% These are:
+% \begin{description}
+% \item[\hook{shipout/before}]
+%
+% This hook is executed after the finished page has been stored in
+% \cs{ShipoutBox} / \cs{l_shipout_box}).
+% It can be used to alter that box content or to discard it
+% completely (see \cs{DiscardShipoutBox} below).
+%
+% \item[\hook{shipout/background}]
+%
+% This hook adds a picture environment into the background of
+% the page with the \texttt{(0,0)} coordinate in the top-left
+% corner using a \cs{unitlength} of \texttt{1pt}.
+%
+% It should therefore only receive \cs{put} commands or other
+% commands suitable in a \texttt{picture} environment and the
+% vertical coordinate values would normally be
+% negative.
+%
+% Technically this is implemented by adding a zero-sized
+% \cs{hbox} as the very first item into the \cs{ShipoutBox}
+% containing that \texttt{picture} environment. Thus the rest of
+% the box content will overprint what ever is typeset by that hook.
+%
+%
+% \item[\hook{shipout/foreground}]
+%
+% This hook adds a picture environment into the foreground of
+% the page with the \texttt{(0,0)} coordinate in the top-left
+% corner using a \cs{unitlength} of \texttt{1pt}.
+%
+% Technically this is implemented by adding a zero-sized
+% \cs{hbox} as the very last item into the \cs{ShipoutBox} and
+% raising it up so that it still has its \texttt{(0,0)} point in
+% the top-left corner.
+% But being placed after the main box content it will be typeset
+% later and thus overprints it (i.e., is in the foreground).
+%
+%
+% \item[\hook{shipout/firstpage}]
+%
+% The material from this hook is executed only once at the very
+% beginning of the first output page that is shipped out (i.e.,
+% not discarded at the last minute). It should only contain
+% \cs{special} or similar commands needed to direct post processors
+% handling the \texttt{.dvi} or \texttt{.pdf} output.\footnotemark
+%
+% ^^A \fmi{not sure it has to be that restrictive.}
+%
+%
+% \item[\hook{shipout/lastpage}]
+%
+% The corresponding hook to add \cs{special}s at the very end of
+% the output file. It is only executed on the very last page ---
+% or rather on the page that \LaTeX{} believes is the last one.
+%
+% It may not be possible for \LaTeX{} to correctly determine
+% which page is the last one without several reruns. If this
+% happens and the hook is non-empty then \LaTeX{} will add an
+% extra page to place the material and also request a rerun to
+% get the correct placement sorted out.
+%
+% \end{description}
+% \end{variable}\footnotetext{In
+% \LaTeXe{} that was already existing, but implemented using a box
+% register with the name \cs{@begindvibox}.}
+%
+% As mentioned above the hook \hook{shipout/before} is executed
+% first and can manipulate the prepared shipout box stored in
+% \cs{ShipoutBox} or set things up for use in \cs{write} during the
+% actual shipout. The other hooks are added inside hboxes to the
+% box being shipped out in the following
+% order:
+% \begin{center}
+% \begin{tabular}{ll}
+% \hook{shipout/firstpage} & only on the first page \\
+% \hook{shipout/background} & \\
+% \meta{boxed content of \cs{ShipoutBox}} & \\
+% \hook{shipout/foreground} & \\
+% \hook{shipout/lastpage} & only on the last page \\
+% \end{tabular}
+% \end{center}
+% If any of the hooks has no code then that particular no box is
+% added at that point.
+%
+% In a document that doesn't produce pages, e.g., only makes
+% \cs{typeout}s, none of the hooks are executed (as there is no
+% \cs{shipout}) not even the \hook{shipout/lastpage} hook.
+%
+% \begin{function}{\AtBeginDvi,\AtEndDvi}
+% \cs{AtBeginDvi} is the existing \LaTeXe{} interface to fill the
+% \hook{shipout/firstpage} hook. This is not really a good name
+% as it is not just supporting \texttt{.dvi} but also \texttt{.pdf}
+% output or \texttt{.dvx}.
+%
+% \cs{AtEndDvi} is the counterpart that was not available in the
+% kernel but only through the package \pkg{atenddvi}. It fills the
+% \hook{shipout/lastpage} hook.
+%
+% \fmi{better names? Any suggestions?}
+%
+% \end{function}
+%
+% \subsection{Special commands for use inside the hooks}
+%
+% \begin{function}{\DiscardShipoutBox,\shipout_discard_box:}
+% \begin{syntax}
+% \cs{AddToHookNext} \texttt{\{shipout/before\} \{...\cs{DiscardShipoutBox}...\}}
+% \end{syntax}
+% The \cs{DiscardShipoutBox} declaration (L3 name
+% \cs{shipout_discard_box:})
+% requests that on the next
+% shipout the page box is thrown away instead of being shipped to
+% the \texttt{.dvi} or \texttt{.pdf} file.
+%
+% Typical applications wouldn't do this unconditionally, but have
+% some processing logic that decides to use or not to use the page.
+%
+% Note that if this declaration is used directly in the document it
+% may depend on the placement to which page it applies, given that
+% \LaTeX{} output routine is called in an asynchronous manner!
+%
+% \fmi{Once we have a new mark mechanism available we can improve
+% on that and make sure that the declaration applies to the page
+% that contains it.}
+% \end{function}
+%
+% In the \pkg{atbegshi} package there are a number of additional
+% commands for use inside the \hook{shipout/before} hook. They
+% should normally not be needed any more as one can instead simply
+% add code to the hooks \hook{shipout/before},
+% \hook{shipout/background} or
+% \hook{shipout/foreground}.\footnote{If that assumption turns out to
+% be wrong it would be trivial to change them to public functions
+% (right now they are private).} If \pkg{atbegshi} gets loaded then
+% those commands become available as public functions with their original
+% names as given below.
+%
+%
+% \subsection{Information counters}
+%
+%
+% \begin{variable}{\ReadonlyShipoutCounter,\g_shipout_readonly_int}
+% \begin{syntax}
+% \cs{ifnum}\cs{ReadOnlyShipoutCounter}\texttt{=...}
+% \cs{int_use:N} \cs{g_shipout_readonly_int} \texttt{\% expl3 usage}
+% \end{syntax}
+% This integer holds the number of pages shipped out up to now
+% (including the one to be shipped out when inside the output
+% routine). More precisely, it is incremented only after it is
+% clear that a page will be shipped out, i.e., after the
+% \hook{shipout/before} hook (because that might discard the page)!
+%
+% Just like with the \texttt{page} counter its value is
+% only accurate within the output routine. In the body of the
+% document it may be off by one as the output routine is called
+% asynchronously!
+%
+% Also important: it \emph{must not} be set, only read. There are
+% no provisions to prevent that but if you do, chaos will be the
+% result. To emphasize this fact it is not provided as a \LaTeX{}
+% counter but as a \TeX{} counter (i.e., a command), so
+% \cs{Alph}\Arg{\cs{ReadonlyShipoutCounter}} etc, would not work.
+% \end{variable}
+%
+% \begin{variable}{totalpages,\g_shipout_totalpages_int}
+% \begin{syntax}
+% \cs{arabic}\texttt{\{totalpages\}}
+% \cs{int_use:N} \cs{g_shipout_totalpage_int} \texttt{\% expl3 usage}
+% \end{syntax}
+% In contrast to \cs{ReadonlyShipoutCounter}, the
+% \texttt{totalpages} counter is a \LaTeX{} counter and incremented
+% for each shipout attempt including those pages that are discarded
+% for one or the other reason. Again \hook{shipout/before} sees
+% the counter before it is incremented).
+%
+% Furthermore, while it is incremented for each page, its value is
+% never used by \LaTeX. It can therefore be freely reset or changed by user
+% code, for example, to additionally count a number of pages that
+% are not build by \LaTeX\ but are added in a later part of the
+% process, e.g., cover pages or picture pages made externally.
+%
+% Important: as this is a page-related counter its value is only
+% reliable inside the output routine!
+% \end{variable}
+%
+% \begin{variable}{\PreviousTotalPages}
+% \begin{syntax}
+% \cs{thetotalpages}/\cs{PreviousTotalPages}
+% \end{syntax}
+% Command that expands to the number of total pages from the
+% previous run. If there was no previous run or if usedin the
+% preamble it expands to
+% \texttt{0}. Note that this is a command to a counter, so in order
+% to display the number in, say, Roman numerals you have to assign
+% its value to a counter and then use \cs{Roman} on that counter.
+% \end{variable}
+%
+%
+% \subsection{Debugging shipout code}
+%
+% \begin{function}{\DebugShipoutsOn,\DebugShipoutsOff,
+% \shipout_debug_on:,\shipout_debug_off:}
+% \begin{syntax}
+% \cs{DebugShipoutsOn}
+% \end{syntax}
+% Turn the debugging of shipout code on or off. This displays
+% changes made to the shipout data structures. \fmi{This needs
+% some rationalizing and may not stay this way.}
+% \end{function}
+%
+%
+%
+%
+% \section{Emulating commands from other packages}
+%
+% The packages in this section are no longer necessary but as they
+% are used in other packages they are emulated when they are loaded
+% via \cs{usepackage} or \cs{RequirePackage}.
+%
+%
+% \subsection{Emulating \pkg{atbegshi}}
+%
+%
+% \begin{function}{\AtBeginShipoutUpperLeft,\AtBeginShipoutUpperLeftForeground}
+% \begin{syntax}
+% \cs{AddToHook} \texttt{\{shipout/before\} \{...\cs{AtBeginShipoutUpperLeft}}\Arg{code}\texttt{...\}}
+% \end{syntax}
+% This adds a \texttt{picture} environment into the background of the shipout
+% box expecting \meta{code} to contain \texttt{picture}
+% commands. The same effect can be obtained by simply using kernel
+% features as follows:
+% \begin{quote}
+% \cs{AddToHook}\texttt{\{shipout/background\}}\Arg{code}
+% \end{quote}
+% There is one technical difference: if
+% \cs{AtBeginShipoutUpperLeft} is used several times each
+% invocation is put into its own box inside the shipout box whereas
+% all \meta{code} going into \hook{shipout/background} ends up
+% all in the same box in the order it is added or sorted based on
+% the rules for the hook chunks.
+%
+% \cs{AtBeginShipoutUpperLeftForeground} is similar with the
+% difference that the \texttt{picture} environment is placed in the
+% foreground. To model it with the kernel functions use the hook
+% \hook{shipout/foreground} instead.
+% \end{function}
+%
+%
+% \begin{function}{\AtBeginShipoutAddToBox,\AtBeginShipoutAddToBoxForeground}
+% \begin{syntax}
+% \cs{AddToHook} \texttt{\{shipout/before\} \{...\cs{AtBeginShipoutAddToBox}}\Arg{code}\texttt{...\}}
+% \end{syntax}
+% These work like \cs{AtBeginShipoutUpperLeft} and
+% \cs{AtBeginShipoutUpperLeftForeground} with the difference that
+% \meta{code} is directly placed into an \cs{hbox} inside the
+% shipout box and not surrounded by a \texttt{picture} environment.
+%
+% To emulate them using \hook{shipout/background} or
+% \hook{shipout/foreground} you may have to wrap \meta{code} into
+% a \cs{put} statement but if the code is not doing any typesetting
+% just adding it to the hook should be sufficient.
+% \end{function}
+%
+%
+%
+% \begin{function}{\AtBeginShipoutBox}
+% This is the name of the shipout box as \pkg{atbegshi} knows it.
+% \end{function}
+%
+% \begin{function}{\AtBeginShipoutInit}
+% By default \pkg{atbegshi} delayed its action until
+% \verb=\begin{document}=. This command was forcing it in an earlier
+% place. With the new concept it does nothing.
+% \end{function}
+%
+% \begin{function}{\AtBeginShipout,\AtBeginShipoutNext}
+% \begin{syntax}
+% \cs{AtBeginShipout}\Arg{code} $\equiv$ \cs{AddToHook}\texttt{\{shipout/before\}}\Arg{code}
+% \cs{AtBeginShipoutNext}\Arg{code} $\equiv$ \cs{AddToHookNext}\texttt{\{shipout/before\}}\Arg{code}
+% \end{syntax}
+% This is equivalent to filling the \hook{shipout/before} hook
+% by either using \cs{AddToHook} or \cs{AddToHookNext}, respectively.
+% \end{function}
+%
+% \begin{function}{\AtBeginShipoutFirst,\AtBeginShipoutDiscard}
+% The \pkg{atbegshi} names for \cs{AtBeginDvi} and \cs{DiscardShipoutBox}.
+% \end{function}
+%
+%
+%
+%
+% \subsection{Emulating \pkg{everyshi}}
+%
+%
+% \begin{function}{\EveryShipout}
+% \begin{syntax}
+% \cs{EveryShipout}\Arg{code} $\equiv$ \cs{AddToHook}\texttt{\{shipout/before\}}\Arg{code}
+% \end{syntax}
+% \end{function}
+%
+% \begin{function}{\AtNextShipout}
+% \begin{syntax}
+% \cs{AtNextShipout}\Arg{code} $\equiv$ \cs{AddToHookNext}\texttt{\{shipout/before\}}\Arg{code}
+% \end{syntax}
+% \end{function}
+%
+%
+%
+% \subsection{Emulating \pkg{atenddvi}}
+%
+% The \pkg{atenddvi} package implemented only a single command:
+% \cs{AtEndDvi} and that is now available out of the box.
+%
+%
+%
+% \subsection{Emulating \pkg{everypage}}
+%
+% This page takes over the original \cs{@begindvi} hook and replaces
+% it. It should be all covered by the hooks offered here (details
+% need checking) and thus could simply use the provided hooks
+% rather than defining its own.
+%
+%
+%
+% \StopEventually{\setlength\IndexMin{200pt} \PrintIndex }
+%
+%
+% \section{The Implementation}
+% \begin{macrocode}
+%<@@=shipout>
+% \end{macrocode}
+%
+% At the moment the whole module rolls back in one go, but if we
+% make any modifications in later releases this will then need
+% splitting.
+% \begin{macrocode}
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\shipout}{Hook mangement (shipout)}%
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\ExplSyntaxOn
+% \end{macrocode}
+%
+%
+% \subsection{Debugging}
+%
+% \begin{macro}{\g_@@_debug_bool}
+% Holds the current debugging state.
+% \begin{macrocode}
+\bool_new:N \g_@@_debug_bool
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\shipout_debug_on:,\shipout_debug_off:}
+% \begin{macro}{\@@_debug:n}
+% \begin{macro}{\@@_debug_gset:}
+% Turns debugging on and off by redefining \cs{@@_debug:n}.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_debug:n \use_none:n
+\cs_new_protected:Npn \shipout_debug_on:
+ {
+ \bool_gset_true:N \g_@@_debug_bool
+ \@@_debug_gset:
+ }
+\cs_new_protected:Npn \shipout_debug_off:
+ {
+ \bool_gset_false:N \g_@@_debug_bool
+ \@@_debug_gset:
+ }
+\cs_new_protected:Npn \@@_debug_gset:
+ {
+ \cs_gset_protected:Npx \@@_debug:n ##1
+ { \bool_if:NT \g_@@_debug_bool {##1} }
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+%
+%
+% \begin{macro}{\ShipoutBox,\l_shipout_box}
+% The box filled with the page to be shipped out (both L3 and
+% \LaTeXe{} name).
+% \begin{macrocode}
+\box_new:N \l_shipout_box
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_set_eq:NN \ShipoutBox \l_shipout_box
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\@@_execute:}
+% This is going to the be the code run by \cs{shipout}. The code
+% follows closely the ideas from \pkg{atbegshi}, so not
+% documenting that here for now.
+% \begin{macrocode}
+\cs_set_protected:Npn \@@_execute: {
+ \tl_set:Nx \l_@@_group_level_tl
+ { \int_value:w \tex_currentgrouplevel:D }
+ \tex_afterassignment:D \@@_execute_test_level:
+ \tex_setbox:D \l_shipout_box
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\shipout}
+% Overloading the \cs{shipout} primitive:
+% \begin{macrocode}
+\cs_gset_eq:NN \shipout \@@_execute:
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\l_@@_group_level_tl}
+% Helper token list to record the group level at which
+% \cs{@@_execute:} is encountered. \begin{macrocode}
+\tl_new:N \l_@@_group_level_tl
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_execute_test_level:}
+% If the group level has changed then we are still constructing
+% \cs{l_shipout_box} and to continue we need to wait until the
+% current group has finished, hence the \cs{tex_aftergroup:D}.
+% \begin{macrocode}
+\cs_new:Npn \@@_execute_test_level: {
+ \int_compare:nNnT
+ \l_@@_group_level_tl < \tex_currentgrouplevel:D
+ \tex_aftergroup:D
+ \@@_execute_cont:
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_execute_cont:}
+% When we have reached this point the shipout box has been
+% processed and is available in \cs{l_shipout_box} and ready for
+% real ship out (perhaps)..
+%
+% First we quickly check if it is void (can't happen in the
+% standard \LaTeX{} output routine but \cs{shipout} might be called
+% from a package that has some special processing logic). If it is
+% void we aren't shipping anything out and processing ends.\footnote{In that
+% case we don't reset the deadcyles, that would be up to the OR
+% processing logic to do.}
+% \begin{macrocode}
+\cs_new:Npn \@@_execute_cont: {
+ \box_if_empty:NTF \l_shipout_box
+ { \PackageWarning{ltshipout}{Ignoring~ void~ shipout~ box} }
+ {
+% \end{macrocode}
+% Otherwise we assume that we will ship something and prepare for
+% final adjustments (in particular setting the state of
+% \cs{protect} while we are running the hook code).
+% We also save the current \cs{protect} state to restore it later.
+% \begin{macrocode}
+ \bool_gset_false:N \g_@@_discard_bool
+ \cs_set_eq:NN \@@_saved_protect: \protect
+ \set@typeset@protect
+% \end{macrocode}
+% We also store the current shipout box dimension in registers, so that
+% they can be used in the hook code.\footnote{This is not really
+% necessary as the code could access them via \cs{box_ht:N}, etc.,
+% but it is perhaps convenient.}
+% \begin{macrocode}
+ \@@_get_box_size:N \l_shipout_box
+% \end{macrocode}
+% Then we execute the \hook{shipout/before} hook.
+% \begin{macrocode}
+ \hook_use:n {shipout/before}
+% \end{macrocode}
+% In \cs{g_shipout_totalpages_int} we count all shipout attempts so
+% we increment that counter already here (the other one is
+% incremented later when we know for sure that we do a
+% \cs{shipout}.
+%
+% We increment it after running the above hook so that the values
+% for \cs{g_shipout_totalpages_int} and \cs{} are in sync while the
+% hook is executed (in the case that totalpages isn't manually
+% altered or through discarding pages that is).
+% \begin{macrocode}
+ \int_gincr:N \g_shipout_totalpages_int
+% \end{macrocode}
+% The above hook might contain code that requests the page to be discarded so
+% we now test for it.
+% \begin{macrocode}
+ \bool_if:NTF \g_@@_discard_bool
+ { \PackageInfo{ltshipout}{Completed~ page~ discarded}
+ \bool_gset_false:N \g_@@_discard_bool
+% \end{macrocode}
+% As we are discarding the page box and not shipping anything out,
+% we need to do some house cleaning and reset \TeX's deadcycles so
+% that it doesn't complain about too many calls to the OR without
+% any shipout.
+% \begin{macrocode}
+ \tex_deadcycles:D \c_zero_int
+% \end{macrocode}
+% \fmi{In \pkg{atbegshi} the box was dropped but is that actually
+% needed? Or the resetting of \cs{protect} to its kernel value?}
+% \begin{macrocode}
+% \group_begin:
+% \box_set_eq_drop:NN \l_shipout_box \l_shipout_box
+% \group_end:
+% \cs_set_eq:NN \protect \exp_not:N
+ }
+% \end{macrocode}
+% Even if there was no explicit request to discard the box it is
+% possible that the code for the hook \hook{shipout/before} has
+% voided the box (by mistake or deliberately). We therefore test
+% once more but this time make it a warning, because the best
+% practice way is to use the request mechanism.
+% \begin{macrocode}
+ { \box_if_empty:NTF \l_shipout_box
+ { \PackageWarning{ltshipout}{
+ Shipout~ box~ was~ voided~ by~ hook,\MessageBreak
+ ignoring~ shipout~ box }
+ }
+% \end{macrocode}
+% Finally, if the box is still non-empty we are nearly ready to
+% ship it out.
+% First we increment the total page counter so that we can later
+% test if we have reached the final page according to our available
+% information.\footnote{Doing that earlier would be wrong because we
+% might end up with the last page counted but discard and then we
+% have no place to add the final objects into the output file.}
+% \begin{macrocode}
+ {
+ \int_gincr:N \g_shipout_readonly_int
+ \@@_debug:n {
+ \typeout{Absolute~ page~ =~ \int_use:N \g_shipout_readonly_int
+ \space (target:~ \@abspage@last)}
+ }
+% \end{macrocode}
+% Then we store the box sizes again (as they may have
+% changed) and then look at the hooks \hook{shipout/foreground}
+% and \hook{shipout/background}. If either or both are non-empty
+% we add a \texttt{picture} environment to the box (in the
+% foreground and or in the background) and execute the hook code
+% inside that environment.
+%
+% \begin{macrocode}
+ \@@_get_box_size:N \l_shipout_box
+ \hook_if_empty:nF {shipout/foreground}
+ { \@@_add_foreground_picture:n
+ { \hook_use:n {shipout/foreground} } }
+ \hook_if_empty:nF {shipout/background}
+ { \@@_add_background_picture:n
+ { \@kernel@before@shipout@background
+ \hook_use:n {shipout/background} } }
+% \end{macrocode}
+% We then run \cs{@@_execute_firstpage_hook:} that adds
+% the content of the hook \hook{shipout/firstpage} to the
+% start of the first page (if non-empty). It is then redefined to
+% do nothing on later pages.
+% \begin{macrocode}
+ \@@_execute_firstpage_hook:
+% \end{macrocode}
+% The we check if we have to add the \hook{shipout/lastpage} hook
+% because we have reached the last page. This test will be false for
+% all but one (and hopefully the correct) page.
+% \begin{macrocode}
+ \int_compare:nNnT \@abspage@last = \g_shipout_readonly_int
+ { \hook_if_empty:nF {shipout/lastpage}
+ { \@@_debug:n { \typeout{Executing~ lastpage~ hook~
+ on~ page~ \int_use:N \g_shipout_readonly_int } }
+ \_@@_add_foreground_box:n { \UseHook{shipout/lastpage}
+ \@kernel@after@shipout@lastpage }
+ }
+ \bool_gset_true:N \g_@@_lastpage_handled_bool
+ }
+% \end{macrocode}
+% Finally we run the actual \TeX{} primitive for shipout. As that will
+% expand delayed \cs{write} statements inside the page in which
+% protected commands should not expand we first change \cs{protect}
+% to the appropriate definition for that case.
+% \begin{macrocode}
+ \cs_set_eq:NN \protect \exp_not:N
+ \tex_shipout:D \box_use:N \l_shipout_box
+ }
+ }
+% \end{macrocode}
+% Restore the value of \cs{protect} in case \cs{shipout} is called
+% outside of the output routine (where it is automatically restored
+% because of the implicit group).
+% \begin{macrocode}
+ \cs_set_eq:NN \protect \@@_saved_protect:
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_saved_protect:}
+% Remeber the current \cs{protect} state.
+% \begin{macrocode}
+\cs_new_eq:NN \@@_saved_protect: \protect
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{shipout/before,
+% shipout/foreground,shipout/background,
+% shipout/firstpage,
+% shipout/lastpage}
+% Declaring all hooks for the shipout code.
+% \begin{macrocode}
+\hook_new:n{shipout/before}
+\hook_new:n{shipout/foreground}
+\hook_new:n{shipout/background}
+\hook_new:n{shipout/firstpage}
+\hook_new:n{shipout/lastpage}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@kernel@after@shipout@lastpage,
+% \@kernel@before@shipout@background}
+% And here are the internal kernel hooks going before or after the
+% public ones where needed.
+% \begin{macrocode}
+\let\@kernel@after@shipout@lastpage\@empty
+\let\@kernel@before@shipout@background\@empty
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_execute_firstpage_hook: }
+% This command adds any specials into a box and adds that to the
+% very beginning of the first box shipped out. After that we
+% redefine it to do nothing on later pages.
+% \begin{macrocode}
+\cs_new:Npn \@@_execute_firstpage_hook: {
+% \end{macrocode}
+% Adding something to the beginning means adding it to the
+% background as that layer is done first in the output. Of course
+% that is only needed if the hook actually contains anything.
+% \begin{macrocode}
+ \hook_if_empty:nF {shipout/firstpage}
+ { \@@_add_background_box:n { \UseHook{shipout/firstpage} } }
+% \end{macrocode}
+% Once we are here we change the definition to do nothing next time
+% and we also change the command used to implement \cs{AtBeginDvi}
+% to become a warning and not add further material to a hook that
+% is never used again.
+% \begin{macrocode}
+ \cs_gset_eq:NN \@@_execute_firstpage_hook: \prg_do_nothing:
+ \cs_gset:Npn \@@_add_firstpage_material:Nn ##1 ##2 {
+ \@latex@warning{
+ First~ page~ is~ already~ shipped~ out,~ ignoring\MessageBreak
+ \string##1 }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\g_@@_lastpage_handled_bool}
+% A boolean to signal if we have already handled the
+% \hook{shipout/lastpage} hook.
+% \begin{macrocode}
+\bool_new:N \g_@@_lastpage_handled_bool
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_add_firstpage_material:Nn}
+% This command adds material to the
+% \hook{shipout/firstpage} hook. It is used in
+% \cs{AtBeginDvi}, etc. The first argument is the
+% command through which is it called. Initially this is ignored but
+% once we are passed the first page it can be used to generate a
+% warning message mentioning the right user command.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_firstpage_material:Nn #1#2 {
+ \AddToHook{shipout/firstpage}{#2}
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
+%
+%
+% \begin{macro}{\@@_get_box_size:N}
+% Store the box dimensions in dimen registers.
+% \fmi{This could/should perhaps be generalized to set height depth and
+% width given an arbitrary box.}
+% \begin{macrocode}
+\cs_new:Npn \@@_get_box_size:N #1 {
+ \dim_set:Nn \l_shipout_box_ht_dim { \box_ht:N #1 }
+ \dim_set:Nn \l_shipout_box_dp_dim { \box_dp:N #1 }
+ \dim_set:Nn \l_shipout_box_wd_dim { \box_wd:N #1 }
+ \dim_set:Nn \l_shipout_box_ht_plus_dp_dim { \l_shipout_box_ht_dim +
+ \l_shipout_box_dp_dim }
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\l_shipout_box_ht_dim,
+% \l_shipout_box_dp_dim,\l_shipout_box_wd_dim,
+% \l_shipout_box_ht_plus_dp_dim}
+% And here are the variables set by \cs{@@_get_box_size:N}.
+% \begin{macrocode}
+\dim_new:N \l_shipout_box_ht_dim
+\dim_new:N \l_shipout_box_dp_dim
+\dim_new:N \l_shipout_box_wd_dim
+\dim_new:N \l_shipout_box_ht_plus_dp_dim
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+%
+% \begin{macro}{\g_@@_discard_bool}
+% Indicate whether or not the current page box should be discarded
+% \begin{macrocode}
+\bool_new:N \g_@@_discard_bool
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\l_@@_tmp_box,\l_@@_saved_badness_tl}
+% We need a box for the background and foreground material and a
+% token register to remember badness settings as we disable them
+% during te buildup below.
+% \begin{macrocode}
+\box_new:N \l_@@_tmp_box
+\tl_new:N \l_@@_saved_badness_tl
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_add_background_box:n}
+% In standard \LaTeX{} the shipout box is always a \cs{vbox} but
+% here we are allow for other usage as well, in case some package
+% has its own output routine.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_background_box:n #1
+{ \@@_get_box_size:N \l_shipout_box
+% \end{macrocode}
+% But we start testing for a vertical box as that should be the
+% normal case.
+% \begin{macrocode}
+ \box_if_vertical:NTF \l_shipout_box
+ {
+% \end{macrocode}
+% Save current values of \cs{vfuzz} and \cs{vbadness} then change
+% them to allow box manipulations without warnings.
+% \begin{macrocode}
+ \tl_set:Nx \l_@@_saved_badness_tl
+ { \vfuzz=\the\vfuzz\relax
+ \vbadness=\the\vbadness\relax }
+ \vfuzz=\c_max_dim
+ \vbadness=\c_max_int
+% \end{macrocode}
+% Then we reconstruct \cs{l_shipout_box} \ldots
+% \begin{macrocode}
+ \vbox_set_to_ht:Nnn \l_shipout_box \l_shipout_box_ht_plus_dp_dim
+ {
+% \end{macrocode}
+% \ldots{} the material in \verb=#1= is placed into a horizontal
+% box with zero dimensions.
+% \begin{macrocode}
+ \hbox_set:Nn \l_@@_tmp_box
+ { \l_@@_saved_badness_tl #1 }
+ \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim
+ \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim
+ \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim
+% \end{macrocode}
+% The we typeset that box followed by whatever was in
+% \cs{l_shipout_box} before (unpacked).
+% \begin{macrocode}
+ \skip_zero:N \baselineskip
+ \skip_zero:N \lineskip
+ \skip_zero:N \lineskiplimit
+ \box_use:N \l_@@_tmp_box
+ \vbox_unpack:N \l_shipout_box
+% \end{macrocode}
+% The \cs{kern} ensures that the box has no depth which is
+% afterwards explicitly corrected.
+% \begin{macrocode}
+ \kern \c_zero_dim
+ }
+ \box_set_ht:Nn \l_shipout_box \l_shipout_box_ht_dim
+ \box_set_dp:Nn \l_shipout_box \l_shipout_box_dp_dim
+% \end{macrocode}
+% \fmi{The whole boxing maneuver looks a bit like overkill to me, but for
+% the moment I leave.}
+% \begin{macrocode}
+ \l_@@_saved_badness_tl
+ }
+ {
+% \end{macrocode}
+% A horizontal box is handled in a similar way. The last case would
+% be a void box in which case we do nothing hence the missing
+% \texttt{F} branch.
+% \begin{macrocode}
+ \box_if_horizontal:NT \l_shipout_box
+ {
+ \tl_set:Nx \l_@@_saved_badness_tl
+ { \hfuzz=\the\hfuzz\relax
+ \hbadness=\the\hbadness\relax }
+ \hfuzz=\c_max_dim
+ \hbadness=\c_max_int
+ \hbox_set_to_wd:Nnn \l_shipout_box \l_shipout_box_wd_dim
+ {
+ \hbox_set:Nn \l_@@_tmp_box
+ { \l_@@_saved_badness_tl #1 }
+ \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim
+ \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim
+ \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim
+ \box_move_up:nn
+ \l_shipout_box_ht_dim
+ { \box_use:N \l_@@_tmp_box }
+ \hbox_unpack:N \l_shipout_box
+ }
+ \l_@@_saved_badness_tl
+ }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\@@_add_foreground_box:n}
+% Foreground boxes are done in the same way, only the order and
+% placement of boxes has to be done differently.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_foreground_box:n #1
+{
+ \box_if_vertical:NTF \l_shipout_box
+ {
+ \tl_set:Nx \l_@@_saved_badness_tl
+ { \vfuzz=\the\vfuzz\relax
+ \vbadness=\the\vbadness\relax }
+ \vfuzz=\c_max_dim
+ \vbadness=\c_max_int
+ \vbox_set_to_ht:Nnn \l_shipout_box \l_shipout_box_ht_plus_dp_dim
+ {
+ \hbox_set:Nn \l_@@_tmp_box
+ { \l_@@_saved_badness_tl #1 }
+ \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim
+ \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim
+ \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim
+ \skip_zero:N \baselineskip
+ \skip_zero:N \lineskip
+ \skip_zero:N \lineskiplimit
+ \vbox_unpack:N \l_shipout_box
+ \kern -\l_shipout_box_ht_plus_dp_dim
+ \box_use:N \l_@@_tmp_box
+ \kern \l_shipout_box_ht_plus_dp_dim
+ }
+ \l_@@_saved_badness_tl
+ \box_set_ht:Nn \l_shipout_box \l_shipout_box_ht_dim
+ \box_set_dp:Nn \l_shipout_box \l_shipout_box_dp_dim
+ }
+ {
+ \box_if_horizontal:NT \l_shipout_box
+ {
+ \tl_set:Nx \l_@@_saved_badness_tl
+ { \hfuzz=\the\hfuzz\relax
+ \hbadness=\the\hbadness\relax }
+ \hfuzz=\c_max_dim
+ \hbadness=\c_max_int
+ \hbox_set_to_wd:Nnn \l_shipout_box \l_shipout_box_wd_dim
+ {
+ \hbox_unpack:N \l_shipout_box
+ \kern -\box_wd:N \l_shipout_box
+ \hbox_set:Nn \l_@@_tmp_box
+ { \l_@@_saved_badness_tl #1 }
+ \box_set_wd:Nn \l_@@_tmp_box \c_zero_dim
+ \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim
+ \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim
+ \box_move_up:nn { \box_ht:N \l_shipout_box }
+ { \box_use:N \l_@@_tmp_box }
+ \kern \box_wd:N \l_shipout_box
+ }%
+ \l_@@_saved_badness_tl
+ }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\@@_init_page_origins:,\c_@@_horigin_tl,\c_@@_vorigin_tl}
+% Two constants holding the offset of the top-left with respect to
+% the media box.
+%
+% Setting the constants this way is courtesy of Bruno.
+%
+% We delay setting the constants to the last possible place as
+% there might be updates in the preamble or even in the
+% \hook{begindocument} hook that affects their setup.
+% \begin{macrocode}
+\cs_new:Npn \@@_init_page_origins: {
+ \tl_const:Nx \c_@@_horigin_tl
+ {
+ \cs_if_exist_use:NTF \pdfvariable { horigin }
+ { \cs_if_exist_use:NF \pdfhorigin { 1in } }
+ }
+ \tl_const:Nx \c_@@_vorigin_tl
+ {
+ \cs_if_exist_use:NTF \pdfvariable { vorigin }
+ { \cs_if_exist_use:NF \pdfvorigin { 1in } }
+ }
+% \end{macrocode}
+% After the constants have been set there is no need to execute
+% this command again, in fact it would raise an error, so we
+% redefine it to do nothing.
+% \begin{macrocode}
+ \cs_gset_eq:NN \@@_init_page_origins: \prg_do_nothing:
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_picture_overlay:n}
+% Put the argument into a \texttt{picture} environment that doesn't take up
+% any size and uses \texttt{1pt} for \cs{unitlength}.
+% \fmi{Could perhaps be generalized as it might be useful elsewhere. For
+% now it is not.}
+% \begin{macrocode}
+\cs_new:Npn \@@_picture_overlay:n #1 {
+% \end{macrocode}
+% The very first time this is executed we have to initializes (and
+% freeze) the origins.
+% \begin{macrocode}
+ \@@_init_page_origins:
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \kern -\c_@@_horigin_tl \scan_stop:
+ \vbox_to_zero:n {
+ \kern -\c_@@_vorigin_tl \scan_stop:
+ \unitlength 1pt \scan_stop:
+% \end{macrocode}
+% This mimics a simple zero-sized picture environment. The \cs{hss}
+% is need in case there is horizontal material (without using
+% \cs{put} with a positive width.
+% \changes{v1.0b}{2020/09/09}
+% {Prevent overfull box warnings (gh/387)}
+% \begin{macrocode}
+ \hbox_set_to_wd:Nnn \l_@@_tmp_box \c_zero_dim
+ { \ignorespaces #1 \hss }
+ \box_set_ht:Nn \l_@@_tmp_box \c_zero_dim
+ \box_set_dp:Nn \l_@@_tmp_box \c_zero_dim
+ \box_use:N \l_@@_tmp_box
+ \tex_vss:D
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\@@_add_background_picture:n}
+% Put a \texttt{picture} env in the background of the shipout box
+% with its reference point in the top-left corner.
+%
+% \begin{macrocode}
+\cs_new:Npn \@@_add_background_picture:n #1 {
+ \@@_add_background_box:n { \@@_picture_overlay:n {#1} }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_add_foreground_picture:n}
+%
+% Put a \texttt{picture} env in the foreground of the shipout box
+% with its reference point in the top-left corner.
+% \begin{macrocode}
+\cs_new:Npn \@@_add_foreground_picture:n #1 {
+ \@@_add_foreground_box:n { \@@_picture_overlay:n {#1} }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\shipout_discard:}
+% Request that the next shipout box should be discarded. At the
+% moment this is just setting a boolean, but we may want to augment
+% this behavior that the position of the call is taken into account
+% (in case \LaTeX{} looks ahead and is not using the position for
+% on the next page).
+% \begin{macrocode}
+\cs_new_protected:Npn \shipout_discard: {
+ \bool_gset_true:N \g_@@_discard_bool
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \subsection{Handling the end of job hook}
+%
+% At the moment this is partly solved by using the existing hooks.
+% But rather than putting the code into these hooks it should be
+% moved to the right place directly as we shouldn't prefill hooks
+% with material unless it needs to interact with other code.
+%
+%
+%
+% \begin{macro}{\g_shipout_readonly_int,\ReadonlyShipoutCounter}
+% We count every shipout activity that makes a page (but not those
+% that are discarded) in order to know how many pages got produced.
+% \begin{macrocode}
+\int_new:N \g_shipout_readonly_int
+% \end{macrocode}
+% For \LaTeXe{} it is available as a command (i.e., a \TeX{}
+% counter only.
+% \begin{macrocode}
+\cs_new_eq:NN \ReadonlyShipoutCounter \g_shipout_readonly_int
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_shipout_totalpages_int,\c@totalpages}
+% We count every shipout attempt (even those that are discarded) in
+% tis counter. It is not used in the code but may get used in user
+% code.
+% \begin{macrocode}
+\int_new:N \g_shipout_totalpages_int
+% \end{macrocode}
+% For \LaTeXe{} this is offered as a \LaTeX{} counter so can be
+% easily typeset inside the output routine to display things like
+% \enquote{\cs{thepage}\texttt{/}\cs{thetotalpages}}, etc.
+% \begin{macrocode}
+\cs_new_eq:NN \c@totalpages \g_shipout_totalpages_int
+\cs_new:Npn \thetotalpages { \arabic{totalpages} }
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+%
+% \begin{macro}{\@abspage@last}
+% In \cs{@abspage@last} record the number of pages from the last
+% run. This is written to the \texttt{.aux} and this way made
+% available to the next run. In case there is no \texttt{.aux} file
+% or the statement is missing from it we initialize it with the
+% largest possible number in \TeX{}. We use this as the default
+% because then we are inserting the \hook{shipout/lastpage} on
+% the last page (or after the last page but not on page 1 for a
+% multipage document.
+% \begin{macrocode}
+\xdef\@abspage@last{\number\maxdimen}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\enddocument}
+%
+% Instead of using the hooks \hook{enddocument} and
+% \hook{enddocument/afterlastpage} we add this code to private
+% kernel hooks to be 100\% when it is executed and to avoid
+% cluttering the hooks with data that is always there.
+%
+% Inside \cs{enddocument} there is a \cs{clearpage}. Just before
+% that we execute this code here. There is a good change that we
+% are on the last page. Therefore, if we don't know the value from
+% the last run, we assume that the current page is the right
+% one. So we set \cs{@abspage@last} and as a result the next
+% shipout will run the \hook{shipout/lastpage} code. Of course,
+% if there are floats that still need a placement this guess will
+% be wrong but then rerunning the document will give us the correct
+% value next time around.
+%
+% \begin{macro}{\@kernel@after@enddocument}
+% \begin{macrocode}
+\g@addto@macro \@kernel@after@enddocument {
+ \int_compare:nNnT \@abspage@last = \maxdimen
+ {
+% \end{macrocode}
+% We use \LaTeXe{} coding as \cs{@abspage@last} is not an L3 name.
+% \begin{macrocode}
+ \xdef\@abspage@last{ \int_eval:n {\g_shipout_readonly_int + 1} }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@kernel@after@enddocument@afterlastpage}
+% Once the \cs{clearpage} has done its work inside \cs{enddocument}
+% we know for sure how many pages this document has, so we record
+% that in the \texttt{.aux} file for the next run.
+%
+% \begin{macrocode}
+\g@addto@macro \@kernel@after@enddocument@afterlastpage {
+% \end{macrocode}
+% There is one special case: If no output is produced then there is
+% no point in a) recording the number as 0 will never match the
+% page number of a real page and b) adding an extra page to ran the
+% \hook{shipout/lastpage} is pointless as well (as it would
+% remain forever). So we test for this and run the code only if
+% there have been pages.
+% \begin{macrocode}
+ \int_compare:nNnF \g_shipout_readonly_int = 0
+ {
+% \end{macrocode}
+% This ends up in the \texttt{.aux} so we use \LaTeXe{} names here.
+% \fmi{This needs an interface for \cs{nofiles} in expl3, doesn't at the moment!}
+% \begin{macrocode}
+ \if@filesw
+ \iow_now:Nx \@auxout {
+ \gdef\string\@abspage@last {\int_use:N \g_shipout_readonly_int}}
+ \fi
+% \end{macrocode}
+% But we may have guessed wrongly earlier and we still have to run the
+% \hook{shipout/lastpage} even though there is no page to place
+% it into. If that is the case we make a trivial extra page and put
+% it there. This temporary page will then vanish again on the next
+% run but helps to keep pdf viewers happy.
+% \begin{macrocode}
+ \bool_if:NF \g_@@_lastpage_handled_bool
+ {
+% \end{macrocode}
+% However, making this extra page in case the hook is actually
+% empty would be forcing a rerun without any reason, so we check
+% that condition and also check if
+% \cs{@kernel@after@shipout@lastpage} contains any code. If both
+% are empty we omit the page generation.
+% \begin{macrocode}
+ \bool_lazy_and:nnF
+ { \hook_if_empty_p:n {shipout/lastpage} }
+ { \tl_if_empty_p:N \@kernel@after@shipout@lastpage }
+ {
+ \tex_shipout:D\vbox to\textheight
+ {
+ \hbox:n { \UseHook{shipout/lastpage}
+ \@kernel@after@shipout@lastpage }
+% \end{macrocode}
+% This extra page could be totally empty except for the hook
+% content, but to help the user understanding why it is there we
+% put some text into it.
+% \begin{macrocode}
+ \@@_excuse_extra_page:
+ \null
+ }
+% \end{macrocode}
+% At this point we also signal to \LaTeX{}'s endgame that a rerun is
+% necessary so that an appropriate message can be shown on the
+% terminal. We do this by simply defining a command used as a flag and
+% tested \cs{enddocument}.
+% \begin{macrocode}
+ \cs_gset_eq:NN \@extra@page@added \relax
+ }
+ }
+ }
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\@@_excuse_extra_page:}
+% Say mea culpa \ldots
+% \begin{macrocode}
+\cs_new:Npn \@@_excuse_extra_page: {
+ \vfil
+ \begin{center}
+ \bfseries Temporary~ page!
+ \end{center}
+ \LaTeX{}~ was~ unable~ to~ guess~ the~ total~ number~ of~ pages~
+ correctly.~ ~ As~ there~ was~ some~ unprocessed~ data~ that~
+ should~ have~ been~ added~ to~ the~ final~ page~ this~ extra~
+ page~ has~ been~ added~ to~ receive~ it.
+ \par
+ If~ you~ rerun~ the~ document~ (without~ altering~ it)~ this~
+ surplus~ page~ will~ go~ away,~ because~ \LaTeX{}~ now~ knows~
+ how~ many~ pages~ to~ expect~ for~ this~ document.
+ \vfil
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\PreviousTotalPages,\@kernel@before@begindocument}
+% In the preamble before the \texttt{aux} file was read
+% \cs{PreviousTotalPages} is always zero.
+% \begin{macrocode}
+\def\PreviousTotalPages{0}
+% \end{macrocode}
+% In the \texttt{aux} file there should be an update for
+% \cs{@abspage@last} recording the number of pages from the
+% previous run. If not that macro holds the value of
+% \cs{maxdimen}. So we test for it and update
+% \cs{PreviousTotalPages} if there was a real value. This should
+% happen just before the \hook{begindocument} hook is executed so
+% that the value can be used inside that hook.
+% \begin{macrocode}
+\g@addto@macro\@kernel@before@begindocument
+ {\ifnum\@abspage@last<\maxdimen
+ \xdef\PreviousTotalPages{\@abspage@last}\fi}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \section{Legacy \LaTeXe{} interfaces}
+%
+%
+%
+% \begin{macro}{\DiscardShipoutBox}
+% Request that the next shipout box is to be discarded.
+% \begin{macrocode}
+\cs_new_eq:NN \DiscardShipoutBox \shipout_discard:
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\AtBeginDvi}
+%
+% \begin{macrocode}
+\cs_new_protected:Npn \AtBeginDvi {\@@_add_firstpage_material:Nn \AtBeginDvi}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\DebugShipoutsOn,\DebugShipoutsOff}
+%
+% \begin{macrocode}
+\cs_new_eq:NN \DebugShipoutsOn \shipout_debug_on:
+\cs_new_eq:NN \DebugShipoutsOff \shipout_debug_off:
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \section{Internal commands needed elsewhere}
+%
+% These internal commands use double and triple \texttt{@} signs so
+% we need to stop getting them translated to the module name.
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+% \begin{macro}{\@expl@@@shipout@add@firstpage@material@@Nn,
+% \@expl@@@shipout@add@background@box@@n,
+% \@expl@@@shipout@add@foreground@box@@n,
+% \@expl@@@shipout@add@background@picture@@n,
+% \@expl@@@shipout@add@foreground@picture@@n}
+% Some internals needed elsewhere.
+%
+% \begin{macrocode}
+\cs_set_eq:NN \@expl@@@shipout@add@firstpage@material@@Nn
+ \__shipout_add_firstpage_material:Nn
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_set_eq:NN \@expl@@@shipout@add@background@box@@n
+ \__shipout_add_background_box:n
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_set_eq:NN \@expl@@@shipout@add@foreground@box@@n
+ \__shipout_add_foreground_box:n
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_set_eq:NN \@expl@@@shipout@add@background@picture@@n
+ \__shipout_add_background_picture:n
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_set_eq:NN \@expl@@@shipout@add@foreground@picture@@n
+ \__shipout_add_foreground_picture:n
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+%
+% Rolling back here doesn't undefine the interface commands as they
+% may be used in packages without rollback functionality. So we
+% just make them do nothing which may or may not work depending on
+% the code usage.
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\shipout}{The hook management (shipout)}%
+%<latexrelease>\expandafter\let\expandafter\shipout\csname tex_shipout:D\endcsname
+%<latexrelease>
+%<latexrelease>\let \ShipoutBox\@undefined
+%<latexrelease>\let \ReadonlyShipoutCounter \@undefined
+%<latexrelease>\let \c@totalpages \@undefined
+%<latexrelease>\let \thetotalpages \@undefined
+%<latexrelease>
+%<latexrelease>\let \DiscardShipoutBox \@undefined
+%<latexrelease>\let \DebugShipoutsOn \@undefined
+%<latexrelease>\let \DebugShipoutsOff \@undefined
+%<latexrelease>
+%<latexrelease>\DeclareRobustCommand \AtBeginDvi [1]{%
+%<latexrelease> \global \setbox \@begindvibox
+%<latexrelease> \vbox{\unvbox \@begindvibox #1}%
+%<latexrelease>}
+%<latexrelease>
+%<latexrelease>\let \AtBeginShipout \@undefined
+%<latexrelease>\let \AtBeginShipoutNext \@undefined
+%<latexrelease>
+%<latexrelease>\let \AtBeginShipoutFirst \@undefined
+%<latexrelease>
+%<latexrelease>\let \ShipoutBoxHeight \@undefined
+%<latexrelease>\let \ShipoutBoxDepth \@undefined
+%<latexrelease>\let \ShipoutBoxWidth \@undefined
+%<latexrelease>
+%<latexrelease>\let \AtBeginShipoutDiscard \@undefined
+%<latexrelease>
+%<latexrelease>\let \AtBeginShipoutAddToBox \@undefined
+%<latexrelease>\let \AtBeginShipoutAddToBoxForeground \@undefined
+%<latexrelease>\let \AtBeginShipoutUpperLeft \@undefined
+%<latexrelease>\let \AtBeginShipoutUpperLeftForeground \@undefined
+%<latexrelease>
+% \end{macrocode}
+% We do not undo a substitution when rolling back. As the file
+% support gets undone the underlying data is no longer used (and
+% sufficiently obscure that should not interfer with existing
+% commands) and properly removing it would mean we need to make the
+% \cs{unclare@...} and its support macros available in all earlier
+% kernel releases which is pointless (and actually worse).
+% \begin{macrocode}
+%\undeclare@file@substitution{everyshi.sty}
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>
+%<latexrelease>\let \AtEndDvi \@undefined
+% \end{macrocode}
+% We do not reenable a disabled package load when rolling back. As the file
+% support gets undone the underlying data is no longer checked (and
+% sufficiently obscure that it should not interfer with existing
+% commands) and properly removing it would mean we need to make the
+% \cs{reenable@package@load} command available in all earlier
+% kernel releases which is pointless (and actually worse).
+% \begin{macrocode}
+%\reenable@package@load{atenddvi}
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+%
+%
+%
+% \section{Package emulation for compatibility}
+%
+%
+% \subsection{Package \pkg{atenddvi} emulation}
+%
+%
+% \begin{macro}{\AtEndDvi}
+% This package has only one public command to simulating it is easy
+% and actually sensible to provide as part of the kernel.
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\AtEndDvi}{atenddvi emulation}%
+\ExplSyntaxOn
+\cs_new_protected:Npn \AtEndDvi {\AddToHook{shipout/lastpage}}
+\ExplSyntaxOff
+% \end{macrocode}
+% As the package is integrate we prevent loading (no need to roll that back):
+% \begin{macrocode}
+\disable@package@load{atenddvi}
+ {\PackageWarning{atenddvi}
+ {Functionality of this package is already\MessageBreak
+ provided by LaTeX.\MessageBreak\MessageBreak
+ It is there no longer necessary to load it\MessageBreak
+ and you can safely remove it.\MessageBreak
+ Found on}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\AtEndDvi}{atenddvi emulation}%
+%<latexrelease>\let \AtEndDvi \@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macrocode}
+%</2ekernel>
+% \end{macrocode}
+%
+%
+% \subsection{Package \pkg{atbegshi} emulation}
+%
+%
+%
+%
+%
+% \begin{macrocode}
+%<*atbegshi-ltx>
+\ProvidesPackage{atbegshi-ltx}
+ [2020/08/17 v1.0a
+ Emulation of the original atbegshi package^^Jwith kernel methods]
+% \end{macrocode}
+%
+%
+% \begin{macro}{\AtBeginShipoutBox}
+% \begin{macrocode}
+\let \AtBeginShipoutBox \ShipoutBox
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\AtBeginShipoutInit}
+% Compatibility only, we aren't delaying \ldots
+% \begin{macrocode}
+\let \AtBeginShipoutInit \@empty
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\AtBeginShipout,\AtBeginShipoutNext}
+% Filling hooks
+% \begin{macrocode}
+\protected \def \AtBeginShipout {\AddToHook{shipout/before}}
+\protected \def \AtBeginShipoutNext {\AddToHookNext{shipout/before}}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\AtBeginShipoutFirst}
+% Slightly more complex as we need to know the name of the command under which the
+% \hook{shipout/firstpage} hook is filled.
+% \begin{macrocode}
+\protected \def \AtBeginShipoutFirst
+ {\@expl@@@shipout@add@firstpage@material@@Nn \AtBeginShipoutFirst}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\AtBeginShipoutDiscard}
+% Just a different name.
+% \begin{macrocode}
+\let \AtBeginShipoutDiscard \DiscardShipoutBox
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\AtBeginShipoutAddToBox,\AtBeginShipoutAddToBoxForeground,
+% \AtBeginShipoutUpperLeft,\AtBeginShipoutUpperLeftForeground}
+% We don't expose them.
+% \begin{macrocode}
+\let \AtBeginShipoutAddToBox
+ \@expl@@@shipout@add@background@box@@n
+\let \AtBeginShipoutAddToBoxForeground
+ \@expl@@@shipout@add@foreground@box@@n
+% \end{macrocode}
+%
+% \begin{macrocode}
+\let \AtBeginShipoutUpperLeft
+ \@expl@@@shipout@add@background@picture@@n
+\let \AtBeginShipoutUpperLeftForeground
+ \@expl@@@shipout@add@foreground@picture@@n
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\ShipoutBoxHeight,\ShipoutBoxWidth,\ShipoutoBoxDepth}
+% This is somewhat different from the original in \pkg{atbegshi}
+% where \cs{ShipoutBoxHeight} etc.\ only holds the
+% \verb=\the\ht<box>= value. This may has some implications in some
+% use cases and if that is a problem then it might need changing.
+% \begin{macrocode}
+\ExplSyntaxOn
+\cs_new:Npn \ShipoutBoxHeight { \dim_use:N \l_shipout_box_ht_dim }
+\cs_new:Npn \ShipoutBoxDepth { \dim_use:N \l_shipout_box_dp_dim }
+\cs_new:Npn \ShipoutBoxWidth { \dim_use:N \l_shipout_box_wd_dim }
+\ExplSyntaxOff
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macrocode}
+%</atbegshi-ltx>
+% \end{macrocode}
+%
+% If the package is requested we substitute the one above:
+% \begin{macrocode}
+%<*2ekernel>
+\declare@file@substitution{atbegshi.sty}{atbegshi-ltx.sty}
+%</2ekernel>
+% \end{macrocode}
+%
+%
+%
+%
+%
+%
+% \subsection{Package \pkg{everyshi} emulation}
+%
+% \begin{macrocode}
+%<*everyshi-ltx>
+% \end{macrocode}
+%
+% \begin{macrocode}
+\ProvidesPackage{everyshi-ltx}
+ [2020/08/17 v1.0a
+ Emulation of the original everyshi package^^Jwith kernel methods]
+% \end{macrocode}
+%
+% \begin{macro}{\EveryShipout,\AtNextShipout}
+% This package has only two public commands so simulating it is easy:
+% \begin{macrocode}
+\protected \def \EveryShipout {\AddToHook{shipout/before}}
+\protected \def \AtNextShipout {\AddToHookNext{shipout/before}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+% This is one difference between \pkg{everyshi} and the kernel
+% implementation, the latter does not directly use box 255.
+%
+% For usage by ordinary users this makes no difference but of a
+% package use complicated code together with \pkg{everyshi} and
+% directly manipulates box 255 then this package needs updating.
+% In most cases the updates are simple because the kernel offers
+% hooks that makes such complicated code unnecessary.
+%
+% We therefore add a little file into the adjusted package
+% \begin{macrocode}
+%%
+%% In normal circumstances the above emulation is sufficient and in
+%% all known packages (we know of) that use everyshi it either works or
+%% the packages have been adjusted.
+%%
+%% Code that directly manipulates box 255, however, might fail.
+%% If that is the case look at the shipout hooks offered now as
+%% they are normally sufficienct to avoid such minpulations (or
+%% replace box 255 with \ShipoutBox in the code.
+%%
+%</everyshi-ltx>
+% \end{macrocode}
+%
+%
+% If the package is requested we substitute the one above:
+% \begin{macrocode}
+%<*2ekernel>
+\declare@file@substitution{everyshi.sty}{everyshi-ltx.sty}
+%</2ekernel>
+% \end{macrocode}
+%
+%
+% Rather important :-)
+% \begin{macrocode}
+%<@@=>
+% \end{macrocode}
+%
+% \Finale
+%
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\endinput
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/Master/texmf-dist/source/latex/base/ltspace.dtx b/Master/texmf-dist/source/latex/base/ltspace.dtx
index 16d7dcb43aa..1a672c6455d 100644
--- a/Master/texmf-dist/source/latex/base/ltspace.dtx
+++ b/Master/texmf-dist/source/latex/base/ltspace.dtx
@@ -32,7 +32,7 @@
%<*driver>
% \fi
\ProvidesFile{ltspace.dtx}
- [2019/11/02 v1.3k LaTeX Kernel (spacing)]
+ [2020/05/06 v1.3n LaTeX Kernel (spacing)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltspace.dtx}
@@ -63,6 +63,8 @@
% \changes{v1.2r}{1996/07/27}{Correct documentation of problems}
% \changes{v1.2w}{1998/08/17}{Documentation fixes.}
% \changes{v1.3j}{2019/08/27}{Make various commands robust}
+% \changes{v1.3l}{2020/03/07}{Moved \cs{thinspace}, \cs{negthinspace}
+% and \cs{,} to ltmath.dtx (gh/303)}
%
%
% \section{Spacing}
@@ -428,6 +430,37 @@
% \end{macrocode}
% \end{macro}
% \end{macro}
+%
+%
+%
+% \begin{macro}{\@vspace@calcify}
+% Helper command to produce a \cs{vskip} that is first run through
+% \cs{setlength}. This way the \texttt{calc} package can operate on
+% the argument value.
+% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@vspace@calcify}{Add calc support}%
+\def\@vspace@calcify#1{\begingroup\setlength\skip@{#1}\vskip\skip@\endgroup}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@vspace@calcify}{Add calc support}%
+%<latexrelease>
+%<latexrelease>\let\@vspace@calcify\@undefined
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+% \end{macro}
+%
+%
+
+
% \begin{macro}{\newline}
% A simple form of the `normal' definition of |\\|.
% \changes{v1.2v}{1997/05/07}{Made completely robust.}
@@ -445,12 +478,31 @@
% \end{macro}
%
% \begin{macro}{\@newline}
+% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@newline}{\newline calc support}%
\def\@newline[#1]{\let \reserved@e \vadjust
- \@gnewline {\vskip #1}}
+ \@gnewline {\@vspace@calcify{#1}}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@newline}{\newline calc support}%
+%<latexrelease>
+%<latexrelease>\def\@newline[#1]{\let \reserved@e \vadjust
+%<latexrelease> \@gnewline {\vskip #1}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
+%
+%
% \begin{macro}{\@gnewline}
% \changes{v1.2u}{1996/10/29}{Added macro}
% The |\nobreak| added to prevent null lines when |\\|
@@ -518,7 +570,7 @@
% |\begin{@float}| \ldots |\end{@float}|
% that want to be invisible --- i.e.,
% not leave any extra space when used in the middle of text. Such
-% a macro should begin with |\@bsphack| and end with |\@esphack|
+% a macro should begin with |\@bsphack| and end with |\@esphack|.
% The macro in question should not create any text, nor change the
% mode.
%
@@ -823,20 +875,48 @@
% \changes{v1.2c}{1994/11/13}{Recorrected error message}
% Add vertical space taking into account space already added, as
% described above.
+% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)}
% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\addvspace}{\addvspace calc support}%
\def\addvspace#1{%
\ifvmode
\if@minipage\else
\ifdim \lastskip =\z@
- \vskip #1\relax
+ \@vspace@calcify{#1}%
\else
- \@tempskipb#1\relax
+ \setlength\@tempskipb{#1}%
\@xaddvskip
\fi
\fi
\else
\@noitemerr
\fi}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\addvspace}{\addvspace calc support}%
+%<latexrelease>
+%<latexrelease>\def\addvspace#1{%
+%<latexrelease> \ifvmode
+%<latexrelease> \if@minipage\else
+%<latexrelease> \ifdim \lastskip =\z@
+%<latexrelease> \vskip #1\relax
+%<latexrelease> \else
+%<latexrelease> \@tempskipb#1\relax
+%<latexrelease> \@xaddvskip
+%<latexrelease> \fi
+%<latexrelease> \fi
+%<latexrelease> \else
+%<latexrelease> \@noitemerr
+%<latexrelease> \fi}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
@@ -938,6 +1018,8 @@
% \end{macrocode}
% \end{macro}
%
+%
+%
% \begin{macro}{\vspace}
% \changes{v1.2m}{1996/01/20}{Made robust}
% \begin{macro}{\@vspace}
@@ -957,14 +1039,25 @@
% \end{itemize}
% \begin{macrocode}
\DeclareRobustCommand\vspace{\@ifstar\@vspacer\@vspace}
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@vspace}{Support calc in \vspace}%
+% \end{macrocode}
+% We support calc syntax in the argument and therefore use \cs{setlength}.
+% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)}
+% \begin{macrocode}
\def\@vspace #1{%
\ifvmode
- \vskip #1
+ \@vspace@calcify{#1}%
\vskip\z@skip
\else
\@bsphack
\vadjust{\@restorepar
- \vskip #1
+ \@vspace@calcify{#1}%
\vskip\z@skip
}%
\@esphack
@@ -977,7 +1070,7 @@
\dimen@\prevdepth
\hrule \@height\z@
\nobreak
- \vskip #1
+ \@vspace@calcify{#1}%
\vskip\z@skip
\prevdepth\dimen@
\else
@@ -985,10 +1078,46 @@
\vadjust{\@restorepar
\hrule \@height\z@
\nobreak
- \vskip #1
+ \@vspace@calcify{#1}%
\vskip\z@skip}%
\@esphack
\fi}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@vspace}{Support calc in \vspace}%
+%<latexrelease>
+%<latexrelease>\def\@vspace #1{%
+%<latexrelease> \ifvmode
+%<latexrelease> \vskip #1
+%<latexrelease> \vskip\z@skip
+%<latexrelease> \else
+%<latexrelease> \@bsphack
+%<latexrelease> \vadjust{\@restorepar
+%<latexrelease> \vskip #1
+%<latexrelease> \vskip\z@skip
+%<latexrelease> }%
+%<latexrelease> \@esphack
+%<latexrelease> \fi}
+%<latexrelease>\def\@vspacer#1{%
+%<latexrelease> \ifvmode
+%<latexrelease> \dimen@\prevdepth
+%<latexrelease> \hrule \@height\z@
+%<latexrelease> \nobreak
+%<latexrelease> \vskip #1
+%<latexrelease> \vskip\z@skip
+%<latexrelease> \prevdepth\dimen@
+%<latexrelease> \else
+%<latexrelease> \@bsphack
+%<latexrelease> \vadjust{\@restorepar
+%<latexrelease> \hrule \@height\z@
+%<latexrelease> \nobreak
+%<latexrelease> \vskip #1
+%<latexrelease> \vskip\z@skip}%
+%<latexrelease> \@esphack
+%<latexrelease> \fi}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
% \end{macro}
@@ -1094,17 +1223,6 @@
% \end{macrocode}
%
%
-% \begin{macro}{\,}
-% Used in paragraph mode produces a |\thinspace|. It has the
-% ordinary definition in math mode. Useful for quotes inside quotes,
-% as in |``\,`Foo', he said.''|
-% \changes{v1.0o}{1994/05/11}{Use \cs{DeclareRobustCommand}. ASAJ.}
-% \begin{macrocode}
-\DeclareRobustCommand{\,}{%
- \relax\ifmmode\mskip\thinmuskip\else\thinspace\fi
-}
-% \end{macrocode}
-% \end{macro}
%
% \begin{macro}{\@}
% Placed before a '.', makes it a sentence-ending period. Does the
@@ -1142,20 +1260,37 @@
% \changes{LaTeX2e}{1993/08/05}
% {(RmS) Removed superfluous \cs{leavevmode} in \cs{@hspace} and
% \cs{@hspacer}, as suggested by CAR.}
+% \changes{v1.3m}{2020/04/21}{Support calc syntax (gh/152)}
+% \begin{macrocode}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@hspace}{Support calc with \hspace}%
+\def\@hspace#1{\begingroup\setlength\skip@{#1}\hskip\skip@\endgroup}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
% \begin{macrocode}
-\def\@hspace#1{\hskip #1\relax}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@hspace}{Support calc with \hspace}%
+
+%<latexrelease>
+%<latexrelease>\def\@hspace#1{\hskip #1\relax}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@hspacer}
-% extra |\hskip 0pt| added 1985/17/12 to guard
+% Extra |\hskip 0pt| added 1985/17/12 to guard
% against a following |\unskip|
% |\relax| added 13 Oct 88 for usual \TeX\ lossage
% replaced both changes by |\hskip\z@skip| 27 Nov 91
% \begin{macrocode}
\def\@hspacer#1{\vrule \@width\z@\nobreak
- \hskip #1\hskip \z@skip}
+ \@hspace{#1}\hskip \z@skip}
% \end{macrocode}
% \end{macro}
%
@@ -1184,19 +1319,12 @@
%<latexrelease> {\thinspace}{Start LR-mode}%
% \end{macrocode}
%
-%
-% \begin{macro}{\thinspace}
-% \begin{macro}{\negthinspace}
% \begin{macro}{\enspace}
% \changes{v1.3h}{2018/09/24}{Start LR-mode if necessary (git/49)}
% \begin{macrocode}
-\DeclareRobustCommand\thinspace{\leavevmode@ifvmode\kern .16667em }
-\DeclareRobustCommand\negthinspace{\leavevmode@ifvmode\kern-.16667em }
\DeclareRobustCommand\enspace{\leavevmode@ifvmode\kern.5em }
% \end{macrocode}
% \end{macro}
-% \end{macro}
-% \end{macro}
%
% \begin{macro}{\leavevmode@ifvmode}
% Leave vmode but only if we are really in vmode, otherwise the
@@ -1234,6 +1362,18 @@
% \end{macro}
% \end{macro}
%
+% \changes{v1.3n}{2020/05/06}{Made softhyphen active in TU engines}
+%
+% For Unicode engines, make the Unicode soft hyphen an active
+% character defined as \cs{-}.
+%
+% \begin{macrocode}
+\ifx\Umathcode\@undefined\else
+ \catcode "AD=13
+ \def^^ad{\-}
+\fi
+% \end{macrocode}
+%
% \begin{macro}{\obeycr}
% \begin{macro}{\restorecr}
% The following definitions will probably get deleted or moved to
diff --git a/Master/texmf-dist/source/latex/base/lttab.dtx b/Master/texmf-dist/source/latex/base/lttab.dtx
index 47cf4a66184..dedd9e5d375 100644
--- a/Master/texmf-dist/source/latex/base/lttab.dtx
+++ b/Master/texmf-dist/source/latex/base/lttab.dtx
@@ -31,7 +31,7 @@
%%% From File: lttab.dtx
%<*driver>
% \fi
-\ProvidesFile{lttab.dtx}[2019/10/07 v1.1q LaTeX Kernel (Columns)]
+\ProvidesFile{lttab.dtx}[2020/04/24 v1.1r LaTeX Kernel (Columns)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{lttab.dtx}
@@ -475,11 +475,28 @@
% \end{macro}
%
% \begin{macro}{\@itabcr}
+% \changes{v1.1r}{2020/04/21}{Support calc syntax (gh/152)}
% \begin{macrocode}
-\def\@itabcr[#1]{\vskip #1\@startline\ignorespaces}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@itabcr}{Tabbing calc syntax}%
+\def\@itabcr[#1]{\@vspace@calcify{#1}\@startline\ignorespaces}
+%</2ekernel|latexrelease>
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@itabcr}{Tabbing calc syntax}%
+%<latexrelease>
+%<latexrelease>\def\@itabcr[#1]{\vskip #1\@startline\ignorespaces}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
%
%
+% \begin{environment}{tabbing}
% \begin{macro}{\tabbing}
% \changes{v1.1f}{1995/10/23}{(CAR)Make \cs{@hightab} consistently a
% local variable}
@@ -513,6 +530,8 @@
\@stopline\ifnum\@tabpush >\z@ \@badpoptabs \fi\endtrivlist}
% \end{macrocode}
% \end{macro}
+% \end{environment}
+%
%
% \begin{macro}{\@rtab}
% Omitted |\global| added to |\@rtab| 17 Jun 86
@@ -815,6 +834,7 @@
% \end{macrocode}
% \end{macro}
%
+% \begin{environment}{array}
% \begin{macro}{\array}
% \begin{macrocode}
\def\array{\let\@acol\@arrayacol \let\@classz\@arrayclassz
@@ -822,6 +842,7 @@
\let\\\@arraycr\let\@halignto\@empty\@tabarray}
% \end{macrocode}
% \end{macro}
+% \end{environment}
%
% \begin{macro}{\endarray}
% \begin{macro}{\endtabular}
@@ -835,11 +856,13 @@
% \end{macro}
% \end{macro}
%
+% \begin{environment}{tabular}
% \begin{macro}{\tabular}
% \begin{macrocode}
\def\tabular{\let\@halignto\@empty\@tabular}
% \end{macrocode}
% \end{macro}
+% \end{environment}
%
% \begin{macro}{\tabular*}
% \changes{v1.1j}{1998/05/18}{Use \cs{setlength}, so that
@@ -1003,8 +1026,24 @@
% \end{macro}
%
% \begin{macro}{\@yargarraycr}
+% \changes{v1.1r}{2020/04/21}{Support calc syntax (gh/152)}
% \begin{macrocode}
-\def\@yargarraycr#1{\cr\noalign{\vskip #1}}
+%</2ekernel>
+%<*2ekernel|latexrelease>
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\@yargarraycr}{tabular support calc syntax}%
+\def\@yargarraycr#1{\cr\noalign{\@vspace@calcify{#1}}}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+% \end{macrocode}
+%
+% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@yargarraycr}{tabular support calc syntax}%
+%<latexrelease>
+%<latexrelease>\def\@yargarraycr#1{\cr\noalign{\vskip #1}}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
% \end{macrocode}
% \end{macro}
%
diff --git a/Master/texmf-dist/source/latex/base/lttextcomp.dtx b/Master/texmf-dist/source/latex/base/lttextcomp.dtx
index ed37b9d9957..3b6231dafdf 100644
--- a/Master/texmf-dist/source/latex/base/lttextcomp.dtx
+++ b/Master/texmf-dist/source/latex/base/lttextcomp.dtx
@@ -33,7 +33,7 @@
%
%
\ProvidesFile{lttextcomp.dtx}
- [2020/02/10 v1.0c LaTeX Kernel (text companion symbols)]
+ [2020/04/29 v1.0d LaTeX Kernel (text companion symbols)]
% \iffalse
\documentclass{ltxdoc}
\begin{document}
@@ -445,7 +445,7 @@
% Using \cs{UndeclareTextCommand} above is enough only if the
% encoding definition files are not reloaded afterwards. In the
% past that happened if \texttt{fontenc} was used in the document
-% preamble (not not any longer). So in some sense it is better to fully remove
+% preamble (not any longer). So in some sense it is better to fully remove
% them from the encoding files, but for rollbacks it is easier to
% keep them in for now.
%
@@ -565,24 +565,25 @@
%
% In Unicode engines we just execute the simple accents:
% \changes{v1.0c}{2020/02/10}{Use \cs{@tabacckludge} for tabbing where necessary (gh/271)}
+% \changes{v1.0d}{2020/04/29}{Make all captial accents text commands for hyperref (gh/332)}
% \begin{macrocode}
\else
- \def\capitalacute{\@tabacckludge'}
- \def\capitalbreve{\u}
- \def\capitalcaron{\v}
- \def\capitalcedilla{\c}
- \def\capitalcircumflex{\^}
- \def\capitaldieresis{\"}
- \def\capitaldotaccent{\.}
- \def\capitalgrave{\@tabacckludge`}
- \def\capitalhungarumlaut{\H}
- \def\capitalmacron{\@tabacckludge=}
- \def\capitalnewtie{\t}
- \def\capitalogonek{\k}
- \def\capitalring{\r}
- \def\capitaltie{\t}
- \def\capitaltilde{\~}
- \def\newtie{\t}
+ \DeclareTextCommandDefault\capitalacute{\@tabacckludge'}
+ \DeclareTextCommandDefault\capitalbreve{\u}
+ \DeclareTextCommandDefault\capitalcaron{\v}
+ \DeclareTextCommandDefault\capitalcedilla{\c}
+ \DeclareTextCommandDefault\capitalcircumflex{\^}
+ \DeclareTextCommandDefault\capitaldieresis{\"}
+ \DeclareTextCommandDefault\capitaldotaccent{\.}
+ \DeclareTextCommandDefault\capitalgrave{\@tabacckludge`}
+ \DeclareTextCommandDefault\capitalhungarumlaut{\H}
+ \DeclareTextCommandDefault\capitalmacron{\@tabacckludge=}
+ \DeclareTextCommandDefault\capitalnewtie{\t}
+ \DeclareTextCommandDefault\capitalogonek{\k}
+ \DeclareTextCommandDefault\capitalring{\r}
+ \DeclareTextCommandDefault\capitaltie{\t}
+ \DeclareTextCommandDefault\capitaltilde{\~}
+ \DeclareTextCommandDefault\newtie{\t}
\fi
% \end{macrocode}
%
diff --git a/Master/texmf-dist/source/latex/base/ltvers.dtx b/Master/texmf-dist/source/latex/base/ltvers.dtx
index f13a6ae6851..2813670115d 100644
--- a/Master/texmf-dist/source/latex/base/ltvers.dtx
+++ b/Master/texmf-dist/source/latex/base/ltvers.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltvers.dtx}
- [2020/01/31 v1.1e LaTeX Kernel (Version Info)]
+ [2020/03/02 v1.1e LaTeX Kernel (Version Info)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltvers.dtx}
@@ -112,10 +112,10 @@
%</2ekernel>
%<latexrelease>\edef\latexreleaseversion
%<*2ekernel|latexrelease>
- {2020-02-02}
+ {2020-10-01}
%</2ekernel|latexrelease>
%<*2ekernel>
-\def\patch@level{5}
+\def\patch@level{0}
% \end{macrocode}
%
% \begin{macro}{\development@branch@name}
@@ -250,6 +250,14 @@
\def\@IncludeInRele@se#1#2#3{%
\toks@{[#1] #3}%
\expandafter\ifx\csname\string#2+\@currname+IIR\endcsname\relax
+% \end{macrocode}
+% If we roll back and the first patch already match then applying
+% that is actually reapplying what is already in the format, i.e.,
+% it is useless and possibly allocating new registers. However, it
+% makes the logic simpler so this is the way it is for now. In
+% theory we could always jump overthe first patch because that is
+% only really needed for rolling forward. So maybe one day \dots
+% \begin{macrocode}
\ifnum\expandafter\@parse@version#1//00\@nil
>\expandafter\@parse@version\fmtversion//00\@nil
\GenericInfo{}{Skipping: \the\toks@}%
diff --git a/Master/texmf-dist/source/latex/base/ltxdoc.dtx b/Master/texmf-dist/source/latex/base/ltxdoc.dtx
index f250b2cb193..696af32ab15 100644
--- a/Master/texmf-dist/source/latex/base/ltxdoc.dtx
+++ b/Master/texmf-dist/source/latex/base/ltxdoc.dtx
@@ -30,7 +30,7 @@
%
%<class>\NeedsTeXFormat{LaTeX2e}
%<class>\ProvidesClass{ltxdoc}
-%<class> [2019/09/16 v2.0y Standard LaTeX documentation class]
+%<class> [2020/08/21 v2.1a Standard LaTeX documentation class]
%
%<*driver>
\documentclass{ltxdoc}
@@ -54,6 +54,7 @@
%
% \changes{v2.0i}{1994/04/29}{Update the documentation.}
% \changes{v2.0s}{1998/08/17}{(RmS) Documentation fixes.}
+% \changes{v2.1a}{2020/08/21}{Integration of new hook management interface}
%
% \section{Documentation of the \LaTeX\ sources}
%
@@ -422,6 +423,10 @@
\def\partname{File}
% \end{macrocode}
%
+%
+%
+% \changes{v2.0z}{2020/05/17}{Support spaces \emph{within} filenames
+% (gh/218)}
% \begin{macrocode}
\newcommand*{\DocInclude}[1]{%
\relax
@@ -432,14 +437,19 @@
{\def\currentfile{#1.dtx}}%
\ifnum\@auxout=\@partaux
\@latexerr{\string\include\space cannot be nested}\@eha
- \else \@docinclude#1 \fi}
+ \else
+ \set@curr@file{#1}%
+ \edef\@curr@file{\@strip@tex@ext\@curr@file}%
+ \expandafter\@docinclude\expandafter{\@curr@file}
+ \fi}
\def\@docinclude#1 {\clearpage
-\if@filesw \immediate\write\@mainaux{\string\@input{#1.aux}}\fi
+\if@filesw \immediate\write\@mainaux{\string\@input{"#1.aux"}}\fi
\@tempswatrue\if@partsw \@tempswafalse\edef\@tempb{#1}\@for
\@tempa:=\@partlist\do{\ifx\@tempa\@tempb\@tempswatrue\fi}\fi
\if@tempswa \let\@auxout\@partaux \if@filesw
-\immediate\openout\@partaux #1.aux
+\immediate\openout\@partaux "#1.aux"
\immediate\write\@partaux{\relax}\fi
+\@filehook@set@CurrentFile
% \end{macrocode}
% We need to save (and later restore) various index-related
% commands which might be changed by the included file.
diff --git a/Master/texmf-dist/source/latex/base/ltxref.dtx b/Master/texmf-dist/source/latex/base/ltxref.dtx
index c20a3245588..56ae09c1650 100644
--- a/Master/texmf-dist/source/latex/base/ltxref.dtx
+++ b/Master/texmf-dist/source/latex/base/ltxref.dtx
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltxref.dtx}
- [2019/09/16 v1.1m LaTeX Kernel (Cross Referencing)]
+ [2020/08/23 v1.1o LaTeX Kernel (Cross Referencing)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltxref.dtx}
@@ -311,14 +311,18 @@
% \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
-%<latexrelease>\IncludeInRelease{2019/10/01}%
-%<latexrelease> {\refstepcounter}{Add \labelformat and \Ref}%
+%<latexrelease>\IncludeInRelease{2020/10/01}%
+%<latexrelease> {\refstepcounter}{Add \@currentcounter}%
% \end{macrocode}
%
% \begin{macro}{\refstepcounter}
% Step the counter and allow for labels to point to its current value.
+% \changes{v1.1n}{2020/05/05}{record the counter name in \cs{@currentcounter}}
+% \changes{v1.1o}{2020/08/23}{add default definition of \cs{@currentcounter}}
% \begin{macrocode}
+\def\@currentcounter{}
\def\refstepcounter#1{\stepcounter{#1}%
+ \edef\@currentcounter{#1}%
\protected@edef\@currentlabel
% \end{macrocode}
% By generating the second csname first the |\p@...| command can
@@ -381,6 +385,17 @@
% \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{2019/10/01}%
+%<latexrelease> {\refstepcounter}{Add \labelformat and \Ref}%
+%<latexrelease>\let\@currentcounter\@undefined
+%<latexrelease>\def\refstepcounter#1{\stepcounter{#1}%
+%<latexrelease> \protected@edef\@currentlabel
+%<latexrelease> {\csname p@#1\expandafter\endcsname\csname the#1\endcsname}%
+%<latexrelease>}
+%<latexrelease>\def\labelformat#1{\expandafter\def\csname p@#1\endcsname##1}
+%<latexrelease>\DeclareRobustCommand\Ref[1]{\protected@edef\@tempa{\ref{#1}}%
+%<latexrelease> \expandafter\MakeUppercase\@tempa}
+%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease> {\refstepcounter}{Add \labelformat and \Ref}%
%<latexrelease>
diff --git a/Master/texmf-dist/source/latex/base/slides.dtx b/Master/texmf-dist/source/latex/base/slides.dtx
index a0dbdabe5f0..8b7276f492d 100644
--- a/Master/texmf-dist/source/latex/base/slides.dtx
+++ b/Master/texmf-dist/source/latex/base/slides.dtx
@@ -53,7 +53,7 @@
%<*driver>
\ProvidesFile{slides.drv}
%</driver>
- [2019/11/04 v2.4b
+ [2020/02/20 v2.4b
%<+class> Standard LaTeX document class]
%<+cmd> SLiTeX definitions]
% \end{macrocode}
@@ -162,7 +162,7 @@
%
% \section{Fonts}
%
-% Note, that that with NFSS you can easily produce slides with special
+% Note, that with NFSS you can easily produce slides with special
% fonts just by calling an appropriate style file (like |times|) in a
% |\usepackage| command. This works, for example, with all
% fonts that are defined to be scaleable (e.g., PostScript fonts) since
@@ -2536,14 +2536,14 @@ COLOR LAYER\\[.75in]%
% \overline, \underline, \frac and \sqrt
%
% \@mathbox{STYLE}{BOX}{MTEXT} : Called in math mode, typesets MTEXT and
-% stores result in BOX, using style STYLE.
+% stores result in BOX, using STYLE.
%
% \@bphant{BOX} : Creates a phantom with dimensions BOX.
% \@vbphant{BOX} : Creates a phantom with ht of BOX and zero width.
% \@hbphant{BOX} : Creates a phantom with width of BOX
% and zero ht & dp.
% \@hvsmash{STYLE}{MTEXT} : Creates a copy of MTEXT with zero height and
-% width in style STYLE.
+% width in STYLE.
%\end{verbatim}
% \begin{macrocode}
\def\@mathbox#1#2#3{\setbox#2\hbox{$\m@th#1{#3}$}}
diff --git a/Master/texmf-dist/source/latex/base/unpack.ins b/Master/texmf-dist/source/latex/base/unpack.ins
index b03dd5c6b1b..3264a401d9e 100644
--- a/Master/texmf-dist/source/latex/base/unpack.ins
+++ b/Master/texmf-dist/source/latex/base/unpack.ins
@@ -123,7 +123,6 @@
\batchinput{latexrelease.ins}
-
\Msg{}
\Msg{*********************************************}
\Msg{*}