ltplain.dtx (The file plain.tex, modified for L^{A}TEX)

Donald E. Knuth Modified by Leslie Lamport, Frank Mittelbach, Rainer Schöpf, David Carlisle

1995/10/17

1 Plain TEX

L^{A}TEX includes almost all of the functionality of Knuth’s original ‘Basic Macros’ That is, the plain TEX format described in Appendix B of the TEXBook.

L^{A}TEX font definitions are done using NFSS2 (file ltfss.dtx) so all of PLAIN’s font definitions are removed.

L^{A}TEX has its own tabbing environment, so PLAIN’s is disabled.

Macro definitions for math have been moved to some other file so that they are grouped together.

L^{A}TEX uses its own output routine, so most of the plain one was removed. A lot of individual macros are now moved to the relevant L^{A}TEX files so that

this file will gradually vanish.

1 ⟨∗2ekernel | autoload⟩

 2 \catcode`\{=1 % left brace is begin-group character
 3 \catcode`\}=2 % right brace is end-group character
 4 \catcode`\$=3 % dollar sign is math shift
 5 \catcode`\&=4 % ampersand is alignment tab
 6 \catcode`\#=6 % hash mark is macro parameter character
 7 \catcode`\^=7 % circumflex and uparrow are for superscripts
 8 \catcode`\_=8 % underline and downarrow are for subscripts
 9 \catcode`\^^I=10 % ascii tab is a blank space
10 \chardef\active=13 \catcode`\~=\active % tilde is active
11 \catcode`\^^L=\active \outer\def^^L{\par}% ascii form-feed is \outer\par
12 \message{catcodes,}

We had to define the \catcodes right away, before the message line, since \message uses the { and } characters. When INITEX (the TEX initializer) starts up, it has defined the following \catcode values: \catcode`\^^@=9 % ascii null is ignored \catcode`\^^M=5 % ascii return is end-line \catcode`\\=0 % backslash is TeX escape character \catcode`\%=14 % percent sign is comment character \catcode`\ =10 % ascii space is blank space \catcode`\^^?=15 % ascii delete is invalid

\catcode`\A=11 ... \catcode`\Z=11 % uppercase letters
\catcode`\a=11 ... \catcode`\z=11 % lowercase letters

all others are type 12 (other)

Here is a list of the characters that have been specially catcoded:

13 \def\dospecials{\do\ \do\\\do\{\do\}\do\$\do\&%
14 \do\#\do\^\do\_\do\%\do\~}

(not counting ascii null, tab, linefeed, formfeed, return, delete) Each symbol in the list is preceded by , which can be defined if you want to do something to every item in the list.

We make @ signs act like letters, temporarily, to avoid conflict between user names and internal control sequences of plain format.

15 \catcode`@=11

To make the plain macros more efficient in time and space, several constant values are declared here as control sequences. If they were changed, anything could happen; so they are private symbols.

\@ne \tw@ \thr@@ \sixt@@n \@cclv Small constants are defined using \chardef.
16 \chardef\@ne=1
17 \chardef\tw@=2
18 \chardef\thr@@=3
19 \chardef\sixt@@n=16
20 \chardef\@cclv=255
\@cclvi \@m \@M \@MM Constants above 255 defined using \mathchardef.
21 \mathchardef\@cclvi=256
22 \mathchardef\@m=1000
23 \mathchardef\@M=10000
24 \mathchardef\@MM=20000

Allocation of registers

Here are macros for the automatic allocation of \count, \box, \dimen, \skip, \muskip, and \toks registers, as well as \read and \write stream numbers, \fam codes, \language codes, and \insert numbers.

25 \message{registers,}

When a register is used only temporarily, it need not be allocated; grouping can be used, making the value previously in the register return after the close of the group. The main use of these macros is for registers that are defined by one macro and used by others, possibly at ifferent nesting levels. All such registers should be defined through these macros; otherwise conflicts may occur, especially when two or more more macro packages are being used at once. The following counters are reserved:

0 to 9 page numbering 10 count allocation 11 dimen allocation 12 skip allocation 13 muskip allocation 14 box allocation 15 toks allocation 16 read file allocation 17 write file allocation 18 math family allocation 19 language allocation 20 insert allocation 21 the most recently allocated number 22 constant -1

New counters are allocated starting with 23, 24, etc. Other registers are allocated starting with 10. This leaves 0 through 9 for the user to play with safely, except that counts 0 to 9 are considered to be the page and subpage numbers (since they are displayed during output). In this scheme, \count 10 always contains the number of the highest-numbered counter that has been allocated, \count 14 the highest-numbered box, etc. Inserts are given numbers 254, 253, etc., since they require a \count, \dimen, \skip, and \box all with the same number; \count 20 contains the lowest-numbered insert that has been allocated. Of course, \box255 is reserved for \output; \count255, \dimen255, and \skip255 can be used freely.

It is recommended that macro designers always use \global assignments with respect to registers numbered 1, 3, 5, 7, 9, and always non-\global assignments with respect to registers 0, 2, 4, 6, 8, 255. This will prevent “save stack buildup” that might otherwise occur.

26 \count10=22 % allocates \count registers 23, 24, ...
27 \count11=9 % allocates \dimen registers 10, 11, ...
28 \count12=9 % allocates \skip registers 10, 11, ...
29 \count13=9 % allocates \muskip registers 10, 11, ...
30 \count14=9 % allocates \box registers 10, 11, ...
31 \count15=9 % allocates \toks registers 10, 11, ...
32 \count16=-1 % allocates input streams 0, 1, ...
33 \count17=-1 % allocates output streams 0, 1, ...
34 \count18=3 % allocates math families 4, 5, ...
35 \count19=0 % allocates \language codes 1, 2, ...
36 \count20=255 % allocates insertions 254, 253, ...

\insc@unt \allocationnumber The insertion counter and most recent allocation.

37 \countdef\insc@unt=20
38 \countdef\allocationnumber=21

\m@ne The constant −1.

39 \countdef\m@ne=22 \m@ne=-1

\wlog Write on log file (only)

40 \def\wlog{\immediate\write\m@ne}

\count@ \dimen@ \dimen@i \dimen@ii \skip@ \toks@ Here are abbreviations for the names of scratch registers that don’t need to be allocated.

41 \countdef\count@=255
42 \dimendef\dimen@=0
43 \dimendef\dimen@i=1 % global only
44 \dimendef\dimen@ii=2
45 \skipdef\skip@=0
46 \toksdef\toks@=0
\newcount \newdimen \newskip \newmuskip \newbox \newhelp \newtoks Now, we define \newcount, \newbox, etc. so that you can say \newcount\foo and

\foo will be defined (with \countdef) to be the next counter.

To find out which counter \foo is, you can look at \allocationnumber.

Since there’s no \boxdef command, \chardef is used to define a \newbox,

\newinsert, \newfam, and so on.

L^{A}TEX change: remove \outer from \newcount and \newdimen (FMi) This is necessary to use \newcount inside \if... later on. Also remove from \newskip, \newbox \newwrite and \newfam (DPC) to save later redefinition.

47 \def\newcount{\alloc@0\count\countdef\insc@unt}
48 \def\newdimen{\alloc@1\dimen\dimendef\insc@unt}
49 \def\newskip{\alloc@2\skip\skipdef\insc@unt}
50 \def\newmuskip{\alloc@3\muskip\muskipdef\@cclvi}
51 \def\newbox{\alloc@4\box\chardef\insc@unt}
52 \def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
53 \def\newtoks{\alloc@5\toks\toksdef\@cclvi}
\newread \newwrite
54 \def\newread{\alloc@6\read\chardef\sixt@@n}
55 \def\newwrite{\alloc@7\write\chardef\sixt@@n}
   L^{A}TEX defines \newfam in ltfss.dtx.
\def\newfam{\alloc@8\fam\chardef\sixt@@n}
\newlanguage
56 \def\newlanguage{\alloc@9\language\chardef\@cclvi}
\alloc@
57 \def\alloc@#1#2#3#4#5{\global\advance\count1#1\@ne
58 \ch@ck#1#4#2% make sure there's still room
59 \allocationnumber\count1#1%
60 \global#3#5\allocationnumber
61 \wlog{\string#5=\string#2\the\allocationnumber}}
\newinsert
62 \def\newinsert#1{\global\advance\insc@unt \m@ne

63 \ch@ck0\insc@unt\count
64 \ch@ck1\insc@unt\dimen
65 \ch@ck2\insc@unt\skip
66 \ch@ck4\insc@unt\box
67 \allocationnumber\insc@unt
68 \global\chardef#1\allocationnumber
69 \wlog{\string#1=\string\insert\the\allocationnumber}}
\ch@ck

70 ⟨/2ekernel | autoload⟩ 71 ⟨∗2ekernel | autoload | autoerr⟩

72 \gdef\ch@ck#1#2#3{%
73 \ifnum\count1#1<#2\else
74 ⟨!autoload⟩ \errmessage{No room for a new #3}%
75 ⟨autoload⟩  \@autoerr\ch@ck#1#2#3%
76 \fi}

77 ⟨/2ekernel | autoload | autoerr⟩ 78 ⟨∗2ekernel | autoload⟩

\maxdimen \hideskip Here are some examples of allocation.

79 \newdimen\maxdimen \maxdimen=16383.99999pt % the largest legal <dimen>
80 \newskip\hideskip \hideskip=-1000pt plus 1fill % negative but can grow
\p@ \z@ \z@skip \voidb@x
81 \newdimen\p@ \p@=1pt % this saves macro space and time
82 \newdimen\z@ \z@=0pt % can be used both for 0pt and 0
83 \newskip\z@skip \z@skip=0pt plus0pt minus0pt
84 \newbox\voidb@x % permanently void box register
85 \message{compatibility for TeX 2, }

If this file is used in an old TEX we define the new features of TEX 3.0 as simple macros or counters so that files that uses these features can be processed in such an environment (They will however produce some other results).

86 \ifx\@undefined\inputlineno
87 \newcount\inputlineno

This could be used to detect that an old TEX is in force

88 \inputlineno-1

Extra test for MLTeX 2, RmS 91/11/07.

89 \ifx\@undefined\language
90  \newcount\language
91 \fi
92 \newcount\lefthyphenmin
93 \newcount\righthyphenmin
94 \newcount\errorcontextlines
95 \newcount\holdinginserts
96 \newdimen\emergencystretch
97 \newcount\badness

98 \let\noboundary\relax
99 \newcount\setlanguage
100 \fi

Assign initial values to TEX’s parameters

101 \message{parameters,}

All of TEX’s numeric parameters are listed here, but the code is commented out if no special value needs to be set. INITEX makes all parameters zero except where noted.

102 \pretolerance=100
103 \tolerance=200 % INITEX sets this to 10000
104 \hbadness=1000
105 \vbadness=1000
106 \linepenalty=10
107 \hyphenpenalty=50
108 \exhyphenpenalty=50
109 \binoppenalty=700
110 \relpenalty=500
111 \clubpenalty=150
112 \widowpenalty=150
113 \displaywidowpenalty=50
114 \brokenpenalty=100
115 \predisplaypenalty=10000
\postdisplaypenalty=0
\interlinepenalty=0
\floatingpenalty=0, set during \insert
\outputpenalty=0, set before TeX enters \output
116 \doublehyphendemerits=10000
117 \finalhyphendemerits=5000
118 \adjdemerits=10000

\looseness=0, cleared by TeX after each paragraph

\pausing=0
\holdinginserts=0
\tracingonline=0
\tracingmacros=0
\tracingstats=0
\tracingparagraphs=0
\tracingpages=0
\tracingoutput=0
119 \tracinglostchars=1
\tracingcommands=0
\tracingrestores=0
\language=0
120 \uchyph=1

\lefthyphenmin=2 \righthyphenmin=3 set below
\globaldefs=0
\maxdeadcycles=25 % INITEX does this

\hangafter=1 % INITEX does this, also TeX after each paragraph

\fam=0

\mag=1000 % INITEX does this

\escapechar=‘\\ % INITEX does this
121 \defaulthyphenchar=`\-
122 \defaultskewchar=-1
\endlinechar=‘\^^M % INITEX does this

\newlinechar=-1 \LaTeX\ sets this in ltdefns.dtx.

123 \delimiterfactor=901

\time=now % TeX does this at beginning of job \day=now % TeX does this at beginning of job \month=now % TeX does this at beginning of job \year=now % TeX does this at beginning of job

In L^{A}TEX we don’t want box information in the transcript unless we do a full tracing.

124 \showboxbreadth=-1
125 \showboxdepth=-1
126 \errorcontextlines=-1
127 \hfuzz=0.1pt
128 \vfuzz=0.1pt
129 \overfullrule=5pt
130 \hsize=6.5in
131 \vsize=8.9in
132 \maxdepth=4pt
133 \splitmaxdepth=\maxdimen
134 \boxmaxdepth=\maxdimen
\lineskiplimit=0pt, changed by \normalbaselines
135 \delimitershortfall=5pt
136 \nulldelimiterspace=1.2pt
137 \scriptspace=0.5pt
\mathsurround=0pt

\predisplaysize=0pt, set before TeX enters $$ \displaywidth=0pt, set before TeX enters $$ \displayindent=0pt, set before TeX enters $$

138 \parindent=20pt

\hangindent=0pt, zeroed by TeX after each paragraph

\hoffset=0pt
\voffset=0pt

  \baselineskip=0pt, changed by \normalbaselines
  \lineskip=0pt, changed by \normalbaselines
139 \parskip=0pt plus 1pt
140 \abovedisplayskip=12pt plus 3pt minus 9pt
141 \abovedisplayshortskip=0pt plus 3pt
142 \belowdisplayskip=12pt plus 3pt minus 9pt
143 \belowdisplayshortskip=7pt plus 3pt minus 4pt
  \leftskip=0pt
  \rightskip=0pt
144 \topskip=10pt
145 \splittopskip=10pt
  \tabskip=0pt
  \spaceskip=0pt
  \xspaceskip=0pt
146 \parfillskip=0pt plus 1fil
\normalbaselineskip \normallineskip \normallineskiplimit We also define special registers that function like parameters:
147 \newskip\normalbaselineskip \normalbaselineskip=12pt
148 \newskip\normallineskip \normallineskip=1pt
149 \newdimen\normallineskiplimit \normallineskiplimit=0pt
\interfootlinepenalty
150 \newcount\interfootnotelinepenalty \interfootnotelinepenalty=100

Definitions for preloaded fonts

\magstephalf
\magstep
151 \def\magstephalf{1095 }
152 \def\magstep#1{\ifcase#1 \@m\or 1200\or 1440\or 1728\or
153  2074\or 2488\fi\relax}

Macros for setting ordinary text

\frenchspacing
\nonfrenchspacing
154 \def\frenchspacing{\sfcode`\.\@m \sfcode`\?\@m \sfcode`\!\@m
155 \sfcode`\:\@m \sfcode`\;\@m \sfcode`\,\@m}
156 \def\nonfrenchspacing{\sfcode`\.3000\sfcode`\?3000\sfcode`\!3000%
157 \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 }
\normalbaselines
158 \def\normalbaselines{\lineskip\normallineskip
159 \baselineskip\normalbaselineskip \lineskiplimit\normallineskiplimit}

{\M \atop \I} Save a bit of space by using \let here.

160 \def\^^M{\ } % control <return> = control <space>
161 \let\^^I\^^M % same for <tab>

{\lq \atop \rq}

162 \def\lq{`}
163 \def\rq{'}
\lbrack \rbrack
164 \def\lbrack{[}
165 \def\rbrack{]}
\endgraf \endline
166 \let\endgraf=\par
167 \let\endline=\cr
\space
168 \def\space{ }

\empty This probably ought to go altogether, but let it to the L^{A}TEX version to save space.

169 \let\empty\@empty
\null
170 \def\null{\hbox{}}
\bgroup \egroup
171 \let\bgroup={
172 \let\egroup=}
\obeylines \obeyspaces In \obeylines, we say \let^^M=\par instead of \def^^M{\par} since this allows,
 for example, \let\par=\cr \obeylines \halign{...
173 {\catcode`\^^M=\active % these lines must end with %
174 \gdef\obeylines{\catcode`\^^M\active \let^^M\par}%
175 \global\let^^M\par} % this is in case ^^M appears in a \write
176 \def\obeyspaces{\catcode`\ \active}
177 {\obeyspaces\global\let =\space}

\loop \iterate \repeat We use Kabelschacht’s method of doing loops, see TUB 8#2 (1987). (unless that breaks something :-). It turned out to need an extra \relax: see pr/642 (\loop could do one iteration too much in certain cases).

178 \long\def \loop #1\repeat{%
179 \def\iterate{#1\relax  % Extra \relax
180  \expandafter\iterate\fi

181 }%

182 \iterate
183 \let\iterate\relax

184 }

This setting of \repeat is needed to make \loop...\if...\repeat skippable within another \if....

185 \let\repeat=\fi
    L^{A}TEX defines \smallskip, etc. in ltspace.dtx.

\nointerlineskip
\offinterlineskip
186 \def\nointerlineskip{\prevdepth-\@m\p@}
187 \def\offinterlineskip{\baselineskip-\@m\p@
188 \lineskip\z@ \lineskiplimit\maxdimen}
\vglue \hglue
189 \def\vglue{\afterassignment\vgl@\skip@=}
190 \def\vgl@{\par \dimen@\prevdepth \hrule \@height\z@
191 \nobreak\vskip\skip@ \prevdepth\dimen@}
192 \def\hglue{\afterassignment\hgl@\skip@=}
193 \def\hgl@{\leavevmode \count@\spacefactor \vrule \@width\z@
194 \nobreak\hskip\skip@ \spacefactor\count@}

L^{A}TEX defines ~ in ltdefns.dtx.

\slash
195 \def\slash{/\penalty\exhyphenpenalty} % a `/' that acts like a `-'
\break \nobreak \allowbreak
196 \def\break{\penalty-\@M}
197 \def\nobreak{\penalty \@M}
198 \def\allowbreak{\penalty \z@}
\filbreak \goodbreak
199 \def\filbreak{\par\vfil\penalty-200\vfilneg}
200 \def\goodbreak{\par\penalty-500 }

\eject Define \eject as in plain TEX but only define \supereject in compatibility file.

201 \def\eject{\par\break}
\removelastskip
202 \def\removelastskip{\ifdim\lastskip=\z@\else\vskip-\lastskip\fi}
\smallbreak \medbreak \bigbreak
203 \def\smallbreak{\par\ifdim\lastskip<\smallskipamount
204 \removelastskip\penalty-50\smallskip\fi}
205 \def\medbreak{\par\ifdim\lastskip<\medskipamount
206 \removelastskip\penalty-100\medskip\fi}
207 \def\bigbreak{\par\ifdim\lastskip<\bigskipamount
208 \removelastskip\penalty-200\bigskip\fi}
\m@th
209 \def\m@th{\mathsurround\z@}

\underbar Due to L^{A}TEX’s redefinition of \underline plain TEX’s \underbar can be done in a simpler fashion (but do we need it at all?).

210 \def\underbar#1{\underline{\sbox\tw@{#1}\dp\tw@\z@\box\tw@}}

\strutbox \strut L^{A}TEX sets \strutbox in \set@fontsize.
211 \newbox\strutbox
212 \def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}

\hidewidth For alignment entries that can stick out.

213 \def\hidewidth{\hskip\hideskip}
\narrower
214 \def\narrower{%
215 \advance\leftskip\parindent
216 \advance\rightskip\parindent}

L^{A}TEX defines \ae and similar commands elsewhere.

217 \chardef\%=`\%
218 \chardef\&=`\&
219 \chardef\#=`\#

Most text commands are actually encoding specific and therefore defined later, so commented out or removed from this file.

\leavevmode begins a paragraph, if necessary

220 \def\leavevmode{\unhbox\voidb@x}
\mathhexbox
221 \def\mathhexbox#1#2#3{\mbox{$\m@th \mathchar"#1#2#3$}}
\ialign
222 \def\ialign{\everycr{}\tabskip\z@skip\halign} % initialized \halign
\oalign \o@lign \ooalign
223 \def\oalign#1{\leavevmode\vtop{\baselineskip\z@skip \lineskip.25ex%
224 \ialign{##\crcr#1\crcr}}}
225 \def\o@lign{\lineskiplimit\z@ \oalign}
226 \def\ooalign{\lineskiplimit-\maxdimen \oalign}
\sh@ft
227 \def\sh@ft#1{\dimen\z@.00#1ex\multiply\dimen\z@\fontdimen1\font
228 \kern-.0156\dimen\z@} % compensate for slant in lowered accents

L^{A}TEX change: \d, \b, \c, \copyright, \TeX defined elsewhere.

L^{A}TEX change: Make \t work in a moving argument. Now defined elsewhere.

\hrulefill \dotfill L^{A}TEX change: \kern\z@ added to end of \hrulefill and \dotfill to make them

work in ‘tabular’ and ‘array’ environments. (Change made 24 July 1987). L^{A}TEX change: \leavevmode added at begining of \dotfill and \hrulefill so that they work as expected in vertical mode.

229 \def\hrulefill{\leavevmode\leaders\hrule\hfill\kern\z@}
230 \def\dotfill{\leavevmode\cleaders
231  \hbox{$\m@th \mkern1.5mu.\mkern1.5mu$}\hfill\kern\z@}

INITEX sets \sfcode x=1000 for all x, except that \sfcode`X=999 for uppercase letters. The following changes are needed:

232 \sfcode`\)=0 \sfcode`\'=0 \sfcode`\]=0

The \nonfrenchspacing macro will make further changes to \sfcode values. Definitions related to output \magnification doesn’t work in L^{A}TEX.

 \def\magnification{\afterassignment\m@g\count@}
 \def\m@g{\mag\count@
   \hsize6.5truein\vsize8.9truein\dimen\footins8truein}

\showoverfull The following commands are used in debugging:

233 \def\showoverfull{\tracingonline\@ne}
\showoutput

234 ⟨/2ekernel | autoload⟩ 235 ⟨∗2ekernel | autoerr⟩

236 \gdef\showoutput{\tracingoutput\@ne
237  \showboxbreadth\maxdimen\showboxdepth\maxdimen\errorstopmode
238  \showoverfull}

239 ⟨/2ekernel | autoerr⟩

240 ⟨autoload⟩\def\showoutput{\@autoerr\showoutput}
\tracingall

241 ⟨∗2ekernel | autoerr⟩

242 \gdef\tracingall{\tracingcommands\tw@\tracingstats\tw@
243 \tracingpages\@ne\tracinglostchars\@ne
244 \tracingmacros\tw@\tracingparagraphs\@ne\tracingrestores\@ne
245 \errorcontextlines\maxdimen\showoutput}

246 ⟨/2ekernel | autoerr⟩

247 ⟨autoload⟩\def\tracingall{\@autoerr\tracingall}

L^{A}TEX change: \showhyphens Defined later.

punctuation affects the spacing

248 ⟨∗2ekernel | autoload⟩

249 \nonfrenchspacing

250 ⟨/2ekernel | autoload⟩