diff options
Diffstat (limited to 'Master/texmf-dist/source/latex-dev/base/ltclass.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex-dev/base/ltclass.dtx | 2598 |
1 files changed, 2598 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex-dev/base/ltclass.dtx b/Master/texmf-dist/source/latex-dev/base/ltclass.dtx new file mode 100644 index 00000000000..b3a23310130 --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/base/ltclass.dtx @@ -0,0 +1,2598 @@ +% \iffalse meta-comment +% +% Copyright 1993-2019 +% The LaTeX3 Project and any individual authors listed elsewhere +% in this file. +% +% 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 2005/12/01 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: ltclass.dtx +% +%<*driver> +% \fi +\ProvidesFile{ltclass.dtx} + [2019/07/09 v1.3a LaTeX Kernel (Class & Package Interface)] +% \iffalse +\documentclass{ltxdoc} +\GetFileInfo{ltclass.dtx} +\begin{document} +\title{The main structure of documents} +\author{Frank Mittelbach\and Chris Rowley\and Alan Jeffrey\and + David Carlisle} +\date{\filedate} + \MaintainedByLaTeXTeam{latex} + \maketitle + \DocInput{\filename} +\end{document} +%</driver> +% \fi +% +% \iffalse +% (C) Copyright Frank Mittelbach, Chris Rowley, +% Alan Jeffrey and David Carlisle 1993-1998. +% All rights reserved. +% \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 +% |\documentstyle| in \LaTeXe\ documents. +% +% Note that old documents containing |\documentstyle| will be run using +% a compatibility option---thus keeping everyone happy, we hope! +% +% The overall idea is that there are two types of `style files': +% `class files' which define elements and provide a default formatting +% for them; and `packages' which provide extra functionality. One +% difference between \LaTeXe\ and \LaTeX2.09 is that \LaTeXe\ packages +% may have options. Note that options to classes packages may be +% implemented such that they input files, but these file names are not +% necessarily directly related to the option name. +% +% \section{User interface} +% +% |\documentclass[|\meta{main-option-list}|]{|^^A +% \meta{class}|}[|\meta{version}|]| +% +% There must be exactly one such declaration, and it must come first. +% The \meta{main-option-list} is a list of options which can modify the +% formatting of elements which are defined in the \meta{class} file +% as well as in all following |\usepackage| declarations (see below). +% The \meta{version} is a version number, beginning with a date in the +% format |YYYY/MM/DD|. If an older version of the class is found, a +% warning is issued. +% +% \bigskip +% +% |\documentstyle[|\meta{main-option-list}|]{|^^A +% \meta{class}|}[|\meta{version}|]| +% +% The |\documentstyle| declaration is kept in order to maintain upward +% compatibility with \LaTeX2.09 documents. It is similar to +% |\documentclass|, but it causes all options in +% \meta{main-option-list} that the \meta{class} does not use to be +% passed to |\RequirePackage| after the options have been processed. +% This maintains compatibility with the 2.09 behaviour. Also a flag is +% set to indicate that the document is to be processed in \LaTeX2.09 +% compatibility mode. As far as most packages are concerned, this +% only affects the warnings and errors \LaTeX\ generates. This flag +% does affect the definition of font commands, and |\sloppy|. +% +% \bigskip +% +% |\usepackage[|\meta{package-option-list}|]{|^^A +% \meta{package-list}|}[|\meta{version}|]| +% +% There can be any number of these declarations. All packages in +% \meta{package-list} are called with the same options. +% +% Each \meta{package} file defines new elements (or modifies those +% defined in the \meta{class}), and thus extends the range of documents +% which can be processed. +% The \meta{package-option-list} is a list of options which can modify +% the formatting of elements defined in the \meta{package} file. +% The \meta{version} is a version number, beginning with a date in the +% format |YYYY/MM/DD|. If an older version of the package is found, a +% warning is issued. +% +% Each package is loaded only once. If the same package is requested +% more than once, nothing happens, unless the package has been requested +% with options that were not given the first time it was loaded, in +% which case an error is produced. +% +% As well as processing the options given in the +% \meta{package-option-list}, each package processes the +% \meta{main-option-list}. This means that options that affect all +% of the packages can be given globally, rather than repeated for every +% package. +% +% Note that class files have the extension |.cls|, packages have the +% extension |.sty|. +% +% \DescribeEnv{filecontents} +% The environment |filecontents| is intended for passing the contents +% of packages, options, or other files along with a document in a +% single file. +% It has one argument, which is the name of the file to create. If that +% file already exists (maybe only in the current directory if the OS +% supports a notion of a `current directory' or `default directory') +% then nothing happens +% (except for an information message) and the body of the environment +% is bypassed. Otherwise, the body of the environment is written +% verbatim to the file name given as the first argument, together with +% some comments about how it was produced. +% +% The environment is allowed only before |\documentclass| to ensure +% that all packages or options necessary for this particular run are +% present when needed. The begin and end tags should each be on a +% line by itself. There is also a star-form; this does not write +% extra comments into the file. +% +% \subsection{Option processing} +% +% When the options are processed, they are divided into two types: {\em +% local\/} and {\em global}: +% \begin{itemize} +% +% \item For a class, the options in the |\documentclass| command are +% local. +% +% \item For a package, the options in the |\usepackage| command are +% local, and the options in the |\documentclass| command are global. +% +% \end{itemize} +% The options for |\documentclass| and |\usepackage| +% are processed in the following way: +% \begin{enumerate} +% +% \item The local and global options that have been declared +% (using |\DeclareOption| as described below) are processed +% first. +% +% In the case of |\ProcessOptions|, they are processed in the order +% that they were declared in the class or package. +% +% In the case of |\ProcessOptions*|, they are processed in the order +% that they appear in the option-lists. First the global options, and +% then the local ones. +% +% \item Any remaining local options are dealt with using the default +% option (declared using the |\DeclareOption*| declaration described +% below). For document classes, this usually does nothing, but +% records the option on a list of unused options. +% For packages, this usually produces an error. +% +% \end{enumerate} +% Finally, when |\begin{document}| is reached, if there are any global +% options which have not been used by either the class or any package, +% the system will produce a warning. +% +% +% \section{Class and Package interface} +% +% \subsection{Class name and version} +% +% \DescribeMacro\ProvidesClass +% A class can identify itself with the +% |\ProvidesClass{|\meta{name}|}[|\meta{version}|]| command. The +% \meta{version} should begin with a date in the format |YYYY/MM/DD|. +% +% \subsection{Package name and version} +% +% \DescribeMacro\ProvidesPackage +% A package can identify itself with the +% |\ProvidesPackage|\marg{name}\oarg{version} command. The +% \meta{version} should begin with a date in the format |YYYY/MM/DD|. +% +% \subsection{Requiring other packages} +% +% \DescribeMacro\RequirePackage +% Packages or classes can load other packages using\\ +% |\RequirePackage|\oarg{options}\marg{name}\oarg{version}.\\ +% If the package has already been loaded, then nothing happens unless +% the requested options are not a subset of the options with which it +% was loaded, in which case an error is called. +% +% \DescribeMacro\LoadClass +% Similar to |\RequirePackage|, but for classes, may not be used in +% package files. +% +% \DescribeMacro\PassOptionsToPackage +% Packages can pass options to other packages using:\\ +% |\PassOptionsToPackage{|\meta{options}|}{|\meta{package}|}|.\\ +% \DescribeMacro\PassOptionsToClass +% This adds the \meta{options} to the options list of any future +% |\RequirePackage| or |\usepackage| command. For example: +% \begin{verbatim} +% \PassOptionsToPackage{foo,bar}{fred} +% \RequirePackage[baz]{fred}\end{verbatim} +% is the same as: +% \begin{verbatim} +% \RequirePackage[foo,bar,baz]{fred}\end{verbatim} +% +% \DescribeMacro\LoadClassWithOptions +% |\LoadClassWithOptions|\marg{name}\oarg{version}:\\ +% This is similar to +% |\LoadClass|, but it always calls class \meta{name} with +% exactly the same option list that is being used by the current class, +% rather than an option explicitly supplied or passed on by +% |\PassOptionsToClass|. +% \DescribeMacro\RequirePackageWithOptions +% |\RequirePackageWithOptions| is the analogous command for packages. +% +% This is mainly intended to allow one class to simply build on another, +% for example: +%\begin{verbatim} +% \LoadClassWithOptions{article} +%\end{verbatim} +% +% This should be contrasted with the slightly different construction +%\begin{verbatim} +% \DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}} +% \ProcessOptions +% \LoadClass{article} +%\end{verbatim} +% +% As used here, the effects are more or less the same, but the +% version using |\LoadClassWithOptions| is slightly quicker +% (and less to type). +% If, however, the class declares options of its own then +% the two constructions are different; compare, for example: +%\begin{verbatim} +% \DeclareOption{landscape}{...} +% \ProcessOptions +% \LoadClassWithOptions{article} +%\end{verbatim} +% with: +%\begin{verbatim} +% \DeclareOption{landscape}{...} +% \DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}} +% \ProcessOptions +% \LoadClass{article} +%\end{verbatim} +% In the first case, the \textsf{article} class will be called with +% option |landscape| precisely when the current class is called with +% this option; but in the second example it will +% not as in that case \textsf{article} is only passed options by the +% default option handler, which is not used for |landscape| as that +% option is explicitly declared. +% +% \DescribeMacro\@ifpackageloaded +% To find out if a package has already been loaded, use\\ +% \DescribeMacro\@ifclassloaded +% |\@ifpackageloaded{|\meta{package}|}{|\meta{true}|}{|\meta{false}|}|. +% +% \DescribeMacro\@ifpackagelater +% \changes{v1.1i}{2013/07/07}{Correctly describe how the date in +% \cs{@ifpackagelater} is used} +% To find out if a package has already been loaded with a version +% equal to or more +% recent than \meta{version}, use\\ +% \DescribeMacro\@ifclasslater +% |\@ifpackagelater{|\meta{package}|}{|\meta{version}|}{|^^A +% \meta{true}|}{|\meta{false}|}|. +% +% \DescribeMacro\@ifpackagewith +% To find out if a package has already been loaded with at least the +% options \meta{options}, use +% \DescribeMacro\@ifclasswith +% |\@ifpackagewith{|\meta{package}|}{|\meta{options}|}{|^^A +% \meta{true}|}{|\meta{false}|}|. +% +% There exists one package that can't be tested with the above +% commands: the \texttt{fontenc} package pretends that it was never +% loaded to allow for repeated reloading with different options (see +% \texttt{ltoutenc.dtx} for details). +% +% +% \subsection{Declaring new options} +% +% Options for classes and packages are built using the same macros. +% +% \DescribeMacro\DeclareOption To define a builtin option, use +% |\DeclareOption{|\meta{name}|}{|\meta{code}|}|. +% +% \DescribeMacro{\DeclareOption*} To define the default action to +% perform for local options which have not been declared, use +% |\DeclareOption*{|\meta{code}|}|. +% +% {\em Note\/}: there should be no use of\\ +% |\RequirePackage|, |\DeclareOption|, |\DeclareOption*| or +% |\ProcessOptions|\\ +% inside |\DeclareOption| or |\DeclareOption*|. +% +% Possible uses for |\DeclareOption*| include: +% +% |\DeclareOption*{}|\\ +% Do nothing. Silently accept unknown options. (This suppresses the +% usual warnings.) +% +% |\DeclareOption*{\@unkownoptionerror}|\\ +% Complain about unknown local options. (The initial setting for +% package files.) +% +% |\DeclareOption*{\PassOptionsToPackage{\CurrentOption}|^^A +% |{|\meta{pkg-name}|}|\\ +% Handle the the current option by passing it on to the package +% \meta{pkg-name}, which will presumably be loaded via +% |\RequirePackage| later in the file. This is useful for building +% `extension' packages, that perhaps handle a couple of new options, +% but then pass everything else on to an existing package. +% +% |\DeclareOption*{\InputIfFileExists{xx-\CurrentOption.yyy}%|\\ +% | {}%|\\ +% | {\OptionNotUsed}}|\\ +% Handle the option foo by loading the file |xx-foo.yyy| if it +% exists, otherwise do nothing, but declare that the option was not +% used. +% Actually the |\OptionNotUsed| declaration is only needed if this is +% being used in class files, but does no harm in package files. +% +% +% \subsection{Safe Input Macros} +% \DescribeMacro{\InputIfFileExists} +% |\InputIfFileExists{|\meta{file}|}{|\meta{then}|}{|\meta{else}|}|\\ +% Inputs \meta{file} if it exists. Immediately before the input, +% \meta{then} is executed. Otherwise \meta{else} is executed. +% +% \DescribeMacro{\IfFileExists} +% As above, but does not input the file. +% +% One thing you might like to put in the \meta{else} clause is +% +% \DescribeMacro{\@missingfileerror} +% This starts an interactive request for a filename, supplying default +% extensions. Just hitting return causes the whole input to be skipped +% and entering |x| quits the current run, +% +% \DescribeMacro{\input} +% This has been redefined from the \LaTeX2.09 definition, in terms of +% the new commands |\InputIfFileExists| and |\@missingfileerror|. +% +% +% \DescribeMacro{\listfiles} Giving this declaration in the preamble +% causes a list of all files input via the `safe input' commands to be +% listed at the end. Any strings specified in the optional argument to +% |\ProvidesPackage| are listed alongside the file name. So files in +% standard (and other non-standard) distributions can put informative +% strings in this argument. +% +% \StopEventually{} +% +% \section{Implementation} +% +% \begin{macrocode} +%<*2ekernel> +% \end{macrocode} +% +% +% \changes{v0.2g}{1993/11/23} +% {Various macros now moved to latex.tex.} +% \changes{v0.2g}{1993/11/23} +% {Warnings and errors now directly coded.} +% \changes{v0.2h}{1993/11/28} +% {Primitive filenames now terminated by space not \cs{relax}.} +% \changes{v0.2h}{1993/11/28} +% {Directory syntax checing moved to dircheck.dtx} +% \changes{v0.2h}{1993/11/28} +% {Assorted commands now in the kernel removed.} +% \changes{v0.2i}{1993/12/03} +% {\cs{@onlypreamble}: Many commands declared.} +% \changes{v0.2i}{1993/12/03} +% {Removed obsolete \cs{@documentclass}} +% \changes{v0.2o}{1993/12/13} +% {Removed setting \cs{errorcontextlines}\ (now in latex.tex)} +% \changes{v0.2p}{1993/12/15} +% {Removed extra `.'s from \cs{@@warning}s} +% \changes{v0.2s}{1994/01/17} +% {Added many more \cs{@onlypreamble} commands} +% \changes{v0.2s}{1994/01/17} +% {Wrapped long lines to column 72} +% \changes{v0.3a}{1994/03/02} +% {Remove need for driver file} +% \changes{v0.3b}{1994/03/08} +% {Modify driver code into `new style'} +% \changes{v0.3c}{1994/03/12} +% {Change name from docclass to ltclass} +% \changes{v0.3h}{1994/04/25} +% {Removed spurious extra `.'s at the end of error messages} +% \changes{v1.0a}{1994/04/29} +% {Change version number to 1 (no other change)} +% \changes{v1.0k}{1994/11/03} +% {Move \cs{@missingfileerror} to ltfiles} +% +% \begin{macro}{\if@compatibility} +% The flag for compatibility mode. +% \begin{macrocode} +\newif\if@compatibility +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@documentclasshook} +% The hook called after the first |\documentclass| command. By +% default this checks to see if |\@normalsize| is undefined, and if +% so, sets it to |\normalsize|. +% \changes{v0.2q}{1993/12/17} +% {Macro added} +% \changes{v0.2z}{1994/02/10} +% {Changed the name from \cs{@compatibility} to +% \cs{@documentclasshook}, and added the check for whether +% \cs{@normalsize} has been defined. ASAJ.} +% \begin{macrocode} +\def\@documentclasshook{% + \ifx\@normalsize\@undefined + \let\@normalsize\normalsize + \fi +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@declaredoptions} +% This list is automatically built by |\DeclareOption|. +% It is the list of options (separated by commas) declared in +% the class or package file and it defines the order in which the +% the corresponding |\ds@|\meta{option} commands are executed. +% All local \meta{option}s which are not declared will be processed +% in the order defined by the optional argument of |\documentclass| +% or |\usepackage|. +% \begin{macrocode} +\let\@declaredoptions\@empty +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@classoptionslist} +% List of options of the main class. +% \changes{v1.0u}{1996/07/26}{made only preamble} +% \begin{macrocode} +\let\@classoptionslist\relax +\@onlypreamble\@classoptionslist +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@unusedoptionlist} +% \changes{v1.0u}{1996/07/26}{made only preamble} +% List of options of the main class that haven't been declared or +% loaded as class option files. +% \begin{macrocode} +\let\@unusedoptionlist\@empty +\@onlypreamble\@unusedoptionlist +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\CurrentOption} +% Name of current package or option. +% \changes{v0.2c}{1993/11/17} +% {Name changed from \cs{@curroption}} +% \begin{macrocode} +\let\CurrentOption\@empty +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@currname} +% Name of current package or option. +% \begin{macrocode} +\let\@currname\@empty +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@currext} +% The current file extension. +% \changes{v0.2a}{1993/11/14}{Name changed from \cs{@currextension}} +% \begin{macrocode} +\global\let\@currext=\@empty +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@clsextension} +% \begin{macro}{\@pkgextension} +% The two possible values of |\@currext|. +% \begin{macrocode} +\def\@clsextension{cls} +\def\@pkgextension{sty} +\@onlypreamble\@clsextension +\@onlypreamble\@pkgextension +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@pushfilename} +% \begin{macro}{\@popfilename} +% \begin{macro}{\@currnamestack} +% Commands to push and pop the file name and extension. \\ +% |#1| current name. \\ +% |#2| current extension. \\ +% |#3| current catcode of |@|. \\ +% |#4| Rest of the stack. +% \begin{macrocode} +\def\@pushfilename{% + \xdef\@currnamestack{% + {\@currname}% + {\@currext}% + {\the\catcode`\@}% + \@currnamestack}} +\@onlypreamble\@pushfilename +% \end{macrocode} +% +% \begin{macrocode} +\def\@popfilename{\expandafter\@p@pfilename\@currnamestack\@nil} +\@onlypreamble\@popfilename +% \end{macrocode} +% +% \begin{macrocode} +\def\@p@pfilename#1#2#3#4\@nil{% + \gdef\@currname{#1}% + \gdef\@currext{#2}% + \catcode`\@#3\relax + \gdef\@currnamestack{#4}} +\@onlypreamble\@p@pfilename +% \end{macrocode} +% +% \begin{macrocode} +\gdef\@currnamestack{} +\@onlypreamble\@currnamestack +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@ptionlist} +% Returns the option list of the file. +% \begin{macrocode} +\def\@ptionlist#1{% + \@ifundefined{opt@#1}\@empty{\csname opt@#1\endcsname}} +\@onlypreamble\@ptionlist +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@ifpackageloaded} +% \begin{macro}{\@ifclassloaded} +% |\@ifpackageloaded{|\meta{name}|}| +% Checks to see whether a file has been loaded. +% \changes{v0.2t}{1994/01/18} +% {Fix typo \cs{@pkgetension}} +% \begin{macrocode} +\def\@ifpackageloaded{\@ifl@aded\@pkgextension} +\def\@ifclassloaded{\@ifl@aded\@clsextension} +\@onlypreamble\@ifpackageloaded +\@onlypreamble\@ifclassloaded +% \end{macrocode} +% +% \begin{macrocode} +\def\@ifl@aded#1#2{% + \expandafter\ifx\csname ver@#2.#1\endcsname\relax + \expandafter\@secondoftwo + \else + \expandafter\@firstoftwo + \fi} +\@onlypreamble\@ifl@aded +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@ifpackagelater} +% \begin{macro}{\@ifclasslater} +% |\@ifpackagelater{|\meta{name}|}{YYYY/MM/DD}| +% Checks that the package loaded is more recent than the given date. +% \begin{macrocode} +\def\@ifpackagelater{\@ifl@ter\@pkgextension} +\def\@ifclasslater{\@ifl@ter\@clsextension} +\@onlypreamble\@ifpackagelater +\@onlypreamble\@ifclasslater +% \end{macrocode} +% +% \begin{macrocode} +\def\@ifl@ter#1#2{% + \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.} +% \changes{v1.2g}{2018/04/08} +% {Strip leading spaces from dates.} +% \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 + \expandafter\@secondoftwo + \else + \expandafter\@firstoftwo + \fi} +\def\@parse@version@#1{\@parse@version0#1} +%</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>\let\@parse@version@\@undefined +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% \begin{macrocode} +\@onlypreamble\@ifl@t@r +% \end{macrocode} +% +% \changes{v1.1j}{2016/06/20} +% {don't declare as \cs{@onlypreamble}} +% \changes{v1.2c}{2017/03/08} +% {add \cs{@parse@version@dash} to support yyyy-mm-dd as well as yyyy/mm/dd } +% \begin{macrocode} +%</2ekernel> +%<*2ekernel|latexreleasefirst> +\def\@parse@version#1/#2/#3#4#5\@nil{% +\@parse@version@dash#1-#2-#3#4\@nil +} +% \end{macrocode} +% +% The |\if| test here ensures that an argument with no |/| or |-| produces 0 (actually 00). +% \begin{macrocode} +\def\@parse@version@dash#1-#2-#3#4#5\@nil{% + \if\relax#2\relax\else#1\fi#2#3#4 } +%</2ekernel|latexreleasefirst> +%<*2ekernel> +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@ifpackagewith} +% \begin{macro}{\@ifclasswith} +% |\@ifpackagewith{|\meta{name}|}{|\meta{option-list}|}| +% Checks that \meta{option-list} is a subset of the options +% \textbf{with} which \meta{name} was loaded. +% \begin{macrocode} +\def\@ifpackagewith{\@if@ptions\@pkgextension} +\def\@ifclasswith{\@if@ptions\@clsextension} +\@onlypreamble\@ifpackagewith +\@onlypreamble\@ifclasswith +% \end{macrocode} +% +% \begin{macrocode} +\def\@if@ptions#1#2{% + \@expandtwoargs\@if@pti@ns{\@ptionlist{#2.#1}}} +\@onlypreamble\@if@ptions +% \end{macrocode} +% +% Probably shouldn't use |\CurrentOption| here\ldots (changed to +% |\reserved@b|.) +% \changes{v0.2y}{1994/02/07} +% {Add extra ,s so `two' is not matched with `twocolumn'} +% \changes{v1.1i}{2011/08/19} +% {Re-jig definition after more stringent \cs{in@} test.} +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2017/01/01}% +%<latexrelease> {\@if@pti@ns}{Spaces in option clash check}% +%<*2ekernel|latexrelease> +\def\@if@pti@ns#1#2{% + \let\reserved@a\@firstoftwo +% \end{macrocode} +% \changes{v1.2a}{2016/10/02} +% {Ignore spaces while checking for option clash} +% \begin{macrocode} + \edef\reserved@b{\zap@space#2 \@empty}% + \@for\reserved@b:=\reserved@b\do{% + \ifx\reserved@b\@empty + \else + \expandafter\in@\expandafter{\expandafter,\reserved@b,}{,#1,}% + \ifin@ + \else + \let\reserved@a\@secondoftwo + \fi + \fi + }% + \reserved@a} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@if@pti@ns}{Spaces in option clash check}% +%<latexrelease>\def\@if@pti@ns#1#2{% +%<latexrelease> \let\reserved@a\@firstoftwo +%<latexrelease> \@for\reserved@b:=#2\do{% +%<latexrelease> \ifx\reserved@b\@empty +%<latexrelease> \else +%<latexrelease> \expandafter\in@\expandafter +%<latexrelease> {\expandafter,\reserved@b,}{,#1,}% +%<latexrelease> \ifin@ +%<latexrelease> \else +%<latexrelease> \let\reserved@a\@secondoftwo +%<latexrelease> \fi +%<latexrelease> \fi +%<latexrelease> }% +%<latexrelease> \reserved@a} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% \begin{macrocode} +\@onlypreamble\@if@pti@ns +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\ProvidesPackage} +% Checks that the current filename is correct, and defines +% |\ver@filename|. +% \changes{v0.3c}{1994/03/12} +% {Add \cs{wlog}} +% \changes{v0.3c}{1994/03/12} +% {use \cs{@gtempa}} +% \begin{macrocode} +\def\ProvidesPackage#1{% + \xdef\@gtempa{#1}% + \ifx\@gtempa\@currname\else + \@latex@warning@no@line{You have requested + \@cls@pkg\space`\@currname',\MessageBreak + but the \@cls@pkg\space provides `#1'}% + \fi + \@ifnextchar[\@pr@videpackage{\@pr@videpackage[]}}%] +\@onlypreamble\ProvidesPackage +% \end{macrocode} +% +% \begin{macrocode} +\def\@pr@videpackage[#1]{% + \expandafter\xdef\csname ver@\@currname.\@currext\endcsname{#1}% + \ifx\@currext\@clsextension + \typeout{Document Class: \@gtempa\space#1}% + \else + \wlog{Package: \@gtempa\space#1}% + \fi} +\@onlypreamble\@pr@videpackage +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ProvidesClass} +% Like |\ProvidesPackage|, but for classes. +% \begin{macrocode} +\let\ProvidesClass\ProvidesPackage +\@onlypreamble\ProvidesClass +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ProvidesFile} +% Like |\ProvidesPackage|, but for arbitrary files. Do not apply +% |\@onlypreamble| to these, as we may want to label files input +% during the document. +% \changes{v0.2l}{1993/12/07} +% {Macro added} +% \changes{v0.3c}{1994/03/12} +% {Add \cs{wlog}} +% \changes{v0.3g}{1994/04/11} +% {Protect against weird catcodes.} +% \begin{macro}{\@providesfile} +% \changes{v1.0r}{1995/10/17} +% {Delay definition of \cs{ProvidesFile} till ltfinal} +% \changes{v1.1a}{1998/03/21} +% {Allow \&. Internal/2702} +% \changes{v1.1d}{2001/05/25}{Explicitly set catcode of +% \cs{endlinechar} to 10 (pr/3334)} +% \changes{v1.1e}{2001/06/04}{But only if it is a char (pr/3334)} +% \changes{v1.1f}{2001/08/26}{Readded setting of space char (pr/3353)} +% \begin{macrocode} +\def\ProvidesFile#1{% + \begingroup + \catcode`\ 10 % + \ifnum \endlinechar<256 % + \ifnum \endlinechar>\m@ne + \catcode\endlinechar 10 % + \fi + \fi + \@makeother\/% + \@makeother\&% +% \end{macrocode} +% \changes{v1.1g}{2004/01/28}{Use kernel version of +% \cs{@ifnextchar} (pr/3501)} +% \begin{macrocode} + \kernel@ifnextchar[{\@providesfile{#1}}{\@providesfile{#1}[]}} +% \end{macrocode} +% +% During initex a special version of |\@providesfile| is used. +% The real definition is installed right at the end, in |ltfinal.dtx|. +%\begin{verbatim} +%\def\@providesfile#1[#2]{% +% \wlog{File: #1 #2}% +% \expandafter\xdef\csname ver@#1\endcsname{#2}% +% \endgroup} +%\end{verbatim} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\PassOptionsToPackage} +% \begin{macro}{\PassOptionsToClass} +% 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} +\def\@pass@ptions#1#2#3{% + \expandafter\xdef\csname opt@#3.#1\endcsname{% + \@ifundefined{opt@#3.#1}\@empty + {\csname opt@#3.#1\endcsname,}% + \zap@space#2 \@empty}} +\@onlypreamble\@pass@ptions +% \end{macrocode} +% +% \begin{macrocode} +\def\PassOptionsToPackage{\@pass@ptions\@pkgextension} +\def\PassOptionsToClass{\@pass@ptions\@clsextension} +\@onlypreamble\PassOptionsToPackage +\@onlypreamble\PassOptionsToClass +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\DeclareOption} +% \begin{macro}{\DeclareOption*} +% Adds an option as a |\ds@| command, or the default |\default@ds| +% command. +% \changes{v0.2c}{1993/11/17} +% {Error checking added} +% \changes{v1.0m}{1995/04/21} +% {Made long /1498} +% \changes{v1.0n}{1995/05/12} +% {Use \cs{toks@} to remove need to double hash /1557} +% \begin{macrocode} +\def\DeclareOption{% + \let\@fileswith@pti@ns\@badrequireerror + \@ifstar\@defdefault@ds\@declareoption} +\long\def\@declareoption#1#2{% + \xdef\@declaredoptions{\@declaredoptions,#1}% + \toks@{#2}% + \expandafter\edef\csname ds@#1\endcsname{\the\toks@}} +\long\def\@defdefault@ds#1{% + \toks@{#1}% + \edef\default@ds{\the\toks@}} +\@onlypreamble\DeclareOption +\@onlypreamble\@declareoption +\@onlypreamble\@defdefault@ds +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\OptionNotUsed} +% If we are in a class file, add |\CurrentOption| to the list of +% unused options. Otherwise, in a package file do nothing. +% \begin{macrocode} +\def\OptionNotUsed{% + \ifx\@currext\@clsextension + \xdef\@unusedoptionlist{% + \ifx\@unusedoptionlist\@empty\else\@unusedoptionlist,\fi + \CurrentOption}% + \fi} +\@onlypreamble\OptionNotUsed +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\default@ds} +% The default default option code. +% Set by |\@onefilewithoptions| to either |\OptionNotUsed| for +% classes, or |\@unknownoptionerror| for packages. This may be reset +% in either case with |\DeclareOption*|. +% \begin{macrocode} +% \let\default@ds\OptionNotUsed +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ProcessOptions} +% \begin{macro}{\ProcessOptions*} +% |\ProcessOptions| calls |\ds@option| for each known package option, +% then calls |\default@ds| for each option on the local options list. +% Finally resets all the declared options to |\relax|. The empty option +% does nothing, this has to be reset on the off chance it's set to +% |\relax| if an empty element gets into the |\@declaredoptions| list. +% +% The star form is similar but executes options given in the order +% specified in the document, not the order they are declared in the +% file. In the case of packages, global options are executed before +% local ones. +% \changes{v0.2a}{1993/11/14} +% {Stop adding the global option list inside class files.} +% \changes{v0.2a}{1993/11/14} +% {Optimise `empty option' code.} +% \changes{v0.2b}{1993/11/15} +% {Star form added.} +% \changes{v0.2c}{1993/11/17} +% {restoring \cs{@fileswith@pti@ns} added.} +% \begin{macrocode} +\def\ProcessOptions{% + \let\ds@\@empty + \edef\@curroptions{\@ptionlist{\@currname.\@currext}}% + \@ifstar\@xprocess@ptions\@process@ptions} +\@onlypreamble\ProcessOptions +% \end{macrocode} +% +% \changes{v0.2y}{1994/02/07} +% {Add extra ,s so `two' is not matched with `twocolumn'} +% \begin{macrocode} +\def\@process@ptions{% + \@for\CurrentOption:=\@declaredoptions\do{% + \ifx\CurrentOption\@empty\else + \@expandtwoargs\in@{,\CurrentOption,}{% + ,\ifx\@currext\@clsextension\else\@classoptionslist,\fi + \@curroptions,}% + \ifin@ + \@use@ption + \expandafter\let\csname ds@\CurrentOption\endcsname\@empty + \fi + \fi}% + \@process@pti@ns} +\@onlypreamble\@process@ptions +% \end{macrocode} +% +% \changes{v0.2y}{1994/02/07} +% {Add extra ,s so `two' is not matched with `twocolumn'} +% \begin{macrocode} +\def\@xprocess@ptions{% + \ifx\@currext\@clsextension\else + \@for\CurrentOption:=\@classoptionslist\do{% + \ifx\CurrentOption\@empty\else + \@expandtwoargs\in@{,\CurrentOption,}{,\@declaredoptions,}% + \ifin@ + \@use@ption + \expandafter\let\csname ds@\CurrentOption\endcsname\@empty + \fi + \fi}% + \fi + \@process@pti@ns} +\@onlypreamble\@xprocess@ptions +% \end{macrocode} +% +% The common part of |\ProcessOptions| and |\ProcessOptions*|. +% \begin{macrocode} +\def\@process@pti@ns{% + \@for\CurrentOption:=\@curroptions\do{% + \@ifundefined{ds@\CurrentOption}% + {\@use@ption + \default@ds}% +% \end{macrocode} +% There should not be any non-empty definition of |\CurrentOption| at +% this point, as all the declared options were executed earlier. This is +% for compatibility with 2.09 styles which use |\def\ds@|\ldots\ +% directly, and so have options which do not appear in +% |\@declaredoptions|. +% \begin{macrocode} + \@use@ption}% +% \end{macrocode} +% Clear all the definitions for option code. First set all the declared +% options to |\relax|, then reset the `default' and `empty' options. and +% the lst of declared options. +% \begin{macrocode} + \@for\CurrentOption:=\@declaredoptions\do{% + \expandafter\let\csname ds@\CurrentOption\endcsname\relax}% +% \end{macrocode} +% \changes{v1.0r}{1995/10/17} +% {Reset \cs{CurrentOption} for graphics/1873} +% \begin{macrocode} + \let\CurrentOption\@empty + \let\@fileswith@pti@ns\@@fileswith@pti@ns + \AtEndOfPackage{\let\@unprocessedoptions\relax}} +\@onlypreamble\@process@pti@ns +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@options} +% |\@options| is a synonym for |\ProcessOptions*| for upward +% compatibility with \LaTeX2.09 style files. +% \begin{macrocode} +\def\@options{\ProcessOptions*} +\@onlypreamble\@options +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@use@ption} +% Execute the code for the current option. +% \changes{v0.2g}{1993/11/23} +% {Name changed from \cs{@executeoption}} +% \changes{v1.0e}{1994/05/17} +% {Execute option after removing from list, not before} +% \begin{macrocode} +\def\@use@ption{% + \@expandtwoargs\@removeelement\CurrentOption + \@unusedoptionlist\@unusedoptionlist + \csname ds@\CurrentOption\endcsname} +\@onlypreamble\@use@ption +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ExecuteOptions} +% |\ExecuteOptions{|\meta{option-list}|}| executes the code declared +% for each option. +% \changes{v0.2d}{1993/11/18} +% {Use \cs{CurrentOption} not \cs{reserved@a}} +% \changes{v0.2k}{1993/12/06} +% {Preserve \cs{CurrentOption}.} +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2017/01/01}% +%<latexrelease> {\ExecuteOptions}{Spaces in \ExecuteOptions}% +%<*2ekernel|latexrelease> +\def\ExecuteOptions#1{% +% \end{macrocode} +% \changes{v1.2a}{2016/10/02} +% {Ignore spaces in argument} +% Use |\@fortmp| here as it is anyway cleared during |\@for| loop +% so does not change any existing names. +% \begin{macrocode} + \edef\@fortmp{\zap@space#1 \@empty}% + \def\reserved@a##1\@nil{% + \@for\CurrentOption:=\@fortmp\do + {\csname ds@\CurrentOption\endcsname}% + \edef\CurrentOption{##1}}% + \expandafter\reserved@a\CurrentOption\@nil} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\ExecuteOptions}{Spaces in \ExecuteOptions}% +%<latexrelease>\def\ExecuteOptions#1{% +%<latexrelease> \def\reserved@a##1\@nil{% +%<latexrelease> \@for\CurrentOption:=#1\do +%<latexrelease> {\csname ds@\CurrentOption\endcsname}% +%<latexrelease> \edef\CurrentOption{##1}}% +%<latexrelease> \expandafter\reserved@a\CurrentOption\@nil} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% \begin{macrocode} +\@onlypreamble\ExecuteOptions +% \end{macrocode} +% \end{macro} +% +% The top-level commands, which just set some parameters then call +% the internal command, |\@fileswithoptions|. +% \begin{macro}{\documentclass} +% \changes{v1.0q}{1995/06/19} +% {Dont redefine \cs{usepackage} in compat mode for /1634} +% The main new-style class declaration. +% \begin{macrocode} +\def\documentclass{% + \let\documentclass\@twoclasseserror + \if@compatibility\else\let\usepackage\RequirePackage\fi + \@fileswithoptions\@clsextension} +\@onlypreamble\documentclass +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\documentstyle} +% 2.09 style class `style' declaration. +% \changes{v0.2a}{1993/11/14} +% {Added \cs{RequirePackage} \cs{@unusedoptionlist} stuff.} +% \changes{v0.2b}{1993/11/15} +% {Modified to match \cs{ProcessOption*}} +% \changes{v0.2d}{1993/11/18} +% {Modified \cs{RequirePackage} stuff.} +% \changes{v0.2n}{1993/12/09} +% {input 209 compatibility file.} +% \changes{v0.2o}{1993/12/13} +% {compatibility file now latex209.sty.} +% \changes{v0.2q}{1993/12/17} +% {Match Alan's new code.} +% \changes{v0.2u}{1994/01/21} +% {compatibility file now latex209.def.} +% \begin{macrocode} +\def\documentstyle{% + \makeatletter\input{latex209.def}\makeatother + \documentclass} +\@onlypreamble\documentstyle +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\RequirePackage} +% Load package if not already loaded. +% \begin{macrocode} +\def\RequirePackage{% + \@fileswithoptions\@pkgextension} +\@onlypreamble\RequirePackage +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\LoadClass} +% Load class. +% \begin{macrocode} +\def\LoadClass{% + \ifx\@currext\@pkgextension + \@latex@error + {\noexpand\LoadClass in package file}% + {You may only use \noexpand\LoadClass in a class file.}% + \fi + \@fileswithoptions\@clsextension} +\@onlypreamble\LoadClass +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@loadwithoptions} +% \changes{v1.0t}{1995/11/14}{macro added} +% Pass the current option list on to a class or package. +% |#1| is |\@|\emph{cls-or-pkg}|extension|, +% |#2| is |\RequirePackage| or |\LoadClass|, +% |#3| is the class or package to be loaded. +% \begin{macrocode} +\def\@loadwithoptions#1#2#3{% + \expandafter\let\csname opt@#3.#1\expandafter\endcsname + \csname opt@\@currname.\@currext\endcsname + #2{#3}} +\@onlypreamble\@loadwithoptions +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\LoadClassWithOptions} +% \changes{v1.0t}{1995/11/14}{macro added} +% Load class `|#1|' with the current option list. +% \begin{macrocode} +\def\LoadClassWithOptions{% + \@loadwithoptions\@clsextension\LoadClass} +\@onlypreamble\LoadClassWithOptions +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\RequirePackageWithOptions} +% \changes{v1.0t}{1995/11/14}{macro added} +% \changes{v1.0v}{1996/10/04}{Reset \cs{@unprocessedoptions} for /2269} +% Load package `|#1|' with the current option list. +% \begin{macrocode} +\def\RequirePackageWithOptions{% + \AtEndOfPackage{\let\@unprocessedoptions\relax}% + \@loadwithoptions\@pkgextension\RequirePackage} +\@onlypreamble\RequirePackageWithOptions +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\usepackage} +% To begin with, |\usepackage| produces an error. This is reset by +% |\documentclass|. +% \changes{v0.2o}{1993/12/13} +% {Fixed error handling} +% \changes{v1.0h}{1994/05/23}{Remove argument if possible} +% \begin{macrocode} +\def\usepackage#1#{% + \@latex@error + {\noexpand \usepackage before \string\documentclass}% + {\noexpand \usepackage may only appear in the document + preamble, i.e.,\MessageBreak + between \noexpand\documentclass and + \string\begin{document}.}% + \@gobble} +\@onlypreamble\usepackage +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\NeedsTeXFormat} +% Check that the document is running on the correct system. +% \changes{v0.2a}{1993/11/14} +% {made more robust for alternative syntax for other formats.} +% \changes{v0.2c}{1993/11/17} +% {Name changed from \cs{NeedsFormat}} +% \changes{v0.2d}{1993/11/18} +% {\cs{fmtname} \cs{fmtversion} not \cs{@}\ldots} +% \begin{macrocode} +\def\NeedsTeXFormat#1{% + \def\reserved@a{#1}% + \ifx\reserved@a\fmtname + \expandafter\@needsformat + \else + \@latex@error{This file needs format `\reserved@a'% + \MessageBreak but this is `\fmtname'}{% + The current input file will not be processed + further,\MessageBreak + because it was written for some other flavor of + TeX.\MessageBreak\@ehd}% +% \end{macrocode} +% If the file is not meant to be processed by \LaTeXe{} we stop +% inputting it, but we do not end the run. We just end inputting +% the current file. +% \changes{v1.0h}{1994/05/23} +% {Don't stop completely when format is wrong} +% \begin{macrocode} + \endinput \fi} +\@onlypreamble\NeedsTeXFormat +% \end{macrocode} +% +% \begin{macrocode} +\def\@needsformat{% + \@ifnextchar[%] + \@needsf@rmat + {}} +\@onlypreamble\@needsformat +% \end{macrocode} +% +% \changes{v1.0b}{1994/05/04} +% {Changed wording of the warning} +% \begin{macrocode} +\def\@needsf@rmat[#1]{% + \@ifl@t@r\fmtversion{#1}{}% + {\@latex@warning@no@line + {You have requested release `#1' of LaTeX,\MessageBreak + but only release `\fmtversion' is available}}} +\@onlypreamble\@needsf@rmat +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\zap@space} +% |\zap@space foo|\meta{space}|\@empty| removes all spaces from |foo| +% that are not protected by |{ }| groups. +% \begin{macrocode} +\def\zap@space#1 #2{% + #1% + \ifx#2\@empty\else\expandafter\zap@space\fi + #2} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@fileswithoptions} +% The common part of |\documentclass| and |\usepackage|. +% \begin{macrocode} +\def\@fileswithoptions#1{% + \@ifnextchar[%] + {\@fileswith@ptions#1}% + {\@fileswith@ptions#1[]}} +\@onlypreamble\@fileswithoptions +% \end{macrocode} +% +% \changes{v0.2f}{1993/11/22} +% {Made the default [] not [\cs{@unknownversion}]} +% \changes{v1.1h}{2007/08/05} +% {Prevent loss of brackets PR/3965} +% \begin{macrocode} +\def\@fileswith@ptions#1[#2]#3{% + \@ifnextchar[%] + {\@fileswith@pti@ns#1[{#2}]#3}% + {\@fileswith@pti@ns#1[{#2}]#3[]}} +\@onlypreamble\@fileswith@ptions +% \end{macrocode} +% Then we do some work. +% +% First of all, we define the global variables. +% Then we look to see if the file has already been loaded. +% If it has, we check that it was first loaded with at least the current +% options. +% If it has not, we add the current options to the package options, +% set the default version to be |0000/00/00|, and load the file if we +% can find it. +% Then we check the version number. +% +% Finally, we restore the old file name, reset the default option, +% and we set the catcode of |@|. +% +% For classes, we can immediately process the file. For other types, +% |#2| could be a comma separated list, so loop through, processing +% each one separately. +% \changes{v0.2q}{1993/12/17} +% {Add \cs{@compatibility} hook} +% \changes{v0.2s}{1994/01/17} +% {Modify to reduce parameter stack usage} +% \changes{v0.2y}{1994/02/07} +% {Run \cs{@compatibility} on the first class to start +% (not the first to finish) } +% \changes{v0.2z}{1994/02/10} +% {Renamed \cs{@compatibility} to \cs{@documentclasshook}. +% ASAJ.} +% \changes{v1.1h}{2007/08/05} +% {Prevent loss of brackets PR/3965} +% \changes{v2.1b}{2016/11/09} +% {Improve \cs{ifx} tests PR/4497} +% \begin{macrocode} +%</2ekernel> +%<latexrelease>\IncludeInRelease{2017/01/01}% +%<latexrelease> {\@fileswith@pti@ns}{ifx tests in \@fileswith@pti@ns}% +%<*2ekernel|latexrelease> +\def\@fileswith@pti@ns#1[#2]#3[#4]{% + \ifx#1\@clsextension + \ifx\@classoptionslist\relax + \xdef\@classoptionslist{\zap@space#2 \@empty}% + \def\reserved@a{% + \@onefilewithoptions#3[{#2}][{#4}]#1% + \@documentclasshook}% + \else + \def\reserved@a{% + \@onefilewithoptions#3[{#2}][{#4}]#1}% + \fi + \else +% \end{macrocode} +% build up a list of calls to |\@onefilewithoptions| +% (one for each package) without thrashing the parameter stack. +% \begin{macrocode} + \def\reserved@b##1,{% +% \end{macrocode} +% If |#1| is |\@nnil| we have reached the end of the list +% (older version used |\@nil| here but |\@nil| is undefined so |\ifx| +% equal to all undefined commands) +% \begin{macrocode} + \ifx\@nnil##1\relax\else +% \end{macrocode} +% If |\ifx\@nnil##1\n@nil| is true then |#1| is (presumably) empty +% (Older code used |\relax| which is slighly easier to get into |#1| +% by mistake, which would spoil this test.) +% \begin{macrocode} + \ifx\@nnil##1\@nnil\else +% \end{macrocode} +% +% \begin{macrocode} + \noexpand\@onefilewithoptions##1[{#2}][{#4}]% + \noexpand\@pkgextension + \fi + \expandafter\reserved@b + \fi}% + \edef\reserved@a{\zap@space#3 \@empty}% + \edef\reserved@a{\expandafter\reserved@b\reserved@a,\@nnil,}% + \fi + \reserved@a} +%</2ekernel|latexrelease> +% \end{macrocode} +% +% \begin{macrocode} +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\@fileswith@pti@ns}{ifx tests in \@fileswith@pti@ns}% +%<latexrelease>\def\@fileswith@pti@ns#1[#2]#3[#4]{% +%<latexrelease> \ifx#1\@clsextension +%<latexrelease> \ifx\@classoptionslist\relax +%<latexrelease> \xdef\@classoptionslist{\zap@space#2 \@empty}% +%<latexrelease> \def\reserved@a{% +%<latexrelease> \@onefilewithoptions#3[{#2}][{#4}]#1% +%<latexrelease> \@documentclasshook}% +%<latexrelease> \else +%<latexrelease> \def\reserved@a{% +%<latexrelease> \@onefilewithoptions#3[{#2}][{#4}]#1}% +%<latexrelease> \fi +%<latexrelease> \else +%<latexrelease> \def\reserved@b##1,{% +%<latexrelease> \ifx\@nil##1\relax\else +%<latexrelease> \ifx\relax##1\relax\else +%<latexrelease> \noexpand\@onefilewithoptions##1[{#2}][{#4}]% +%<latexrelease> \noexpand\@pkgextension +%<latexrelease> \fi +%<latexrelease> \expandafter\reserved@b +%<latexrelease> \fi}% +%<latexrelease> \edef\reserved@a{\zap@space#3 \@empty}% +%<latexrelease> \edef\reserved@a{% +%<latexrelease> \expandafter\reserved@b\reserved@a,\@nil,}% +%<latexrelease> \fi +%<latexrelease> \reserved@a} +%<latexrelease>\EndIncludeInRelease +%<*2ekernel> +% \end{macrocode} +% +% \begin{macrocode} +\@onlypreamble\@fileswith@pti@ns +% \end{macrocode} +% +% Have the main argument as |#1|, so we only need one |\expandafter| +% above. +% \changes{v0.2a}{1993/11/14} +% {Moved resetting of \cs{default@ds}, \cs{ds@} and +% \cs{@declaredoptions} here, from the end of +% \cs{ProcessOptions}.} +% \changes{v0.2f}{1993/11/22} +% {Made the initial version [] not [\cs{@unknownversion}]} +% \changes{v0.2m}{1993/12/07} +% {Reset \cs{CurrentOption}} +% \begin{macrocode} +\def\@onefilewithoptions#1[#2][#3]#4{% + \@pushfilename + \xdef\@currname{#1}% + \global\let\@currext#4% + \expandafter\let\csname\@currname.\@currext-h@@k\endcsname\@empty + \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 + \InputIfFileExists + {\@currname.\@currext}% + {}% + {\@missingfileerror\@currname\@currext}% +% \end{macrocode} +% |\@unprocessedoptions| will 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 + \csname\@currname.\@currext-h@@k\endcsname + \expandafter\let\csname\@currname.\@currext-h@@k\endcsname + \@undefined + \@unprocessedoptions}% +% \end{macrocode} +% +% \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}}% +% \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}% + \reserved@a} +\@onlypreamble\@onefilewithoptions +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@fileswith@pti@ns} +% Save the definition (for error checking). +% \changes{v0.2c}{1993/11/17} +% {Macro added} +% \begin{macrocode} +\let\@@fileswith@pti@ns\@fileswith@pti@ns +\@onlypreamble\@@fileswith@pti@ns +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@reset@ptions} +% Reset the default option, and clear lists of declared options. +% \changes{v0.2a}{1993/11/14}{macro added} +% \begin{macrocode} +\def\@reset@ptions{% + \global\ifx\@currext\@clsextension + \let\default@ds\OptionNotUsed + \else + \let\default@ds\@unknownoptionerror + \fi + \global\let\ds@\@empty + \global\let\@declaredoptions\@empty} +\@onlypreamble\@reset@ptions +% \end{macrocode} +% \end{macro} +% +% \subsection{Hooks} +% +% Allow code do 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 +% contents in the case of required packages, so just generate a new +% macro for each package. +% \begin{macro}{\@begindocumenthook} +% \changes{v1.0s}{1995/10/20} +% {Make setting conditional, for autoload version} +% \begin{macro}{\@enddocumenthook} +% Stuff to appear at the beginning or end of the document. +% \begin{macrocode} +\ifx\@begindocumenthook\@undefined + \let\@begindocumenthook\@empty +\fi +\let\@enddocumenthook\@empty +% \end{macrocode} +% \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} +% \begin{macro}{\AtBeginDocument} +% \begin{macro}{\AtEndDocument} +% The access functions. +% \changes{v0.2a}{1993/11/14} +% {Included extension in the generated macro name for package +% and class hooks.} +% \begin{macrocode} +\def\AtEndOfPackage{% + \expandafter\g@addto@macro\csname\@currname.\@currext-h@@k\endcsname} +\let\AtEndOfClass\AtEndOfPackage +\@onlypreamble\AtEndOfPackage +\@onlypreamble\AtEndOfClass +% \end{macrocode} +% +% \begin{macrocode} +\def\AtBeginDocument{\g@addto@macro\@begindocumenthook} +\def\AtEndDocument{\g@addto@macro\@enddocumenthook} +\@onlypreamble\AtBeginDocument +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\@cls@pkg} +% The current file type. +% \changes{v0.2i}{1993/12/03} +% {Name changed to avoid clash with output routine.} +% \begin{macrocode} +\def\@cls@pkg{% + \ifx\@currext\@clsextension + document class% + \else + package% + \fi} +\@onlypreamble\@cls@pkg +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@unknownoptionerror} +% Bad option. +% \begin{macrocode} +\def\@unknownoptionerror{% + \@latex@error + {Unknown option `\CurrentOption' for \@cls@pkg\space`\@currname'}% + {The option `\CurrentOption' was not declared in + \@cls@pkg\space`\@currname', perhaps you\MessageBreak + misspelled its name. + Try typing \space <return> + \space to proceed.}} +\@onlypreamble\@unknownoptionerror +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@unprocessedoptions} +% Declare an error for each option, unless a |\ProcessOptions| occurred. +% \changes{v0.2v}{1994/01/29} +% {Macro added.} +% \changes{v1.0t}{1995/11/14}{Allow empty option} +% \begin{macrocode} +\def\@@unprocessedoptions{% + \ifx\@currext\@pkgextension + \edef\@curroptions{\@ptionlist{\@currname.\@currext}}% + \@for\CurrentOption:=\@curroptions\do{% + \ifx\CurrentOption\@empty\else\@unknownoptionerror\fi}% + \fi} +\@onlypreamble\@unprocessedoptions +\@onlypreamble\@@unprocessedoptions +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@badrequireerror} +% |\RequirePackage| or |\LoadClass| occurs in the options section. +% \changes{v0.2c}{1993/11/17} +% {Macro added} +% \begin{macrocode} +\def\@badrequireerror#1[#2]#3[#4]{% + \@latex@error + {\noexpand\RequirePackage or \noexpand\LoadClass + in Options Section}% + {The \@cls@pkg\space `\@currname' is defective.\MessageBreak + It attempts to load `#3' in the options section, i.e.,\MessageBreak + between \noexpand\DeclareOption and \string\ProcessOptions.}} +\@onlypreamble\@badrequireerror +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@twoloadclasserror} +% Two |\LoadClass| in a class. +% \changes{v0.2c}{1993/11/17} +% {Macro added} +% \begin{macrocode} +\def\@twoloadclasserror{% + \@latex@error + {Two \noexpand\LoadClass commands}% + {You may only use one \noexpand\LoadClass in a class file}} +\@onlypreamble\@twoloadclasserror +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@twoclasseserror} +% Two |\documentclass| or |\documentstyle|. +% \changes{v0.2h}{1993/11/28} +% {Macro added} +% \begin{macrocode} +\def\@twoclasseserror#1#{% + \@latex@error + {Two \noexpand\documentclass or \noexpand\documentstyle commands}% + {The document may only declare one class.}\@gobble} +\@onlypreamble\@twoclasseserror +% \end{macrocode} +% \end{macro} +% +% \subsection{Providing shipment} +% +% \begin{macro}{\two@digits} +% Prefix a number less than 10 with `0'. +% \begin{macrocode} +\def\two@digits#1{\ifnum#1<10 0\fi\number#1} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\filecontents} +% \begin{macro}{\endfilecontents} +% This environment implements inline files. +% The star-form does not write extra comments into the file. +% +% \changes{v0.2h}{1993/11/28} +% {Don't globally allocate a write stream (always use 15)} +% \changes{v0.2r}{1993/12/19}{Different message when ignoring a file} +% \changes{v0.3g}{1994/04/11} +% {Add star form, +% dont write \cs{endinput} at the end of the file.} +% \changes{v1.0c}{1994/05/11} +% {Add checks for form feed and tab} +% \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} +%</2ekernel> +%<*2ekernel|latexrelease> +%<latexrelease>\IncludeInRelease{2019/10/01}% +%<latexrelease> {\filec@ntents}{Spaces in file names}% +\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% +\catcode`\^^I\active% +% \end{macrocode} +% +% \begin{macrocode} +\gdef\filecontents{\@tempswatrue\filec@ntents}% +\gdef\filecontents*{\@tempswafalse\filec@ntents}% +% \end{macrocode} +% +% \begin{macrocode} +\gdef\filec@ntents#1{% + \set@curr@file{#1}% + \edef\q@curr@file{\expandafter\quote@name\expandafter{\@curr@file}}% + \openin\@inputcheck\q@curr@file \space % + \ifeof\@inputcheck% + \@latex@warning@no@line% + {Writing file `\@currdir\@curr@file'}% +% \end{macrocode} +% +% \changes{v1.0y}{1997/10/10} +% {\cs{reserved@c} not \cs{verbatim@out} to save a csname} +% \begin{macrocode} + \chardef\reserved@c15 % + \ch@ck7\reserved@c\write% + \immediate\openout\reserved@c\q@curr@file\relax% + \else% +% \end{macrocode} +% +% \changes{v1.0y}{1997/10/10} +% {Use \cs{@gobbletwo}} +% \begin{macrocode} + \closein\@inputcheck% + \@latex@warning@no@line% + {File `\@curr@file' already exists on the system.\MessageBreak% + Not generating it from this source}% + \let\write\@gobbletwo% + \let\closeout\@gobble% + \fi% + \if@tempswa% +% \end{macrocode} +% +% \changes{v1.0y}{1997/10/10} +% {\cs{@currenvir} in banner} +% \begin{macrocode} + \immediate\write\reserved@c{% + \@percentchar\@percentchar\space% + \expandafter\@gobble\string\LaTeX2e file `\@curr@file'^^J% + \@percentchar\@percentchar\space generated by the % + `\@currenvir' \expandafter\@gobblefour\string\newenvironment^^J% + \@percentchar\@percentchar\space from source `\jobname' on % + \number\year/\two@digits\month/\two@digits\day.^^J% + \@percentchar\@percentchar}% + \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} +% \begin{macrocode} + \edef\E{\@backslashchar end\string{\@currenvir\string}}% + \edef\reserved@b{% + \def\noexpand\reserved@b% + ####1\E####2\E####3\relax}% + \reserved@b{% + \ifx\relax##3\relax% +% \end{macrocode} +% There was no |\end{filecontents}| +% \begin{macrocode} + \immediate\write\reserved@c{##1}% + \else% +% \end{macrocode} +% There was a |\end{filecontents}|, so stop this time. +% \begin{macrocode} + \edef^^M{\noexpand\end{\@currenvir}}% + \ifx\relax##1\relax% + \else% +% \end{macrocode} +% Text before the |\end|, write it with a warning. +% \begin{macrocode} + \@latex@warning{Writing text `##1' before % + \string\end{\@currenvir}\MessageBreak as last line of \@curr@file}% + \immediate\write\reserved@c{##1}% + \fi% + \ifx\relax##2\relax% + \else% +% \end{macrocode} +% Text after the |\end|, ignore it with a warning. +% \begin{macrocode} + \@latex@warning{% + Ignoring text `##2' after \string\end{\@currenvir}}% + \fi% + \fi% + ^^M}% +% \end{macrocode} +% +% +% \changes{v1.2j}{2018/05/29}{use \cs{csname} not \cs{@undefined}} +% \begin{macrocode} + \catcode`\^^L\active% + \let\L\@undefined% + \def^^L{\expandafter\ifx\csname L\endcsname\relax\fi ^^J^^J}% + \catcode`\^^I\active% + \let\I\@undefined% + \def^^I{\expandafter\ifx\csname I\endcsname\relax\fi\space}% + \catcode`\^^M\active% + \edef^^M##1^^M{% + \noexpand\reserved@b##1\E\E\relax}}% +\endgroup% +% \end{macrocode} +% +% +% \begin{macrocode} +%</2ekernel|latexrelease> +%<latexrelease>\EndIncludeInRelease +%<latexrelease>\IncludeInRelease{0000/00/00}% +%<latexrelease> {\filec@ntents}{Spaces in file names}% +%<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> +%<latexrelease>\gdef\filec@ntents#1{% +%<latexrelease> \openin\@inputcheck#1 % +%<latexrelease> \ifeof\@inputcheck% +%<latexrelease> \@latex@warning@no@line% +%<latexrelease> {Writing file `\@currdir#1'}% +%<latexrelease> \chardef\reserved@c15 % +%<latexrelease> \ch@ck7\reserved@c\write% +%<latexrelease> \immediate\openout\reserved@c#1\relax% +%<latexrelease> \else% +%<latexrelease> \closein\@inputcheck% +%<latexrelease> \@latex@warning@no@line% +%<latexrelease> {File `#1' already exists on the system.\MessageBreak% +%<latexrelease> Not generating it from this source}% +%<latexrelease> \let\write\@gobbletwo% +%<latexrelease> \let\closeout\@gobble% +%<latexrelease> \fi% +%<latexrelease> \if@tempswa% +%<latexrelease> \immediate\write\reserved@c{% +%<latexrelease> \@percentchar\@percentchar\space% +%<latexrelease> \expandafter\@gobble\string\LaTeX2e file `#1'^^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 #1}% +%<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> +%<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 +%<*2ekernel> +% \end{macrocode} +% +% +% \begin{macrocode} +\begingroup +\catcode`|=\catcode`\% +\catcode`\%=12 +\catcode`\*=11 +\gdef\@percentchar{%} +\gdef\endfilecontents{| + \immediate\closeout\reserved@c + \def\T##1##2##3{| + \ifx##1\@undefined\else + \@latex@warning@no@line{##2 has been converted to Blank ##3e}| + \fi}| + \T\L{Form Feed}{Lin}| + \T\I{Tab}{Spac}| + \immediate\write\@unused{}} +\global\let\endfilecontents*\endfilecontents +\@onlypreamble\filecontents +\@onlypreamble\endfilecontents +\@onlypreamble\filecontents* +\@onlypreamble\endfilecontents* +\endgroup +\@onlypreamble\filec@ntents +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% +% +% +% \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 the content of |\pkgcls@mindate|. We need to pass the +% value not the command, otherwise nested packages may pick up the +% wrong information. +% \changes{v1.2h}{2018-04-08}{Pass expanded date} +% \begin{macrocode} + \begingroup + \edef\reserved@a{% + \endgroup + \unexpanded{\load@onefilewithoptions#1[#2]}% + [\pkgcls@mindate]% + \unexpanded{#4}}% + \reserved@a + } +\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 a warning. +% \changes{v1.2i}{2018/05/08} +% {Make suspicious rollback a warning not error: github issue 43} +% \begin{macrocode} + \ifnum \pkgcls@targetdate > \z@ + \ifnum \@parse@version0#1//00\@nil > \pkgcls@targetdate + \@latex@warning@no@line{Suspicious rollback/min-date date given\MessageBreak + A minimal date of #1 has been specified for + \@cls@pkg\MessageBreak '\pkgcls@name'.\MessageBreak + But this is in conflict + with a rollback request to \requestedpatchdate} + \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 of 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 +% above to be |\@onlypreamble| to be used after |\begin{document}|. +% \changes{v0.3f}{1994/03/16} +% {Add pkgindoc package} +% \changes{v1.1a}{1998/03/21} +% {Correct to new onlypreamble command list} +% \begin{macrocode} +%<*afterpreamble> +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{pkgindoc} + [1994/10/20 v1.1 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 +%</afterpreamble> +% \end{macrocode} +% +% \Finale |