summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/base/ltclass.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/base/ltclass.dtx')
-rw-r--r--Master/texmf-dist/source/latex/base/ltclass.dtx674
1 files changed, 662 insertions, 12 deletions
diff --git a/Master/texmf-dist/source/latex/base/ltclass.dtx b/Master/texmf-dist/source/latex/base/ltclass.dtx
index b1d81c5d6bf..91194a2adda 100644
--- a/Master/texmf-dist/source/latex/base/ltclass.dtx
+++ b/Master/texmf-dist/source/latex/base/ltclass.dtx
@@ -1,6 +1,6 @@
% \iffalse meta-comment
%
-% Copyright 1993-2016
+% Copyright 1993-2018
% The LaTeX3 Project and any individual authors listed elsewhere
% in this file.
%
@@ -11,7 +11,7 @@
% 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
-% http://www.latex-project.org/lppl.txt
+% https://www.latex-project.org/lppl.txt
% and version 1.3c or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
@@ -33,7 +33,7 @@
%<*driver>
% \fi
\ProvidesFile{ltclass.dtx}
- [2017/03/08 v1.2c LaTeX Kernel (Class & Package Interface)]
+ [2018/03/27 v1.2f LaTeX Kernel (Class & Package Interface)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltclass.dtx}
@@ -56,11 +56,16 @@
% \fi
%
%
+% \changes{v0.2f}{1993/11/22}
+% {\cs{@unknownversion} removed}
+% \changes{v1.0j}{1994/10/18}
+% {Move \cs{listfiles} to ltfiles.dtx}
% \changes{v1.0f}{1994/05/22}{Use new warning and error commands}
% \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.}
%
+%
% \section{Introduction}
%
% This file implements the following declarations, which replace
@@ -613,19 +618,41 @@
\expandafter\@ifl@t@r
\csname ver@#2.#1\endcsname}
\@onlypreamble\@ifl@ter
+%</2ekernel>
% \end{macrocode}
%
% This internal macro is also used in |\NeedsTeXFormat|.
% \changes{v0.2f}{1993/11/22}
% {Added //00 so parsing never produces a runaway argument.}
+% \changes{v1.2d}{2018/02/18}
+% {Added 0 up front to make bad data come out as 0.}
% \begin{macrocode}
+%<latexrelease>\IncludeInRelease{2018/04/01}%
+%<latexrelease> {\@ifl@t@r}{Guard against bad input}%
+%<*2ekernel|latexrelease>
\def\@ifl@t@r#1#2{%
- \ifnum\expandafter\@parse@version#1//00\@nil<%
- \expandafter\@parse@version#2//00\@nil
+ \ifnum\expandafter\@parse@version\expandafter0#1//00\@nil<%
+ \expandafter\@parse@version\expandafter0#2//00\@nil
\expandafter\@secondoftwo
\else
\expandafter\@firstoftwo
\fi}
+%</2ekernel|latexrelease>
+%<latexrelease>\EndIncludeInRelease
+%<latexrelease>\IncludeInRelease{0000/00/00}%
+%<latexrelease> {\@ifl@t@r}{Guard against bad input}%
+%<latexrelease>\def\@ifl@t@r#1#2{%
+%<latexrelease> \ifnum\expandafter\@parse@version#1//00\@nil<%
+%<latexrelease> \expandafter\@parse@version#2//00\@nil
+%<latexrelease> \expandafter\@secondoftwo
+%<latexrelease> \else
+%<latexrelease> \expandafter\@firstoftwo
+%<latexrelease> \fi}
+%<latexrelease>\EndIncludeInRelease
+%<*2ekernel>
+% \end{macrocode}
+%
+% \begin{macrocode}
\@onlypreamble\@ifl@t@r
% \end{macrocode}
%
@@ -635,7 +662,7 @@
% {add \cs{@parse@version@dash} to support yyyy-mm-dd as well as yyyy/mm/dd }
% \begin{macrocode}
%</2ekernel>
-%<*2ekernel|isodate>
+%<*2ekernel|latexreleasefirst>
\def\@parse@version#1/#2/#3#4#5\@nil{%
\@parse@version@dash#1-#2-#3#4\@nil
}
@@ -645,7 +672,7 @@
% \begin{macrocode}
\def\@parse@version@dash#1-#2-#3#4#5\@nil{%
\if\relax#2\relax\else#1\fi#2#3#4 }
-%</2ekernel|isodate>
+%</2ekernel|latexreleasefirst>
%<*2ekernel>
% \end{macrocode}
% \end{macro}
@@ -716,6 +743,7 @@
%<latexrelease> \fi
%<latexrelease> }%
%<latexrelease> \reserved@a}
+%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
%
@@ -1043,6 +1071,7 @@
%<latexrelease> {\csname ds@\CurrentOption\endcsname}%
%<latexrelease> \edef\CurrentOption{##1}}%
%<latexrelease> \expandafter\reserved@a\CurrentOption\@nil}
+%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
%
@@ -1362,6 +1391,7 @@
%<latexrelease> \expandafter\reserved@b\reserved@a,\@nil,}%
%<latexrelease> \fi
%<latexrelease> \reserved@a}
+%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
% \end{macrocode}
%
@@ -1437,7 +1467,7 @@
\csname\@currname.\@currext-h@@k\endcsname
\expandafter\let\csname\@currname.\@currext-h@@k\endcsname
\@undefined
- \@unprocessedoptions}
+ \@unprocessedoptions}%
% \end{macrocode}
%
% \begin{macrocode}
@@ -1672,6 +1702,12 @@
% \changes{v1.0p}{1995/05/25}{Delete \cs{filec@ntents} after preamble}
% \begin{macrocode}
\begingroup%
+\@tempcnta=1
+\loop
+ \catcode\@tempcnta=12 %
+ \advance\@tempcnta\@ne %
+\ifnum\@tempcnta<32 %
+\repeat %
\catcode`\*=11 %
\catcode`\^^M\active%
\catcode`\^^L\active\let^^L\relax%
@@ -1727,6 +1763,19 @@
\fi%
\let\do\@makeother\dospecials%
% \end{macrocode}
+% If there are active characters in the upper half (e.g., from
+% \texttt{inputenc} there would be confusion so we render everything
+% harmless.
+% \changes{v1.2f}{2018/03/27}
+% {Use full file name for old release}
+% \begin{macrocode}
+ \count@ 128\relax%
+ \loop%
+ \catcode\count@ 11\relax%
+ \advance\count@ \@ne%
+ \ifnum\count@<\@cclvi%
+ \repeat%
+% \end{macrocode}
%
% \changes{v1.0y}{1997/10/10}
% {Check for text before or after \cs{end} environment. latex/2636}
@@ -1807,14 +1856,615 @@
% \end{macro}
%
%
-% \changes{v0.2f}{1993/11/22}
-% {\cs{@unknownversion} removed}
-% \changes{v1.0j}{1994/10/18}
-% {Move \cs{listfiles} to ltfiles.dtx}
%
+%
+%
+% \section{Package/class rollback mechanism}
+%
+%
+%
% \begin{macrocode}
%</2ekernel>
+%<*2ekernel|latexreleasefirst>
+% \end{macrocode}
+%
+% \changes{v1.2d}{2018/02/18}{Introduce rollback concept}
+%
+% \begin{macro}{\pkgcls@debug}
+% For testing we have a few extra lines of code that by default do
+% nothing but one can set |\pkgcls@debug| to |\typeout| to get
+% extra info. Sometime in the future this will be dropped.
+% \begin{macrocode}
+%<*tracerollback>
+%\let\pkgcls@debug\typeout
+\let\pkgcls@debug\@gobble
+%</tracerollback>
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\requestedLaTeXdate}
+% The macro (!) |\requestedLaTeXdate| holds the globally requested
+% rollback date (via \texttt{latexrelease}) or zero if no such
+% request was made.
+% \begin{macrocode}
+\def\requestedLaTeXdate{0}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\pkgcls@targetdate}
+% \begin{macro}{\pkgcls@targetlabel}
+% \begin{macro}{\pkgcls@innerdate}
+%
+% If a rollback for a package or class is requested then
+% |\pkgcls@targetdate| holds the requested date as a number
+% YYYYMMDD (if there was one, otherwise the value of
+% |\requestedLaTeXdate|) and |\pkgcls@targetlabel| will be
+% empty. If there was a request for a named version then
+% |\pkgcls@targetlabel| holds the verion name and
+% |\pkgcls@targetdate| is set to \texttt{1}.
+%
+% |\pkgcls@targetdate=0| is used to indicate that there was no
+% rollback request.
+% While loading an old release |\pkgcls@targetdate| is also reset to
+% zero so that |\DeclareRelease| declarations are bypassed.
+%
+% In contrast |\pkgcls@innerdate| will always hold the requested
+% date (in a macro not a counter) if there was one, otherwise,
+% e.g., if there was no request or a request to a version name it
+% will contain \TeX{} largest legal number. While loading a file
+% this can be used to provide conditionals that select code based
+% on the request.
+%
+%
+% \begin{macrocode}
+\ifx\pkgcls@targetdate\@undefined
+ \newcount\pkgcls@targetdate
+\fi
+\let\pkgcls@targetlabel\@empty
+\def\pkgcls@innerdate{\maxdimen}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+
+% \begin{macro}{\pkgcls@candidate}
+% \begin{macro}{\pkgcls@releasedate}
+% When looping through the |\DeclareRelease| declarations we
+% record if the release is the best candidate we have seen so far.
+% This is recorded in |\pkgcls@candidate| and we update it whenever
+% we see a better one.
+%
+% In |\pkgcls@releasedate| we keep track of the release date of
+% that candidate.
+% \begin{macrocode}
+\let\pkgcls@candidate\@empty
+\let\pkgcls@releasedate\@empty
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\load@onefilewithoptions}
+% \begin{macro}{\@onefilewithoptions}
+% the best place to add the rollback code is at the point where
+% |\@onefilewithoptions| is called to load a single class or
+% package.
+%
+% To make things easy we save the old definition as
+% |\load@onefilewithoptions| and then provide a new interface.
+%
+% Important: as this code is also unconditionally placed into
+% latexrelease we can only do this name change once otherwise both
+% macros will contain the same code.
+% \begin{macrocode}
+\ifx\load@onefilewithoptions\@undefined
+ \let\load@onefilewithoptions\@onefilewithoptions
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \def\@onefilewithoptions#1[#2][#3]#4{%
+% \end{macrocode}
+% First a bit of tracing normally disabled.
+% \begin{macrocode}
+%<*tracerollback>
+ \pkgcls@debug{--- File loaded request (\noexpand\usepackage or ...)}%
+ \pkgcls@debug{\@spaces 1: #1}%
+ \pkgcls@debug{\@spaces 2: #2}%
+ \pkgcls@debug{\@spaces 3: #3}%
+ \pkgcls@debug{\@spaces 4: #4}%
+%</tracerollback>
+% \end{macrocode}
+% Two of the arguments are needed later on in error/warning
+% messages so we save them.
+% \begin{macrocode}
+ \def\pkgcls@name{#1}% % for info message
+ \def\pkgcls@arg {#3}% % for info message
+% \end{macrocode}
+% then we parse the final optional argument to determine if there
+% is a specific rollback request for the current file. This will
+% set |\pkgcls@targetdate|, |\pkgcls@targetlabel| and
+% |\pkgcls@mindate|.
+% \begin{macrocode}
+ \pkgcls@parse@date@arg{#3}%
+% \end{macrocode}
+% When determining the correct release to load we keep track of
+% candiates in |\pkgcls@candidate| and initially we don't have any:
+% \begin{macrocode}
+ \let\pkgcls@candidate\@empty
+% \end{macrocode}
+% If we had a rollback request then |#3| may contain data but not
+% necessarily a ``minimal date'' so instead of passing it on we
+% pass on |\pkgcls@mindate|.
+% \begin{macrocode}
+ \load@onefilewithoptions#1[#2][\pkgcls@mindate]#4%
+ }
+\fi
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \begin{macro}{\pkgcls@parse@date@arg}
+% The |\pkgcls@parse@date@arg| command parses the second optional
+% argument of |\usepackage|, |\RequirePackage| or |\documentclass|
+% for a rollback request setting the values of |\pkgcls@targetdate|
+% and |\pkgcls@targetlabel|.
+%
+% This optional argument has a dual purpose: If it just contains a
+% date string then this means that the package should have at least
+% that date (to ensure that a certain feature is actually available,
+% or a certain bug has been fixed). When the package gets loaded the
+% information in |\Provides...| will then be checked against this
+% request.
+%
+% But if it starts with an equal sign followed by a date string or
+% followed by a version name then this means that we should roll
+% back to the state of the package at tht date or to the version
+% with the requested name.
+%
+% If there was no optional argument or the optional argument
+% does not start with ``\texttt{=}'' then the |\pkgcls@targetdate|
+% is set to the date of the overall rollback request (via
+% \texttt{latexrelease}) or if that was not given it is set to
+% \texttt{0}.
+% In either case |\pkgcls@targetlabel| will be made empty.
+%
+% If the argument doesn't start with ``\texttt{=}'' then it is
+% supposed to be a ``minimal date'' and we therefore save the value
+% in |\pkgcls@mindate|, otherwise this macro is made empty.
+%
+% So in summary we have:
+% \begin{flushleft}
+% \hspace*{-1in}\begin{tabular}{ccccc@{}}
+% Input & & \cs{pkgcls@targetdate}
+% & \cs{pkgcls@targetlabel}
+% & \cs{pkgcls@mindate}\\[3pt]
+% \meta{empty} & $\to$ & \meta{global-rollbackdate-as-number}
+% & \meta{empty} & \meta{empty}
+% \\
+% \meta{date} & $\to$ & \meta{global-rollbackdate-as-number}
+% & \meta{empty} & \meta{date}
+% \\
+% \texttt{=}\meta{date} & $\to$ & \meta{date-as-number}
+% & \meta{empty} & \meta{empty}
+% \\
+% \texttt{=}\meta{version}& $\to$ & \texttt{1}
+% & \meta{version} & \meta{empty}
+% \\
+% \meta{other} & $\to$ & \meta{global-rollbackdate-as-number}
+% & \meta{empty} & \meta{other}
+% \\
+% \end{tabular}
+% \end{flushleft}
+% where \meta{global-rollbackdate-as-number} is a date request given
+% via \texttt{latexrelease} or if there wasn't one \texttt{0}.
+%
+% \begin{macrocode}
+\def\pkgcls@parse@date@arg #1{%
+% \end{macrocode}
+% If the argument is empty we use the rollback date from
+% \texttt{latexrelease} which has the value of zero if there was no
+% rollback request. The label and the minimal date is made empty in that case.
+% \begin{macrocode}
+ \ifx\@nil#1\@nil
+ \pkgcls@targetdate\requestedLaTeXdate\relax
+ \let\pkgcls@targetlabel\@empty
+ \let\pkgcls@mindate\@empty
+% \end{macrocode}
+% Otherwise we parse the argument further, checking for a \texttt{=}
+% as the first character. We append a \texttt{=} at the end so that
+% there is at least one such character in the argument.
+% \begin{macrocode}
+ \else
+ \pkgcls@parse@date@arg@#1=\@nil\relax
+ \fi
+ }
% \end{macrocode}
+% The actual parsing work then happens in |\pkgcls@parse@date@arg@|:
+% \begin{macrocode}
+\def\pkgcls@parse@date@arg@#1=#2\@nil{%
+% \end{macrocode}
+% We set |\pkgcls@targetdate| depending on the parsing result; the
+% code is expandable so we can do the parsing as part of the assignment.
+% \begin{macrocode}
+ \pkgcls@targetdate
+% \end{macrocode}
+% If a \texttt{=} was in first position then |#1| will be empty. In
+% that case |#2| will be the original argument with a \texttt{=}
+% appended.
+%
+% This can be parsed with |\@parse@version|, the trailing character
+% is simply ignored. This macro returns the parsed date as a number
+% (or zero if it wasn't a date) and accepts both YYYY/MM/DD and YYYY-MM-DD
+% formats.
+% \begin{macrocode}
+ \ifx\@nil#1\@nil
+ \@parse@version0#2//00\@nil\relax
+% \end{macrocode}
+% Whatever is returned is thus assigned to |\pkgcls@targetdate|
+% and therefore we can now test its value. If the value is zero we
+% assume that the remaining argument string represents a version
+% and change |\pkgcls@targetdate| and set |\pkgcls@targetlabel| to
+% the version name (after stripping off the trailing \texttt{=}.
+% \begin{macrocode}
+ \ifnum \pkgcls@targetdate=\z@
+ \pkgcls@targetdate\@ne
+ \def\pkgcls@innerdate{\maxdimen}%
+ \pkgcls@parse@date@arg@version#2%
+ \else
+ \edef\pkgcls@innerdate{\the\pkgcls@targetdate}%
+ \fi
+ \let\pkgcls@mindate\@empty
+ \else
+% \end{macrocode}
+% If |#1| was not empty then there wasn't a \texttt{=} character in
+% first position so we we are dealing either with a ``minimum
+% date'' or with some incorrect data. We assume the former and make
+% the following assignments (the first one finishing the assignment
+% of |\pkgcls@targetdate|):
+% \begin{macrocode}
+ \requestedLaTeXdate\relax
+ \let\pkgcls@targetlabel\@empty
+ \def\pkgcls@innerdate{\maxdimen}%
+ \def\pkgcls@mindate{#1}%
+% \end{macrocode}
+% If the min-date is after the requested rollback date (if there is
+% any, i.e., if it is not zero) then we have a conflict and
+% therefore issue an error.
+% \begin{macrocode}
+ \ifnum \pkgcls@targetdate > \z@
+ \ifnum \@parse@version0#1//00\@nil > \pkgcls@targetdate
+ \@latex@error{Suspicious rollback/min-date date given}%
+ {There is a minimal date of #1 specified for
+ \@cls@pkg\space'\pkgcls@name'.\MessageBreak
+ But this is in conflict
+ with a rollback request to \requestedpatchdate,
+ so something\MessageBreak
+ is wrong here. Continue and I
+ ignore the minimal date request.}%
+ \fi
+ \fi
+ \fi
+}
+% \end{macrocode}
+% Strip off te trailing \texttt{=} and assign the version name to
+% |\pkgcls@targetlabel|.
+% \begin{macrocode}
+\def\pkgcls@parse@date@arg@version#1={%
+ \def\pkgcls@targetlabel{#1}}
+% \end{macrocode}
+% \end{macro}
+
+
+
+
+% \begin{macro}{\DeclareRelease}
+% First argument is the ``name'' of the release and it can be left empty
+% if one doesn't like to give a name to the release.
+% The second argument is that from which on this release was
+% available (or should be used in case of minor updates).
+% The final argument is the external file name of this release, by
+% convention this should be
+% \meta{pkg/cls-name}\texttt{-}\meta{date}\texttt{.}\meta{extension}
+% but this is not enforced and through this argument one can
+% overwrite it.
+% \begin{macrocode}
+\def\DeclareRelease#1#2#3{%
+ \ifnum\pkgcls@targetdate>\z@ % some sort of rollback request
+%<*tracerollback>
+ \pkgcls@debug{---\string\DeclareRelease:}%
+ \pkgcls@debug{\@spaces 1: #1}%
+ \pkgcls@debug{\@spaces 2: #2}%
+ \pkgcls@debug{\@spaces 3: #3}%
+%</tracerollback>
+% \end{macrocode}
+% If the date argument |#2| is empty we are dealing with a special
+% release that should be only accessible via its name; a typical
+% use case would be a ``beta'' release. So if we are
+% currently processing a date request we ignore it and otherwise we
+% check if we can match the name and if so load the corresponding
+% release file.
+% \begin{macrocode}
+ \ifx\@nil#2\@nil
+ \ifnum\pkgcls@targetdate=\@ne % named request
+ \def\reserved@a{#1}%
+ \ifx\pkgcls@targetlabel\reserved@a
+ \pkgcls@use@this@release{#3}{}%
+%<*tracerollback>
+ \else
+ \pkgcls@debug{Label doesn't match}%
+%</tracerollback>
+ \fi
+%<*tracerollback>
+ \else
+ \pkgcls@debug{Date request: ignored}%
+%</tracerollback>
+ \fi
+ \else
+% \end{macrocode}
+% If the value of |\pkgcls@targetdate| is greater than 1 (or in
+% reality greater than something like 19930101) we are dealing with a
+% rollback request to a specific date.
+% \begin{macrocode}
+ \ifnum\pkgcls@targetdate>\@ne % a real request
+% \end{macrocode}
+% So we parse the date of this release to check if it is before or
+% after the request date.
+% \begin{macrocode}
+ \ifnum\@parse@version#2//00\@nil
+ >\pkgcls@targetdate
+% \end{macrocode}
+% If it is after we have to distinguish between two cases: If there
+% was an earlier candidate we use that one because the other is too
+% late, but if there wasn't one (i.e., if current release is the
+% oldest that exists) we use it as the best choice. However in
+% that case something is wrong (as there shouldn't be a rollback to
+% a date where a package used doesn't yet exists. So we make a
+% complained to the user.
+% \begin{macrocode}
+ \ifx\pkgcls@candidate\@empty
+ \pkgcls@rollbackdate@error{#2}%
+ \pkgcls@use@this@release{#3}{#2}%
+ \else
+ \pkgcls@use@this@release\pkgcls@candidate
+ \pkgcls@releasedate
+ \fi
+ \else
+% \end{macrocode}
+% Otherwise, if the release date of this version is before the
+% target rollback and we record it as a candidate. But we don't use
+% it yet as there may be another release which is still before the
+% target rollback.
+% \begin{macrocode}
+ \def\pkgcls@candidate{#3}%
+ \def\pkgcls@releasedate{#2}%
+%<*tracerollback>
+ \pkgcls@debug{New candidate: #3}%
+%</tracerollback>
+ \fi
+ \else
+% \end{macrocode}
+% If we end up in this branch we have a named version request. So
+% we check if |\pkgcls@targetlabel| matches the current name and if
+% yes we use this release immediately, otherwise we do nothing as a
+% later declaration may match it.
+% \begin{macrocode}
+ \def\reserved@a{#1}%
+ \ifx\pkgcls@targetlabel\reserved@a
+ \pkgcls@use@this@release{#3}{#2}%
+%<*tracerollback>
+ \else
+ \pkgcls@debug{Label doesn't match}%
+%</tracerollback>
+ \fi
+ \fi
+ \fi
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+
+
+
+
+% \begin{macro}{\pkgcls@use@this@release}
+% If a certain release has been selected (stored in the external
+% file given in \verb=#1=) we need to input it and afterwards stop
+% reading the current file.
+% \begin{macrocode}
+\def\pkgcls@use@this@release#1#2{%
+% \end{macrocode}
+% Before that we record the selection made inside the transcript.
+% \begin{macrocode}
+ \pkgcls@show@selection{#1}{#2}%
+% \end{macrocode}
+% We then set the |\pkgcls@targetdate| to zero so that any
+% |\DeclareRelease| or |\DeclareCurrentRelease| in the file we
+% now load are bypassed\footnote{The older release may also have
+% such declarations inside if it was a simply copy od the
+% \texttt{.sty} or \texttt{.cls} file current at that
+% date. Removing these declarations would make the file load a tiny
+% bit faster, but this way it works in any case.} and then we
+% finally load the correct release.
+%
+% After loading that file we need to stop reading the current file
+% so we issue |\endinput|. Note that the |\relax| before that is
+% essential to ensure that the |\endinput| is only happening after
+% the file has been fully processed, otherwise it would act after the
+% first line of the |\@@input|!
+% \changes{v1.2e}{2018/03/24}
+% {Use full file name for old release}
+% \begin{macrocode}
+ \pkgcls@targetdate\z@
+ \@@input #1\relax
+ \endinput
+}
+% \end{macrocode}
+% \end{macro}
+
+
+% \begin{macro}{\pkgcls@show@selection}
+% This command records what selection was made. As that is needed
+% in two places (and it is rather lengthly) it was placed in a
+% separate command. The first argument is the name of the external
+% file that is being loaded and is only needed for debugging. The
+% second argument is the date that corresponds to this file and it
+% is used as part of the message.
+% \begin{macrocode}
+\def\pkgcls@show@selection#1#2{%
+%<*tracerollback>
+ \pkgcls@debug{Result: use #1}%
+%</tracerollback>
+ \GenericInfo
+ {\@spaces\@spaces\space}{Rollback for
+ \@cls@pkg\space'\@currname' requested ->
+ \ifnum\pkgcls@targetdate>\@ne
+ date
+ \ifnum\requestedLaTeXdate=\pkgcls@targetdate
+ \requestedpatchdate
+ \else
+ \expandafter\@gobble\pkgcls@arg
+ \fi.\MessageBreak
+% \end{macrocode}
+% Instead of ``best approximation'' we could say that we have been
+% able to exactly match the date (if it is exact), but that would
+% mean extra tests without much gain, so not done.
+% \begin{macrocode}
+ Best approximation is
+ \else
+ version '\pkgcls@targetlabel'.\MessageBreak
+ This corresponds to
+ \fi
+ \ifx\@nil#2\@nil
+ a special release%
+ \else
+ the release introduced on #2%
+ \fi
+ \@gobble}%
+}
+% \end{macrocode}
+% \end{macro}
+
+
+% \begin{macro}{\pkgcls@rollbackdate@error}
+% This is called if the requested rollback date is earlier than the
+% earliest known release of a package or class.
+%
+% A similar error is given if global rollback date and min-date on
+% a specific package conflict with each other, but that case is
+% happens only once so it is is inlined.
+% \begin{macrocode}
+\def\pkgcls@rollbackdate@error#1{%
+ \@latex@error{Suspicious rollback date given}%
+ {The \@cls@pkg\space'\@currname' claims that it
+ came into existence on #1 which\MessageBreak
+ is after your requested rollback date --- so
+ something is wrong here.\MessageBreak
+ Continue and we use the earliest known release.}}
+% \end{macrocode}
+% \end{macro}
+%
+%
+%
+% \begin{macro}{\DeclareCurrentRelease}
+% This declares the date (and possible name) of the current version
+% of a package or class.
+% \begin{macrocode}
+\def\DeclareCurrentRelease#1#2{%
+% \end{macrocode}
+% First we test if |\pkgcls@targetdate| is greater than zero,
+% otherwise this code is bypassed (as there is no rollback
+% request).
+% \begin{macrocode}
+ \ifnum\pkgcls@targetdate>\z@ % some sort of rollback request
+%<*tracerollback>
+ \pkgcls@debug{---DeclareCurrentRelease}%
+ \pkgcls@debug{ 1: #1}%
+ \pkgcls@debug{ 2: #2}%
+%</tracerollback>
+% \end{macrocode}
+% If the value is greater than 1 we have to deal with a date
+% request, so we parse |#2| as a date and compare it with
+% |\pkgcls@targetdate|.
+% \begin{macrocode}
+ \ifnum\pkgcls@targetdate>\@ne % a date request
+ \ifnum\@parse@version#2//00\@nil
+ >\pkgcls@targetdate
+% \end{macrocode}
+% If it is greater that means the release date if this file is
+% later than the requested rollback date. Again we have two cases:
+% If there was a previous candidate release we use that one as the
+% current release is too young, but if there wasn't we have to use
+% this release nevertheless as there isn't any alternative.
+%
+% However this case can only happen if there is a
+% |\DeclareCurrentRelease| but no declared older releases (so
+% basically the use of the declaration is a bit dubious).
+% \begin{macrocode}
+
+ \ifx\pkgcls@candidate\@empty
+ \pkgcls@rollbackdate@error{#2}%
+ \else
+ \pkgcls@use@this@release\pkgcls@candidate
+ \pkgcls@releasedate
+ \fi
+% \end{macrocode}
+% Otherwise the curent file is the right release, so we record that
+% in the transcript and then carry on.
+% \begin{macrocode}
+ \else
+ \pkgcls@show@selection{current version}{#2}%
+ \fi
+ \else % a label request
+% \end{macrocode}
+% Otherwise we have a rollback request to a named version so we
+% check if that fits the current name and if not give an error as
+% this was the last possible opportunity.
+% \begin{macrocode}
+ \def\reserved@a{#1}%
+ \ifx\pkgcls@targetlabel\reserved@a
+ \pkgcls@show@selection{current version}{#2}%
+ \else
+ \@latex@error{Requested version '\pkgcls@targetlabel' for
+ \@cls@pkg\space'\@currname' is unknown}\@ehc
+ \fi
+ \fi
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+
+% \begin{macro}{\IfTargetDateBefore}
+% This enables a simple form of conditional code inside a class or
+% package file. If there is a date request and the request date is
+% earlier than the first argument the code in the second argument
+% is processed otherwise the code in the third argument is
+% processed. If there was no date request then we also execute the
+% third argument, i.e., we will get the ``latest'' version of the
+% file.
+%
+% Most often the second argument (before-date-code) will be empty.
+% \begin{macrocode}
+\long\def\IfTargetDateBefore#1{%
+ \ifnum\pkgcls@innerdate <%
+ \expandafter\@parse@version\expandafter0#1//00\@nil
+ \typeout{Exclude code introduced on #1}%
+ \expandafter\@firstoftwo
+ \else
+ \typeout{Include code introduced on #1}%
+ \expandafter\@secondoftwo
+ \fi
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+%</2ekernel|latexreleasefirst>
+% \end{macrocode}
+%
%
% \section{After Preamble}
% Finally we declare a package that allows all the commands declared