§220  TEX82  PART 17: THE TABLE OF EQUIVALENTS 81

220. The table of equivalents. Now that we have studied the data structures for TEX’s semantic routines, we ought to consider the data structures used by its syntactic routines. In other words, our next concern will be the tables that TEX looks at when it is scanning what the user has written.

The biggest and most important such table is called eqtb. It holds the current “equivalents” of things; i.e., it explains what things mean or what their current values are, for all quantities that are subject to the nesting structure provided by TEX’s grouping mechanism. There are six parts to eqtb:

1) eqtb[active base . . (hash base − 1)] holds the current equivalents of single-character control sequences.

2) eqtb[hash base . . (glue base − 1)] holds the current equivalents of multiletter control sequences.

3) eqtb[glue base . . (local base − 1)] holds the current equivalents of glue parameters like the current baselineskip.

4) eqtb[local base . . (int base − 1)] holds the current equivalents of local halfword quantities like the current box registers, the current “catcodes,” the current font, and a pointer to the current paragraph shape.

5) eqtb[int base . . (dimen base − 1)] holds the current equivalents of fullword integer parameters like the current hyphenation penalty.

6) eqtb[dimen base . . eqtb size] holds the current equivalents of fullword dimension parameters like the current hsize or amount of hanging indentation.

Note that, for example, the current amount of baselineskip glue is determined by the setting of a particular location in region 3 of eqtb, while the current meaning of the control sequence ‘ ’ (which might

have been changed by  or  ) appears in region 2.

221. Each entry in eqtb is a memory word . Most of these words are of type two halves , and subdivided into three fields:

1) The eq level (a quarterword) is the level of grouping at which this equivalent was defined. If the level is level zero, the equivalent has never been defined; level one refers to the outer level (outside of all groups), and this level is also used for global definitions that never go away. Higher levels are for equivalents that will disappear at the end of their group.

2) The eq type (another quarterword) specifies what kind of entry this is. There are many types, since each TEX primitive like , , etc., has its own special code. The list of command codes above includes all possible settings of the eq type field.

3) The equiv (a halfword) is the current equivalent value. This may be a font number, a pointer into mem,

82  PART 17: THE TABLE OF EQUIVALENTS  TEX82 §222

or a variety of other things. define eq level field (#) ≡ #.hh.b1 define eq type field (#) ≡ #.hh.b0 define equiv field (#) ≡ #.hh.rh define eq level (#) ≡ eq level field (eqtb[#]) { level of definition } define eq type(#) ≡ eq type field (eqtb[#]) { command code for equivalent } define equiv (#) ≡ equiv field (eqtb[#]) { equivalent value } define level zero = min quarterword { level for undefined quantities } define level one = level zero + 1 { outermost level for defined quantities } 222. Many locations in eqtb have symbolic names. The purpose of the next paragraphs is to define these names, and to set up the initial values of the equivalents.

In the first region we have 256 equivalents for “active characters” that act as control sequences, followed by 256 equivalents for single-character control sequences.

Then comes region 2, which corresponds to the hash table that we will define later. The maximum address in this region is used for a dummy control sequence that is perpetually undefined. There also are several locations for control sequences that are perpetually defined (since they are used in error recovery).

define active base = 1 { beginning of region 1, for active character equivalents } define single base = active base + 256 { equivalents of one-character control sequences } define null cs = single base + 256 { equivalent of } define hash base = null cs + 1 { beginning of region 2, for the hash table } define frozen control sequence = hash base + hash size { for error recovery } define frozen protection = frozen control sequence { inaccessible but definable } define frozen cr = frozen control sequence + 1 { permanent ‘ ’ } define frozen end group = frozen control sequence + 2 { permanent ‘ ’ } define frozen right = frozen control sequence + 3 { permanent ‘ ’ } define frozen fi = frozen control sequence + 4 { permanent ‘ ’ } define frozen end template = frozen control sequence + 5 { permanent ‘ ’ } define frozen endv = frozen control sequence + 6 { second permanent ‘ ’ } define frozen relax = frozen control sequence + 7 { permanent ‘ ’ } define end write = frozen control sequence + 8 { permanent ‘ ’ } define frozen dont expand = frozen control sequence + 9 { permanent ‘ ’ } define frozen null font = frozen control sequence + 10 { permanent ‘ ’ } define font id base = frozen null font − font base { begins table of 257 permanent font identifiers } define undefined control sequence = frozen null font + 257 { dummy location } define glue base = undefined control sequence + 1 { beginning of region 3 }

⟨ Initialize table entries (done by only) 164 ⟩ +≡ eq type(undefined control sequence) ← undefined cs ; equiv (undefined control sequence) ← null ; eq level (undefined control sequence) ← level zero; for k ← active base to undefined control sequence − 1 do eqtb[k] ← eqtb[undefined control sequence];

223. Here is a routine that displays the current meaning of an eqtb entry in region 1 or 2. (Similar routines for the other regions will appear below.) ⟨ Show equivalent n, in region 1 or 2 223 ⟩ ≡

begin sprint cs (n); print char ( ); print cmd chr (eq type(n), equiv (n)); if eq type(n) ≥ call then

begin print char ( ); show token list (link (equiv (n)), null , 32); end;

end

This code is used in section 252.

224. Region 3 of eqtb contains the 256 registers, as well as the glue parameters defined here. It is important that the “muskip” parameters have larger numbers than the others.

define line skip code = 0 { interline glue if baseline skip is infeasible } define baseline skip code = 1 { desired glue between baselines } define par skip code = 2 { extra glue just above a paragraph } define above display skip code = 3 { extra glue just above displayed math } define below display skip code = 4 { extra glue just below displayed math } define above display short skip code = 5 { glue above displayed math following short lines } define below display short skip code = 6 { glue below displayed math following short lines } define left skip code = 7 { glue at left of justified lines } define right skip code = 8 { glue at right of justified lines } define top skip code = 9 { glue at top of main pages } define split top skip code = 10 { glue at top of split pages } define tab skip code = 11 { glue between aligned entries } define space skip code = 12 { glue between words (if not zero glue) } define xspace skip code = 13 { glue after sentences (if not zero glue) } define par fill skip code = 14 { glue on last line of paragraph } define thin mu skip code = 15 { thin space in math formula } define med mu skip code = 16 { medium space in math formula } define thick mu skip code = 17 { thick space in math formula } define glue pars = 18 { total number of glue parameters } define skip base = glue base + glue pars { table of 256 “skip” registers } define mu skip base = skip base + 256 { table of 256 “muskip” registers } define local base = mu skip base + 256 { beginning of region 4 } define skip(#) ≡ equiv (skip base + #) { mem location of glue specification } define mu skip(#) ≡ equiv (mu skip base + #) { mem location of math glue spec } define glue par (#) ≡ equiv (glue base + #) { mem location of glue specification } define line skip ≡ glue par (line skip code) define baseline skip ≡ glue par (baseline skip code) define par skip ≡ glue par (par skip code) define above display skip ≡ glue par (above display skip code) define below display skip ≡ glue par (below display skip code) define above display short skip ≡ glue par (above display short skip code) define below display short skip ≡ glue par (below display short skip code) define left skip ≡ glue par (left skip code) define right skip ≡ glue par (right skip code) define top skip ≡ glue par (top skip code) define split top skip ≡ glue par (split top skip code) define tab skip ≡ glue par (tab skip code) define space skip ≡ glue par (space skip code) define xspace skip ≡ glue par (xspace skip code) define par fill skip ≡ glue par (par fill skip code) define thin mu skip ≡ glue par (thin mu skip code) define med mu skip ≡ glue par (med mu skip code) define thick mu skip ≡ glue par (thick mu skip code)

⟨ Current mem equivalent of glue parameter number n 224 ⟩ ≡

glue par (n)

This code is used in sections 152 and 154.

225. Sometimes we need to convert TEX’s internal code numbers into symbolic form. The print skip param routine gives the symbolic name of a glue parameter. ⟨ Declare the procedure called print skip param 225 ⟩ ≡ procedure print skip param(n : integer );

begin case n of

line skip code: print esc( ); baseline skip code: print esc( ); par skip code: print esc( ); above display skip code: print esc( ); below display skip code: print esc( ); above display short skip code: print esc( ); below display short skip code: print esc( ); left skip code: print esc( ); right skip code: print esc( ); top skip code: print esc( ); split top skip code: print esc( ); tab skip code: print esc( ); space skip code: print esc( ); xspace skip code: print esc( ); par fill skip code: print esc( ); thin mu skip code: print esc( ); med mu skip code: print esc( ); thick mu skip code: print esc( ); othercases print ( ␣ ␣ ) endcases; end;

This code is used in section 179.

226. The symbolic names for glue parameters are put into TEX’s hash table by using the routine called primitive, defined below. Let us enter them now, so that we don’t have to list all those parameter names anywhere else. ⟨ Put each of TEX’s primitives into the hash table 226 ⟩ ≡

primitive( , assign glue, glue base + line skip code); primitive( , assign glue, glue base + baseline skip code); primitive( , assign glue, glue base + par skip code); primitive( , assign glue, glue base + above display skip code); primitive( , assign glue, glue base + below display skip code); primitive( , assign glue, glue base + above display short skip code); primitive( , assign glue, glue base + below display short skip code); primitive( , assign glue, glue base + left skip code); primitive( , assign glue, glue base + right skip code); primitive( , assign glue, glue base + top skip code); primitive( , assign glue, glue base + split top skip code); primitive( , assign glue, glue base + tab skip code); primitive( , assign glue, glue base + space skip code); primitive( , assign glue, glue base + xspace skip code); primitive( , assign glue, glue base + par fill skip code); primitive( , assign mu glue, glue base + thin mu skip code); primitive( , assign mu glue, glue base + med mu skip code); primitive( , assign mu glue, glue base + thick mu skip code);

See also sections 230, 238, 248, 265, 334, 376, 384, 411, 416, 468, 487, 491, 553, 780, 983, 1052, 1058, 1071, 1088, 1107, 1114,

1141, 1156, 1169, 1178, 1188, 1208, 1219, 1222, 1230, 1250, 1254, 1262, 1272, 1277, 1286, 1291, and 1344. This code is used in section 1336.

227. ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ ≡ assign glue, assign mu glue: if chr code < skip base then print skip param(chr code − glue base)

else if chr code < mu skip base then begin print esc( ); print int (chr code − skip base); end

else begin print esc( ); print int (chr code − mu skip base);

end;

See also sections 231, 239, 249, 266, 335, 377, 385, 412, 417, 469, 488, 492, 781, 984, 1053, 1059, 1072, 1089, 1108, 1115, 1143,

1157, 1170, 1179, 1189, 1209, 1220, 1223, 1231, 1251, 1255, 1261, 1263, 1273, 1278, 1287, 1292, 1295, and 1346. This code is used in section 298.

228. All glue parameters and registers are initially ‘ ’. ⟨ Initialize table entries (done by only) 164 ⟩ +≡

equiv (glue base) ← zero glue; eq level (glue base) ← level one; eq type(glue base) ← glue ref ; for k ← glue base + 1 to local base − 1 do eqtb[k] ← eqtb[glue base]; glue ref count (zero glue) ← glue ref count (zero glue) + local base − glue base; 229. ⟨ Show equivalent n, in region 3 229 ⟩ ≡

if n < skip base then begin print skip param(n − glue base); print char ( ); if n < glue base + thin mu skip code then print spec(equiv (n), ) else print spec(equiv (n), ); end

else if n < mu skip base then begin print esc( ); print int (n − skip base); print char ( ); print spec(equiv (n), ); end

else begin print esc( ); print int (n − mu skip base); print char ( ); print spec(equiv (n), ); end

This code is used in section 252.

230. Region 4 of eqtb contains the local quantities defined here. The bulk of this region is taken up by five tables that are indexed by eight-bit characters; these tables are important to both the syntactic and semantic portions of TEX. There are also a bunch of special things like font and token parameters, as well as the tables of and registers.

define par shape loc = local base { specifies paragraph shape } define output routine loc = local base + 1 { points to token list for } define every par loc = local base + 2 { points to token list for } define every math loc = local base + 3 { points to token list for } define every display loc = local base + 4 { points to token list for } define every hbox loc = local base + 5 { points to token list for } define every vbox loc = local base + 6 { points to token list for } define every job loc = local base + 7 { points to token list for } define every cr loc = local base + 8 { points to token list for } define err help loc = local base + 9 { points to token list for } define toks base = local base + 10 { table of 256 token list registers } define box base = toks base + 256 { table of 256 box registers } define cur font loc = box base + 256 { internal font number outside math mode } define math font base = cur font loc + 1 { table of 48 math font numbers } define cat code base = math font base + 48 { table of 256 command codes (the “catcodes”) } define lc code base = cat code base + 256 { table of 256 lowercase mappings } define uc code base = lc code base + 256 { table of 256 uppercase mappings } define sf code base = uc code base + 256 { table of 256 spacefactor mappings } define math code base = sf code base + 256 { table of 256 math mode mappings } define int base = math code base + 256 { beginning of region 5 } define par shape ptr ≡ equiv (par shape loc) define output routine ≡ equiv (output routine loc) define every par ≡ equiv (every par loc) define every math ≡ equiv (every math loc) define every display ≡ equiv (every display loc) define every hbox ≡ equiv (every hbox loc) define every vbox ≡ equiv (every vbox loc) define every job ≡ equiv (every job loc) define every cr ≡ equiv (every cr loc) define err help ≡ equiv (err help loc) define toks (#) ≡ equiv (toks base + #) define box (#) ≡ equiv (box base + #) define cur font ≡ equiv (cur font loc) define fam fnt (#) ≡ equiv (math font base + #) define cat code(#) ≡ equiv (cat code base + #) define lc code(#) ≡ equiv (lc code base + #) define uc code(#) ≡ equiv (uc code base + #) define sf code(#) ≡ equiv (sf code base + #) define math code(#) ≡ equiv (math code base + #)

{ Note: math code(c) is the true math code plus min halfword }

⟨ Put each of TEX’s primitives into the hash table 226 ⟩ +≡ primitive( , assign toks , output routine loc); primitive( , assign toks , every par loc); primitive( , assign toks , every math loc); primitive( , assign toks , every display loc);

primitive(  , assign toks , every hbox loc); primitive(  , assign toks , every vbox loc);
primitive(  , assign toks , every job loc); primitive(  , assign toks , every cr loc);

primitive( , assign toks , err help loc); 231. ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ assign toks : if chr code ≥ toks base then

begin print esc( ); print int (chr code − toks base); end

else case chr code of

output routine loc: print esc( ); every par loc: print esc( ); every math loc: print esc( ); every display loc: print esc( ); every hbox loc: print esc( ); every vbox loc: print esc( ); every job loc: print esc( ); every cr loc: print esc( ); othercases print esc( ) endcases;

232. We initialize most things to null or undefined values. An undefined font is represented by the internal code font base.

However, the character code tables are given initial values based on the conventional interpretation of ASCII code. These initial values should not be changed when TEX is adapted for use with non-English languages; all changes to the initialization conventions should be made in format packages, not in TEX itself, so that global interchange of formats is possible.

define null font ≡ font base define var code ≡ ´ 70000 { math code meaning “use the current family” }

⟨ Initialize table entries (done by only) 164 ⟩ +≡ par shape ptr ← null ; eq type(par shape loc) ← shape ref ; eq level (par shape loc) ← level one; for k ← output routine loc to toks base + 255 do eqtb[k] ← eqtb[undefined control sequence]; box (0) ← null ; eq type(box base) ← box ref ; eq level (box base) ← level one; for k ← box base + 1 to box base + 255 do eqtb[k] ← eqtb[box base]; cur font ← null font ; eq type(cur font loc) ← data; eq level (cur font loc) ← level one; for k ← math font base to math font base + 47 do eqtb[k] ← eqtb[cur font loc]; equiv (cat code base) ← 0; eq type(cat code base) ← data; eq level (cat code base) ← level one; for k ← cat code base + 1 to int base − 1 do eqtb[k] ← eqtb[cat code base]; for k ← 0 to 255 do

begin cat code(k) ← other char ; math code(k) ← hi (k); sf code(k) ← 1000; end;

cat code(carriage return) ← car ret ; cat code( ␣ ) ← spacer ; cat code( ) ← escape; cat code( % ) ← comment ; cat code(invalid code) ← invalid char ; cat code(null code) ← ignore;

for k ←  to  do math code(k) ← hi (k + var code);
for k ←  to  do

begin cat code(k) ← letter ; cat code(k + − ) ← letter ; math code(k) ← hi (k + var code + ˝ 100);

math code(k +  − ) ← hi (k +  −  + var code + ˝ 100);
lc code(k) ← k +  − ; lc code(k +  − ) ← k +  − ;

uc code(k) ← k; uc code(k + − ) ← k; sf code(k) ← 999; end; 233. ⟨ Show equivalent n, in region 4 233 ⟩ ≡

if n = par shape loc then begin print esc( ); print char ( ); if par shape ptr = null then print char ( ) else print int (info(par shape ptr )); end

else if n < toks base then begin print cmd chr (assign toks , n); print char ( ); if equiv (n) ≠ null then show token list (link (equiv (n)), null , 32); end

else if n < box base then begin print esc( ); print int (n − toks base); print char ( ); if equiv (n) ≠ null then show token list (link (equiv (n)), null , 32); end

else if n < cur font loc then begin print esc( ); print int (n − box base); print char ( ); if equiv (n) = null then print ( ) else begin depth threshold ← 0; breadth max ← 1; show node list (equiv (n));

end; end

else if n < cat code base then ⟨ Show the font identifier in eqtb[n] 234 ⟩

else ⟨ Show the halfword code in eqtb[n] 235 ⟩

This code is used in section 252.

234. ⟨ Show the font identifier in eqtb[n] 234 ⟩ ≡ begin if n = cur font loc then print ( ␣ ) else if n < math font base + 16 then

begin print esc( ); print int (n − math font base);

end else if n < math font base + 32 then

begin print esc( ); print int (n − math font base − 16); end

else begin print esc( ); print int (n − math font base − 32);

end; print char ( ); print esc(hash[font id base + equiv (n)].rh); { that’s font id text (equiv (n)) } end

This code is used in section 233.

235. ⟨ Show the halfword code in eqtb[n] 235 ⟩ ≡

if n < math code base then

begin if n < lc code base then begin print esc( ); print int (n − cat code base); end

else if n < uc code base then begin print esc( ); print int (n − lc code base); end

else if n < sf code base then begin print esc( ); print int (n − uc code base); end

else begin print esc( ); print int (n − sf code base);

end; print char ( ); print int (equiv (n)); end

else begin print esc( ); print int (n − math code base); print char ( ); print int (ho(equiv (n))); end

This code is used in section 233.

236. Region 5 of eqtb contains the integer parameters and registers defined here, as well as the del code table. The latter table differs from the cat code . . math code tables that precede it, since delimiter codes are fullword integers while the other kinds of codes occupy at most a halfword. This is what makes region 5 different from region 4. We will store the eq level information in an auxiliary array of quarterwords that will be defined later.

define pretolerance code = 0 { badness tolerance before hyphenation } define tolerance code = 1 { badness tolerance after hyphenation } define line penalty code = 2 { added to the badness of every line } define hyphen penalty code = 3 { penalty for break after discretionary hyphen } define ex hyphen penalty code = 4 { penalty for break after explicit hyphen } define club penalty code = 5 { penalty for creating a club line } define widow penalty code = 6 { penalty for creating a widow line } define display widow penalty code = 7 { ditto, just before a display } define broken penalty code = 8 { penalty for breaking a page at a broken line } define bin op penalty code = 9 { penalty for breaking after a binary operation } define rel penalty code = 10 { penalty for breaking after a relation } define pre display penalty code = 11 { penalty for breaking just before a displayed formula } define post display penalty code = 12 { penalty for breaking just after a displayed formula } define inter line penalty code = 13 { additional penalty between lines } define double hyphen demerits code = 14 { demerits for double hyphen break } define final hyphen demerits code = 15 { demerits for final hyphen break } define adj demerits code = 16 { demerits for adjacent incompatible lines } define mag code = 17 { magnification ratio } define delimiter factor code = 18 { ratio for variable-size delimiters } define looseness code = 19 { change in number of lines for a paragraph } define time code = 20 { current time of day } define day code = 21 { current day of the month } define month code = 22 { current month of the year } define year code = 23 { current year of our Lord } define show box breadth code = 24 { nodes per level in show box } define show box depth code = 25 { maximum level in show box } define hbadness code = 26 { hboxes exceeding this badness will be shown by hpack } define vbadness code = 27 { vboxes exceeding this badness will be shown by vpack } define pausing code = 28 { pause after each line is read from a file } define tracing online code = 29 { show diagnostic output on terminal } define tracing macros code = 30 { show macros as they are being expanded } define tracing stats code = 31 { show memory usage if TEX knows it } define tracing paragraphs code = 32 { show line-break calculations } define tracing pages code = 33 { show page-break calculations } define tracing output code = 34 { show boxes when they are shipped out } define tracing lost chars code = 35 { show characters that aren’t in the font } define tracing commands code = 36 { show command codes at big switch } define tracing restores code = 37 { show equivalents when they are restored } define uc hyph code = 38 { hyphenate words beginning with a capital letter } define output penalty code = 39 { penalty found at current page break } define max dead cycles code = 40 { bound on consecutive dead cycles of output } define hang after code = 41 { hanging indentation changes after this many lines } define floating penalty code = 42 { penalty for insertions heldover after a split } define global defs code = 43 { override specifications } define cur fam code = 44 { current family } define escape char code = 45 { escape character for token output } define default hyphen char code = 46 { value of when a font is loaded } define default skew char code = 47 { value of when a font is loaded } define end line char code = 48 { character placed at the right end of the buffer } define new line char code = 49 { character that prints as print ln } define language code = 50 { current hyphenation table } define left hyphen min code = 51 { minimum left hyphenation fragment size } define right hyphen min code = 52 { minimum right hyphenation fragment size } define holding inserts code = 53 { do not remove insertion nodes from } define error context lines code = 54 { maximum intermediate line pairs shown } define int pars = 55 { total number of integer parameters } define count base = int base + int pars { 256 user registers } define del code base = count base + 256 { 256 delimiter code mappings } define dimen base = del code base + 256 { beginning of region 6 }

define del code(#) ≡ eqtb[del code base + #].int define count (#) ≡ eqtb[count base + #].int define int par (#) ≡ eqtb[int base + #].int { an integer parameter } define pretolerance ≡ int par (pretolerance code) define tolerance ≡ int par (tolerance code) define line penalty ≡ int par (line penalty code) define hyphen penalty ≡ int par (hyphen penalty code) define ex hyphen penalty ≡ int par (ex hyphen penalty code) define club penalty ≡ int par (club penalty code) define widow penalty ≡ int par (widow penalty code) define display widow penalty ≡ int par (display widow penalty code) define broken penalty ≡ int par (broken penalty code) define bin op penalty ≡ int par (bin op penalty code) define rel penalty ≡ int par (rel penalty code) define pre display penalty ≡ int par (pre display penalty code) define post display penalty ≡ int par (post display penalty code) define inter line penalty ≡ int par (inter line penalty code) define double hyphen demerits ≡ int par (double hyphen demerits code) define final hyphen demerits ≡ int par (final hyphen demerits code) define adj demerits ≡ int par (adj demerits code) define mag ≡ int par (mag code) define delimiter factor ≡ int par (delimiter factor code) define looseness ≡ int par (looseness code) define time ≡ int par (time code) define day ≡ int par (day code) define month ≡ int par (month code) define year ≡ int par (year code) define show box breadth ≡ int par (show box breadth code) define show box depth ≡ int par (show box depth code) define hbadness ≡ int par (hbadness code) define vbadness ≡ int par (vbadness code) define pausing ≡ int par (pausing code) define tracing online ≡ int par (tracing online code) define tracing macros ≡ int par (tracing macros code) define tracing stats ≡ int par (tracing stats code) define tracing paragraphs ≡ int par (tracing paragraphs code) define tracing pages ≡ int par (tracing pages code) define tracing output ≡ int par (tracing output code) define tracing lost chars ≡ int par (tracing lost chars code) define tracing commands ≡ int par (tracing commands code) define tracing restores ≡ int par (tracing restores code) define uc hyph ≡ int par (uc hyph code) define output penalty ≡ int par (output penalty code) define max dead cycles ≡ int par (max dead cycles code) define hang after ≡ int par (hang after code) define floating penalty ≡ int par (floating penalty code) define global defs ≡ int par (global defs code) define cur fam ≡ int par (cur fam code) define escape char ≡ int par (escape char code) define default hyphen char ≡ int par (default hyphen char code) define default skew char ≡ int par (default skew char code) define end line char ≡ int par (end line char code) define new line char ≡ int par (new line char code) define language ≡ int par (language code) define left hyphen min ≡ int par (left hyphen min code) define right hyphen min ≡ int par (right hyphen min code) define holding inserts ≡ int par (holding inserts code) define error context lines ≡ int par (error context lines code)

⟨ Assign the values depth threshold ← show box depth and breadth max ← show box breadth 236 ⟩ ≡

depth threshold ← show box depth; breadth max ← show box breadth

This code is used in section 198.

237. We can print the symbolic name of an integer parameter as follows.

procedure print param(n : integer );

begin case n of

pretolerance code: print esc( ); tolerance code: print esc( ); line penalty code: print esc( ); hyphen penalty code: print esc( ); ex hyphen penalty code: print esc( ); club penalty code: print esc( ); widow penalty code: print esc( ); display widow penalty code: print esc( ); broken penalty code: print esc( ); bin op penalty code: print esc( ); rel penalty code: print esc( ); pre display penalty code: print esc( ); post display penalty code: print esc( ); inter line penalty code: print esc( ); double hyphen demerits code: print esc( ); final hyphen demerits code: print esc( ); adj demerits code: print esc( ); mag code: print esc( ); delimiter factor code: print esc( ); looseness code: print esc( ); time code: print esc( ); day code: print esc( ); month code: print esc( ); year code: print esc( ); show box breadth code: print esc( ); show box depth code: print esc( ); hbadness code: print esc( ); vbadness code: print esc( ); pausing code: print esc( ); tracing online code: print esc( ); tracing macros code: print esc( ); tracing stats code: print esc( ); tracing paragraphs code: print esc( ); tracing pages code: print esc( ); tracing output code: print esc( ); tracing lost chars code: print esc( ); tracing commands code: print esc( ); tracing restores code: print esc( ); uc hyph code: print esc( ); output penalty code: print esc( ); max dead cycles code: print esc( ); hang after code: print esc( ); floating penalty code: print esc( ); global defs code: print esc( ); cur fam code: print esc( ); escape char code: print esc( ); default hyphen char code: print esc( ); default skew char code: print esc( ); end line char code: print esc( ); new line char code: print esc( ); language code: print esc( ); left hyphen min code: print esc( ); right hyphen min code: print esc( ); holding inserts code: print esc( ); error context lines code: print esc( ); othercases print ( ␣ ␣ ) endcases; end; 238. The integer parameter names must be entered into the hash table.

⟨ Put each of TEX’s primitives into the hash table 226 ⟩ +≡ primitive( , assign int , int base + pretolerance code); primitive( , assign int , int base + tolerance code); primitive( , assign int , int base + line penalty code); primitive( , assign int , int base + hyphen penalty code); primitive( , assign int , int base + ex hyphen penalty code); primitive( , assign int , int base + club penalty code); primitive( , assign int , int base + widow penalty code); primitive( , assign int , int base + display widow penalty code); primitive( , assign int , int base + broken penalty code); primitive( , assign int , int base + bin op penalty code); primitive( , assign int , int base + rel penalty code); primitive( , assign int , int base + pre display penalty code); primitive( , assign int , int base + post display penalty code); primitive( , assign int , int base + inter line penalty code); primitive( , assign int , int base + double hyphen demerits code); primitive( , assign int , int base + final hyphen demerits code); primitive( , assign int , int base + adj demerits code); primitive( , assign int , int base + mag code); primitive( , assign int , int base + delimiter factor code); primitive( , assign int , int base + looseness code); primitive( , assign int , int base + time code); primitive( , assign int , int base + day code); primitive( , assign int , int base + month code); primitive( , assign int , int base + year code); primitive( , assign int , int base + show box breadth code); primitive( , assign int , int base + show box depth code); primitive( , assign int , int base + hbadness code); primitive( , assign int , int base + vbadness code); primitive( , assign int , int base + pausing code); primitive( , assign int , int base + tracing online code); primitive( , assign int , int base + tracing macros code); primitive( , assign int , int base + tracing stats code); primitive( , assign int , int base + tracing paragraphs code); primitive( , assign int , int base + tracing pages code); primitive( , assign int , int base + tracing output code); primitive( , assign int , int base + tracing lost chars code); primitive( , assign int , int base + tracing commands code); primitive( , assign int , int base + tracing restores code); primitive( , assign int , int base + uc hyph code); primitive( , assign int , int base + output penalty code); primitive( , assign int , int base + max dead cycles code); primitive( , assign int , int base + hang after code); primitive( , assign int , int base + floating penalty code); primitive( , assign int , int base + global defs code); primitive( , assign int , int base + cur fam code); primitive( , assign int , int base + escape char code); primitive( , assign int , int base + default hyphen char code); primitive( , assign int , int base + default skew char code); primitive( , assign int , int base + end line char code); primitive( , assign int , int base + new line char code); primitive( , assign int , int base + language code); primitive( , assign int , int base + left hyphen min code); primitive( , assign int , int base + right hyphen min code); primitive( , assign int , int base + holding inserts code); primitive( , assign int , int base + error context lines code);

239. ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ assign int : if chr code < count base then print param(chr code − int base)

else begin print esc( ); print int (chr code − count base); end;

240. The integer parameters should really be initialized by a macro package; the following initialization does the minimum to keep TEX from complete failure. ⟨ Initialize table entries (done by only) 164 ⟩ +≡

for k ← int base to del code base − 1 do eqtb[k].int ← 0; mag ← 1000; tolerance ← 10000; hang after ← 1; max dead cycles ← 25; escape char ← ; end line char ← carriage return; for k ← 0 to 255 do del code(k) ← −1; del code( ) ← 0; { this null delimiter is used in error recovery }

241. The following procedure, which is called just before TEX initializes its input and output, establishes the initial values of the date and time. Since standard Pascal cannot provide such information, something special is needed. The program here simply specifies July 4, 1776, at noon; but users probably want a better approximation to the truth. procedure fix date and time;

begin time ← 12 ∗ 60; { minutes since midnight } day ← 4; { fourth day of the month } month ← 7; { seventh month of the year } year ← 1776; { Anno Domini } end;

242. ⟨ Show equivalent n, in region 5 242 ⟩ ≡ begin if n < count base then print param(n − int base) else if n < del code base then

begin print esc( ); print int (n − count base); end

else begin print esc( ); print int (n − del code base);

end; print char ( ); print int (eqtb[n].int ); end

This code is used in section 252.

243. ⟨ Set variable c to the current escape character 243 ⟩ ≡ c ← escape char

This code is used in section 63.

244. ⟨ Character s is the current new-line character 244 ⟩ ≡ s = new line char

This code is used in sections 58 and 59.

245. TEX is occasionally supposed to print diagnostic information that goes only into the transcript file, unless tracing online is positive. Here are two routines that adjust the destination of print commands: procedure begin diagnostic; { prepare to do some tracing }

begin old setting ← selector ;

if (tracing online ≤ 0) ∧ (selector = term and log ) then begin decr (selector ); if history = spotless then history ← warning issued ; end;

end; procedure end diagnostic(blank line : boolean); { restore proper conditions after tracing }

begin print nl ( );

if blank line then print ln;

selector ← old setting ;

end;

246. Of course we had better declare another global variable, if the previous routines are going to work. ⟨ Global variables 13 ⟩ +≡ old setting : 0 . . max selector ; 247. The final region of eqtb contains the dimension parameters defined here, and the 256 registers.

define par indent code = 0 { indentation of paragraphs } define math surround code = 1 { space around math in text } define line skip limit code = 2 { threshold for line skip instead of baseline skip } define hsize code = 3 { line width in horizontal mode } define vsize code = 4 { page height in vertical mode } define max depth code = 5 { maximum depth of boxes on main pages } define split max depth code = 6 { maximum depth of boxes on split pages } define box max depth code = 7 { maximum depth of explicit vboxes } define hfuzz code = 8 { tolerance for overfull hbox messages } define vfuzz code = 9 { tolerance for overfull vbox messages } define delimiter shortfall code = 10 { maximum amount uncovered by variable delimiters } define null delimiter space code = 11 { blank space in null delimiters } define script space code = 12 { extra space after subscript or superscript } define pre display size code = 13 { length of text preceding a display } define display width code = 14 { length of line for displayed equation } define display indent code = 15 { indentation of line for displayed equation } define overfull rule code = 16 { width of rule that identifies overfull hboxes } define hang indent code = 17 { amount of hanging indentation } define h offset code = 18 { amount of horizontal offset when shipping pages out } define v offset code = 19 { amount of vertical offset when shipping pages out } define emergency stretch code = 20 { reduces badnesses on final pass of line-breaking } define dimen pars = 21 { total number of dimension parameters } define scaled base = dimen base + dimen pars { table of 256 user-defined registers } define eqtb size = scaled base + 255 { largest subscript of eqtb } define dimen(#) ≡ eqtb[scaled base + #].sc define dimen par (#) ≡ eqtb[dimen base + #].sc { a scaled quantity } define par indent ≡ dimen par (par indent code) define math surround ≡ dimen par (math surround code) define line skip limit ≡ dimen par (line skip limit code) define hsize ≡ dimen par (hsize code) define vsize ≡ dimen par (vsize code) define max depth ≡ dimen par (max depth code) define split max depth ≡ dimen par (split max depth code) define box max depth ≡ dimen par (box max depth code) define hfuzz ≡ dimen par (hfuzz code) define vfuzz ≡ dimen par (vfuzz code) define delimiter shortfall ≡ dimen par (delimiter shortfall code) define null delimiter space ≡ dimen par (null delimiter space code) define script space ≡ dimen par (script space code) define pre display size ≡ dimen par (pre display size code) define display width ≡ dimen par (display width code) define display indent ≡ dimen par (display indent code) define overfull rule ≡ dimen par (overfull rule code) define hang indent ≡ dimen par (hang indent code) define h offset ≡ dimen par (h offset code) define v offset ≡ dimen par (v offset code) define emergency stretch ≡ dimen par (emergency stretch code)

procedure print length param(n : integer );

begin case n of

par indent code: print esc( ); math surround code: print esc( ); line skip limit code: print esc( ); hsize code: print esc( ); vsize code: print esc( ); max depth code: print esc( ); split max depth code: print esc( ); box max depth code: print esc( ); hfuzz code: print esc( ); vfuzz code: print esc( ); delimiter shortfall code: print esc( ); null delimiter space code: print esc( ); script space code: print esc( ); pre display size code: print esc( ); display width code: print esc( ); display indent code: print esc( ); overfull rule code: print esc( ); hang indent code: print esc( ); h offset code: print esc( ); v offset code: print esc( ); emergency stretch code: print esc( ); othercases print ( ␣ ␣ ) endcases; end;

248. ⟨ Put each of TEX’s primitives into the hash table 226 ⟩ +≡ primitive( , assign dimen, dimen base + par indent code); primitive( , assign dimen, dimen base + math surround code); primitive( , assign dimen, dimen base + line skip limit code); primitive( , assign dimen, dimen base + hsize code); primitive( , assign dimen, dimen base + vsize code); primitive( , assign dimen, dimen base + max depth code); primitive( , assign dimen, dimen base + split max depth code); primitive( , assign dimen, dimen base + box max depth code); primitive( , assign dimen, dimen base + hfuzz code); primitive( , assign dimen, dimen base + vfuzz code); primitive( , assign dimen, dimen base + delimiter shortfall code); primitive( , assign dimen, dimen base + null delimiter space code); primitive( , assign dimen, dimen base + script space code); primitive( , assign dimen, dimen base + pre display size code); primitive( , assign dimen, dimen base + display width code); primitive( , assign dimen, dimen base + display indent code); primitive( , assign dimen, dimen base + overfull rule code); primitive( , assign dimen, dimen base + hang indent code); primitive( , assign dimen, dimen base + h offset code); primitive( , assign dimen, dimen base + v offset code); primitive( , assign dimen, dimen base + emergency stretch code);

249. ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ assign dimen: if chr code < scaled base then print length param(chr code − dimen base)

else begin print esc( ); print int (chr code − scaled base); end; 250. ⟨ Initialize table entries (done by only) 164 ⟩ +≡

for k ← dimen base to eqtb size do eqtb[k].sc ← 0;

251. ⟨ Show equivalent n, in region 6 251 ⟩ ≡ begin if n < scaled base then print length param(n − dimen base) else begin print esc( ); print int (n − scaled base);

end; print char ( ); print scaled (eqtb[n].sc); print ( ); end

This code is used in section 252.

252. Here is a procedure that displays the contents of eqtb[n] symbolically. ⟨ Declare the procedure called print cmd chr 298 ⟩

stat procedure show eqtb(n : pointer );

begin if n < active base then print char ( ) { this can’t happen } else if n < glue base then ⟨ Show equivalent n, in region 1 or 2 223 ⟩

else if n < local base then ⟨ Show equivalent n, in region 3 229 ⟩ else if n < int base then ⟨ Show equivalent n, in region 4 233 ⟩

else if n < dimen base then ⟨ Show equivalent n, in region 5 242 ⟩ else if n ≤ eqtb size then ⟨ Show equivalent n, in region 6 251 ⟩

else print char ( ); { this can’t happen either }

end;

tats

253. The last two regions of eqtb have fullword values instead of the three fields eq level , eq type, and equiv . An eq type is unnecessary, but TEX needs to store the eq level information in another array called xeq level . ⟨ Global variables 13 ⟩ +≡ eqtb: array [active base . . eqtb size] of memory word ; xeq level : array [int base . . eqtb size] of quarterword ;

254. ⟨ Set initial values of key variables 21 ⟩ +≡ for k ← int base to eqtb size do xeq level [k] ← level one;

255. When the debugging routine search mem is looking for pointers having a given value, it is interested only in regions 1 to 3 of eqtb, and in the first part of region 4. ⟨ Search eqtb for equivalents equal to p 255 ⟩ ≡

for q ← active base to box base + 255 do

begin if equiv (q) = p then begin print nl ( ); print int (q); print char ( ); end; end

This code is used in section 172.