The latexrelease package∗
The LATEX Project2022/11/14
This file is maintained by the LATEX Project team.
Bug reports can be opened (category latex) at
https://latex-project.org/bugs.html.

1

Introduction

Prior to the 2015 release of LATEX, essentially no changes had been made to the
LATEX format code for some years, with all improvements being instead added tothe package fixltx2e.
While this worked at a technical level it meant that you had to explicitly optin to bug fixes and improvements, and the vast majority of documents did notbenefit.
As described in LATEX News 22, a new policy is being implemented in which
improvements will now be added to the format by default, and this latexreleasepackage may be used to ensure stability where needed, either by making a newformat use an older definition of some commands, or conversely may be used tosupply the new definitions for use with an old format.
The basic use is:\RequirePackage[2015/01/01]{latexrelease}\documentclass{article}....

After such a declaration the document will use definitions current in the January 2015 LATEX, whether the actual format being used is older, or newer thanthat date. In the former case a copy of latexrelease.sty would need to be madeavailable for use with the older format. This may be used, for example, to share adocument between co-workers using different LATEX releases, or to protect a document from being affected by system updates. As well as the definitions within theformat itself, individual packages may use the commands defined here to adjust
their definitions to the specified date as described below.
Note that the latexrelease package is intended for use at the start of a document. Package and class code should not include this package as loading a package
should not normally globally reset the effective version of LATEX that is in force,
so affecting all other packages used in the document.
∗ This file has version number v1.0p, last revised 2022/11/14.

1The bulk of this package, after some initial setup and option handling consistsof a series of \IncludeInRelease commands which have been extracted from themain source files of the LATEX format. These contain the old and new versions of
any commands with modified definitions.

2

Package Options• yyyy/mm/dd or yyyy-nn-dd The package accepts any possible LATEX format
date as argument, although dates in the future for which the current releaseof this package has no information will generate a warning. Dates earlier than
2015 will work but will roll back to some point in 2015 when the method
was introduced. The \requestedLaTeXdate is set to the normalized dateargument so that package rollback defaults to the specified date.
• current This is the default behaviour, it does not change the effective dateof the format but does ensure that the \IncludeInRelease command isdefined. The \requestedLaTeXdate macro is reset to 0 so that package
rollback does not use the implicit date.
• latest sets the effective date of the format to the release date of thisfile, so in an older format applies all patches currently available. The\requestedLaTeXdate macro is reset to 0 so that package rollback does
not use the implicit date.

In all cases, when the package is loaded, the \sourceLaTeXdate is defined to be
the numerical representation of \fmtversion before the rollback/forward actually
happens, so it is possible to test from which was the original LATEX version before
latexrelease was loaded. This is particularly useful when some code in a package
has to be redefined differently if rolling backwards in time or forwards.

3

Release Specific CodeThe \IncludeInRelease mechanism allows the kernel developer to associate codewith a specific date to choose different versions of definitions depending on thedate specified as an option to the latexrelease package. Is also available for use by
package authors (or even in a document if necessary).
\IncludeInRelease {⟨code-date⟩}[⟨format-date⟩]{⟨label ⟩}{⟨message⟩}⟨code⟩\EndIncludeInRelease{⟨code-date⟩} This date is associated with the {⟨code⟩} argument and will becompared to the requested date in the option to the latexrelease.
[⟨format-date⟩] This optional argument can be used to specify a format datewith the code in addition to the mandatory {⟨code-date⟩} argument. Thiscan be useful for package developers as described below.
{⟨label ⟩} The {⟨label ⟩} argument is an identifier (string) that within a given package must be a unique label for each related set of optional definitions. Per
package at most one code block from all the \IncludeInRelease declarations with the same label will be executed.

2{⟨message⟩} The {⟨message⟩} is an informative string that is used in messages.
It has no other function.
⟨code⟩ Any TEX code after the \IncludeInRelease arguments up until the andthe following \EndIncludeInRelease is to be conditionally included depending on the date of the format as described below.
The \IncludeInRelease declarations with a given label should be in reverse
chronological order in the file. The one chosen will depend on this order, theeffective format version and the date options, as described below.
If your package mypackage defines a \widget command but has one definition
using the features available in the 2015 LATEX release, and a different definition isrequired for older formats then you can use:
\IncludeInRelease{2015/01/01}{\widget}{Widget Definition}\def\widget{new version}%\EndIncludeInRelease\IncludeInRelease{0000/00/00}{\widget}{Widget Definition}\def\widget{old version}%\EndIncludeInRelease

If a document using this package is used with a format with effective release
date of 2015/01/01 or later the new code will be used, otherwise the old code will
be used. Note the effective release date might be the original LATEX release date as
shown at the start of every LATEX job, or it may be set by the latexrelease package,so for example a document author who wants to ensure the new version is used
could use
\RequirePackage[2015/01/01]{latexrelease}\documentclass{article}\usepackage{mypackage}

If the document is used with a LATEX format from 2014 or before, then latexrelease will not have been part of the original distribution, but it may be obtained
from a later LATEX release or from CTAN and distributed with the document, it
will make an older LATEX release act essentially like the 2015 release.

3.1

Intermediate Package Releases

The above example works well for testing against the latex format but is not always
ideal for controlling code by the release date of the package. Suppose LATEX is not
updated but in March you update the mypackage package and modify the definitionof \widget. You could code the package as:\IncludeInRelease{2015/03/01}{\widget}{Widget Definition}\def\widget{even newer improved March version}%\EndIncludeInRelease\IncludeInRelease{2015/01/01}{\widget}{Widget Definition}\def\widget{new version}%\EndIncludeInRelease\IncludeInRelease{0000/00/00}{\widget}{Widget Definition}

3\def\widget{old version}%\EndIncludeInRelease

This would work and allow a document author to choose a date such as\RequirePackage[2015/03/01]{latexrelease}\documentclass{article}\usepackage{mypackage}

To use the latest version, however it would have disadvantage that until thenext release of LATEX, by default, if the document does not use latexrelease to
specify a date, the new improved code will not be selected as the effective date
will be 2015/01/01 and so the first code block will be skipped.
For this reason \IncludeInRelease has an optional argument that specifies
an alternative date to use if a date option has not been specified to latexrelease.
\IncludeInRelease{2015/03/01}[2015/01/01]{\widget}{Widget Definition}\def\widget{even newer improved March version}%\EndIncludeInRelease\IncludeInRelease{2015/01/01}{\widget}{Widget Definition}\def\widget{new version}%\EndIncludeInRelease\IncludeInRelease{0000/00/00}{\widget}{Widget Definition}\def\widget{old version}%\EndIncludeInRelease

Now, by default on a 2015/01/01 LATEX format, the first code block will compare the format date to the optional argument 2015/01/01 and so will execute
the even newer improved version. The remaining blocks using the \widget label
argument will all then be skipped.
If on the other hand the document requests an explicit release date using
latexrelease then this date will be used to decide what code block to include.

3.2

Using \IncludeInRelease in Packages

If \IncludeInRelease is used within a package then all such conditional codeneeds to be within such declarations, e.g., it is not possible in the above example tohave the “current” definition of \widget somewhere in the main code and only thetwo older definitions inside \IncludeInRelease declarations. If you would do thisthen one of those \IncludeInRelease declarations would be included overwriting
the even newer code in the main part of the package. As a result your package may
get fragmented over time with various \IncludeInRelease declarations sprinkled
throughout your code or you have to interrupt the reading flow by putting thosedeclarations together but not necessarily in the place where they belong.
To avoid this issue you can use the following coding strategy: place the current\widget definition in the main code where it correctly belongs.
...
\def\widget {even newer improved March version}\def\@widget{newly added helper command no defined in older releases}...

4

Then, near the end of your package place the following:\IncludeInRelease{2015/03/01}[2015/01/01]{\widget}{Widget Definition}\EndIncludeInRelease\IncludeInRelease{2015/01/01}{\widget}{Widget Definition}\def\widget{new version}%\let\@widget\@undefined % this doesn’t exist in earlier releases\EndIncludeInRelease\IncludeInRelease{0000/00/00}{\widget}{Widget Definition}\def\widget{old version}%\EndIncludeInRelease

This way the empty code block hides the other \IncludeInRelease declarations
unless there is an explicit request with a date 2015/01/01 or earlier.
Now if you make a further change to \widget in the future you simply copy
the current definition into the empty block and add a new empty declaration withtoday’s date and the current format date. This way your main code stays readable
and the old versions accumulate at the end of the package.1
The only other “extra effort” necessary when using this approach is that it may
be advisable to undo new definitions in the code block for the previous release,e.g., in the above example we undefined \@widget as that isn’t available in the2015/01/01 release but was defined in the main code. If all your conditional codeis within \IncludeInRelease declarations that wouldn’t been necessary as the
new code only gets defined if that release is chosen.

4Declaring entire modules

Sometimes a large chunk of code is added as a module to another larger code base.
As example of that in the 2020-10-01 release LATEX got a new hook management
system, lthooks, which was added in one go and, as with all changes to the kernel,
it was added to latexrelease. However rolling back from a future date to the 202010-01 release didn’t work because latexrelease would try to define again all thosecommands, which would result in many “already defined” errors and similar issues.
To solve that problem, completely new modules can be defined in latexreleaseusing the commands:\NewModuleRelease{⟨initial release date⟩}{⟨name⟩}{⟨message⟩}⟨module code⟩\IncludeInRelease{0000/00/00}{⟨name⟩}{⟨message⟩}⟨undefine module code⟩\EndModuleRelease
With that setup, the module ⟨name⟩ will be declared to exist only in releases equalor later ⟨initial release date⟩.
1 Of course there may be some cases in which the old code has to be in a specific place within
the package as other code depends on it (e.g., if you \let something to it). In that case you haveto place the code variations in the right place in your package rather than accumulating themat the very end.

5

If latexrelease is rolling backwards or forwards between dates after ⟨initial
release date⟩, then all the ⟨module code⟩ is skipped, except when inside ⟨IncludeInRelease⟩
guards, in which case the code is applied or skipped as discussed above.
If rolling forward from a date before the module’s ⟨initial release date⟩ toa date after that, then all the ⟨module code⟩ is executed to define the module,
and \IncludeInRelease guards are executed accordingly, depending on the datedeclared and the target date.
If latexrelease is rolling back to a date before ⟨release date⟩, then the code in
the \IncludeInRelease guard dated 0000/00/00 is executed instead to undefine
the module. This guard is not ended by the usual \EndIncludeInRelease, butinstead by \EndModuleRelease.
Finally, if rolling backwards or forwards between dates both before ⟨initial
release date⟩, the entire code between ⟨NewModuleRelease⟩ and ⟨EndModuleRelease⟩is entirely skipped.

4.1

ExampleHere is an example usage of the structure described above, as it would be used in
the LATEX kernel, taking lthooks as example:%<*2ekernel|latexrelease>\ExplSyntaxOn%<latexrelease>\NewModuleRelease{2020/10/01}{lthooks}%%<latexrelease>{The~hook~management~system}\NewDocumentCommand \NewHook { m }{ \hook_new:n {#1} }%<latexrelease>\IncludeInRelease{2021/06/01}{\AddToHook}{Long~argument}\NewDocumentCommand \AddToHook { m o +m }{ \hook_gput_code:nnn {#1} {#2} {#3} }%<latexrelease>\EndIncludeInRelease%<latexrelease>%<latexrelease>\IncludeInRelease{2020/10/01}{\AddToHook}{Long~argument}%<latexrelease>\NewDocumentCommand \AddToHook { m o m }%<latexrelease> { \hook_gput_code:nnn {#1} {#2} {#3} }%<latexrelease>\EndIncludeInRelease%<latexrelease>%<latexrelease>\IncludeInRelease{0000/00/00}{lthooks}{Undefine~lthooks}%<latexrelease>\cs_undefine:N \NewHook%<latexrelease>\cs_undefine:N \AddToHook%<latexrelease>\EndModuleRelease\ExplSyntaxOff%</2ekernel|latexrelease>

In the example above, \NewHook is declared only once, and unchanged in thenext release (2021/06/01 in the example), so it has no \IncludeInRelease guards,
and will only be defined if needed. \AddToHook, on the other hand, changed
between the two releases (made up for the example; it didn’t really happen) andhas an \IncludeInRelease block for the current release (off docstrip guards, so it
goes into the kernel too), and another for the previous release (in docstrip guards
so it goes only into latexrelease).
Note that in the example above, \ExplSyntaxOn and \ExplSyntaxOff wereadded outside the module code because, as discussed above, sometimes the code6

outside \IncludeInRelease guards may be skipped, but not the code inside them,and in that case the catcodes would be wrong when defining the code.

5

fixltx2e

As noted above, prior to the 2015 LATEX release updates to the LATEX kernel were
not made in the format source files but were made available in the fixltx2e package.
That package is no longer needed but we generate a small package from this sourcethat just makes a warning message but otherwise does nothing.

6

Implementation

We require at least a somewhat sane version of LATEX 2ε . Earlier ones where reallyquite different from one another.
1 ⟨∗latexrelease⟩
2 \NeedsTeXFormat{LaTeX2e}[1996/06/01]

6.1

Setup

\sourceLaTeXdate Store the original LATEX format version as a number in the format YYYYMMDD .

This macro has to be defined conditionally, so that it isn’t changed in caselatexrelease.sty is reloaded, but it can’t be defined in the kernel only, otherwise
latexrelease.sty wouldn’t work in older LATEX due to the missing macro.
3 \@ifundefined{sourceLaTeXdate}{%4
5\edef\sourceLaTeXdate{%\expandafter\@parse@version\fmtversion//00\@nil}}{}%\IncludeInRelease These are defined in ltvers.dtx.
\EndIncludeInRelease
6 \DeclareOption*{%7\def\@IncludeInRelease#1[#2]{\@IncludeInRele@se{#1}}%
8\let\requestedpatchdate\CurrentOption}
9 \DeclareOption{latest}{%10\let\requestedpatchdate\latexreleaseversion
11\AtEndOfPackage{\def\requestedLaTeXdate{0}}}12 \DeclareOption{current}{%
13\let\requestedpatchdate\fmtversion
14\AtEndOfPackage{\def\requestedLaTeXdate{0}}}15 \let\requestedpatchdate\fmtversion
16 \ProcessOptions\relax

Sanity check options, it allows some non-legal dates but always ensures
requestedLaTeXdate gets set to a number. Generate an error if there are any
non digit tokens remaining after removing the //.
17 \def\reserved@a{%18 \edef\requestedLaTeXdate{\the\count@}%
19 \reserved@b}
20 \def\reserved@b#1\\{%
21 \def\reserved@b{#1}%22 \ifx\reserved@b\@empty\else
23 \PackageError{latexrelease}%7

{Unexpected option \requestedpatchdate}%{The option must be of the form yyyy/mm/dd or yyyy-mm-dd}%

24
25
26 \fi}27 \afterassignment\reserved@a
28 \count@\expandafter\@parse@version\expandafter0\requestedpatchdate//00\@nil\\29

less precautions needed for \fmtversion
30 \edef\currentLaTeXdate{%\expandafter\@parse@version\fmtversion//00\@nil}

31

32 \ifnum\requestedLaTeXdate=\currentLaTeXdate
33 \PackageWarningNoLine{latexrelease}{%Current format date selected, no patches applied}34

35 \expandafter\endinput
36 \fiA newer version of latexrelease should have been distributed with the later
format.
37 \ifnum\currentLaTeXdate>\expandafter\@parse@version\latexreleaseversion//00\@nil

38

39 \PackageWarningNoLine{latexrelease}{%40 The current package is for an older LaTeX format:\MessageBreak
41 LaTeX \latexreleaseversion\space\MessageBreak
42 Obtain a newer version of this package!}
43 \expandafter\endinput
44 \fican’t patch into the future, could make this an error but it has some uses to control
package updates so allow for now.
45 \ifnum\requestedLaTeXdate>\expandafter\@parse@version\latexreleaseversion//00\@nil

46

47 \PackageWarningNoLine{latexrelease}{%48 The current package is for LaTeX \latexreleaseversion:\MessageBreak
49 It has no patches beyond that date\MessageBreak
50 There may be an updated version\MessageBreak51 of this package available from CTAN}
52 \expandafter\endinput
53 \fiUpdate the format version to the requested date.
54 \let\fmtversion\requestedpatchdate
55 \let\currentLaTeXdate\requestedLaTeXdate

6.2

Ignoring _new errors when rolling back

Enforce \ExplSyntaxOn and \ExplSyntaxOff to be \relax in latexrelease if they
are not yet defined. They are later restored to be undefined if needed.
56 \csname ExplSyntaxOn\endcsname
57 \csname ExplSyntaxOff\endcsname

Define a set of changes here, but we’ll only use them later to make sure they
are applied after expl3 is loaded. If loading from a rather old format, we don’t
have \ExplSyntaxOn yet.
58 \begingroup59\endlinechar=-1

8

\catcode95=11 % _\catcode58=11 % :62\catcode126=10 % ~63\catcode32=09 % <space>
64\xdef\latexrelease@postltexpl{\unexpanded{%
65 ⟨@@=latexrelease⟩
60
61First we’ll define a \declarecommand that does \renewcommand if the command being defined already exists, and \newcommand otherwise.
66 \cs_gset_protected:Npn \@@_declare_command:w
67{ \@star@or@long \@@_declare_command:Nw }68 \cs_gset_protected:Npn \@@_declare_command:Nw #1
69{ \cs_if_exist:NTF #1 { \renew@command } { \new@command } #1 }Then define a version of \e@alloc that checks if the control sequence being
defined already exists, and if so, checks if its meaning is the same as the one thatwould be defined with the call to \e@alloc. If both tests pass, nothing is defined
to save a register. This version also takes care of setting \allocationnumber tothe value it would have after the register is allocated.
70 \cs_gset_protected:Npn \@@_e@alloc:NnnnnN #1 #2 #3 #4 #5 #671{\cs_if_free:NTF #6{ \use:n }{\exp_after:wN \@@_e@alloc:N\token_to_meaning:N #6 \scan_stop: {#2} #6}{ \@@_e@alloc #1 {#2} {#3} {#4} {#5} #6 }

72
73
74
75
76
77
78
79

}

Walk through the meaning of the control sequence token by token, looking for theregister allocation number.
80 \cs_gset_protected:Npn \@@_e@alloc:N #1
81{\if_int_compare:w 0 < 0\if_int_compare:w 10 < 9#1 ~ 1 \fi:
\if_charcode:w " #1 1 \fi: \exp_stop_f:\tex_afterassignment:D \@@_e@alloc:w\@tempcnta #1\use_i:nnn\fi:\use:n{\if_meaning:w \scan_stop: #1\exp_after:wN \use_iv:nnnn\fi:\@@_e@alloc:N
}

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

}

When found, check if it is the exact same register as it would be allocated, and if
it is, set \allocationnumber accordingly and exit, otherwise undefine the registerand allocate from scratch.
97 \cs_gset_protected:Npn \@@_e@alloc:w #1 \scan_stop: #2 #3
98

{

9

#2 \@@_tmp:w = \@tempcnta\token_if_eq_meaning:NNTF #3 \@@_tmp:w{ \int_set_eq:NN \allocationnumber \@tempcnta{ \cs_set_eq:NN #3 \tex_undefined:D

99
100
101
102
103

\use_none:n }\use:n}}Now create a token list to hold the list of changed commands, and define
a temporary macro that will loop through the command list, store each in\l_@@_restores_tl, save a copy, and redefine each.
104 \tl_clear_new:N \l_@@_restores_tl
105 \cs_gset:Npn \@@_redefines:w #1 #2
106{\quark_if_recursion_tail_stop:N #1\tl_put_right:Nn \l_@@_restores_tl {#1}\cs_set_eq:cN { @@_ \cs_to_str:N #1 } #1
\cs_set_eq:NN #1 #2\@@_redefines:w

107
108
109
110
111
112

}

The redefinitions below are needed because:\__kernel_chk_if_free_cs:N This function is used ubiquitously in the l3kernel tocheck if a control sequence is definable, and give an error otherwise (similar
to \@ifdefinable). Making it a no-op is enough for most cases (except
when defining new registers);\e@alloc In the case of new registers, we waste an allocation number if we do\new\meta {thing} in a register that’s already allocated, so the redefinitionof \e@alloc checks if the new register is really necessary. This code does
not clear the register, which might cause problems in the future, if a register
is allocated but not properly cleared before using;\__kernel_msg_error:nnx This command is used to error on already defined scanmarks. Just making the error do nothing is enough, as no action is taken inthat case;\msg_new:nnnn Used to define new messages. Making it _gset is enough. Other
msg commands like \msg_new:nnn and \__kernel_msg_new:nnn(n) are defined in terms of \msg_new:nnnn, so there is no need to change the otherones;\NewDocumentCommand Used to define user-level commands in the kernel. Making
it equal to \DeclareDocumentCommand solves the problem;\newcommand Same as above.
And here we go:
113 \@@_redefines:w
114
115
116
117
118
119

\__kernel_chk_if_free_cs:N \use_none:n\e@alloc \@@_e@alloc:NnnnnN\__kernel_msg_error:nnx \use_none:nnn\msg_new:nnnn \msg_gset:nnnn% \NewDocumentCommand \DeclareDocumentCommand % after ltcmd.dtx\newcommand \@@_declare_command:w

10

Temp addition . . .
\__kernel_msg_error:nnn \use_none:nnn\q_recursion_tail \q_recursion_tail\q_recursion_stop

120
121
122

% needed while redirect for kernel msgs doesn’t wor

Finally, redirect the error thrown by \NewHook to nowhere so it can be safely
reused (the hook isn’t redeclared if it already exists). The same happens for\NewMarkClass.
123 \msg_redirect_name:nnn { hooks } { exists } { none }124 \msg_redirect_name:nnn { mark } { class-already-defined }{ none }Now a one-off for ltcmd.dtx: we need to make \NewDocumentCommand
not complain on an already existing command, but it has to be done after\NewDocumentCommand is defined, so this is separate from the \latexrelease@postltexpl
actions above:
125 \cs_gset_protected:Npn \latexrelease@postltcmd{

126\@@_redefines:w\NewDocumentCommand \DeclareDocumentCommand\q_recursion_tail \q_recursion_tail\q_recursion_stop

127
128
129
130
131

}

132

}}%

133 \endgroup134 ⟨/latexrelease⟩

6.3

Undoing the temp modifications

If \ExplSyntaxOn exists (defined and not equal \relax), then use the expl3 restore
code, otherwise restore \ExplSyntaxOn and \ExplSyntaxOff to be undefined.
135 ⟨∗latexrelease-finish⟩
136 \@ifundefined{ExplSyntaxOn}%
137
138
139
140
141
142

{\let\ExplSyntaxOn\@undefined\let\ExplSyntaxOff\@undefined\@gobble}%{\ExplSyntaxOn\@firstofone}%{%Now just loop through the list of redefined commands and restore their previous
meanings.
143 \tl_map_inline:Nn \l_@@_restores_tl
144{\cs_set_eq:Nc #1 { @@_ \cs_to_str:N #1 }\cs_undefine:c { @@_ \cs_to_str:N #1 }

145
146
147

}

148 \tl_clear:N \l_@@_restores_tl

And restore the silenced error messages.
149 \msg_redirect_name:nnn { hooks } { exists } { }150 \msg_redirect_name:nnn { mark } { class-already-defined } { }151 ⟨@@=⟩
152\ExplSyntaxOff}%153 ⟨/latexrelease-finish⟩

11

6.4

Individual Changes

The code for each change will be inserted at this point, extracted from the kernel
source files.

6.5

fixltx2e

Generate a stub fixltx2e package:154 ⟨∗fixltx2e⟩155 \IncludeInRelease{2015/01/01}{\fixltxe}{Old fixltx2e package}156 \NeedsTeXFormat{LaTeX2e}157 \PackageWarningNoLine{fixltx2e}{%
158 fixltx2e is not required with releases after 2015\MessageBreak
159 All fixes are now in the LaTeX kernel.\MessageBreak160 See the latexrelease package for details}
161 \EndIncludeInRelease
162 \IncludeInRelease{0000/00/00}{\fixltxe}{Old fixltx2e package}
163 \def\@outputdblcol{%
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

\if@firstcolumn\global\@firstcolumnfalse\global\setbox\@leftcolumn\copy\@outputbox\splitmaxdepth\maxdimen\vbadness\maxdimen\setbox\@outputbox\vbox{\unvbox\@outputbox\unskip}%\setbox\@outputbox\vsplit\@outputbox to\maxdimen\toks@\expandafter{\topmark}%\xdef\@firstcoltopmark{\the\toks@}%\toks@\expandafter{\splitfirstmark}%\xdef\@firstcolfirstmark{\the\toks@}%\ifx\@firstcolfirstmark\@empty\global\let\@setmarks\relax\else\gdef\@setmarks{%\let\firstmark\@firstcolfirstmark\let\topmark\@firstcoltopmark}%
\fi
\else
\global\@firstcolumntrue\setbox\@outputbox\vbox{%\hb@xt@\textwidth{%\hb@xt@\columnwidth{\box\@leftcolumn \hss}%\hfil{\normalcolor\vrule \@width\columnseprule}%\hfil\hb@xt@\columnwidth{\box\@outputbox \hss}}}%\@combinedblfloats\@setmarks\@outputpage\begingroup\@dblfloatplacement\@startdblcolumn\@whilesw\if@fcolmade \fi{\@outputpage\@startdblcolumn}%\endgroup\fi}

12200 \def\end@dblfloat{%
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

\if@twocolumn\@endfloatbox\ifnum\@floatpenalty <\z@\@largefloatcheck\global\dp\@currbox1sp %\@cons\@currlist\@currbox\ifnum\@floatpenalty <-\@Mii\penalty -\@Miv\@tempdima\prevdepth\vbox{}%\prevdepth\@tempdima\penalty\@floatpenalty\else\vadjust{\penalty -\@Miv \vbox{}\penalty\@floatpenalty}\@Esphack
\fi
\fi
\else
\end@float
\fi

220 }
221 \def\@testwrongwidth #1{%

\ifdim\dp#1=\f@depth
\else
224
\global\@testtrue
225\fi}
226 \let\f@depth\z@
227 \def\@dblfloatplacement{\global\@dbltopnum\c@dbltopnumber
228\global\@dbltoproom \dbltopfraction\@colht
229\@textmin \@colht
230\advance \@textmin -\@dbltoproom
231\@fpmin \dblfloatpagefraction\textheight232\@fptop \@dblfptop
233\@fpsep \@dblfpsep
234\@fpbot \@dblfpbot
235\def\f@depth{1sp}}
236 \def \@doclearpage {%237\ifvoid\footins238\setbox\@tempboxa\vsplit\@cclv to\z@ \unvbox\@tempboxa
239\setbox\@tempboxa\box\@cclv
240\xdef\@deferlist{\@toplist\@botlist\@deferlist}%241\global \let \@toplist \@empty
242\global \let \@botlist \@empty
243\global \@colroom \@colht
244\ifx \@currlist\@empty
245
\else
246
\@latexerr{Float(s) lost}\@ehb
247\global \let \@currlist \@empty
248
\fi
249
\@makefcolumn\@deferlist
250\@whilesw\if@fcolmade \fi{\@opcol\@makefcolumn\@deferlist}%251\if@twocolumn
252\if@firstcolumn
253\xdef\@deferlist{\@dbltoplist\@deferlist}%
222
223

13

254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271

\global \let \@dbltoplist \@empty\global \@colht \textheight\begingroup\@dblfloatplacement\@makefcolumn\@deferlist\@whilesw\if@fcolmade \fi{\@outputpage\@makefcolumn\@deferlist}%\endgroup\else\vbox{}\clearpage\fi\fi\ifx\@deferlist\@empty \else\clearpage \fi\else\setbox\@cclv\vbox{\box\@cclv\vfil}%\@makecol\@opcol\clearpage
\fi

272 }
273 \def \@startdblcolumn {%
274
275
276
277
278
279
280
281
282
283

\@tryfcolumn \@deferlist\if@fcolmade\else\begingroup\let \reserved@b \@deferlist\global \let \@deferlist \@empty\let \@elt \@sdblcolelt\reserved@b\endgroup
\fi

284 }
285 \def\@addtonextcol{%
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

\begingroup\@insertfalse\@setfloattypecounts\ifnum \@fpstype=8\else\ifnum \@fpstype=24\else\@flsettextmin\@reqcolroom \ht\@currbox\advance \@reqcolroom \@textmin\ifdim \@colroom>\@reqcolroom\@flsetnum \@colnum\ifnum\@colnum>\z@\@bitor\@currtype\@deferlist\@testwrongwidth\@currbox\if@test\else\@addtotoporbot
\fi
\fi
\fi
\fi

14

308
309
310
311
312
313

\fi
\if@insert\else\@cons\@deferlist\@currbox\fi\endgroup314 }315 \def\@addtodblcol{%
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357

\begingroup\@insertfalse\@setfloattypecounts\@getfpsbit \tw@\ifodd\@tempcnta\@flsetnum \@dbltopnum\ifnum \@dbltopnum>\z@\@tempswafalse\ifdim \@dbltoproom>\ht\@currbox\@tempswatrue\else\ifnum \@fpstype<\sixt@@n\advance \@dbltoproom \@textmin\ifdim \@dbltoproom>\ht\@currbox\@tempswatrue\fi\advance \@dbltoproom -\@textmin\fi\fi\if@tempswa\@bitor \@currtype \@deferlist\@testwrongwidth\@currbox\if@test\else\@tempdima -\ht\@currbox\advance\@tempdima-\ifx \@dbltoplist\@empty \dbltextfloatsep \else\dblfloatsep \fi\global \advance \@dbltoproom \@tempdima\global \advance \@colht \@tempdima\global \advance \@dbltopnum \m@ne\@cons \@dbltoplist \@currbox\@inserttrue
\fi
\fi
\fi
\fi
\if@insert\else\@cons\@deferlist\@currbox\fi\endgroup358 }359 \def \@addtocurcol {%360
361\@insertfalse\@setfloattypecounts

15

362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415

\ifnum \@fpstype=8\else\ifnum \@fpstype=24\else\@flsettextmin\advance \@textmin \@textfloatsheight\@reqcolroom \@pageht\ifdim \@textmin>\@reqcolroom\@reqcolroom \@textmin\fi\advance \@reqcolroom \ht\@currbox\ifdim \@colroom>\@reqcolroom\@flsetnum \@colnum\ifnum \@colnum>\z@\@bitor\@currtype\@deferlist\@testwrongwidth\@currbox\if@test\else\@bitor\@currtype\@botlist\if@test\@addtobot\else\ifodd \count\@currbox\advance \@reqcolroom \intextsep\ifdim \@colroom>\@reqcolroom\global \advance \@colnum \m@ne\global \advance \@textfloatsheight \ht\@currbox\global \advance \@textfloatsheight 2\intextsep\@cons \@midlist \@currbox\if@nobreak\nobreak\@nobreakfalse\everypar{}%\else\addpenalty \interlinepenalty\fi\vskip \intextsep\box\@currbox\penalty\interlinepenalty\vskip\intextsep\ifnum\outputpenalty <-\@Mii \vskip -\parskip\fi\outputpenalty \z@\@inserttrue\fi\fi\if@insert\else\@addtotoporbot
\fi
\fi
\fi
\fi
\fi
\fi

16

416
417
418
419
420
421

\fi
\if@insert\else\@resethfps\@cons\@deferlist\@currbox
\fi

422 }
423 \def\@xtryfc #1{%\@next\reserved@a\@trylist{}{}%\@currtype \count #1%
426\divide\@currtype\@xxxii
427\multiply\@currtype\@xxxii
428\@bitor \@currtype \@failedlist
429\@testfp #1%
430\@testwrongwidth #1%
431\ifdim \ht #1>\@colht
432\@testtrue
433
\fi
434
\if@test
435\@cons\@failedlist #1%
436
\else
437
\@ytryfc #1%438\fi}
439 \def\@ztryfc #1{%
440\@tempcnta\count #1%
441\divide\@tempcnta\@xxxii
442\multiply\@tempcnta\@xxxii
443\@bitor \@tempcnta {\@failedlist \@flfail}%444\@testfp #1%
445\@testwrongwidth #1%
446\@tempdimb\@tempdima
447\advance\@tempdimb\ht #1%
448\advance\@tempdimb\@fpsep
449\ifdim \@tempdimb >\@colht
450\@testtrue
451
\fi
452
\if@test
453\@cons\@flfail #1%
454
\else
455
\@cons\@flsucceed #1%
456\@tempdima\@tempdimb
457\fi}
458 \def\@{\spacefactor\@m{}}459 \def\@tempa#1#2{#1#2\relax}
460 \ifx\setlength\@tempa
461\def\setlength#1#2{#1 #2\relax}462 \fi
463 \def\addpenalty#1{%
464\ifvmode465\if@minipage
466
\else
467
\if@nobreak
468
\else
469
\ifdim\lastskip=\z@
424
425

17

\penalty#1\relax
\else
472
\@tempskipb\lastskip
473\begingroup474\advance \@tempskipb
475\ifdim\prevdepth>\maxdepth\maxdepth\else476\ifdim \prevdepth = -\@m\p@ \z@ \else \prevdepth \fi
477
\fi
478
\vskip -\@tempskipb
479\penalty#1%
480\vskip\@tempskipb
481\endgroup482\vskip -\@tempskipb
483\vskip \@tempskipb
484
\fi
485
\fi
486
\fi
487
\else
488
\@noitemerr489\fi}490 \def\@fnsymbol#1{%
491\ifcase#1\or \TextOrMath\textasteriskcentered *\or492
\TextOrMath \textdagger \dagger\or493\TextOrMath \textdaggerdbl \ddagger \or494\TextOrMath \textsection \mathsection\or495\TextOrMath \textparagraph \mathparagraph\or496\TextOrMath \textbardbl \|\or497\TextOrMath {\textasteriskcentered\textasteriskcentered}{**}\or
498\TextOrMath {\textdagger\textdagger}{\dagger\dagger}\or499\TextOrMath {\textdaggerdbl\textdaggerdbl}{\ddagger\ddagger}\else
500\@ctrerr \fi
501 }502 \begingroup\expandafter\expandafter\expandafter\endgroup503 \expandafter\ifx\csname eTeXversion\endcsname\relax
504 \DeclareRobustCommand\TextOrMath{%
505\ifmmode \expandafter\@secondoftwo
506
\else
\expandafter\@firstoftwo \fi}507 \protected@edef\TextOrMath#1#2{\TextOrMath{#1}{#2}}508 \else509 \protected\expandafter\def\csname TextOrMath\space\endcsname{%
510\ifmmode \expandafter\@secondoftwo
511
\else
\expandafter\@firstoftwo \fi}
512 \edef\TextOrMath#1#2{%
513\expandafter\noexpand\csname TextOrMath\space\endcsname514{#1}{#2}}
515 \fi
516 \def\@esphack{%
517\relax518\ifhmode519\spacefactor\@savsf
520\ifdim\@savsk>\z@521\nobreak \hskip\z@skip % <-----522\ignorespaces
523
\fi
470
471

18

524

\fi}

525 \def\@Esphack{%\relax\ifhmode528\spacefactor\@savsf
529\ifdim\@savsk>\z@530\nobreak \hskip\z@skip % <-----531\@ignoretrue532\ignorespaces
533
\fi
534
\fi}
535 \DeclareRobustCommand\em536{\@nomath\em \ifdim \fontdimen\@ne\font >\z@537
\eminnershape \else \itshape \fi}538 \def\eminnershape{\upshape}
539 \DeclareRobustCommand*\textsubscript[1]{%540\@textsubscript{\selectfont#1}}
541 \def\@textsubscript#1{%
542{\m@th\ensuremath{_{\mbox{\fontsize\sf@size\z@#1}}}}}
543 \def\@DeclareMathSizes #1#2#3#4#5{%
544\@defaultunits\dimen@ #2pt\relax\@nnil
545\if $#3$%546\expandafter\let\csname S@\strip@pt\dimen@\endcsname\math@fontsfalse
547
\else
548
\@defaultunits\dimen@ii #3pt\relax\@nnil
549\@defaultunits\@tempdima #4pt\relax\@nnil
550\@defaultunits\@tempdimb #5pt\relax\@nnil
551\toks@{#1}%552\expandafter\xdef\csname S@\strip@pt\dimen@\endcsname{%553\gdef\noexpand\tf@size{\strip@pt\dimen@ii}%
554\gdef\noexpand\sf@size{\strip@pt\@tempdima}%
555\gdef\noexpand\ssf@size{\strip@pt\@tempdimb}%
556\the\toks@
557
}%
558
\fi
559 }
560 \providecommand*\MakeRobust[1]{%561\@ifundefined{\expandafter\@gobble\string#1}{%
562\@latex@error{The control sequence ‘\string#1’ is undefined!%
563\MessageBreak There is nothing here to make robust}%
564
\@eha
565
}%
566
{%
567
\@ifundefined{\expandafter\@gobble\string#1\space}%
568
{%
569
\expandafter\let\csname
570\expandafter\@gobble\string#1\space\endcsname=#1%
571\edef\reserved@a{\string#1}%572\def\reserved@b{#1}%573\edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}%574\edef#1{%
575\ifx\reserved@a\reserved@b576\noexpand\x@protect\noexpand#1%
577
\fi
526
527

19

578
579
580
581
582

\noexpand\protect\expandafter\noexpand\csname\expandafter\@gobble\string#1\space\endcsname}%}%{\@latex@info{The control sequence ‘\string#1’ is already robust}}%
}%

583 }
584 \MakeRobust\(
585 \MakeRobust\)
586 \MakeRobust\[
587 \MakeRobust\]
588 \MakeRobust\makebox
589 \MakeRobust\savebox
590 \MakeRobust\framebox
591 \MakeRobust\parbox
592 \MakeRobust\rule593 \MakeRobust\raisebox
594 \def\@xfloat #1[#2]{%
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631

\@nodocument\def \@captype {#1}%\def \@fps {#2}%\@onelevel@sanitize \@fps\def \reserved@b {!}%
\ifx \reserved@b \@fps\@fpsadddefault\else\ifx \@fps \@empty\@fpsadddefault\fi\fi\ifhmode\@bsphack\@floatpenalty -\@Mii\else\@floatpenalty-\@Miii\fi\ifinner\@parmoderr\@floatpenalty\z@\else\@next\@currbox\@freelist{%\@tempcnta \sixt@@n\expandafter \@tfor \expandafter \reserved@a\expandafter :\expandafter =\@fps\do{%\if \reserved@a h%\ifodd \@tempcnta\else\advance \@tempcnta \@ne\fi\else\if \reserved@a t%\@setfpsbit \tw@\else\if \reserved@a b%\@setfpsbit 4%20

\else\if \reserved@a p%\@setfpsbit 8%\else\if \reserved@a !%\ifnum \@tempcnta>15\advance\@tempcnta -\sixt@@n\relax
\fi
\else
\@latex@error{Unknown float option ‘\reserved@a’}%{Option ‘\reserved@a’ ignored and ‘p’ used.}%\@setfpsbit 8%\fi\fi\fi\fi\fi}%\@tempcntb \csname ftype@\@captype \endcsname\multiply \@tempcntb \@xxxii\advance \@tempcnta \@tempcntb\global \count\@currbox \@tempcnta}%\@fltovf\fi\global \setbox\@currbox\color@vbox\normalcolor\vbox \bgroup\hsize\columnwidth\@parboxrestore\@floatboxreset

632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658 }
659

\def\@stpelt#1{\global\csname c@#1\endcsname \m@ne\stepcounter{#1}}660 \EndIncludeInRelease661 ⟨/fixltx2e⟩21