§1 ε-TEX 3.14159 [PD VMS 3.6] changes PART 1: INTRODUCTION 3

1* . Introduction. This is ε-TEX, a program derived from and extending the capabilities of TEX, a document compiler intended to produce typesetting of high quality. The Pascal program that follows is the definition of TEX82, a standard version of TEX that is designed to be highly portable so that identical output will be obtainable on a great variety of computers.

The main purpose of the following program is to explain the algorithms of TEX as clearly as possible. As a result, the program will not necessarily be very efficient when a particular Pascal compiler has translated it into a particular machine language. However, the program has been written so that it can be tuned to run efficiently in a wide variety of operating environments by making comparatively few changes. Such flexibility is possible because the documentation that follows is written in the language, which is at a higher level than Pascal; the preprocessing step that converts to Pascal is able to introduce most of the necessary refinements. Semi-automatic translation to other languages is also feasible, because the program below does not make extensive use of features that are peculiar to Pascal.

A large piece of software like TEX has inherent complexity that cannot be reduced below a certain level of difficulty, although each individual part is fairly simple by itself. The language is intended to make the algorithms as readable as possible, by reflecting the way the individual program pieces fit together and by providing the cross-references that connect different parts. Detailed comments about what is going on, and about why things were done in certain ways, have been liberally sprinkled throughout the program. These comments explain features of the implementation, but they rarely attempt to explain the TEX language itself, since the reader is supposed to be familiar with The TEXbook.

4  PART 1: INTRODUCTION  ε-TEX 3.14159 [PD VMS 3.6] changes §2

2* . The present implementation has a long ancestry, beginning in the summer of 1977, when Michael F. Plass and Frank M. Liang designed and coded a prototype based on some specifications that the author had made in May of that year. This original protoTEX included macro definitions and elementary manipulations on boxes and glue, but it did not have line-breaking, page-breaking, mathematical formulas, alignment routines, error recovery, or the present semantic nest; furthermore, it used character lists instead of token lists, so that a control sequence like was represented by a list of seven characters. A complete version of TEX was designed and coded by the author in late 1977 and early 1978; that program, like its prototype, was written in the SAIL language, for which an excellent debugging system was available. Preliminary plans to convert the SAIL code into a form somewhat like the present “web” were developed by Luis Trabb Pardo and the author at the beginning of 1979, and a complete implementation was created by Ignacio A. Zabala in 1979 and 1980. The TEX82 program, which was written by the author during the latter part of 1981 and the early part of 1982, also incorporates ideas from the 1979 implementation of TEX in MESA that was written by Leonidas Guibas, Robert Sedgewick, and Douglas Wyatt at the Xerox Palo Alto Research Center. Several hundred refinements were introduced into TEX82 based on the experiences gained with the original implementations, so that essentially every part of the system has been substantially improved. After the appearance of “Version 0” in September 1982, this program benefited greatly from the comments of many other people, notably David R. Fuchs and Howard W. Trickey. A final revision in September 1989 extended the input character set to eight-bit codes and introduced the ability to hyphenate words from different languages, based on some ideas of Michael J. Ferguson.

No doubt there still is plenty of room for improvement, but the author is firmly committed to keeping TEX82 “frozen” from now on; stability and reliability are to be its main virtues.

On the other hand, the description can be extended without changing the core of TEX82 itself, and the program has been designed so that such extensions are not extremely difficult to make. The banner string defined here should be changed whenever TEX undergoes any modifications, so that it will be clear which version of TEX might be the guilty party when a problem arises.

This program contains code for various features extending TEX, therefore this program is called ‘ε-TEX’ and not ‘TEX’; the official name ‘TEX’ by itself is reserved for software systems that are fully compatible with each other. A special test suite called the “ test” is available for helping to determine whether a particular implementation deserves to be known as ‘TEX’ [cf. Stanford Computer Science report CS1027, November 1984].

A similar test suite called the “ test” is available for helping to determine whether a particular implementation deserves to be known as ‘ε-TEX’.

This change file is the result of a long odyssey of change files beginning with the original change files created in 1984 by David Fuchs; many people have made significant contributions since then, the most notable of whom have been Brian Hamilton Kelly, Niel Kempson, and Adrian Clark

define banner ≡ ´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´

define eTeX version string ≡ ´ ´ { current ε-TEX version }

define eTeX version = 2 { }

define eTeX revision ≡ { }

define eTeX banner ≡ ´ ␣ ␣ ␣ ␣´ , eTeX version string , ´ ␣ ␣ ␣ ´

{ printed when ε-TEX starts }

define TEX ≡ ETEX { change program name into ETEX }

define TeXXeT code = 0 { the TEX-���� feature is optional }

define eTeX states = 1 { number of ε-TEX state variables in eqtb } 4* . The program begins with a normal Pascal program heading, whose components will be filled in later, using the conventions of . For example, the portion of the program called ‘⟨ Global variables 13 ⟩’ below will be replaced by a sequence of variable declarations that starts in §13 of this documentation. In this way, we are able to define each individual global variable when we are prepared to understand what it means; we do not have to define all of the globals at once. Cross references in §13, where it says “See also sections 20, 26, …,” also make it possible to look at the set of all global variables, if desired. Similar remarks apply to the other portions of the program heading.

Actually the heading shown here is not quite normal: The program line does not mention any output file, because Pascal-H would ask the TEX user to specify a file name if output were specified here.

define mtype ≡ t y p e { this is a coding trick: } format mtype ≡ type { ‘mtype’ will be equivalent to ‘type’ } format type ≡ true { but ‘type’ will not be treated as a reserved word }

⟨ Compiler directives 9* ⟩ program TEX ; { all file names are defined dynamically }

label ⟨ Labels in the outer block 6 ⟩ const ⟨ Constants in the outer block 11* ⟩ mtype ⟨ Types in the outer block 18 ⟩ var ⟨ Global variables 13 ⟩ ⟨ VMS procedures 34* ⟩ procedure initialize; { this procedure gets things started properly }

var ⟨ Local variables for initialization 19 ⟩

begin ⟨ Initialize whatever TEX might access 8* ⟩ end;

⟨ Basic printing procedures 56* ⟩ ⟨ Error handling procedures 78 ⟩

7* . Some of the code below is intended to be used only when diagnosing the strange behavior that sometimes occurs when TEX is being installed or when system wizards are fooling around with TEX without quite knowing what they are doing. Such code will not normally be compiled; it is delimited by the codewords ‘debug … gubed’, with apologies to people who wish to preserve the purity of English.

Similarly, there is some conditional code delimited by ‘stat … tats’ that is intended for use when statistics are to be kept about TEX’s memory usage. The stat … tats code also implements diagnostic information for and .

define debug ≡ define gubed ≡ format debug ≡ begin format gubed ≡ end define stat ≡ define tats ≡ format stat ≡ begin format tats ≡ end 8* . This program has two important variations: (1) There is a long and slow version called , which does the extra calculations needed to initialize TEX’s internal tables; and (2) there is a shorter and faster production version, which cuts the initialization to a bare minimum. Parts of the program that are needed in (1) but not in (2) are delimited by the codewords ‘init … tini’ for declarations and by the codewords ‘Init … Tini’ for executable code. This distinction is helpful for implementations where a run-time switch differentiates between the two versions of the program.

define init ≡

define tini ≡

define Init ≡ init

if init flag then

begin

define Tini ≡

end ; tini format Init ≡ begin format Tini ≡ end format init ≡ begin format tini ≡ end

⟨ Initialize whatever TEX might access 8* ⟩ ≡ ⟨ Set initial values of key variables 21 ⟩ Init ⟨ Initialize table entries (done by only) 164 ⟩ Tini

This code is used in section 4*.

9* . When the Pascal program generated as a result of ‘tangling’ the with the change file is compiled under VMS, command line qualifiers should be included to specify full checking and inclusion of debugger symbol records whilst TEX is being debugged, but eliminate range checking and other redundant code when the production system is being generated. Arithmetic overflow should be detected in all cases.

Under VMS, we arrange to ‘inherit’ the descriptions of standard system services and named constants from the precompiled Pascal environment held in ´ $ ´ —we do not specify whether or not any specific level of run-time checks shall be included, because any such attribute applied within the source code cannot be overridden by a command line qualifier when TEX is compiled.

This library does not include all the library routines that are used by TEX82 under VMS, so other routines are declared as required using Pascal’s syntax for extern routines.

format extern ≡ forward ⟨ Compiler directives 9* ⟩ ≡

\underline{\overline{´ $}}  ´  \{ allows us to use system symbols and routines \}

This code is used in section 4*.

10* . This TEX implementation conforms to the rules of the Pascal User Manual published by Jensen and Wirth in 1975, except where system-dependent code is necessary to make a useful system program, and except in another respect where such conformity would unnecessarily obscure the meaning and clutter up the code: We assume that case statements may include a default case that applies if no matching label is found. Thus, we shall use constructions like

case x of

1: ⟨ code for x = 1 ⟩; 3: ⟨ code for x = 3 ⟩; othercases ⟨ code for x ≠ 1 and x ≠ 3 ⟩ endcases

since most Pascal compilers have plugged this hole in the language by incorporating some sort of default mechanism. For example, the Pascal-H compiler allows ‘others :’ as a default label, and other Pascals allow syntaxes like ‘else’ or ‘otherwise’ or ‘otherwise:’, etc. The definitions of othercases and endcases should be changed to agree with local conventions. Note that no semicolon appears before endcases in this program, so the definition of endcases should include a semicolon if the compiler wants one. (Of course, if no default mechanism is available, the case statements of TEX will have to be laboriously extended by listing all remaining cases. People who are stuck with such Pascals have, in fact, done this, successfully but not happily!)

Fortunately for us, VAX-Pascal does support this default mechanism.

define othercases ≡ otherwise { default for cases not listed explicitly } define endcases ≡ end { follows the default case in an extended case statement } format othercases ≡ else format endcases ≡ end 11* . The following parameters can be changed at compile time to extend or reduce TEX’s capacity. They may have different values in and in production versions of TEX.

Since a number of arrays of file name size are used in this program to receive the full file specification of files when they are opened, it is necessary to extend this constant to 255, which is the maximum possible size that VAX/RMS can return. It is not necessary, however, to pad out pool name to this size (which would in any case prove “difficult” in WEB, because VAX-Pascal automatically pads short strings with spaces when assigned into longer variables. Furthermore, because the area where the pool file resides is specified at run time, we need to make pool name into a variable which will be set shortly after we determine the value of the name of the format area. Here, we define the constant pool f name instead, which holds the name of the pool file without any area specification. ⟨ Constants in the outer block 11* ⟩ ≡

mem max = 327144; { greatest index in TEX’s internal mem array; must be strictly less than

max halfword ; must be equal to mem top in , otherwise ≥ mem top } mem min = 0; { smallest index in TEX’s internal mem array; must be min halfword or more; must be

equal to mem bot in , otherwise ≤ mem bot } buf size = 2048; { maximum number of characters simultaneously present in current lines of open files

and in control sequences between and ; must not exceed max halfword } size input line = 133; { maximum size of an input line } error line = 79; { width of context lines on terminal error messages } half error line = 50; { width of first lines of contexts in terminal error messages; should be between 30

and error line − 15 } max print line = 79; { width of longest text lines output; should be at least 60 } stack size = 200; { maximum number of simultaneous input sources } max in open = 12;

{ maximum number of input files and error insertions that can be going on simultaneously } font max = 255; { maximum internal font number; must not exceed max quarterword and must be at

most font base + 256 } font mem size = 81920; { number of words of font info for all fonts } param size = 60; { maximum number of simultaneous macro parameters } nest size = 40; { maximum number of semantic levels simultaneously active } max strings = 15400; { maximum number of strings; must not exceed max halfword } string vacancies = 160000; { the minimum number of characters that should be available for the user’s

control sequences and font names, after TEX’s own error messages are stored } pool size = 186000; { maximum number of characters in strings, including all error messages and help

texts, and the names of all fonts and control sequences; must exceed string vacancies by the total length of TEX’s own strings, which is currently about 23800 for VMS TEX and 24550 for VMS ε-TEX }

save size = 2000; { space for saving values outside of current group; must be at most max halfword } trie size = 45000; { space for hyphenation patterns; should be larger for than it is in production

versions of TEX } trie op size = 1000; { space for “opcodes” in the hyphenation patterns } dvi buf size = 1024; { size of the output buffer; must be a multiple of 8 } VAX block length = 512; { must be half dvi buf size on VMS } file name size = 255; { file names shouldn’t be longer than this } pool f name = ´ ´ ; { string not of length file name size; tells the name of the string pool }

This code is used in section 4*.

12* . Like the preceding parameters, the following quantities can be changed at compile time to extend or reduce TEX’s capacity. But if they are changed, it is necessary to rerun the initialization program to generate new tables for the production TEX program. One can’t simply make helter-skelter changes to the following constants, since certain rather complex initialization numbers are computed from them. They are defined here using macros, instead of being put into Pascal’s const list, in order to emphasize this distinction.

define mem bot = 0

{ smallest index in the mem array dumped by ; must not be less than mem min }

define mem top ≡ 327144 { largest index in the mem array dumped by ; must be substantially

larger than mem bot and not greater than mem max }

define font base = 0 { smallest internal font number; must not be less than min quarterword } define hash size = 10000 { maximum number of control sequences; it should be at most about

(mem max − mem min)/10 }

define hash prime = 8501 { a prime number equal to about 85% of hash size } define hyph size = 503 { another prime; the number of exceptions }

15* . Labels are given symbolic names by the following definitions, so that occasional goto statements will be meaningful. We insert the label ‘exit :’ just before the ‘end’ of a procedure in which we have used the ‘return’ statement defined below; the label ‘restart ’ is occasionally used at the very beginning of a procedure; and the label ‘reswitch’ is occasionally used just prior to a case statement in which some cases change the conditions and we wish to branch to the newly applicable case. Loops that are set up with the loop construction defined below are commonly exited by going to ‘done’ or to ‘found ’ or to ‘not found ’, and they are sometimes repeated by going to ‘continue’. If two or more parts of a subroutine start differently but end up the same, the shared code may be gathered together at ‘common ending ’.

Incidentally, this program never declares a label that isn’t actually used, because some fussy Pascal compilers will complain about redundant labels.

define exit = 10 { go here to leave a procedure } define restart = 20 { go here to start a procedure again } define reswitch = 21 { go here to start a case statement again } define continue = 22 { go here to resume a loop } define done = 30 { go here to exit a loop } define done1 = 31 { like done, when there is more than one loop } define done2 = 32 { for exiting the second loop in a long block } define done3 = 33 { for exiting the third loop in a very long block } define done4 = 34 { for exiting the fourth loop in an extremely long block } define done5 = 35 { for exiting the fifth loop in an immense block } define done6 = 36 { for exiting the sixth loop in a block } define found = 40 { go here when you’ve found it } define found1 = 41 { like found , when there’s more than one per routine } define found2 = 42 { like found , when there’s more than two per routine } define not found = 45 { go here when you’ve found nothing } define not found1 = 46 { like not found , when there’s more than one } define not found2 = 47 { like not found , when there’s more than two } define not found3 = 48 { like not found , when there’s more than three } define not found4 = 49 { like not found , when there’s more than four } define common ending = 50 { go here when you want to merge with another branch }

10  PART 2: THE CHARACTER SET  ε-TEX 3.14159 [PD VMS 3.6] changes §17

23* . The ASCII code is “standard” only to a certain extent, since many computer installations have found it advantageous to have ready access to more than 94 printing characters. Appendix C of The TEXbook gives a complete specification of the intended correspondence between characters and TEX’s internal representation.

If TEX is being used on a garden-variety Pascal for which only standard ASCII codes will appear in the input and output files, it doesn’t really matter what codes are specified in xchr [0 . . ´ 37 ], but the safest policy is to blank everything out by using the code shown below.

However, other settings of xchr will make TEX more friendly on computers that have an extended character set, so that users can type things like ‘ ’ instead of ‘ ’. People with extended character sets can assign codes arbitrarily, giving an xchr equivalent to whatever characters the users of TEX are allowed to have in their input files. It is best to make the codes correspond to the intended interpretations as shown in Appendix C whenever possible; but this is not necessary. For example, in countries with an alphabet of more than 26 letters, it is usually best to map the additional letters into codes less than ´ 40 . To get the most “permissive” character set, change ´ ␣´ on the right of these assignment statements to chr (i).

The code shown here is intended to be used on VMS systems, and at other installations where only the printable ASCII set, plus carriage return, tab, and form feed will show up in text files. All line feed and null characters are skipped.

We also permit characters taken from columns 10–15 of the extended ISO character set; macro packages can then utilize these character codes for multilingual support.

define form feed = ´ 14 { ASCII code used at end of a page }

define tab = ´ 11 ⟨ Set initial values of key variables 21 ⟩ +≡

xchr [0] ← ´ ␣´ ;

for i ← 1 to ´ 37 do xchr [i] ← chr (i);

xchr [form feed ] ← chr (form feed ); xchr [tab] ← chr (tab);

for i ← ´ 177 to ´ 237 do xchr [i] ← ´ ␣´ ;

§25 ε-TEX 3.14159 [PD VMS 3.6] changes PART 3: INPUT AND OUTPUT 11

for i ← ´ 240 to ´ 377 do xchr [i] ← chr (i); 25* . Input and output. The bane of portability is the fact that different operating systems treat input and output quite differently, perhaps because computer scientists have not given sufficient attention to this problem. People have felt somehow that input and output are not part of “real” programming. Well, it is true that some kinds of programming are more fun than others. With existing input/output conventions being so diverse and so messy, the only sources of joy in such parts of the code are the rare occasions when one can find a way to make the program a little less bad than it might have been. We have two choices, either to attack I/O now and get it over with, or to postpone I/O until near the end. Neither prospect is very attractive, so let’s get it over with.

The basic operations we need to do are (1) inputting and outputting of text, to or from a file or the user’s terminal; (2) inputting and outputting of eight-bit bytes, to or from a file; (3) instructing the operating system to initiate (“open”) or to terminate (“close”) input or output from a specified file; (4) testing whether the end of an input file has been reached.

TEX needs to deal with two kinds of files. We shall use the term alpha file for a file that contains textual data, and the term byte file for a file that contains eight-bit binary information. These two types turn out to be the same on many computers, but sometimes there is a significant distinction, so we shall be careful to distinguish between them. Standard protocols for transferring such files from computer to computer, via high-speed networks, are now becoming available to more and more communities of users.

The program actually makes use also of a third kind of file, called a word file, when dumping and reloading base information for its own initialization. We shall define a word file later; but it will be possible for us to specify simple operations on word files before they are defined.

Since the already uses the name text for its own purposes, we have to define a macro to permit access to this VAX-Pascal file type identifier.

define VAX text ≡ \underline{\overline{␣ ␣}} ⟨ Types in the outer block 18 ⟩ +≡

eight bits = 0 . . 255; { unsigned one-byte quantity }

alpha file = VAX text ; { files that contain textual data }

byte block = packed array [0 . . VAX block length − 1] of eight bits ;

byte file = packed file of byte block ; { files that contain binary data }

26* . Most of what we need to do with respect to input and output can be handled by the I/O facilities that are standard in Pascal, i.e., the routines called get , put , eof , and so on. But standard Pascal does not allow file variables to be associated with file names that are determined at run time, so it cannot be used to implement TEX; some sort of extension to Pascal’s ordinary reset and rewrite is crucial for our purposes. We shall assume that name of file is a variable of an appropriate type such that the Pascal run-time system being used to implement TEX can open a file whose external name is specified by name of file. Any VAX-Pascal defaults may be supplied in default name; this is used to expand partial file specifications given on such qualifiers as , in combination with other parts taken from the file specification of the file. ⟨ Global variables 13 ⟩ +≡ name of file, default name: packed array [1 . . file name size] of char ;

{ on some systems this may be a record variable } name length, deflt length: file size;

12  PART 3: INPUT AND OUTPUT  ε-TEX 3.14159 [PD VMS 3.6] changes §27

{ this many characters are actually relevant in name of file (the rest are blank) } 27* . Under VAX-Pascal, we can open files with names that are not known at compile time through use of the VAX-specific procedure open, which takes too many varied parameters to describe here: for example, the third parameter controls whether a new file shall be generated, or can enforce that an existing file cannot possibly be altered. However, one in particular deserves special mention: the user action parameter when included causes execution of a user-supplied routine which can manipulate the data structures used by RMS (Record Management Services) and thus permit finer control over the actions undertaken during the opening or creation of files.

All file manipulation procedures in VAX-Pascal (including open/close, read /write, etc.) can take an optional parameter which specifies whether or no the program shall continue execution after an error. Since we code to detect such errors, we nearly always make use of this facility.

TEX’s file-opening procedures return false if no file identified by name of file could be opened: note that VAX-Pascal’s status function returns zero if the previous file operation was successfully completed, −1 if eof would be true, and a positive integer if any error was detected.

When a new file is opened, we specify that it shall be deleted when the program exits; this ensures that output files are correctly discarded if TEX is interrupted in its work. Later, when the files are closed, we can arrange to keep the files instead. VAX-Pascal’s open procedure also allows us to specify a ‘default’ file specification, which is used to supply defaults for those parts of the specification of the file being created that have not otherwise been provided by the user.

Whenever a word file is opened, the variable fmt count is reset to zero to ensure that the first byte of the VAX block is that first accessed.

define VAX user action ≡ \underline{\overline{}}

define VAX new ≡ \underline{\overline{␣ ␣}} define VAX readonly ≡ \underline{\overline{␣ ␣}}

define VAX default ≡ \underline{\overline{␣ ␣}}

define VAX disposition delete ≡ \underline{\overline{}} define VAX ignore error ≡ \underline{\overline{}}

function a open in(var f : alpha file): boolean; { open a text file for input } begin open(f, name of file, VAX readonly , VAX user action ← user reset , VAX ignore error ); if status (f) > 0 then a open in ← false else begin reset (f, VAX ignore error ); a open in ← status (f) ≤ 0;

end; end;

function a open out (var f : alpha file): boolean; { open a text file for output }

begin open(f, name of file, VAX new , 16383, VAX disposition delete, VAX default ← default name,

VAX user action ← user rewrite, VAX ignore error ); if status (f) > 0 then a open out ← false else begin linelimit (f, maxint ); rewrite(f, VAX ignore error ); a open out ← status (f) ≤ 0;

end; end;

function b open in(var f : byte file): boolean; { open a binary file for input } begin open(f, name of file, VAX readonly , VAX user action ← user reset , VAX ignore error ); if status (f) > 0 then b open in ← false else begin reset (f, VAX ignore error ); b open in ← status (f) ≤ 0;

end; end;

function b open out (var f : byte file): boolean; { open a binary file for output }

begin open(f, name of file, VAX new , VAX disposition delete, VAX default ← default name,

VAX user action ← user rewrite, VAX ignore error ); if status (f) > 0 then b open out ← false else begin rewrite(f, VAX ignore error ); b open out ← status (f) ≤ 0;

end; end;

function w open in(var f : word file): boolean; { open a word file for input } begin open(f, name of file, VAX readonly , VAX user action ← user reset , VAX ignore error ); if status (f) > 0 then w open in ← false else begin reset (f, VAX ignore error ); w open in ← status (f) ≤ 0;

end; fmt count ← 0; end;

function w open out (var f : word file): boolean; { open a word file for output }

begin open(f, name of file, VAX new , VAX disposition delete, VAX user action ← user rewrite,

VAX ignore error ); if status (f) > 0 then w open out ← false else begin rewrite(f, VAX ignore error ); w open out ← status (f) ≤ 0;

end; fmt count ← 0; end;

28* . Files can be closed with the VAX-Pascal routine close(f, disposition, error ), which should be used when all input or output with respect to f has been completed. This makes f available to be opened again, if desired; and if f was used for output, the close operation can make the corresponding external file appear in the user’s directory, ready to be read: this depends upon the value of the disposition parameter, which can (inter alia) control whether the file is kept or discarded. If this parameter is not specified, then disposition of the file is determined by the corresponding parameter of the open routine.

It is through this mechanism that we are able to ensure that all output files are discarded if the operation of TEX is aborted by the user, and yet are kept if the program terminates correctly.

These procedures should not generate error messages if a file is being closed before it has been successfully opened; the error parameter is used here to ensure that any such errors do not cause run-time failures.

define VAX disposition save ≡ \underline{\overline{}} procedure a close(var f : alpha file); { close a text file }

begin close(f, VAX disposition save, VAX ignore error ); end;

procedure b close(var f : byte file); { close a binary file } begin close(f, VAX disposition save, VAX ignore error ); end;

procedure w close(var f : word file); { close a word file } begin close(f, VAX disposition save, VAX ignore error ); end; 30* . Input from text files is read one line at a time, using a routine called input ln. This function is defined in terms of global variables called buffer , first , and last that will be described in detail later; for now, it suffices for us to know that buffer is an array of ASCII code values, and that first and last are indices into this array representing the beginning and ending of a line of text.

On VMS, we will read the lines first into an auxiliary buffer, in order to save the running time of procedurecall overhead. We have to be very careful to handle lines longer than the arbitrarily chosen length of the aux buf . This buffer is declared using a VAX-Pascal extension for variable length strings, namely the varying array type. Such arrays actually appear as if they were a record declared with two fields, thus: varying [max size] of = record length: 0 . . max size; body : packed array [1 . . max size] of.

define VAX length(#) ≡ #. \underline{\overline{}}

define VAX body (#) ≡ #. \underline{\overline{}}

format varying ≡ array ⟨ Global variables 13 ⟩ +≡ aux buf : varying [size input line] of char ; { where the characters go first } buffer : array [0 . . buf size] of ASCII code; { lines of characters being read } first : 0 . . buf size; { the first unused position in buffer } last : 0 . . buf size; { end of the line just input to buffer } max buf stack : 0 . . buf size; { largest index used in buffer } 31* . The input ln function brings the next line of input from the specified file into available positions of the buffer array and returns the value true, unless the file has already been entirely read, in which case it returns false and sets last ← first . In general, the ASCII code numbers that represent the next line of the file are input into buffer [first ], buffer [first + 1], …, buffer [last − 1]; and the global variable last is set equal to first plus the length of the line. Trailing blanks are removed from the line; thus, either last = first (in which case the line was entirely blank) or buffer [last − 1] ≠ ␣ .

An overflow error is given, however, if the normal actions of input ln would make last ≥ buf size; this is done so that other parts of TEX can safely look at the contents of buffer [last + 1] without overstepping the bounds of the buffer array. Upon entry to input ln, the condition first < buf size will always hold, so that there is always room for an “empty” line.

The variable max buf stack , which is used to keep track of how large the buf size parameter must be to accommodate the present job, is also kept up to date by input ln.

If the bypass eoln parameter is true, input ln will do a get before looking at the first character of the line; this skips over an eoln that was in f↑. The procedure does not do a get when it reaches the end of the line; therefore it can be used to acquire input from the user’s terminal as well as from ordinary text files.

Standard Pascal says that a file should have eoln immediately before eof , but TEX needs only a weaker restriction: If eof occurs in the middle of a line, the system function eoln should return a true result (even though f↑ will be undefined).

Since the inner loop of input ln is part of TEX’s “inner loop”—each character of input comes in at this place—it is wise to reduce system overhead by making use of special routines that read in an entire array of characters at once, if such routines are available. The following code uses VAX-Pascal extensions, such as varying strings to perform input of larger amounts of characters with a single input instruction.

Under VAX-Pascal, it is not necessary to take special action to bypass eoln, since the terminator character will be included in those read into the aux buf . function input ln(var f : alpha file; bypass eoln : boolean): boolean;

{ inputs the next line or returns false } label found ; var len: integer ; { length of line input }

k: 0 . . buf size; { index into buffer } begin last ← first ; { cf. Matthew 19 : 30 } if status (f) ≠ 0 then input ln ← false else begin while ¬eoln(f) do

begin read (f, aux buf , VAX ignore error ); len ← VAX length(aux buf ); if last + len ≥ max buf stack then

begin if last + len < buf size then max buf stack ← last + len else ⟨ Report overflow of the input buffer, and abort 35 ⟩; end;

for k ← last to last + len − 1 do buffer [k] ← xord [aux buf [k − last + 1]]; last ← last + len; end;

found : if last > first then

if buffer [last − 1] = ␣ then begin decr (last ); goto found ; end;

input ln ← true; read ln(f, VAX ignore error ); end;

end; 33* . Here is how to open the terminal files under VMS. The standard input and output proces-permanent files $ and $ are opened, and the addresses of the associated FAB and RAB noted so that special actions (such as flushing the input buffer) can be coded.

Output occurs without any implicit carriage-control: this permits the output buffer to be flushed to the terminal without terminating the line of output; it is necessary to output the carriage-return, line-feed character pair explicitly when the line is to be terminated.

define VAX sys input ≡ \underline{\overline{␣´ $ ´ ␣}} define VAX sys output ≡ \underline{\overline{␣´ $ ´ ␣}} define VAX PAS FAB ≡ \underline{\overline{␣ $}} define VAX PAS RAB ≡ \underline{\overline{␣ $}} define VAX carriage control ≡ \underline{\overline{␣ ␣}} define VAX none ≡ \underline{\overline{␣ ␣}} define t open in ≡

begin open(term in, VAX sys input ); reset (term in); in FAB ← VAX PAS FAB (term in); in RAB ← VAX PAS RAB (term in); end { open the terminal for text input }

define t open out ≡ begin open(term out , VAX sys output , VAX carriage control ← VAX none); linelimit (term out , maxint ); rewrite(term out ); out FAB ← VAX PAS FAB (term out ); out RAB ← VAX PAS RAB (term out ); end { open the terminal for text output }

34* . Sometimes it is necessary to synchronize the input/output mixture that happens on the user’s terminal, and three system-dependent procedures are used for this purpose. The first of these, update terminal , is called when we want to make sure that everything we have output to the terminal so far has actually left the computer’s internal buffers and been sent. The second, clear terminal , is called when we wish to cancel any input that the user may have typed ahead (since we are about to issue an unexpected error message). The third, wake up terminal , is supposed to revive the terminal if the user has disabled it by some instruction to the operating system. The following macros show how these operations can be specified on VMS in VAX-Pascal or DEC-Pascal, through manipulation of the data structures maintained in the RAB (Record Access Block) by RMS.

Since wake up terminal is only called just before output of an error message, there’s no significant overhead in its being a procedure, and this saves 8k bytes of Pascal source compared with having it as a definition.

To prevent spurious empty writes to the terminal in batch mode, we apply a condition to update terminal . define VAX RAB purge typeahead ≡ \underline{\overline{$}} define VAX RAB cancel ctrlO ≡ \underline{\overline{$}} define update terminal ≡

if odd (selector ) then write ln(term out ) { empty the terminal output buffer }

define clear terminal ≡ in RAB ↑.VAX RAB purge typeahead ← true { clear the terminal input buffer } define crlf ≡ chr (13), chr (10)

⟨ VMS procedures 34* ⟩ ≡ procedure wake up terminal ;

begin out RAB ↑.VAX RAB cancel ctrlO ← true; write ln(term out ); out RAB ↑.VAX RAB cancel ctrlO ← false; end; { cancel the user’s cancellation of output }

See also sections 1618*, 1625*, 1627*, 1629*, 1631*, 1632*, 1633*, 1635*, and 1640*. This code is used in section 4*.

37* . The following program does the required initialization by retrieving a possible command line, and if none exists, prompting the user for the first line of input.

VMS standard library routines are used to “input” an initial command line from the pseudo-qualifier of the Command Line Interface.

Since any command line passed to TEX from DCL via $ will have been “up-cased”, we might consider converting everything to lower-case, so that all (usually lowercase) TEX commands therein can be recognized; of course, any such commands which are named with upper-case letters would be “ruined”. But, since we are using the full DCL command line interpreter interface, commands consisting of more than one word have to be enclosed in ‘ ’ quotation marks, anyway. The correct case is thus preserved; and file names (which are by far the most common single word arguments) are case insensitive on VMS. Therefore, lower case conversion has not been implemented.

define VAX cli present ≡ \underline{\overline{␣ $}}

define VAX cli get value ≡ \underline{\overline{␣ $}} function init terminal : boolean; { gets the terminal input started }

label exit ;

var command line: packed array [1 . . 256] of char ;

len: sixteen bits ; i: integer ; begin t open in;

if cmd line present then

begin VAX cli get value(´ ´ , command line, len); i ← 1; while (i ≤ len) ∧ (command line[i] = ´ ␣´ ) do incr (i); if i ≤ len then

begin loc ← first ; last ← first ;

while i ≤ len do begin buffer [last ] ← xord [command line[i]]; incr (last ); incr (i); end;

init terminal ← true; return;

end; end;

loop begin wake up terminal ; write(term out , ´ ´ ); update terminal ;

if ¬input ln(term in, true) then { this shouldn’t happen } begin write(term out , crlf ); write ln(term out , ´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ , crlf ); init terminal ← false; return; end; loc ← first ; while (loc < last ) ∧ (buffer [loc] = ␣ ) do incr (loc); if loc < last then

begin init terminal ← true; return; { return unless the line was all blank }

end; write ln(term out , ´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ , crlf ); end;

exit : end;

18  PART 4: STRING HANDLING  ε-TEX 3.14159 [PD VMS 3.6] changes §38

47* . The initial values of str pool , str start , pool ptr , and str ptr are computed by the program, based in part on the information that has output while processing TEX.

init function get strings started : boolean;

{ initializes the string pool, but returns false if something goes wrong } label done, exit ; var k, l: 0 . . 255; { small indices or counters }

m, n: text char ; { characters input from pool file } g: str number ; { garbage } a: integer ; { accumulator for check sum } c: boolean; { check sum has been checked }

begin pool ptr ← 0; str ptr ← 0; str start [0] ← 0; ⟨ Make the first 256 strings 48 ⟩;

⟨ Read the other strings from the file and return true, or give an error message and return

false 51* ⟩;

exit : end; tini

49* . The first 128 strings will contain 95 standard ASCII characters, and the other 33 characters will be printed in three-symbol form like ‘ ’ unless a system-dependent change is made here. Installations that have an extended character set, where for example xchr [´ 32 ] = ´ ´ , would like string ´ 32 to be the single character ´ 32 instead of the three characters ´ 136 , ´ 136 , ´ 132 ( ). On the other hand, even people with an extended character set will want to represent string ´ 15 by , since ´ 15 is carriage return; the idea is to produce visible strings instead of tabs or line-feeds or carriage-returns or bell-rings or characters that are treated anomalously in text files.

Unprintable characters of codes 128–159 and 255 are, similarly, rendered – and . We will print characters in the range 160–254 if the qualifier is used.

The boolean expression defined here should be true unless TEX internal code number k corresponds to a non-troublesome visible symbol in the local character set. An appropriate formula for the extended character set recommended in The TEXbook would, for example, be ‘k ∈ [0, ´ 10 . . ´ 12 , ´ 14 , ´ 15 , ´ 33 , ´ 177 . . ´ 377 ]’. If character k cannot be printed, and k < ´ 200 , then character k + ´ 100 or k − ´ 100 must be printable; moreover, ASCII codes [´ 41 . . ´ 46 , ´ 60 . . ´ 71 , ´ 141 . . ´ 146 , ´ 160 . . ´ 171 ] must be printable. Thus, at least 80 printable characters are needed. ⟨ Character k cannot be printed 49* ⟩ ≡

(k < ␣ ) ∨ ((k > ) ∧ (k < 160)) ∨ (k = 255) ∨ ((k ≥ 160) ∧ ¬eight qual )

This code is used in section 48.

50* . When the  system program called  processes the  description that you are now

reading, together with the merged change file for your system’s implementation of ε-TEX, it should output the Pascal program and also a string pool file called . The program reads the latter file, where each string appears as a two-digit decimal length followed by the string itself, and the information is recorded in TEX’s string memory. ⟨ Global variables 13 ⟩ +≡

init pool file: alpha file; { the string-pool file output by }

tini

§51 ε-TEX 3.14159 [PD VMS 3.6] changes PART 4: STRING HANDLING 19

51* . As noted before, it is not necessary for the string pool name to have the same length as the array name of file, because VAX-Pascal automatically pads such shorter strings with spaces when an assignment is made into a longer string variable.

define bad pool (#) ≡ begin wake up terminal ; write ln(term out , #, crlf ); a close(pool file); get strings started ← false; return; end

⟨ Read the other strings from the file and return true, or give an error message and return

false 51* ⟩ ≡

name of file ← pool name; { we needn’t set name length } if a open in(pool file) then

begin c ← false; repeat ⟨ Read one string, but return false if the string memory space is getting too tight for

comfort 52* ⟩; until c; a close(pool file); get strings started ← true; end

else bad pool (´ ␣ ␣ ´ ´ ␣ ␣ ´ )

This code is used in section 47*.

52* . ⟨ Read one string, but return false if the string memory space is getting too tight for comfort 52* ⟩ ≡ begin if eof (pool file) then bad pool (´ ␣ ␣ ␣ ␣ ␣ ´ ); read (pool file, m, n); { read two digits of string length } if m = ´ ´ then ⟨ Check the pool check sum 53* ⟩ else begin if (xord [m] < ) ∨ (xord [m] > ) ∨ (xord [n] < ) ∨ (xord [n] > ) then

bad pool (´ ␣ ␣ ␣ ´ ´ ␣ ␣ ␣ ␣ ´ ); l ← xord [m] ∗ 10 + xord [n] − ∗ 11; { compute the length } if pool ptr + l + string vacancies > pool size then bad pool (´ ␣ ␣ ␣ ␣ ␣ ´ ); for k ← 1 to l do

begin if eoln(pool file) then m ← ´ ␣´ else read (pool file, m); append char (xord [m]); end;

read ln(pool file); g ← make string ; end;

end

This code is used in section 51*.

53* . The  operation $ denotes the value that should be at the end of this  file; any other

value means that the wrong pool file has been loaded. ⟨ Check the pool check sum 53* ⟩ ≡

begin a ← 0; k ← 1; loop begin if (xord [n] < ) ∨ (xord [n] > ) then

bad pool (´ ␣ ␣ ␣ ␣ ´ ´ ␣ ␣ ␣ ´ ); a ← 10 ∗ a + xord [n] − ; if k = 9 then goto done; incr (k); read (pool file, n); end;

done: if a ≠ $ then bad pool (´ ␣ ␣ ´ ´ ␣ ␣ ␣ ␣ ´ ); c ← true; end

This code is used in section 52*.

20  PART 5: ON-LINE AND OFF-LINE PRINTING  ε-TEX 3.14159 [PD VMS 3.6] changes §54

54* . On-line and off-line printing. Messages that are sent to a user’s terminal and to the transcriptlog file are produced by several ‘print ’ procedures. These procedures will direct their output to a variety of places, based on the setting of the global variable selector , which has the following possible values: term and log , the normal setting, prints on the terminal and on the transcript file. log only , prints only on the transcript file. term only , prints only on the terminal. no print , doesn’t print at all. This is used only in rare cases before the transcript file is open. pseudo, puts output into a cyclic buffer that is used by the show context routine; when we get to that routine

we shall discuss the reasoning behind this curious mode. new string , appends the output to the current string in the string pool. edcmd write, prints the characters into the edcmd file only. 0 to 15, prints on one of the sixteen files for output. The symbolic names ‘term and log ’, etc., have been assigned numeric codes that satisfy the convenient relations no print + 1 = term only , no print + 2 = log only , term only + 2 = log only + 1 = term and log .

The interface to various “callable editors”, described toward the end of this program, necessitates the use of a separate output file (in addition to TEX’s 16 auxiliary output streams), edcmd file, which is declared here, together with the associated value edcmd write of the global selector variable.

Three additional global variables, tally and term offset and file offset , record the number of characters that have been printed since they were most recently cleared to zero. We use tally to record the length of (possibly very long) stretches of printing; term offset and file offset , on the other hand, keep track of how many characters have appeared so far on the current line that has been output to the terminal or to the transcript file, respectively.

define no print = 16 { selector setting that makes data disappear }

define term only = 17 { printing is destined for the terminal only }

define log only = 18 { printing is destined for the transcript file only }

define term and log = 19 { normal selector setting }

define pseudo = 20 { special selector setting for show context }

define new string = 21 { printing is deflected to the string pool }

define edcmd write = 22 { printing is deflected to the edcmd file }

§56 ε-TEX 3.14159 [PD VMS 3.6] changes PART 5: ON-LINE AND OFF-LINE PRINTING 21

define max selector = 22 { highest selector setting } ⟨ Global variables 13 ⟩ +≡ log file: alpha file; { transcript of TEX session } edcmd file: alpha file; { command file used when invoking some editors } selector : 0 . . max selector ; { where to print a message } dig : array [0 . . 22] of 0 . . 15; { digits in a number being output } tally : integer ; { the number of characters recently printed } term offset : 0 . . max print line; { the number of characters on the current terminal line } file offset : 0 . . max print line; { the number of characters on the current file line } trick buf : array [0 . . error line] of ASCII code; { circular buffer for pseudoprinting } trick count : integer ; { threshold for pseudoprinting, explained later } first count : integer ; { another variable for pseudoprinting } 56* . Macro abbreviations for output to the terminal and to the log file are defined here for convenience. Some systems need special conventions for terminal output, and it is possible to adhere to those conventions by changing wterm, wterm ln, and wterm cr in this section.

We also introduce here analogous macros for writing to the diag file, which is used to generate diagnostic messages for use in conjunction with DEC’s Language-sensitive editor (LSEdit).

Yet another set of macros is concerned with writing to temp file, which is a purely internal file, used to concatenate the various elements of TEX’s error messages for use in diagnostic and other files.

define wterm(#) ≡ write(term out , #) define wterm ln(#) ≡ write ln(term out , #, crlf ) define wterm cr ≡ write ln(term out , crlf ) define wlog (#) ≡

if log qual then write(log file, #)

define wlog ln(#) ≡

if log qual then write ln(log file, #)

define wlog cr ≡

if log qual then write ln(log file)

define wdiag (#) ≡

if diag qual then write(diag file, #)

define wdiag ln(#) ≡

if diag qual then write ln(diag file, #)

define wdiag cr ≡

if diag qual then write ln(diag file)

define wtemp(#) ≡ write(temp file, #) define wtemp ln(#) ≡ write ln(temp file, #) define wtemp cr ≡ write ln(temp file)

⟨ Basic printing procedures 56* ⟩ ≡ procedure diag char (s : ASCII code);

var ch: char ; begin ch ← xchr [s]; wdiag (ch); if ch = ´ ´ then wdiag (ch) end;

procedure temp char (s : ASCII code); var ch: char ; begin ch ← xchr [s]; wtemp(ch); if ch = ´ ´ then wtemp(ch) end;

procedure diag print (s : integer ); var j: pool pointer ; begin j ← str start [s]; while j < str start [s + 1] do

begin diag char (so(str pool [j])); incr (j)

end; end;

See also sections 57*, 58*, 59, 60, 62, 63, 64, 65, 262, 263, 518, 699, 1355, 1555*, 1649*, and 1650*. This code is used in section 4*.

57* . To end a line of text output, we call print ln. ⟨ Basic printing procedures 56* ⟩ +≡ procedure print ln; { prints an end-of-line }

begin case selector of

term and log : begin wterm cr ; wlog cr ; term offset ← 0; file offset ← 0;

end; log only : begin wlog cr ; file offset ← 0;

end; term only : begin wterm cr ; term offset ← 0;

end; no print , pseudo, new string : do nothing ; edcmd write: write ln(edcmd file); othercases write ln(write file[selector ]) endcases; end; { tally is not affected }

58* . The print char procedure sends one character to the desired destination, using the xchr array to map it into an external character compatible with input ln. All printing comes through print ln or print char . ⟨ Basic printing procedures 56* ⟩ +≡ procedure print char (s : ASCII code); { prints a single character }

label exit ; begin if ⟨ Character s is the current new-line character 244 ⟩ then

if selector < pseudo then begin print ln; return; end;

⟨ Save printed character for diagnostic messages 1602* ⟩;

case selector of

term and log : begin wterm(xchr [s]); wlog (xchr [s]); incr (term offset ); incr (file offset );

if term offset = max print line then begin wterm cr ; term offset ← 0; end;

if file offset = max print line then begin wlog cr ; file offset ← 0; end;

end; log only : begin wlog (xchr [s]); incr (file offset );

if file offset = max print line then print ln;

end; term only : begin wterm(xchr [s]); incr (term offset );

if term offset = max print line then print ln; end;

no print : do nothing ; pseudo: if tally < trick count then trick buf [tally mod error line] ← s; new string : begin if pool ptr < pool size then append char (s);

end; { we drop characters if the string space is full } edcmd write: write(edcmd file, xchr [s]); { Copy character to editor command file } othercases write(write file[selector ], xchr [s]) endcases; incr (tally );

exit : end; 61* . Here is the very first thing that TEX prints: a headline that identifies the version number and format package. The term offset variable is temporarily incorrect, but the discrepancy is not serious since we assume that the banner and format identifier together will occupy at most max print line character positions. ⟨ Initialize the output routines 55 ⟩ +≡

wterm(eTeX banner ); if format ident = 0 then wterm ln(´ ␣ ␣ ␣ ´ ) else begin slow print (format ident ); print ln;

end; update terminal ;

71* . Here is a procedure that asks the user to type a line of input, assuming that the selector setting is either term only or term and log . The input is placed into locations first through last − 1 of the buffer array, and echoed on the transcript file if appropriate.

This procedure is never called when interaction < scroll mode. define prompt input (#) ≡

begin wake up terminal ; print (#); term input ; end { prints a string and gets a line of input }

procedure term input ; { gets a line from the terminal } var k: 0 . . buf size; { index into buffer } begin update terminal ; { Now the user sees the prompt for sure } if ¬input ln(term in, true) then fatal error ( ␣ ␣ ␣ ␣ ␣ ); in RAB ↑.VAX RAB purge typeahead ← false; { turn off purging of typeahead } term offset ← 0; { the user’s line ended with ⟨return⟩ } decr (selector ); { prepare to echo the input } if last ≠ first then

24  PART 6: REPORTING ERRORS  ε-TEX 3.14159 [PD VMS 3.6] changes §72

for k ← first to last − 1 do print (buffer [k]); print ln; incr (selector ); { restore previous status } end; 73* . The global variable interaction has four settings, representing increasing amounts of user interaction:

This version of TEX can generate a diagnostics file for use with the mode of DEC’s Languagesensitive editor (LSEdit). So whenever TEX starts to generate an error message, we arrange for the text which is sent to the terminal and/or the transcript file to be copied also into our temp file.

define batch mode = 0 { omits all stops and omits terminal output } define nonstop mode = 1 { omits all stops } define scroll mode = 2 { omits error stops } define error stop mode = 3 { stops at every opportunity to interact } define print err (#) ≡

begin if interaction = error stop mode then wake up terminal ; print nl ( ␣ ); copy err ← save it ; rewrite(temp file); print (#);

{ Other print s will add to temp file } end

⟨ Global variables 13 ⟩ +≡ interaction: batch mode . . error stop mode; { current level of interaction }

82* . Here now is the general error routine, which completes output of the error message. ⟨ Error handling procedures 78 ⟩ +≡ procedure error ; { completes the job of error reporting }

label continue, exit ; var c: ASCII code; { what the user types }

s1 , s2 , s3 , s4 : integer ; { used to save global variables when deleting tokens } begin if history < error message issued then history ← error message issued ; print char ( ); ⟨ Ensure temp file not in use 1604* ⟩; show context ; if interaction = error stop mode then ⟨ Get user’s advice and return 83 ⟩; incr (error count ); if error count = 100 then

begin print nl ( ␣ ␣ ␣ ␣ ␣ ␣ ); history ← fatal error stop; jump out ; end;

⟨ Put help message on the transcript file 90 ⟩; exit : end;

§84 ε-TEX 3.14159 [PD VMS 3.6] changes PART 6: REPORTING ERRORS 25

84* . It is desirable to provide an ‘ ’ option here that gives the user an easy way to return from TEX to the system editor, with the offending line ready to be edited. This version of TEX invokes callable versions of various DEC editors, depending upon the value of the switch (normally set to ), including , , DEC’s Language-sensitive editor (LSEdit), and even . Other editors may be run in a subprocess by setting to any DCL command, including activating a command procedure. In addition, if the qualifier is present on the command line, TEX will continue processing after returning from the editor.

There is a secret ‘ ’ option available when the debugging routines haven’t been commented out. ⟨ Interpret code c and return if done 84* ⟩ ≡

case c of

, , , , , , , , , : if deletions allowed then

⟨ Delete c − tokens and goto continue 88 ⟩; debug : begin debug help; goto continue; end; gubed : if base ptr > 0 then

begin if edit file(input stack [base ptr ], line) then

begin if continue qual then

begin show context ; goto continue; end

else begin interaction ← scroll mode; jump out ;

end end

else begin print nl ( ␣ ␣ ␣ ␣ ␣ ); slow print (input stack [base ptr ].name field ); print ( ␣ ␣ ␣ ); print int (line); interaction ← scroll mode; jump out ; end end;

: ⟨ Print the help information and goto continue 89 ⟩; : ⟨ Introduce new material from the terminal and return 87 ⟩; , , : ⟨ Change the interaction level and return 86* ⟩; : begin interaction ← scroll mode; jump out ;

end;

othercases do nothing

endcases; ⟨ Print the menu of available options 85 ⟩

This code is used in section 83.

86* . Here the author of TEX apologizes for making use of the numerical relation between , , , and the desired interaction settings batch mode, nonstop mode, scroll mode. ⟨ Change the interaction level and return 86* ⟩ ≡

begin error count ← 0; interaction ← batch mode + c − ; print ( ␣ ␣ );

case c of

: print esc( ); : print esc( ); : print esc( ); end; { there are no other cases } print ( ); print ln; update terminal ; if c = then decr (selector ); return; end

This code is used in section 84*.

96* . Users occasionally want to interrupt TEX while it’s running. By using a VAX system service, we can declare an Asynchronous System Trap (AST) handler which will be called when the user types . The AST handler then sets the global variable interrupt to some nonzero value when such an interrupt is signalled. Since this variable may be changed at any time, we must prevent the compiler from applying optimizations to the code related to this variable (for example, it would not do for it to be held in a machine register), so we give it the VAX-Pascal ‘attribute’ , which is defined at this point. We also define a couple of other attributes that may be applied to affect the placement of variables under VAX-Pascal.

Assuming that it’s possible to assign an I/O channel to device $ , which should be the case provided the program is being run interactively, then the Control-C handler is declared by a call of the $ system service. Some parameters for this system service have to passed by the ‘immediate’ parameter-passing mechanism; we take this opportunity to define all the means used in TEX to override VAX-Pascal’s default parameter-passing mechanisms.

define VAX volatile ≡ \underline{\overline{␣ ␣}} define VAX unsafe ≡ \underline{\overline{␣ ␣}} define VAX aligned ≡ \underline{\overline{␣ ␣}} define VAX static ≡ \underline{\overline{␣ ␣}}

define VAX immed ≡ \underline{\overline{␣% ␣}} define VAX stdescr ≡ \underline{\overline{␣% ␣}} define VAX ref ≡ \underline{\overline{␣% ␣}}

define VAX io setmode ≡ \underline{\overline{␣ $ ␣}} define VAX iom ctrlcast ≡ \underline{\overline{␣ $ ␣}}

define VAX qiow ≡ \underline{\overline{␣$}} define VAX assign ≡ \underline{\overline{␣$}} define check interrupt ≡

begin if interrupt ≠ 0 then pause for instructions ; end

define enable control C ≡ VAX qiow (, tt chan, VAX io setmode + VAX iom ctrlcast , , , ,

VAX immed ctrlc rout , , VAX immed 3, , ,);

⟨ Global variables 13 ⟩ +≡ interrupt : [VAX volatile]integer ; { should TEX pause for instruction? } OK to interrupt : boolean; { should interrupts be observed? }

97* . ⟨ Set initial values of key variables 21 ⟩ +≡ interrupt ← 0; OK to interrupt ← true; if VAX assign(´ $ ´ , tt chan, ,) = VAX ss normal then enable control C ;

§99 ε-TEX 3.14159 [PD VMS 3.6] changes PART 7: ARITHMETIC WITH SCALED DIMENSIONS 27

109* . When TEX “packages” a list into a box, it needs to calculate the proportionality ratio by which the glue inside the box should stretch or shrink. This calculation does not affect TEX’s decision making, so the precise details of rounding, etc., in the glue calculation are not of critical importance for the consistency of results on different computers.

We shall use the type glue ratio for such proportionality ratios. A glue ratio should take the same amount of memory as an integer (usually 32 bits) if it is to blend smoothly with TEX’s other data structures. Thus glue ratio should be equivalent to short real in some implementations of Pascal. Alternatively, it is possible to deal with glue ratios using nothing but fixed-point arithmetic; see TUGboat 3,1 (March 1982), 10–27. (But the routines cited there must be modified to allow negative glue ratios.)

On VMS, we use some hackery to cause floating point numbers stored in mem to be single, but other real variables and expressions are done as double length reals.

define set glue ratio zero(#) ≡ # ← 0.0 { store the representation of zero ratio }

define set glue ratio one(#) ≡ # ← 1.0 { store the representation of unit ratio }

define real ≡ double { use double precision reals for computation }

define float (#) ≡ dble(#) { convert from glue ratio to type real }

{ FIX ME }

define unfloat (#) ≡ sngl (1.0 D0 ∗ #) { convert from real to type glue ratio }

define float constant (#) ≡ #.0 D0 { convert integer constant to real } ⟨ Types in the outer block 18 ⟩ +≡

glue ratio = r e a l; { one-word representation of a glue expansion factor }

28  PART 8: PACKED DATA  ε-TEX 3.14159 [PD VMS 3.6] changes §110

110* . Packed data. In order to make efficient use of storage space, TEX bases its major data structures on a memory word , which contains either a (signed) integer, possibly scaled, or a (signed) glue ratio, or a small number of fields that are one half or one quarter of the size used for storing integers.

If x is a variable of type memory word , it contains up to four fields that can be referred to as follows:

x.int (an integer )
x.sc  (a scaled integer)
x.gr  (a glue ratio)
x.hh.lh, x.hh.rh  (two halfword fields)
x.hh.b0 , x.hh.b1 , x.hh.rh  (two quarterword fields, one halfword field)
x.qqqq .b0 , x.qqqq .b1 , x.qqqq .b2 , x.qqqq .b3  (four quarterword fields)

This is somewhat cumbersome to write, and not very readable either, but macros will be used to make the notation shorter and more transparent. The Pascal code below gives a formal definition of memory word and its subsidiary types, using packed variant records. TEX makes no assumptions about the relative positions of the fields within a word.

Since we are assuming 32-bit integers, a halfword must contain at least 16 bits, and a quarterword must contain at least 8 bits. But it doesn’t hurt to have more bits; for example, with enough 36-bit words you might be able to have mem max as large as 262142, which is eight times as much memory as anybody had during the first four years of TEX’s existence.

N.B.: Valuable memory space will be dreadfully wasted unless TEX is compiled by a Pascal that packs all of the memory word variants into the space of a single integer. This means, for example, that glue ratio words should be short real instead of real on some computers. Some Pascal compilers will pack an integer whose subrange is ‘0 . . 255’ into an eight-bit field, but others insist on allocating space for an additional sign bit; on such systems you can get 256 values into a quarterword only if the subrange is ‘−128 . . 127’.

The present implementation tries to accommodate as many variations as possible, so it makes few assumptions. If integers having the subrange ‘min quarterword . . max quarterword ’ can be packed into a quarterword, and if integers having the subrange ‘min halfword . . max halfword ’ can be packed into a halfword, everything should work satisfactorily.

It is usually most efficient to have min quarterword = min halfword = 0, so one should try to achieve this unless it causes a severe problem. The values defined here are recommended for most 32-bit computers.

define min quarterword = 0 { smallest allowable value in a quarterword }

define max quarterword = 511 { largest allowable value in a quarterword }

define min halfword ≡ 0 { smallest allowable value in a halfword }

define max halfword ≡ 327144 + 1 { largest allowable value in a halfword }

112* . The operation of adding or subtracting min quarterword occurs quite frequently in TEX, so it is convenient to abbreviate this operation by using the macros qi and qo for input and output to and from quarterword format.

The inner loop of TEX will run faster with respect to compilers that don’t optimize expressions like ‘x + 0’ and ‘x − 0’, if these macros are simplified in the obvious way when min quarterword = 0.

define qi (#) ≡ #

define qo(#) ≡ #

define hi (#) ≡ #

define ho(#) ≡ #

§113 ε-TEX 3.14159 [PD VMS 3.6] changes PART 8: PACKED DATA 29

113* . The reader should study the following definitions closely:

define sc ≡ int { scaled data is equivalent to integer } ⟨ Types in the outer block 18 ⟩ +≡

quarterword = min quarterword . . max quarterword ; { 1/4 of a word } halfword = min halfword . . max halfword ; { 1/2 of a word } two choices = 1 . . 2; { used when there are two variants in a record } four choices = 1 . . 4; { used when there are four variants in a record } two halves = packed record rh: halfword ;

case two choices of

1: (lh : halfword ); 2: (b0 : quarterword ; b1 : quarterword ); end;

four quarters = packed record b0 : quarterword ; b1 : quarterword ; b2 : quarterword ; b3 : quarterword ; end;

memory word = packed record

case four choices of

1: (int : integer ); 2: (gr : glue ratio); 3: (hh : two halves ); 4: (qqqq : four quarters ); end;

word block = packed array [0 . . VAX block length − 1] of memory word ; word file = packed file of word block ;

30 PART 10: DATA STRUCTURES FOR BOXES AND THEIR FRIENDSε-TEX 3.14159 [PD VMS 3.6] changes §115

141* . A mark node has a mark ptr field that points to the reference count of a token list that contains the user’s text. In addition there is a mark class field that contains the mark class.

define mark node = 4 { type of a mark node } define small node size = 2 { number of words to allocate for most node types } define mark ptr (#) ≡ link (# + 1) { head of the token list for a mark } define mark class (#) ≡ info(# + 1) { the mark class }

142* . An adjust node, which occurs only in horizontal lists, specifies material that will be moved out into the surrounding vertical list; i.e., it is used to implement TEX’s ‘ ’ operation. The adjust ptr field points to the vlist containing this material.

define adjust node = 5 { type of an adjust node } define adjust ptr (#) ≡ mem[# + 1].int { vertical list to be moved out of horizontal list }

147* . A math node, which occurs only in horizontal lists, appears before and after mathematical formulas. The subtype field is before before the formula and after after it. There is a width field, which represents the amount of surrounding space inserted by .

In addition a math node with subtype > after and width = 0 will be (ab)used to record a regular math node reinserted after being discarded at a line break or one of the text direction primitives ( , , , and ).

define math node = 9 { type of a math node } define before = 0 { subtype for math node that introduces a formula } define after = 1 { subtype for math node that winds up a formula } define M code = 2 define begin M code = M code + before { subtype for node } define end M code = M code + after { subtype for node } define L code = 4 define begin L code = L code + begin M code { subtype for node } define end L code = L code + end M code { subtype for node } define R code = L code + L code define begin R code = R code + begin M code { subtype for node } define end R code = R code + end M code { subtype for node } define end LR(#) ≡ odd (subtype(#)) define end LR type(#) ≡ (L code ∗ (subtype(#) div L code) + end M code) define begin LR type(#) ≡ (# − after + before)

function new math(w : scaled ; s : small number ): pointer ; var p: pointer ; { the new node } begin p ← get node(small node size); type(p) ← math node; subtype(p) ← s; width(p) ← w; new math ← p; end;

§162 ε-TEX 3.14159 [PD VMS 3.6] changes PART 12: DISPLAYING BOXES 31

175* . ⟨ Print a short indication of the contents of node p 175* ⟩ ≡ case type(p) of hlist node, vlist node, ins node, whatsit node, mark node, adjust node, unset node: print ( ); rule node: print char ( ); glue node: if glue ptr (p) ≠ zero glue then print char ( ␣ ); math node: if subtype(p) ≥ L code then print ( )

else print char ( $ ); ligature node: short display (lig ptr (p)); disc node: begin short display (pre break (p)); short display (post break (p));

n ← replace count (p);

while n > 0 do begin if link (p) ≠ null then p ← link (p); decr (n); end;

end;

othercases do nothing

endcases

This code is used in section 174.

184* . ⟨ Display box p 184* ⟩ ≡ begin if type(p) = hlist node then print esc( ) else if type(p) = vlist node then print esc( )

else print esc( ); print ( ); print scaled (height (p)); print char ( ); print scaled (depth(p)); print ( ); print scaled (width(p)); if type(p) = unset node then ⟨ Display special fields of the unset node p 185 ⟩ else begin ⟨ Display the value of glue set (p) 186* ⟩;

if shift amount (p) ≠ 0 then begin print ( ␣ ␣ ); print scaled (shift amount (p)); end;

if eTeX ex then ⟨ Display if this box is never to be reversed 1438* ⟩; end;

node list display (list ptr (p)); { recursive call } end

This code is used in section 183.

32  PART 12: DISPLAYING BOXES  ε-TEX 3.14159 [PD VMS 3.6] changes §186

186* . The code will have to change in this place if glue ratio is a structured type instead of an ordinary real . Note that this routine should avoid arithmetic errors even if the glue set field holds an arbitrary random value. The following WEB macro simulates VAX/DEC-Pascal’s predeclared routine undefined , which returns true if its argument is not a properly constituted real number. (The real function cannot be used, because it is currently unsupported on DEC-Pascal for AXP.)

define VAX undefined (#) ≡ (# :: VAX F float .Sign ∧ (# :: VAX F float .Expo = 0)) ⟨ Display the value of glue set (p) 186* ⟩ ≡

g ← float (glue set (p)); if (g ≠ float constant (0)) ∧ (glue sign(p) ≠ normal ) then

begin print ( ␣ ␣ ␣ ); if glue sign(p) = shrinking then print ( ␣ ); if VAX undefined (glue set (p)) then print ( ) else if abs (g) > float constant (20000) then

begin if g > float constant (0) then print char ( ) else print ( ␣ ); print glue(20000 ∗ unity , glue order (p), 0); end

else print glue(round (unity ∗ g), glue order (p), 0); end

This code is used in section 184*.

192* . ⟨ Display math node p 192* ⟩ ≡

if subtype(p) > after then begin if end LR(p) then print esc( ) else print esc( ); if subtype(p) > R code then print char ( ) else if subtype(p) > L code then print char ( )

else print char ( ); end

else begin print esc( ); if subtype(p) = before then print ( ) else print ( ); if width(p) ≠ 0 then

begin print ( ␣ ␣ ); print scaled (width(p)); end;

end

This code is used in section 183.

196* . ⟨ Display mark p 196* ⟩ ≡ begin print esc( ); if mark class (p) ≠ null then

begin print char ( ); print int (mark class (p)); end;

print mark (mark ptr (p)); end

This code is used in section 183.

§199 ε-TEX 3.14159 [PD VMS 3.6] changes PART 15: THE COMMAND CODES 33

208* . Next are the ordinary run-of-the-mill command codes. Codes that are min internal or more represent internal quantities that might be expanded by ‘ ’.

define char num = 16 { character specified numerically ( ) } define math char num = 17 { explicit math code ( ) } define mark = 18 { mark definition ( ) }

define xray = 19 { peek inside of TEX (  ,  , etc. ) }
define make box = 20 { make a box (  ,  ,  , etc. ) }
define hmove = 21 { horizontal motion (  ,  ) }
define vmove = 22 { vertical motion (  ,  ) }
define un hbox = 23 { unglue a box (  ,  ) }
define un vbox = 24 { unglue a box (  ,  ) }
{ ( or  ,  ) }
define remove item = 25 { nullify last item (  ,  ,  ) }
define hskip = 26 { horizontal glue (  ,  , etc. ) }
define vskip = 27 { vertical glue (  ,  , etc. ) }

define mskip = 28 { math glue ( ) } define kern = 29 { fixed space ( ) } define mkern = 30 { math kern ( ) } define leader ship = 31 { use a box ( , , etc. ) } define halign = 32 { horizontal table alignment ( ) } define valign = 33 { vertical table alignment ( ) }

{ or text direction directives ( , etc. ) }

define no align = 34 { temporary escape from alignment ( ) } define vrule = 35 { vertical rule ( ) } define hrule = 36 { horizontal rule ( ) } define insert = 37 { vlist inserted in box ( ) } define vadjust = 38 { vlist inserted in enclosing paragraph ( ) } define ignore spaces = 39 { gobble spacer tokens ( ) } define after assignment = 40 { save till assignment is done ( ) } define after group = 41 { save till group is done ( ) } define break penalty = 42 { additional badness ( ) } define start par = 43 { begin paragraph ( , ) } define ital corr = 44 { italic correction ( ) } define accent = 45 { attach accent in text ( ) } define math accent = 46 { attach accent in math ( ) } define discretionary = 47 { discretionary texts ( , ) }

define eq no = 48 { equation number (  ,  ) }
define left right = 49 { variable delimiter (  ,  ) }
{ ( or ) }

define math comp = 50 { component of formula ( , etc. ) } define limit switch = 51 { diddle limit conventions ( , etc. ) } define above = 52 { generalized fraction ( , , etc. ) } define math style = 53 { style specification ( , etc. ) } define math choice = 54 { choice specification ( ) } define non script = 55 { conditional math glue ( ) } define vcenter = 56 { vertically center a vbox ( ) }

define case shift = 57 { force specific case (  ,  ) }
define message = 58 { send to user (  ,  ) }
define extension = 59 { extensions to TEX (  ,  , etc. ) }
define in stream = 60 { files for reading (  ,  ) }

define begin group = 61 { begin local grouping ( ) } define end group = 62 { end local grouping ( ) }

34  PART 15: THE COMMAND CODES  ε-TEX 3.14159 [PD VMS 3.6] changes §208

define omit = 63 { omit alignment template ( ) } define ex space = 64 { explicit space ( ␣ ) } define no boundary = 65 { suppress boundary ligatures ( ) } define radical = 66 { square root and similar signs ( ) } define end cs name = 67 { end control sequence ( ) } define min internal = 68 { the smallest code that can follow } define char given = 68 { character code defined by } define math given = 69 { math code defined by } define last item = 70 { most recent item ( , , ) } define max non prefixed command = 70 { largest command code that can’t be }

209* . The next codes are special; they all relate to mode-independent assignment of values to TEX’s internal registers or tables. Codes that are max internal or less represent internal quantities that might be expanded by ‘ ’.

define toks register = 71 { token list register ( ) }

define assign toks = 72 { special token list (  ,  , etc. ) }
define assign int = 73 { user-defined integer (  ,  , etc. ) }

define assign dimen = 74 { user-defined length ( , etc. ) } define assign glue = 75 { user-defined glue ( , etc. ) } define assign mu glue = 76 { user-defined muglue ( , etc. ) } define assign font dimen = 77 { user-defined font dimension ( ) }

define assign font int = 78 { user-defined font integer (  ,  ) }
define set aux = 79 { specify state info (  ,  ) }

define set prev graf = 80 { specify state info ( ) } define set page dimen = 81 { specify state info ( , etc. ) } define set page int = 82 { specify state info ( , ) }

{ ( or ) }

define set box dimen = 83 { change dimension of box ( , , ) } define set shape = 84 { specify fancy paragraph shape ( ) }

{ (or , etc. ) }

define def code = 85 { define a character code ( , etc. ) } define def family = 86 { declare math fonts ( , etc. ) } define set font = 87 { set current font ( font identifiers ) } define def font = 88 { define a font file ( ) } define register = 89 { internal register ( , , etc. ) } define max internal = 89 { the largest code that can follow } define advance = 90 { advance a register or parameter ( ) } define multiply = 91 { multiply a register or parameter ( ) } define divide = 92 { divide a register or parameter ( ) } define prefix = 93 { qualify a definition ( , , ) }

{ ( or ) }

define let = 94 { assign a command code (  ,  ) }
define shorthand def = 95 { code definition (  ,  , etc. ) }

define read to cs = 96 { read into a control sequence ( ) }

{ ( or ) }

define def = 97 { macro definition ( , , , ) } define set box = 98 { set a box ( ) } define hyph data = 99 { hyphenation data ( , ) } define set interaction = 100 { define level of interaction ( , etc. ) } define max command = 100 { the largest command code seen at big switch } 210* . The remaining command codes are extra special, since they cannot get through TEX’s scanner to the main control routine. They have been given values higher than max command so that their special nature is easily discernible. The “expandable” commands come first.

define undefined cs = max command + 1 { initial state of most eq type fields } define expand after = max command + 2 { special expansion ( ) } define no expand = max command + 3 { special nonexpansion ( ) } define input = max command + 4 { input a source file ( , ) }

{ ( or ) }

define if test = max command + 5 { conditional text ( , , etc. ) } define fi or else = max command + 6 { delimiters for conditionals ( , etc. ) } define cs name = max command + 7 { make a control sequence from tokens ( ) } define convert = max command + 8 { convert to text ( , , etc. ) } define the = max command + 9 { expand an internal quantity ( ) }

{ ( or , ) }

define top bot mark = max command + 10 { inserted mark ( , etc. ) } define call = max command + 11 { non-long, non-outer control sequence } define long call = max command + 12 { long, non-outer control sequence } define outer call = max command + 13 { non-long, outer control sequence } define long outer call = max command + 14 { long, outer control sequence } define end template = max command + 15 { end of an alignment template } define dont expand = max command + 16 { the following token was marked by } define glue ref = max command + 17 { the equivalent points to a glue specification } define shape ref = max command + 18 { the equivalent points to a parshape specification } define box ref = max command + 19 { the equivalent points to a box node, or is null } define data = max command + 20 { the equivalent is simply a halfword number }

36  PART 16: THE SEMANTIC NEST  ε-TEX 3.14159 [PD VMS 3.6] changes §211

212* . The state of affairs at any semantic level can be represented by five values: mode is the number representing the semantic mode, as just explained. head is a pointer to a list head for the list being built; link (head ) therefore points to the first element of the

list, or to null if the list is empty. tail is a pointer to the final node of the list being built; thus, tail = head if and only if the list is empty. prev graf is the number of lines of the current paragraph that have already been put into the present vertical

list. aux is an auxiliary memory word that gives further information that is needed to characterize the situation. In vertical mode, aux is also known as prev depth; it is the scaled value representing the depth of the previous box, for use in baseline calculations, or it is ≤ −1000pt if the next box on the vertical list is to be exempt from baseline calculations. In horizontal mode, aux is also known as space factor and clang ; it holds the current space factor used in spacing calculations, and the current language used for hyphenation. (The value of clang is undefined in restricted horizontal mode.) In math mode, aux is also known as incompleat noad ; if not null , it points to a record that represents the numerator of a generalized fraction for which the denominator is currently being formed in the current list.

There is also a sixth quantity, mode line, which correlates the semantic nest with the user’s input; mode line contains the source line number at which the current level of nesting was entered. The negative of this line number is the mode line at the level of the user’s output routine.

A seventh quantity, eTeX aux , is used by the extended features ε-TEX. In vertical modes it is known as LR save and holds the LR stack when a paragraph is interrupted by a displayed formula. In display math mode it is known as LR box and holds a pointer to a prototype box for the display. In math mode it is known as delim ptr and points to the most recent left noad or middle noad of a math left group.

In horizontal mode, the prev graf field is used for initial language data.

The semantic nest is an array called nest that holds the mode, head , tail , prev graf , aux , and mode line values for all semantic levels below the currently active one. Information about the currently active level is kept in the global quantities mode, head , tail , prev graf , aux , and mode line, which live in a Pascal record that is ready to be pushed onto nest if necessary.

define ignore depth ≡ −65536000 { prev depth value that is ignored } ⟨ Types in the outer block 18 ⟩ +≡

list state record = record mode field : −mmode . . mmode; head field , tail field : pointer ; eTeX aux field : pointer ; pg field , ml field : integer ; aux field : memory word ; end;

§213 ε-TEX 3.14159 [PD VMS 3.6] changes PART 16: THE SEMANTIC NEST 37

213* . define mode ≡ cur list .mode field { current mode } define head ≡ cur list .head field { header node of current list } define tail ≡ cur list .tail field { final node on current list } define eTeX aux ≡ cur list .eTeX aux field { auxiliary data for ε-TEX } define LR save ≡ eTeX aux { LR stack when a paragraph is interrupted } define LR box ≡ eTeX aux { prototype box for display } define delim ptr ≡ eTeX aux { most recent left or right noad of a math left group } define prev graf ≡ cur list .pg field { number of paragraph lines accumulated } define aux ≡ cur list .aux field { auxiliary data about the current list } define prev depth ≡ aux .sc { the name of aux in vertical mode } define space factor ≡ aux .hh.lh { part of aux in horizontal mode } define clang ≡ aux .hh.rh { the other part of aux in horizontal mode } define incompleat noad ≡ aux .int { the name of aux in math mode } define mode line ≡ cur list .ml field { source file line number at beginning of list }

⟨ Global variables 13 ⟩ +≡ nest : array [0 . . nest size] of list state record ; nest ptr : 0 . . nest size; { first unused location of nest } max nest stack : 0 . . nest size; { maximum of nest ptr when pushing } cur list : list state record ; { the “top” semantic state } shown mode: −mmode . . mmode; { most recent mode shown by }

215* . We will see later that the vertical list at the bottom semantic level is split into two parts; the “current page” runs from page head to page tail , and the “contribution list” runs from contrib head to tail of semantic level zero. The idea is that contributions are first formed in vertical mode, then “contributed” to the current page (during which time the page-breaking decisions are made). For now, we don’t need to know any more details about the page-building process. ⟨ Set initial values of key variables 21 ⟩ +≡

nest ptr ← 0; max nest stack ← 0; mode ← vmode; head ← contrib head ; tail ← contrib head ; eTeX aux ← null ; prev depth ← ignore depth; mode line ← 0; prev graf ← 0; shown mode ← 0; ⟨ Start a new current page 991* ⟩;

216* . When TEX’s work on one level is interrupted, the state is saved by calling push nest . This routine changes head and tail so that a new (empty) list is begun; it does not change mode or aux . procedure push nest ; { enter a new semantic level, save the old }

begin if nest ptr > max nest stack then begin max nest stack ← nest ptr ; if nest ptr = nest size then overflow ( ␣ ␣ , nest size); end;

38  PART 17: THE TABLE OF EQUIVALENTS  ε-TEX 3.14159 [PD VMS 3.6] changes §220

nest [nest ptr ] ← cur list ; { stack the record } incr (nest ptr ); head ← get avail ; tail ← head ; prev graf ← 0; mode line ← line; eTeX aux ← null ; end; 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 inter line penalties loc = local base + 1 { additional penalties between lines } define club penalties loc = local base + 2 { penalties for creating club lines } define widow penalties loc = local base + 3 { penalties for creating widow lines } define display widow penalties loc = local base + 4 { ditto, just before a display } define token base = local base + 5 { table of token list parameters } define output routine loc = token base { points to token list for } define every par loc = token base + 1 { points to token list for } define every math loc = token base + 2 { points to token list for } define every display loc = token base + 3 { points to token list for } define every hbox loc = token base + 4 { points to token list for } define every vbox loc = token base + 5 { points to token list for } define every job loc = token base + 6 { points to token list for } define every cr loc = token base + 7 { points to token list for } define every eof loc = token base + 8 { points to token list for } define err help loc = token base + 9 { points to token list for } define toks base = token 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);

§230 ε-TEX 3.14159 [PD VMS 3.6] changes PART 17: THE TABLE OF EQUIVALENTS 39

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( );

⟨ Cases of assign toks for print cmd chr 1392* ⟩ 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 ← par shape loc + 1 to token base − 1 do eqtb[k] ← eqtb[par shape loc]; 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(form feed ) ← car ret ; 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 < token base then begin print cmd chr (set shape, n); print char ( ); if equiv (n) = null then print char ( ) else if n > par shape loc then

begin print int (penalty (equiv (n))); print char ( ␣ ); print int (penalty (equiv (n) + 1)); if penalty (equiv (n)) > 1 then print esc( ); end

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.

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 tracing assigns code = int pars { show assignments } define tracing groups code = int pars + 1 { show save/restore groups } define tracing ifs code = int pars + 2 { show conditionals } define tracing scan tokens code = int pars + 3 { show pseudo file open and close } define tracing nesting code = int pars + 4 { show incomplete groups and ifs within files } define pre display direction code = int pars + 5 { text direction preceding a display } define last line fit code = int pars + 6 { adjustment for last line of paragraph } define saving vdiscards code = int pars + 7 { save items discarded from vlists } define saving hyph codes code = int pars + 8 { save hyphenation codes for languages } define eTeX state code = int pars + 9 { ε-TEX state variables } define count base = int base + eTeX state code + eTeX states { 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) define tracing assigns ≡ int par (tracing assigns code) define tracing groups ≡ int par (tracing groups code) define tracing ifs ≡ int par (tracing ifs code) define tracing scan tokens ≡ int par (tracing scan tokens code) define tracing nesting ≡ int par (tracing nesting code) define pre display direction ≡ int par (pre display direction code) define last line fit ≡ int par (last line fit code) define saving vdiscards ≡ int par (saving vdiscards code) define saving hyph codes ≡ int par (saving hyph codes 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( );

⟨ Cases for print param 1393* ⟩ othercases print ( ␣ ␣ ) endcases; end;

241* . The following procedure, which is called just before TEX initializes its input and output, establishes the initial values of the date and time. The requisite information is obtained through a call of the $ system service.

define VAX numtim ≡ \underline{\overline{␣$}} procedure fix date and time;

var t: array [1 . . 7] of signed halfword ; { raw year, month, day and time } begin VAX numtim(t); year ← t[1]; month ← t[2]; day ← t[3]; time ← t[4] ∗ 60 + t[5];

§256 ε-TEX 3.14159 [PD VMS 3.6] changes PART 18: THE HASH TABLE 47

{ minutes since midnight } end; 264* . We need to put TEX’s “primitive” control sequences into the hash table, together with their command code (which will be the eq type) and an operand (which will be the equiv ). The primitive procedure does this, in a way that no TEX user can. The global value cur val contains the new eqtb pointer after primitive has acted.

init procedure primitive(s : str number ; c : quarterword ; o : halfword ); var k: pool pointer ; { index into str pool }

j: 0 . . buf size; { index into buffer }

l: small number ; { length of the string } begin if s < 256 then cur val ← s + single base else begin k ← str start [s]; l ← str start [s + 1] − k;

{ we will move s into the (possibly non-empty) buffer } if first + l > buf size + 1 then overflow ( ␣ , buf size); for j ← 0 to l − 1 do buffer [first + j] ← so(str pool [k + j]); cur val ← id lookup(first , l); { no new control sequence is false } flush string ; text (cur val ) ← s; { we don’t want to have the string twice } end;

48  PART 18: THE HASH TABLE  ε-TEX 3.14159 [PD VMS 3.6] changes §265

eq level (cur val ) ← level one; eq type(cur val ) ← c; equiv (cur val ) ← o; end; tini 265* . Many of TEX’s primitives need no equiv , since they are identifiable by their eq type alone. These primitives are loaded into the hash table as follows: ⟨ Put each of TEX’s primitives into the hash table 226 ⟩ +≡

primitive( ␣ , ex space, 0); primitive( , ital corr , 0); primitive( , accent , 0); primitive( , advance, 0); primitive( , after assignment , 0); primitive( , after group, 0); primitive( , begin group, 0); primitive( , char num, 0); primitive( , cs name, 0); primitive( , delim num, 0); primitive( , divide, 0); primitive( , end cs name, 0); primitive( , end group, 0); text (frozen end group) ← ; eqtb[frozen end group] ← eqtb[cur val ]; primitive( , expand after , 0); primitive( , def font , 0); primitive( , assign font dimen, 0); primitive( , halign, 0); primitive( , hrule, 0); primitive( , ignore spaces , 0); primitive( , insert , 0); primitive( , mark , 0); primitive( , math accent , 0); primitive( , math char num, 0); primitive( , math choice, 0); primitive( , multiply , 0); primitive( , no align, 0); primitive( , no boundary , 0); primitive( , no expand , 0); primitive( , non script , 0); primitive( , omit , 0); primitive( , set shape, par shape loc); primitive( , break penalty , 0); primitive( , set prev graf , 0); primitive( , radical , 0); primitive( , read to cs , 0); primitive( , relax , 256); { cf. scan file name } text (frozen relax ) ← ; eqtb[frozen relax ] ← eqtb[cur val ]; primitive( , set box , 0); primitive( , the, 0); primitive( , toks register , mem bot ); primitive( , vadjust , 0); primitive( , valign, 0); primitive( , vcenter , 0); primitive( , vrule, 0); 266* . Each primitive has a corresponding inverse, so that it is possible to display the cryptic numeric contents of eqtb in symbolic form. Every call of primitive in this program is therefore accompanied by some straightforward code that forms part of the print cmd chr routine below.

⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ accent : print esc( ); advance: print esc( ); after assignment : print esc( ); after group: print esc( ); assign font dimen: print esc( ); begin group: print esc( ); break penalty : print esc( ); char num: print esc( ); cs name: print esc( ); def font : print esc( ); delim num: print esc( ); divide: print esc( ); end cs name: print esc( ); end group: print esc( ); ex space: print esc( ␣ ); expand after : if chr code = 0 then print esc( )

⟨ Cases of expandafter for print cmd chr 1496* ⟩; halign: print esc( ); hrule: print esc( ); ignore spaces : print esc( ); insert : print esc( ); ital corr : print esc( ); mark : begin print esc( );

if chr code > 0 then print char ( ); end;

math accent : print esc( ); math char num: print esc( ); math choice: print esc( ); multiply : print esc( ); no align: print esc( ); no boundary : print esc( ); no expand : print esc( ); non script : print esc( ); omit : print esc( ); radical : print esc( ); read to cs : if chr code = 0 then print esc( ) ⟨ Cases of read for print cmd chr 1493* ⟩; relax : print esc( ); set box : print esc( ); set prev graf : print esc( ); set shape: case chr code of

par shape loc: print esc( );

⟨ Cases of set shape for print cmd chr 1598* ⟩ end; { there are no other cases }

the: if chr code = 0 then print esc( ) ⟨ Cases of the for print cmd chr 1421* ⟩; toks register : ⟨ Cases of toks register for print cmd chr 1566* ⟩; vadjust : print esc( ); valign: if chr code = 0 then print esc( )

§268 ε-TEX 3.14159 [PD VMS 3.6] changes PART 19: SAVING AND RESTORING EQUIVALENTS 51

⟨ Cases of valign for print cmd chr 1436* ⟩; vcenter : print esc( ); vrule: print esc( ); 268* . Saving and restoring equivalents. The nested structure provided by ‘ … ’ groups in TEX means that eqtb entries valid in outer groups should be saved and restored later if they are overridden inside the braces. When a new eqtb value is being assigned, the program therefore checks to see if the previous entry belongs to an outer level. In such a case, the old value is placed on the save stack just before the new value enters eqtb. At the end of a grouping level, i.e., when the right brace is sensed, the save stack is used to restore the outer values, and the inner ones are destroyed.

Entries on the save stack are of type memory word . The top item on this stack is save stack [p], where p = save ptr − 1; it contains three fields called save type, save level , and save index , and it is interpreted in one of five ways:

1) If save type(p) = restore old value, then save index (p) is a location in eqtb whose current value should be destroyed at the end of the current group and replaced by save stack [p − 1]. Furthermore if save index (p) ≥ int base, then save level (p) should replace the corresponding entry in xeq level .

2) If save type(p) = restore zero, then save index (p) is a location in eqtb whose current value should be destroyed at the end of the current group, when it should be replaced by the current value of eqtb[undefined control sequence].

3) If save type(p) = insert token, then save index (p) is a token that should be inserted into TEX’s input when the current group ends.

4) If save type(p) = level boundary , then save level (p) is a code explaining what kind of group we were previously in, and save index (p) points to the level boundary word at the bottom of the entries for that group. Furthermore, in extended ε-TEX mode, save stack [p − 1] contains the source line number at which the current level of grouping was entered.

5) If save type(p) = restore sa, then sa chain points to a chain of sparse array entries to be restored at the end of the current group. Furthermore save index (p) and save level (p) should replace the values of sa chain and sa level respectively.

define save type(#) ≡ save stack [#].hh.b0 { classifies a save stack entry }

define save level (#) ≡ save stack [#].hh.b1 { saved level for regions 5 and 6, or group code } define save index (#) ≡ save stack [#].hh.rh { eqtb location or save stack location } define restore old value = 0 { save type when a value should be restored later } define restore zero = 1 { save type when an undefined entry should be restored } define insert token = 2 { save type when a token is being saved for later use } define level boundary = 3 { save type corresponding to beginning of group } define restore sa = 4 { save type when sparse array entries should be restored }

⟨ Declare ε-TEX procedures for tracing and input 284* ⟩

273* . The following macro is used to test if there is room for up to seven more entries on save stack . By making a conservative test like this, we can get by with testing for overflow in only a few places.

define check full save stack ≡

52  PART 19: SAVING AND RESTORING EQUIVALENTS  ε-TEX 3.14159 [PD VMS 3.6] changes §274

if save ptr > max save stack then begin max save stack ← save ptr ; if max save stack > save size − 7 then overflow ( ␣ , save size); end 274* . Procedure new save level is called when a group begins. The argument is a group identification code like ‘hbox group’. After calling this routine, it is safe to put five more entries on save stack .

In some cases integer-valued items are placed onto the save stack just below a level boundary word, because this is a convenient place to keep information that is supposed to “pop up” just when the group has finished. For example, when ‘ ’ is being treated, the 100pt dimension is stored on save stack just before new save level is called.

We use the notation saved (k) to stand for an integer item that appears in location save ptr + k of the save stack.

define saved (#) ≡ save stack [save ptr + #].int procedure new save level (c : group code); { begin a new level of grouping }

begin check full save stack ;

if eTeX ex then

begin saved (0) ← line; incr (save ptr );

end; save type(save ptr ) ← level boundary ; save level (save ptr ) ← cur group; save index (save ptr ) ← cur boundary ; if cur level = max quarterword then

overflow ( ␣ , max quarterword − min quarterword );

{ quit if (cur level + 1) is too big to be stored in eqtb } cur boundary ← save ptr ; cur group ← c; stat if tracing groups > 0 then group trace(false); tats incr (cur level ); incr (save ptr ); end;

275* . Just before an entry of eqtb is changed, the following procedure should be called to update the other data structures properly. It is important to keep in mind that reference counts in mem include references from within save stack , so these counts must be handled carefully. procedure eq destroy (w : memory word ); { gets ready to forget w }

var q: pointer ; { equiv field of w } begin case eq type field (w) of call , long call , outer call , long outer call : delete token ref (equiv field (w)); glue ref : delete glue ref (equiv field (w)); shape ref : begin q ← equiv field (w); { we need to free a block }

if q ≠ null then free node(q, info(q) + info(q) + 1);

end; { such a block is 2n + 1 words long, where n = info(q) } box ref : flush node list (equiv field (w));

⟨ Cases for eq destroy 1567* ⟩

othercases do nothing

endcases; end; 277* . The procedure eq define defines an eqtb entry having specified eq type and equiv fields, and saves the former value if appropriate. This procedure is used only for entries in the first four regions of eqtb, i.e., only for entries that have eq type and equiv fields. After calling this routine, it is safe to put four more entries on save stack , provided that there was room for four more entries before the call, since eq save makes the necessary test.

define assign trace(#) ≡ stat if tracing assigns > 0 then restore trace(#); tats

procedure eq define(p : pointer ; t : quarterword ; e : halfword ); { new data for eqtb } label exit ; begin if eTeX ex ∧ (eq type(p) = t) ∧ (equiv (p) = e) then

begin assign trace(p, )

eq destroy (eqtb[p]); return;

end; assign trace(p, ) if eq level (p) = cur level then eq destroy (eqtb[p]) else if cur level > level one then eq save(p, eq level (p)); eq level (p) ← cur level ; eq type(p) ← t; equiv (p) ← e; assign trace(p, )

exit : end;

278* . The counterpart of eq define for the remaining (fullword) positions in eqtb is called eq word define. Since xeq level [p] ≥ level one for all p, a ‘restore zero’ will never be used in this case. procedure eq word define(p : pointer ; w : integer );

label exit ; begin if eTeX ex ∧ (eqtb[p].int = w) then

begin assign trace(p, )

return;

end; assign trace(p, ) if xeq level [p] ≠ cur level then

begin eq save(p, xeq level [p]); xeq level [p] ← cur level ; end;

eqtb[p].int ← w; assign trace(p, ) exit : end;

279* . The eq define and eq word define routines take care of local definitions. Global definitions are done in almost the same way, but there is no need to save old values, and the new value is associated with level one. procedure geq define(p : pointer ; t : quarterword ; e : halfword ); { global eq define }

begin assign trace(p, ␣ ) begin eq destroy (eqtb[p]); eq level (p) ← level one; eq type(p) ← t; equiv (p) ← e; end; assign trace(p, ) end;

procedure geq word define(p : pointer ; w : integer ); { global eq word define } begin assign trace(p, ␣ ) begin eqtb[p].int ← w; xeq level [p] ← level one; end; assign trace(p, ) end; 281* . The unsave routine goes the other way, taking items off of save stack . This routine takes care of restoration when a level ends; everything belonging to the topmost group is cleared off of the save stack. procedure back input ; forward ; procedure unsave; { pops the top level off the save stack }

label done; var p: pointer ; { position to be restored }

l: quarterword ; { saved level, if in fullword regions of eqtb }

t: halfword ; { saved value of cur tok }

a: boolean; { have we already processed an ? } begin a ← false; if cur level > level one then

begin decr (cur level ); ⟨ Clear off top level from save stack 282* ⟩;

end else confusion( ); { unsave is not used when cur group = bottom level } end;

282* . ⟨ Clear off top level from save stack 282* ⟩ ≡

loop begin decr (save ptr ); if save type(save ptr ) = level boundary then goto done; p ← save index (save ptr ); if save type(save ptr ) = insert token then ⟨ Insert token p into TEX’s input 326* ⟩ else if save type(save ptr ) = restore sa then

begin sa restore; sa chain ← p; sa level ← save level (save ptr );

end else begin if save type(save ptr ) = restore old value then begin l ← save level (save ptr ); decr (save ptr ); end

else save stack [save ptr ] ← eqtb[undefined control sequence];

⟨ Store save stack [save ptr ] in eqtb[p], unless eqtb[p] holds a global value 283 ⟩; end;

end; done: stat if tracing groups > 0 then group trace(true);

tats if grp stack [in open] = cur boundary then group warning ;

{ groups possibly not properly nested with files } cur group ← save level (save ptr ); cur boundary ← save index (save ptr ); if eTeX ex then decr (save ptr )

This code is used in section 281*.

284* . ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ ≡ stat procedure restore trace(p : pointer ; s : str number ); { eqtb[p] has just been restored or retained } begin begin diagnostic; print char ( ); print (s); print char ( ␣ ); show eqtb(p); print char ( ); end diagnostic(false); end; tats

See also sections 1395*, 1396*, 1489*, 1490*, 1507*, 1509*, 1510*, 1554*, 1556*, 1570*, 1571*, 1572*, 1573*, and 1574*. This code is used in section 268*.

§289 ε-TEX 3.14159 [PD VMS 3.6] changes PART 20: TOKEN LISTS 55

289* . Token lists. A TEX token is either a character or a control sequence, and it is represented internally in one of two ways: (1) A character whose ASCII code number is c and whose command code is m is represented as the number 2^{8}m + c; the command code is in the range 1 ≤ m ≤ 14. (2) A control sequence whose eqtb address is p is represented as the number cs token flag + p. Here cs token flag = 2^{12} − 1 is larger than 2^{8}m + c, yet it is small enough that cs token flag + p < max halfword ; thus, a token fits comfortably in a halfword.

A token t represents a left brace command if and only if t < left brace limit ; it represents a right brace command if and only if we have left brace limit ≤ t < right brace limit ; and it represents a match or end match command if and only if match token ≤ t ≤ end match token. The following definitions take care of these token-oriented constants and a few others.

define cs token flag ≡ ´ 7777 { amount added to the eqtb location in a token that stands for a control

sequence; is a multiple of 256, less 1 }

define left brace token = ´ 0400 { 2^{8} · left brace } define left brace limit = ´ 1000 { 2^{8} · (left brace + 1) } define right brace token = ´ 1000 { 2^{8} · right brace } define right brace limit = ´ 1400 { 2^{8} · (right brace + 1) } define math shift token = ´ 1400 { 2^{8} · math shift } define tab token = ´ 2000 { 2^{8} · tab mark } define out param token = ´ 2400 { 2^{8} · out param } define space token = ´ 5040 { 2^{8} · spacer + ␣ } define letter token = ´ 5400 { 2^{8} · letter } define other token = ´ 6000 { 2^{8} · other char } define match token = ´ 6400 { 2^{8} · match } define end match token = ´ 7000 { 2^{8} · end match } define protected token = ´ 7001 { 2^{8} · end match + 1 }

294* . The procedure usually “learns” the character code used for macro parameters by seeing one in a match command before it runs into any out param commands. ⟨ Display the token (m, c) 294* ⟩ ≡

case m of

left brace, right brace, math shift , tab mark , sup mark , sub mark , spacer , letter , other char : print (c); mac param: begin print (c); print (c);

end; out param: begin print (match chr );

if c ≤ 9 then print char (c + )

else begin print char ( ); return;

end; end;

match: begin match chr ← c; print (c); incr (n); print char (n); if n > then return; end;

end match: if c = 0 then print ( );

othercases print esc( ) endcases

This code is used in section 293.

56  PART 20: TOKEN LISTS  ε-TEX 3.14159 [PD VMS 3.6] changes §296

296* . The print meaning subroutine displays cur cmd and cur chr in symbolic form, including the expansion of a macro or mark. procedure print meaning ;

begin print cmd chr (cur cmd , cur chr ); if cur cmd ≥ call then

begin print char ( ); print ln; token show (cur chr ); end

else if (cur cmd = top bot mark ) ∧ (cur chr < marks code) then begin print char ( ); print ln; token show (cur mark [cur chr ]); end;

end;

§297 ε-TEX 3.14159 [PD VMS 3.6] changes PART 21: INTRODUCTION TO THE SYNTACTIC ROUTINES 57

298* . The print cmd chr routine prints a symbolic interpretation of a command code and its modifier. This is used in certain ‘ ´ ’ error messages, and in the implementation of diagnostic routines like .

The body of print cmd chr is a rather tedious listing of print commands, and most of it is essentially an inverse to the primitive routine that enters a TEX primitive into eqtb. Therefore much of this procedure appears elsewhere in the program, together with the corresponding primitive calls.

define chr cmd (#) ≡ begin print (#); print ASCII (chr code); end

⟨ Declare the procedure called print cmd chr 298* ⟩ ≡ procedure print cmd chr (cmd : quarterword ; chr code : halfword );

var n: integer ; { temp variable }

begin case cmd of

left brace: chr cmd ( ␣ ␣ ); right brace: chr cmd ( ␣ ␣ ); math shift : chr cmd ( ␣ ␣ ␣ ); mac param: chr cmd ( ␣ ␣ ␣ ); sup mark : chr cmd ( ␣ ␣ ); sub mark : chr cmd ( ␣ ␣ ); endv : print ( ␣ ␣ ␣ ); spacer : chr cmd ( ␣ ␣ ); letter : chr cmd ( ␣ ␣ ); other char : chr cmd ( ␣ ␣ ); ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ othercases print ( ␣ ␣ ) endcases; end;

This code is used in section 252.

58 PART 21: INTRODUCTION TO THE SYNTACTIC ROUTINES ε-TEX 3.14159 [PD VMS 3.6] changes §299

299* . Here is a procedure that displays the current command. procedure show cur cmd chr ;

var n: integer ; { level of nesting } l: integer ; { line where started } p: pointer ;

begin begin diagnostic; print nl ( ); if mode ≠ shown mode then

begin print mode(mode); print ( ␣ ); shown mode ← mode; end;

print cmd chr (cur cmd , cur chr ); if tracing ifs > 0 then

if cur cmd ≥ if test then

if cur cmd ≤ fi or else then begin print ( ␣ ); if cur cmd = fi or else then

begin print cmd chr (if test , cur if ); print char ( ␣ ); n ← 0; l ← if line; end

else begin n ← 1; l ← line;

end; p ← cond ptr ; while p ≠ null do

begin incr (n); p ← link (p);

end; print ( ␣ ); print int (n); print char ( ); print if line(l); end;

§300 ε-TEX 3.14159 [PD VMS 3.6] changes PART 22: INPUT STACKS AND STATES 59

print char ( ); end diagnostic(false); end; 303* . Let’s look more closely now at the control variables (state, index , start , loc, limit , name), assuming that TEX is reading a line of characters that have been input from some file or from the user’s terminal. There is an array called buffer that acts as a stack of all lines of characters that are currently being read from files, including all lines on subsidiary levels of the input stack that are not yet completed. TEX will return to the other lines when it is finished with the present input file.

(Incidentally, on a machine with byte-oriented addressing, it might be appropriate to combine buffer with the str pool array, letting the buffer entries grow downward from the top of the string pool and checking that these two tables don’t bump into each other.)

The line we are currently working on begins in position start of the buffer; the next character we are about to read is buffer [loc]; and limit is the location of the last character present. If loc > limit , the line has been completely read. Usually buffer [limit ] is the end line char , denoting the end of a line, but this is not true if the current line is an insertion that was entered on the user’s terminal in response to an error message.

The name variable is a string number that designates the name of the current file, if we are reading a text file. It is zero if we are reading from the terminal; it is n + 1 if we are reading from input stream n, where 0 ≤ n ≤ 16. (Input stream 16 stands for an invalid stream number; in such cases the input is actually from the terminal, under control of the procedure read toks .) Finally 18 ≤ name ≤ 19 indicates that we are reading a pseudo file created by the command.

The state variable has one of three values, when we are scanning such files:

1) state = mid line is the normal state.

2) state = skip blanks is like mid line, but blanks are ignored.

3) state = new line is the state at the beginning of a line.

These state values are assigned numeric codes so that if we add the state code to the next character’s command code, we get distinct values. For example, ‘mid line + spacer ’ stands for the case that a blank space character occurs in the middle of a line when it is not being ignored; after this case is processed, the next value of state will be skip blanks .

define mid line = 1 { state code when scanning a line of characters }

define skip blanks = 2 + max char code { state code when ignoring blanks }

60  PART 22: INPUT STACKS AND STATES  ε-TEX 3.14159 [PD VMS 3.6] changes §307

define new line = 3 + max char code + max char code { state code at start of line } 307* . However, all this discussion about input state really applies only to the case that we are inputting from a file. There is another important case, namely when we are currently getting input from a token list. In this case state = token list , and the conventions about the other state variables are different: loc is a pointer to the current node in the token list, i.e., the node that will be read next. If loc = null , the

token list has been fully read. start points to the first node of the token list; this node may or may not contain a reference count, depending

on the type of token list involved. token type, which takes the place of index in the discussion above, is a code number that explains what kind

of token list is being scanned. name points to the eqtb address of the control sequence being expanded, if the current token list is a macro. param start , which takes the place of limit , tells where the parameters of the current macro begin in the

param stack , if the current token list is a macro. The token type can take several values, depending on where the current token list came from: parameter , if a parameter is being scanned; u template, if the ⟨u_{j}⟩ part of an alignment template is being scanned; v template, if the ⟨v_{j}⟩ part of an alignment template is being scanned; backed up, if the token list being scanned has been inserted as ‘to be read again’. inserted , if the token list being scanned has been inserted as the text expansion of a or similar

variable; macro, if a user-defined control sequence is being scanned; output text , if an routine is being scanned; every par text , if the text of is being scanned; every math text , if the text of is being scanned; every display text , if the text of is being scanned; every hbox text , if the text of is being scanned; every vbox text , if the text of is being scanned; every job text , if the text of is being scanned; every cr text , if the text of is being scanned; mark text , if the text of a is being scanned; write text , if the text of a is being scanned. The codes for output text , every par text , etc., are equal to a constant plus the corresponding codes for token list parameters output routine loc, every par loc, etc. The token list begins with a reference count if and only if token type ≥ macro.

define token list = 0 { state code when scanning a token list } define token type ≡ index { type of current token list } define param start ≡ limit { base of macro parameters in param stack } define parameter = 0 { token type code for parameter } define u template = 1 { token type code for ⟨u_{j}⟩ template } define v template = 2 { token type code for ⟨v_{j}⟩ template } define backed up = 3 { token type code for text to be reread } define inserted = 4 { token type code for inserted texts } define macro = 5 { token type code for defined control sequences } define output text = 6 { token type code for output routines } define every par text = 7 { token type code for } define every math text = 8 { token type code for } define every display text = 9 { token type code for } define every hbox text = 10 { token type code for } define every vbox text = 11 { token type code for } define every job text = 12 { token type code for } define every cr text = 13 { token type code for } define every eof text = 14 { token type code for } define mark text = 15 { token type code for , etc. } define write text = 16 { token type code for }

311* . The status at each level is indicated by printing two lines, where the first line indicates what was read so far and the second line shows what remains to be read. The context is cropped, if necessary, so that the first line contains at most half error line characters, and the second contains at most error line. Non-current input levels whose token type is ‘backed up’ are shown only if they have not been fully read. procedure show context ; { prints where the scanner is }

label done; var old setting : 0 . . max selector ; { saved selector setting }

nn: integer ; { number of contexts shown so far, less one }

bottom line: boolean; { have we reached the final context to be shown? } ⟨ Local variables for formatting calculations 315 ⟩

begin base ptr ← input ptr ; input stack [base ptr ] ← cur input ; { store current state } ⟨ Commence an LSE diagnostic report 1605* ⟩; nn ← −1; bottom line ← false; loop begin cur input ← input stack [base ptr ]; { enter into the context }

if (state ≠ token list ) then

if (name > 19) ∨ (base ptr = 0) then bottom line ← true; if (base ptr = input ptr ) ∨ bottom line ∨ (nn < error context lines ) then

⟨ Display the current context 312 ⟩ else if nn = error context lines then

begin print nl ( ); incr (nn); { omitted if error context lines < 0 } end;

if bottom line then goto done;

decr (base ptr );

end; done: cur input ← input stack [input ptr ]; { restore original state }

⟨ Terminate an LSE diagnostic report 1606* ⟩; end; 313* . This routine should be changed, if necessary, to give the best possible indication of where the current line resides in the input file. For example, on some systems it is best to print both a page and line number. ⟨ Print location of current line 313* ⟩ ≡

if name ≤ 17 then begin ⟨ Output the location to the diagnostics file 1607* ⟩;

if terminal input then

if base ptr = 0 then print nl ( )

else print nl ( ␣ ) else begin print nl ( ␣ );

if name = 17 then print char ( ) else print int (name − 1); print char ( ); end;

⟨ Prepare to copy tokens to the diagnostic region 1608* ⟩;

end else if index ≠ in open then { input from a pseudo file }

begin print nl ( ); print int (line stack [index + 1]); end

else begin print nl ( ); print int (line); ⟨ Report location within source file to diagnostics 1609* ⟩;

end; print char ( ␣ )

This code is used in section 312.

314* . ⟨ Print type of token list 314* ⟩ ≡ ⟨ Include token report within diagnostics file 1610* ⟩;

case token type of

parameter : print nl ( ␣ ); u template, v template: print nl ( ␣ ); backed up: if loc = null then print nl ( ␣ ␣ )

else print nl ( ␣ ␣ ␣ ␣ ); inserted : print nl ( ␣ ␣ ); macro: begin print ln; print cs (name);

end; output text : print nl ( ␣ ); every par text : print nl ( ␣ ); every math text : print nl ( ␣ ); every display text : print nl ( ␣ ); every hbox text : print nl ( ␣ ); every vbox text : print nl ( ␣ ); every job text : print nl ( ␣ ); every cr text : print nl ( ␣ ); every eof text : print nl ( ␣ ); mark text : print nl ( ␣ ); write text : print nl ( ␣ ); othercases print nl ( ) { this should never happen } endcases; ⟨ Prepare to copy tokens to the diagnostic region 1608* ⟩

This code is used in section 312.

317* . And the following code uses the information after it has been gathered. ⟨ Print two lines using the tricky pseudoprinted information 317* ⟩ ≡

if trick count = 1000000 then set trick count ; { set trick count must be performed } if tally < trick count then m ← tally − first count else m ← trick count − first count ; { context on line 2 } if l + first count ≤ half error line then

begin p ← 0; n ← l + first count ; end

else begin print ( ); p ← l + first count − half error line + 3; n ← half error line;

end; for q ← p to first count − 1 do print char (trick buf [q mod error line]); ⟨ Split the context line display 1611* ⟩; if m + n ≤ error line then p ← first count + m else p ← first count + (error line − n − 3); for q ← first count to p − 1 do print char (trick buf [q mod error line]); if m + n > error line then print ( ); ⟨ Indicate offending character 1612* ⟩

This code is used in section 312.

318* . But the trick is distracting us from our current goal, which is to understand the input state. So let’s concentrate on the data structures that are being pseudoprinted as we finish up the show context procedure. ⟨ Pseudoprint the line 318* ⟩ ≡

begin pseudoprint ; if buffer [limit ] = end line char then j ← limit else j ← limit + 1; { determine the effective end of the line } if j > 0 then

for i ← start to j − 1 do begin if i = loc then set trick count ; print (buffer [i]); end;

if name ≤ 17 then ⟨ Copy remainder of context to diagnostic file 1613* ⟩

This code is used in section 312.

319* . ⟨ Pseudoprint the token list 319* ⟩ ≡ begin pseudoprint ; if token type < macro then show token list (start , loc, 100000) else show token list (link (start ), loc, 100000); { avoid reference count } ⟨ Copy remainder of context to diagnostic file 1613* ⟩;

This code is used in section 312.

64  PART 23: MAINTAINING THE INPUT STACKS  ε-TEX 3.14159 [PD VMS 3.6] changes §321

326* . ⟨ Insert token p into TEX’s input 326* ⟩ ≡ begin t ← cur tok ; cur tok ← p;

if a then

begin p ← get avail ; info(p) ← cur tok ; link (p) ← loc; loc ← p; start ← p; if cur tok < right brace limit then

if cur tok < left brace limit then decr (align state)

else incr (align state); end

else begin back input ; a ← eTeX ex ;

end; cur tok ← t; end

This code is used in section 282*.

328* . The begin file reading procedure starts a new level of input for lines of characters to be read from a file, or as an insertion from the terminal. It does not take care of opening the file, nor does it set loc or limit or line. procedure begin file reading ;

begin if in open = max in open then overflow (  ␣     ␣  , max in open);
if first = buf size then overflow (  ␣  , buf size);

incr (in open); push input ; index ← in open; eof seen[index ] ← false; grp stack [index ] ← cur boundary ; if stack [index ] ← cond ptr ; line stack [index ] ← line; start ← first ; state ← mid line; name ← 0; { terminal input is now true } end;

329* . Conversely, the variables must be downdated when such a level of input is finished: procedure end file reading ;

begin first ← start ; line ← line stack [index ]; if (name = 18) ∨ (name = 19) then pseudo close else if name > 17 then a close(cur file); { forget it } pop input ; decr (in open); end;

331* . To get TEX’s whole input mechanism going, we perform the following actions. ⟨ Initialize the input routines 331* ⟩ ≡

begin input ptr ← 0; max in stack ← 0; in open ← 0; open parens ← 0; max buf stack ← 0; grp stack [0] ← 0; if stack [0] ← null ; param ptr ← 0; max param stack ← 0; first ← buf size; repeat buffer [first ] ← 0; decr (first ); until first = 0; scanner status ← normal ; warning index ← null ; first ← 1; state ← new line; start ← 1; index ← 0; line ← 0; name ← 0; force eof ← false; align state ← 1000000; if ¬init terminal then goto final end ; limit ← last ; first ← last + 1; { init terminal has set loc and last } end

This code is used in section 1337*.

§332 ε-TEX 3.14159 [PD VMS 3.6] changes PART 24: GETTING THE NEXT TOKEN 65

362* . ⟨ Read next line of file into buffer , or goto restart if the file has ended 362* ⟩ ≡ begin incr (line); first ← start ; if ¬force eof then

if name ≤ 19 then

begin if pseudo input then { not end of file }

firm up the line { this sets limit } else if (every eof ≠ null ) ∧ ¬eof seen[index ] then

begin limit ← first − 1; eof seen[index ] ← true; { fake one empty line } begin token list (every eof , every eof text ); goto restart ; end

else force eof ← true; end

else begin if input ln(cur file, true) then { not end of file }

firm up the line { this sets limit } else if (every eof ≠ null ) ∧ ¬eof seen[index ] then

begin limit ← first − 1; eof seen[index ] ← true; { fake one empty line } begin token list (every eof , every eof text ); goto restart ; end

else force eof ← true; end;

if force eof then

begin if tracing nesting > 0 then

if (grp stack [in open] ≠ cur boundary ) ∨ (if stack [in open] ≠ cond ptr ) then file warning ;

{ give warning for some unfinished groups and/or conditionals }

if name ≥ 19 then begin print char ( ); decr (open parens ); update terminal ; { show user that file has been read } end;

force eof ← false; end file reading ; { resume previous level } check outer validity ; goto restart ; end;

if end line char inactive then decr (limit ) else buffer [limit ] ← end line char ; first ← limit + 1; loc ← start ; { ready to read } end

This code is used in section 360.

66  PART 25: EXPANDING THE NEXT TOKEN  ε-TEX 3.14159 [PD VMS 3.6] changes §366

366* . Expanding the next token. Only a dozen or so command codes > max command can possibly be returned by get next ; in increasing order, they are undefined cs , expand after , no expand , input , if test , fi or else, cs name, convert , the, top bot mark , call , long call , outer call , long outer call , and end template.

The expand subroutine is used when cur cmd > max command . It removes a “call” or a conditional or one of the other special operations just listed. It follows that expand might invoke itself recursively. In all cases, expand destroys the current token, but it sets things up so that the next get next will deliver the appropriate next token. The value of cur tok need not be known when expand is called.

Since several of the basic scanning routines communicate via global variables, their values are saved as local variables of expand so that recursive calls don’t invalidate them. ⟨ Declare the procedure called macro call 389* ⟩ ⟨ Declare the procedure called insert relax 379 ⟩ ⟨ Declare ε-TEX procedures for expanding 1485* ⟩ procedure pass text ; forward ; procedure start input ; forward ; procedure conditional ; forward ; procedure get x token; forward ; procedure conv toks ; forward ; procedure ins the toks ; forward ; procedure expand ;

label reswitch;

var t: halfword ; { token that is being “expanded after” } p, q, r: pointer ; { for list manipulation } j: 0 . . buf size; { index into buffer } cv backup: integer ; { to save the global quantity cur val } cvl backup, radix backup, co backup: small number ; { to save cur val level , etc. } backup backup: pointer ; { to save link (backup head ) } save scanner status : small number ; { temporary storage of scanner status }

begin cv backup ← cur val ; cvl backup ← cur val level ; radix backup ← radix ; co backup ← cur order ; backup backup ← link (backup head );

reswitch: if cur cmd < call then ⟨ Expand a nonmacro 367* ⟩

else if cur cmd < end template then macro call

§367 ε-TEX 3.14159 [PD VMS 3.6] changes PART 25: EXPANDING THE NEXT TOKEN 67

else ⟨ Insert a token containing frozen endv 375 ⟩; cur val ← cv backup; cur val level ← cvl backup; radix ← radix backup; cur order ← co backup; link (backup head ) ← backup backup; end; 367* . ⟨ Expand a nonmacro 367* ⟩ ≡

begin if tracing commands > 1 then show cur cmd chr ;

case cur cmd of

top bot mark : ⟨ Insert the appropriate mark text into the scanner 386* ⟩; expand after : if cur chr = 0 then ⟨ Expand the token after the next token 368 ⟩

else ⟨ Negate a boolean conditional and goto reswitch 1498* ⟩; no expand : ⟨ Suppress expansion of the next token 369 ⟩; cs name: ⟨ Manufacture a control sequence name 372 ⟩; convert : conv toks ; { this procedure is discussed in Part 27 below } the: ins the toks ; { this procedure is discussed in Part 27 below } if test : conditional ; { this procedure is discussed in Part 28 below } fi or else: ⟨ Terminate the current conditional and skip to 510* ⟩; input : ⟨ Initiate or terminate input from a file 378* ⟩; othercases ⟨ Complain about an undefined macro 370 ⟩ endcases; end

This code is used in section 366*.

377* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ input : if chr code = 0 then print esc( )

⟨ Cases of input for print cmd chr 1481* ⟩ else print esc( );

378* . ⟨ Initiate or terminate input from a file 378* ⟩ ≡ if cur chr = 1 then force eof ← true ⟨ Cases for input 1482* ⟩

else if name in progress then insert relax
else start input

This code is used in section 367*.

382* . A control sequence that has been ’ed by the user is expanded by TEX’s macro call procedure.

Before we get into the details of macro call , however, let’s consider the treatment of primitives like , since they are essentially macros without parameters. The token lists for such marks are kept in a global array of five pointers; we refer to the individual entries of this array by symbolic names top mark , etc. The value of top mark is either null or a pointer to the reference count of a token list.

define marks code ≡ 5 { add this for etc. } define top mark code = 0 { the mark in effect at the previous page break } define first mark code = 1 { the first mark between top mark and bot mark } define bot mark code = 2 { the mark in effect at the current page break } define split first mark code = 3 { the first mark found by } define split bot mark code = 4 { the last mark found by } define top mark ≡ cur mark [top mark code] define first mark ≡ cur mark [first mark code] define bot mark ≡ cur mark [bot mark code] define split first mark ≡ cur mark [split first mark code] define split bot mark ≡ cur mark [split bot mark code]

⟨ Global variables 13 ⟩ +≡ cur mark : array [top mark code . . split bot mark code] of pointer ; { token lists for marks } 385* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ top bot mark : begin case (chr code mod marks code) of

first mark code: print esc( ); bot mark code: print esc( ); split first mark code: print esc( ); split bot mark code: print esc( ); othercases print esc( ) endcases; if chr code ≥ marks code then print char ( ); end;

386* . The following code is activated when cur cmd = top bot mark and when cur chr is a code like top mark code. ⟨ Insert the appropriate mark text into the scanner 386* ⟩ ≡

begin t ← cur chr mod marks code; if cur chr ≥ marks code then scan register num else cur val ← 0; if cur val = 0 then cur ptr ← cur mark [t] else ⟨ Compute the mark pointer for mark type t and class cur val 1557* ⟩; if cur ptr ≠ null then begin token list (cur ptr , mark text ); end

This code is used in section 367*.

389* . After parameter scanning is complete, the parameters are moved to the param stack . Then the macro body is fed to the scanner; in other words, macro call places the defined text of the control sequence at the top of TEX’s input stack, so that get next will proceed to read it next.

The global variable cur cs contains the eqtb address of the control sequence being expanded, when macro call begins. If this control sequence has not been declared , i.e., if its command code in the eq type field is not long call or long outer call , its parameters are not allowed to contain the control sequence . If an illegal appears, the macro call is aborted, and the will be rescanned. ⟨ Declare the procedure called macro call 389* ⟩ ≡ procedure macro call ; { invokes a user-defined control sequence }

label exit , continue, done, done1 , found ; var r: pointer ; { current node in the macro’s token list }

p: pointer ; { current node in parameter token list being built } q: pointer ; { new node being put into the token list } s: pointer ; { backup pointer for parameter matching } t: pointer ; { cycle pointer for backup recovery } u, v: pointer ; { auxiliary pointers for backup recovery } rbrace ptr : pointer ; { one step before the last right brace token } n: small number ; { the number of parameters scanned } unbalance: halfword ; { unmatched left braces in current parameter } m: halfword ; { the number of tokens or groups (usually) } ref count : pointer ; { start of the token list } save scanner status : small number ; { scanner status upon entry } save warning index : pointer ; { warning index upon entry } match chr : ASCII code; { character used in parameter }

begin save scanner status ← scanner status ; save warning index ← warning index ; warning index ← cur cs ; ref count ← cur chr ; r ← link (ref count ); n ← 0; if tracing macros > 0 then ⟨ Show the text of the macro being expanded 401 ⟩; if info(r) = protected token then r ← link (r); if info(r) ≠ end match token then ⟨ Scan the parameters and make link (r) point to the macro body;

but return if an illegal is detected 391 ⟩; ⟨ Feed the macro body and its parameters to the scanner 390 ⟩;

exit : scanner status ← save scanner status ; warning index ← save warning index ;

end;

This code is used in section 366*.

70  PART 26: BASIC SCANNING SUBROUTINES  ε-TEX 3.14159 [PD VMS 3.6] changes §402

409* . The next routine ‘scan something internal ’ is used to fetch internal numeric quantities like ‘ ’, and also to handle the ‘ ’ when expanding constructions like ‘ ’ and ‘ ’. Soon we will be considering the scan int procedure, which calls scan something internal ; on the other hand, scan something internal also calls scan int , for constructions like ‘ ` $ ’ or ‘ ’. So we have to declare scan int as a forward procedure. A few other procedures are also declared at this point. procedure scan int ; forward ; { scans an integer value } ⟨ Declare procedures that scan restricted classes of integers 433 ⟩ ⟨ Declare ε-TEX procedures for scanning 1416* ⟩ ⟨ Declare procedures that scan font-related stuff 577 ⟩

411* . The hash table is initialized with ‘  ’, ‘  ’, ‘  ’, and ‘  ’ all having register as

their command code; they are distinguished by the chr code, which is either int val , dimen val , glue val , or mu val more than mem bot (dynamic variable-size nodes cannot have these values) ⟨ Put each of TEX’s primitives into the hash table 226 ⟩ +≡

primitive(  , register , mem bot + int val ); primitive(  , register , mem bot + dimen val );
primitive(  , register , mem bot + glue val ); primitive(  , register , mem bot + mu val );

§413 ε-TEX 3.14159 [PD VMS 3.6] changes PART 26: BASIC SCANNING SUBROUTINES 71

412* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ register : ⟨ Cases of register for print cmd chr 1565* ⟩; 413* . OK, we’re ready for scan something internal itself. A second parameter, negative, is set true if the value that is found should be negated. It is assumed that cur cmd and cur chr represent the first token of the internal quantity to be scanned; an error will be signalled if cur cmd < min internal or cur cmd > max internal .

define scanned result end (#) ≡ cur val level ← #; end define scanned result (#) ≡ begin cur val ← #; scanned result end

procedure scan something internal (level : small number ; negative : boolean);

{ fetch an internal parameter } label exit ; var m: halfword ; { chr code part of the operand token }

q: halfword ; { general purpose index } i: four quarters ; { character info } p: 0 . . nest size; { index into nest }

begin m ← cur chr ;

case cur cmd of

def code: ⟨ Fetch a character code from some table 414 ⟩; toks register , assign toks , def family , set font , def font : ⟨ Fetch a token list or font identifier, provided

that level = tok val 415* ⟩; assign int : scanned result (eqtb[m].int )(int val ); assign dimen: scanned result (eqtb[m].sc)(dimen val ); assign glue: scanned result (equiv (m))(glue val ); assign mu glue: scanned result (equiv (m))(mu val ); set aux : ⟨ Fetch the space factor or the prev depth 418 ⟩; set prev graf : ⟨ Fetch the prev graf 422 ⟩; set page int : ⟨ Fetch the dead cycles or the insert penalties 419* ⟩; set page dimen: ⟨ Fetch something on the page so far 421 ⟩; set shape: ⟨ Fetch the par shape size 423* ⟩; set box dimen: ⟨ Fetch a box dimension 420* ⟩; char given, math given: scanned result (cur chr )(int val ); assign font dimen: ⟨ Fetch a font dimension 425 ⟩; assign font int : ⟨ Fetch a font integer 426 ⟩; register : ⟨ Fetch a register 427* ⟩; last item: ⟨ Fetch an item in the current node, if appropriate 424* ⟩; othercases ⟨ Complain that can’t do this; give zero result 428 ⟩ endcases; while cur val level > level do ⟨ Convert cur val to a lower level 429 ⟩; ⟨ Fix the reference count, if any, and negate cur val if negative 430 ⟩;

exit : end; 415* . ⟨ Fetch a token list or font identifier, provided that level = tok val 415* ⟩ ≡

if level ≠ tok val then

begin print err (  ␣       ␣       ␣  ␣  );

  help3 ( ␣      ␣      ␣    ␣    ␣     ␣ ␣        ␣` ´  )
  (  ␣   ␣   ´ ␣      ␣   ␣   ␣ ␣      ␣  ␣   ␣ ␣  )

(  ␣  ␣` ␣     ´ ␣  ␣   ␣     ␣  ␣   ␣  ); back error ;

scanned result (0)(dimen val );

end else if cur cmd ≤ assign toks then

begin if cur cmd < assign toks then { cur cmd = toks register }

if m = mem bot then begin scan register num; if cur val < 256 then cur val ← equiv (toks base + cur val ) else begin find sa element (tok val , cur val , false);

if cur ptr = null then cur val ← null else cur val ← sa ptr (cur ptr ); end; end

else cur val ← sa ptr (m) else cur val ← equiv (m); cur val level ← tok val ; end

else begin back input ; scan font ident ; scanned result (font id base + cur val )(ident val );

end

This code is used in section 413*.

416* . Users refer to ‘  ’ only in horizontal mode, and to ‘  ’ only in vertical

mode; so we put the associated mode in the modifier part of the set aux command. The set page int command has modifier 0 or 1, for ‘ ’ and ‘ ’, respectively. The set box dimen command is modified by either width offset , height offset , or depth offset . And the last item command is modified by either int val , dimen val , glue val , last node type code, input line no code, badness code, eTeX version code, or one of the other codes for ε-TEX extensions.

define last node type code = glue val + 1 { code for } define input line no code = glue val + 2 { code for } define badness code = glue val + 3 { code for } define eTeX int = glue val + 4 { first of ε-TEX codes for integers } define eTeX dim = eTeX int + 8 { first of ε-TEX codes for dimensions } define eTeX glue = eTeX dim + 9 { first of ε-TEX codes for glue } define eTeX mu = eTeX glue + 1 { first of ε-TEX codes for muglue } define eTeX expr = eTeX mu + 1 { first of ε-TEX codes for expressions }

⟨ Put each of TEX’s primitives into the hash table 226 ⟩ +≡

primitive(  , set aux , hmode); primitive(  , set aux , vmode);
primitive(  , set page int , 0); primitive(  , set page int , 1);
primitive(  , set box dimen, width offset ); primitive(  , set box dimen, height offset );
primitive(  , set box dimen, depth offset ); primitive(  , last item, int val );
primitive(  , last item, dimen val ); primitive(  , last item, glue val );
primitive(  , last item, input line no code); primitive(  , last item, badness code);

417* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ set aux : if chr code = vmode then print esc( ) else print esc( ); set page int : if chr code = 0 then print esc( )

⟨ Cases of set page int for print cmd chr 1427* ⟩ else print esc( ); set box dimen: if chr code = width offset then print esc( )

else if chr code = height offset then print esc( )

else print esc( ); last item: case chr code of

int val : print esc( ); dimen val : print esc( ); glue val : print esc( ); input line no code: print esc( );

⟨ Cases of last item for print cmd chr 1381* ⟩ othercases print esc( ) endcases;

419* . ⟨ Fetch the dead cycles or the insert penalties 419* ⟩ ≡ begin if m = 0 then cur val ← dead cycles ⟨ Cases for ‘Fetch the dead cycles or the insert penalties ’ 1428* ⟩

else cur val ← insert penalties ; cur val level ← int val ;

end

This code is used in section 413*.

420* . ⟨ Fetch a box dimension 420* ⟩ ≡ begin scan register num; fetch box (q); if q = null then cur val ← 0 else cur val ← mem[q + m].sc; cur val level ← dimen val ; end

This code is used in section 413*.

423* . ⟨ Fetch the par shape size 423* ⟩ ≡ begin if m > par shape loc then ⟨ Fetch a penalties array element 1599* ⟩ else if par shape ptr = null then cur val ← 0

else cur val ← info(par shape ptr ); cur val level ← int val ; end

This code is used in section 413*.

424* . Here is where  ,  , and  are implemented. The reference count for

will be updated later. A final node is temporarily removed.

We also handle and here, because they are legal in similar contexts. ⟨ Fetch an item in the current node, if appropriate 424* ⟩ ≡

if m > last node type code then if m ≥ eTeX glue then ⟨ Process an expression and return 1513* ⟩ else if m ≥ eTeX dim then

begin case m of

⟨ Cases for fetching a dimension value 1405* ⟩ end; { there are no other cases } cur val level ← dimen val ; end

else begin case m of

input line no code: cur val ← line; badness code: cur val ← last badness ;

⟨ Cases for fetching an integer value 1382* ⟩ end; { there are no other cases } cur val level ← int val ; end

else begin if cur chr = glue val then cur val ← zero glue else cur val ← 0;

if cur chr = last node type code then begin cur val ← int val ; if (tail = head ) ∨ (mode = 0) then cur val ← −1; end

else cur val level ← cur chr ; if ¬is char node(tail ) ∧ (mode ≠ 0) then

begin if (type(tail ) = math node) ∧ (subtype(tail ) = end M code) then remove end M ;

case cur chr of

int val : if type(tail ) = penalty node then cur val ← penalty (tail ); dimen val : if type(tail ) = kern node then cur val ← width(tail ); glue val : if type(tail ) = glue node then

begin cur val ← glue ptr (tail );

if subtype(tail ) = mu glue then cur val level ← mu val ; end;

last node type code: if (type(tail ) ≠ math node) ∨ (subtype(tail ) ≠ end M code) then if type(tail ) ≤ unset node then cur val ← type(tail ) + 1 else cur val ← unset node + 2;

end; { there are no other cases } if LR temp ≠ null then insert end M ; end

else if (mode = vmode) ∧ (tail = head ) then

case cur chr of

int val : cur val ← last penalty ; dimen val : cur val ← last kern; glue val : if last glue ≠ max halfword then cur val ← last glue; last node type code: cur val ← last node type; end; { there are no other cases }

end

This code is used in section 413*.

427* . ⟨ Fetch a register 427* ⟩ ≡

begin if (m < mem bot ) ∨ (m > lo mem stat max ) then begin cur val level ← sa type(m); if cur val level < glue val then cur val ← sa int (m) else cur val ← sa ptr (m); end

else begin scan register num; cur val level ← m − mem bot ;

if cur val > 255 then begin find sa element (cur val level , cur val , false); if cur ptr = null then

if cur val level < glue val then cur val ← 0 else cur val ← zero glue

else if cur val level < glue val then cur val ← sa int (cur ptr )

else cur val ← sa ptr (cur ptr ); end

else case cur val level of

int val : cur val ← count (cur val );

dimen val : cur val ← dimen(cur val );

glue val : cur val ← skip(cur val );

mu val : cur val ← mu skip(cur val );

end; { there are no other cases } end;

end

This code is used in section 413*.

461* . The final member of TEX’s value-scanning trio is scan glue, which makes cur val point to a glue specification. The reference count of that glue spec will take account of the fact that cur val is pointing to it.

The level parameter should be either glue val or mu val . Since scan dimen was so much more complex than scan int , we might expect scan glue to be even worse.

But fortunately, it is very simple, since most of the work has already been done. procedure scan glue(level : small number ); { sets cur val to a glue spec pointer }

label exit ; var negative: boolean; { should the answer be negated? }

q: pointer ; { new glue specification } mu: boolean; { does level = mu val ? }

begin mu ← (level = mu val ); ⟨ Get the next non-blank non-sign token; set negative appropriately 441 ⟩; if (cur cmd ≥ min internal ) ∧ (cur cmd ≤ max internal ) then

begin scan something internal (level , negative); if cur val level ≥ glue val then

begin if cur val level ≠ level then mu error ;

return;

end; if cur val level = int val then scan dimen(mu, false, true) else if level = mu val then mu error ; end

else begin back input ; scan dimen(mu, false, false); if negative then negate(cur val ); end;

⟨ Create a new glue specification whose width is cur val ; scan for its stretch and shrink components 462 ⟩; exit : end;

⟨ Declare procedures needed for expressions 1515* ⟩

76  PART 27: BUILDING TOKEN LISTS  ε-TEX 3.14159 [PD VMS 3.6] changes §464
464* . Building token lists. The token lists for macros and for other things like  and  and

are produced by a procedure called scan toks .

Before we get into the details of scan toks , let’s consider a much simpler task, that of converting the current string into a token list. The str toks function does this; it classifies spaces as type spacer and everything else as type other char .

The token list created by str toks begins at link (temp head ) and ends at the value p that is returned. (If p = temp head , the list is empty.) ⟨ Declare ε-TEX procedures for token lists 1417* ⟩ function str toks (b : pool pointer ): pointer ; { changes the string str pool [b . . pool ptr ] to a token list }

var p: pointer ; { tail of the token list } q: pointer ; { new node being added to the token list via store new token } t: halfword ; { token being appended } k: pool pointer ; { index into str pool }

begin str room(1); p ← temp head ; link (p) ← null ; k ← b; while k < pool ptr do

begin t ← so(str pool [k]); if t = ␣ then t ← space token else t ← other token + t; fast store new token(t); incr (k); end;

pool ptr ← b; str toks ← p; end;

465* . The main reason for wanting str toks is the next function, the toks , which has similar input/output characteristics.

This procedure is supposed to scan something like ‘ ’, i.e., whatever can follow ‘ ’, and it constructs a token list containing something like ‘ ’. function the toks : pointer ;

label exit ; var old setting : 0 . . max selector ; { holds selector setting }

p, q, r: pointer ; { used for copying a token list } b: pool pointer ; { base of temporary string } c: small number ; { value of cur chr }

begin ⟨ Handle or and return 1422* ⟩; get x token; scan something internal (tok val , false); if cur val level ≥ ident val then ⟨ Copy the token list 466 ⟩ else begin old setting ← selector ; selector ← new string ; b ← pool ptr ;

case cur val level of

int val : print int (cur val ); dimen val : begin print scaled (cur val ); print ( );

end; glue val : begin print spec(cur val , ); delete glue ref (cur val );

end; mu val : begin print spec(cur val , ); delete glue ref (cur val );

end; end; { there are no other cases } selector ← old setting ; the toks ← str toks (b); end;

§469 ε-TEX 3.14159 [PD VMS 3.6] changes PART 27: BUILDING TOKEN LISTS 77

exit : end; 469* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ convert : case chr code of

number code: print esc( ); roman numeral code: print esc( ); string code: print esc( ); meaning code: print esc( ); font name code: print esc( );

⟨ Cases of convert for print cmd chr 1383* ⟩ othercases print esc( ) endcases;

470* . The procedure conv toks uses str toks to insert the token list for convert functions into the scanner; ‘ ’ control sequences are allowed to follow ‘ ’ and ‘ ’. procedure conv toks ;

var old setting : 0 . . max selector ; { holds selector setting } c: small number ; { desired type of conversion } save scanner status : small number ; { scanner status upon entry } b: pool pointer ; { base of temporary string }

begin c ← cur chr ; ⟨ Scan the argument for command c 471* ⟩; old setting ← selector ; selector ← new string ; b ← pool ptr ; ⟨ Print the result of command c 472* ⟩; selector ← old setting ; link (garbage) ← str toks (b); ins list (link (temp head )); end;

471* . ⟨ Scan the argument for command c 471* ⟩ ≡

case c of

number code, roman numeral code: scan int ; string code, meaning code: begin save scanner status ← scanner status ; scanner status ← normal ;

get token; scanner status ← save scanner status ;

end; font name code: scan font ident ; job name code: if job name = 0 then open log file;

⟨ Cases of ‘Scan the argument for command c’ 1384* ⟩ end { there are no other cases }

This code is used in section 470*.

472* . ⟨ Print the result of command c 472* ⟩ ≡

case c of

number code: print int (cur val ); roman numeral code: print roman int (cur val ); string code: if cur cs ≠ 0 then sprint cs (cur cs )

else print char (cur chr ); meaning code: print meaning ; font name code: begin print (font name[cur val ]);

if font size[cur val ] ≠ font dsize[cur val ] then begin print ( ␣ ␣ ); print scaled (font size[cur val ]); print ( ); end;

end; job name code: print (job name);

⟨ Cases of ‘Print the result of command c’ 1385* ⟩ end { there are no other cases }

This code is used in section 470*.

478* . Here we insert an entire token list created by the toks without expanding it further. ⟨ Expand the next part of the input 478* ⟩ ≡

begin loop

begin get next ;

if cur cmd ≥ call then

if info(link (cur chr )) = protected token then begin cur cmd ← relax ; cur chr ← no expand flag ; end;

if cur cmd ≤ max command then goto done2 ;

if cur cmd ≠ the then expand

else begin q ← the toks ;

if link (temp head ) ≠ null then begin link (p) ← link (temp head ); p ← q; end; end;

end; done2 : x token

end

This code is used in section 477.

482* . The read toks procedure constructs a token list like that for any macro definition, and makes cur val point to it. Parameter r points to the control sequence that will receive this token list. procedure read toks (n : integer ; r : pointer ; j : halfword );

label done; var p: pointer ; { tail of the token list }

q: pointer ; { new node being added to the token list via store new token } s: integer ; { saved value of align state } m: small number ; { stream number }

begin scanner status ← defining ; warning index ← r; def ref ← get avail ; token ref count (def ref ) ← null ; p ← def ref ; { the reference count } store new token(end match token); if (n < 0) ∨ (n > 15) then m ← 16 else m ← n; s ← align state; align state ← 1000000; { disable tab marks, etc. } repeat ⟨ Input and store tokens from the next line of the file 483* ⟩; until align state = 1000000; cur val ← def ref ; scanner status ← normal ; align state ← s; end; 483* . ⟨ Input and store tokens from the next line of the file 483* ⟩ ≡

begin file reading ; name ← m + 1; if read open[m] = closed then ⟨ Input for from the terminal 484 ⟩ else if read open[m] = just open then ⟨ Input the first line of read file[m] 485 ⟩

else ⟨ Input the next line of read file[m] 486 ⟩; limit ← last ; if end line char inactive then decr (limit ) else buffer [limit ] ← end line char ; first ← limit + 1; loc ← start ; state ← new line; ⟨ Handle and goto done 1494* ⟩; loop begin get token;

if cur tok = 0 then goto done; { cur cmd = cur chr = 0 will occur at the end of the line } if align state < 1000000 then { unmatched ‘ ’ aborts the line }

begin repeat get token;

until cur tok = 0;

align state ← 1000000; goto done; end;

store new token(cur tok );

end; done: end file reading

This code is used in section 482*.

80  PART 28: CONDITIONAL PROCESSING  ε-TEX 3.14159 [PD VMS 3.6] changes §487

487* . Conditional processing. We consider now the way TEX handles various kinds of commands. define unless code = 32 { amount added for ‘ ’ prefix } define if char code = 0 { ‘ ’ } define if cat code = 1 { ‘ ’ } define if int code = 2 { ‘ ’ } define if dim code = 3 { ‘ ’ } define if odd code = 4 { ‘ ’ } define if vmode code = 5 { ‘ ’ } define if hmode code = 6 { ‘ ’ } define if mmode code = 7 { ‘ ’ } define if inner code = 8 { ‘ ’ } define if void code = 9 { ‘ ’ } define if hbox code = 10 { ‘ ’ } define if vbox code = 11 { ‘ ’ } define ifx code = 12 { ‘ ’ } define if eof code = 13 { ‘ ’ } define if true code = 14 { ‘ ’ } define if false code = 15 { ‘ ’ } define if case code = 16 { ‘ ’ }

⟨ Put each of TEX’s primitives into the hash table 226 ⟩ +≡

primitive(  , if test , if char code); primitive(  , if test , if cat code);
primitive(  , if test , if int code); primitive(  , if test , if dim code);
primitive(  , if test , if odd code); primitive(  , if test , if vmode code);
primitive(  , if test , if hmode code); primitive(  , if test , if mmode code);
primitive(  , if test , if inner code); primitive(  , if test , if void code);
primitive(  , if test , if hbox code); primitive(  , if test , if vbox code);
primitive(  , if test , ifx code); primitive(  , if test , if eof code);
primitive(  , if test , if true code); primitive(  , if test , if false code);

§488 ε-TEX 3.14159 [PD VMS 3.6] changes PART 28: CONDITIONAL PROCESSING 81

primitive( , if test , if case code); 488* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ if test : begin if chr code ≥ unless code then print esc( );

case chr code mod unless code of

if cat code: print esc( ); if int code: print esc( ); if dim code: print esc( ); if odd code: print esc( ); if vmode code: print esc( ); if hmode code: print esc( ); if mmode code: print esc( ); if inner code: print esc( ); if void code: print esc( ); if hbox code: print esc( ); if vbox code: print esc( ); ifx code: print esc( ); if eof code: print esc( ); if true code: print esc( ); if false code: print esc( ); if case code: print esc( );

⟨ Cases of if test for print cmd chr 1497* ⟩ othercases print esc( ) endcases; end;

494* . Here is a procedure that ignores text until coming to an ,  , or  at level zero of  …

nesting. After it has acted, cur chr will indicate the token that was found, but cur tok will not be set (because this makes the procedure run faster). procedure pass text ;

label done; var l: integer ; { level of … nesting }

save scanner status : small number ; { scanner status upon entry } begin save scanner status ← scanner status ; scanner status ← skipping ; l ← 0; skip line ← line; loop begin get next ;

if cur cmd = fi or else then begin if l = 0 then goto done; if cur chr = fi code then decr (l); end

else if cur cmd = if test then incr (l);

end; done: scanner status ← save scanner status ;

if tracing ifs > 0 then show cur cmd chr ; end;

496* . ⟨ Pop the condition stack 496* ⟩ ≡

begin if if stack [in open] = cond ptr then if warning ;

{ conditionals possibly not properly nested with files } p ← cond ptr ; if line ← if line field (p); cur if ← subtype(p); if limit ← type(p); cond ptr ← link (p); free node(p, if node size); end

This code is used in sections 498*, 500, 509, and 510*.

498* . A condition is started when the expand procedure encounters an if test command; in that case expand reduces to conditional , which is a recursive procedure. procedure conditional ;

label exit , common ending ; var b: boolean; { is the condition true? }

r: . . ; { relation to be evaluated }

m, n: integer ; { to be tested against the second operand }

p, q: pointer ; { for traversing token lists in tests }

save scanner status : small number ; { scanner status upon entry }

save cond ptr : pointer ; { cond ptr corresponding to this conditional }

this if : small number ; { type of this conditional }

is unless : boolean; { was this if preceded by ‘ ’ ? } begin if tracing ifs > 0 then

if tracing commands ≤ 1 then show cur cmd chr ; ⟨ Push the condition stack 495 ⟩; save cond ptr ← cond ptr ; is unless ← (cur chr ≥ unless code); this if ← cur chr mod unless code; ⟨ Either process or set b to the value of a boolean condition 501* ⟩; if is unless then b ← ¬b; if tracing commands > 1 then ⟨ Display the value of b 502 ⟩;

if b then

begin change if limit (else code, save cond ptr ); return; { wait for or } end;

⟨ Skip to or , then goto common ending 500 ⟩; common ending : if cur chr = fi code then ⟨ Pop the condition stack 496* ⟩

else if limit ← fi code; { wait for } exit : end;

501* . ⟨ Either process or set b to the value of a boolean condition 501* ⟩ ≡

case this if of

if char code, if cat code: ⟨ Test if two characters match 506 ⟩; if int code, if dim code: ⟨ Test relation between integers or dimensions 503 ⟩; if odd code: ⟨ Test if an integer is odd 504 ⟩; if vmode code: b ← (abs (mode) = vmode); if hmode code: b ← (abs (mode) = hmode); if mmode code: b ← (abs (mode) = mmode); if inner code: b ← (mode < 0); if void code, if hbox code, if vbox code: ⟨ Test box register status 505* ⟩; ifx code: ⟨ Test if two tokens match 507 ⟩; if eof code: begin scan four bit int ; b ← (read open[cur val ] = closed );

end; if true code: b ← true; if false code: b ← false;

⟨ Cases for conditional 1499* ⟩ if case code: ⟨ Select the appropriate case and return or goto common ending 509 ⟩; end { there are no other cases }

This code is used in section 498*.

505* . ⟨ Test box register status 505* ⟩ ≡ begin scan register num; fetch box (p); if this if = if void code then b ← (p = null ) else if p = null then b ← false

else if this if = if hbox code then b ← (type(p) = hlist node)

else b ← (type(p) = vlist node); end

This code is used in section 501*.

510* . The processing of conditionals is complete except for the following code, which is actually part of expand . It comes into play when , , or is scanned. ⟨ Terminate the current conditional and skip to 510* ⟩ ≡

begin if tracing ifs > 0 then

if tracing commands ≤ 1 then show cur cmd chr ; if cur chr > if limit then

if if limit = if code then insert relax { condition not yet evaluated } else begin print err ( ␣ ); print cmd chr (fi or else, cur chr );

help1 ( ´ ␣ ␣ ␣ ␣ ´ ␣ ␣ ␣ ); error ; end

else begin while cur chr ≠ fi code do pass text ; { skip to } ⟨ Pop the condition stack 496* ⟩; end;

end

This code is used in section 367*.

84  PART 29: FILE NAMES  ε-TEX 3.14159 [PD VMS 3.6] changes §511

513* . The file names we shall deal with for illustrative purposes have the following structure: If the name contains ‘ ’, ‘ ’ or ‘ ’, the directory consists of all characters up to and including the final such character; otherwise the directory is null. If the remaining file name contains ‘ ’, the file extension consists of all such characters from the first remaining ‘ ’ to the end, otherwise the file extension is null.

We can scan such file names easily by using two global variables that keep track of the occurrences of area and extension delimiters:

We also take this opportunity to add some more global definitions for an upcoming section. ⟨ Global variables 13 ⟩ +≡ area delimiter : pool pointer ; { the most recent ‘ ’, ‘ ’ or ‘ ’, if any } TEX area, TEX font area: str number ; inp name, fonts name: packed array [1 . . file name size] of char ; inp len, fonts len: file size; i: integer ; ext delimiter : pool pointer ; { the relevant ‘ ’, if any }

514* . Input files that can’t be found in the user’s area may appear in a standard system area called TEX area. Font metric files whose areas are not given explicitly are assumed to appear in a standard system area called TEX font area. These system area names will, of course, vary from place to place.

For VMS, we handle setting the names for these two logicals by defining them in the file. We’ll deal with getting that information later. The code that follows here will be executed after we’ve read the command line and file and assumes that the first inp len characters of inp name are the value to use for TEX area and the first fonts len characters of fonts name are the value to use for TEX font area. This code must be inserted just after TEX has initialized all of its strings but before its first attempt at reading a file.

I apologize for adding i to the globals above, by the way. There’s only so much searching for a global in one can take. ⟨ Read the values of and and put them into the string pool 514* ⟩ ≡

VAX cli get value(´ ´ , inp name, inp len); str room(inp len);

for i ← 1 to inp len do append char (xord [inp name[i]]);

TEX area ← make string ;

VAX cli get value(´ ´ , fonts name, fonts len); str room(fonts len);

for i ← 1 to fonts len do append char (xord [fonts name[i]]);

TEX font area ← make string

This code is used in section 1337*.

§516 ε-TEX 3.14159 [PD VMS 3.6] changes PART 29: FILE NAMES 85

516* . And here’s the second. The string pool might change as the file name is being scanned, since a new might be entered; therefore we keep area delimiter and ext delimiter relative to the beginning of the current string, instead of assigning an absolute address like pool ptr to them.

On VMS, we support wildcards in filenames. But, since the single char wildcard ‘%’ is interpreted as comment delimiter in the TEX input stream, the question mark ‘ ’ should be used for that purpose, instead. Here, we have to convert those ‘ ’ characters back to ‘%’. function more name(c : ASCII code): boolean;

begin if c = ␣ then more name ← false else begin str room(1); { check for enough string space to add one char }

if (c = ) then c ← % ; { convert ‘ ’ “single char wildcard” into ‘%’ } append char (c); { contribute c to the current string } if (c = ) ∨ (c = ) ∨ (c = ) then

begin area delimiter ← cur length; ext delimiter ← 0; end

else if (c = ) ∧ (ext delimiter = 0) then ext delimiter ← cur length; more name ← true; end;

end;

517* . The third. We have to check to see if a logical name has been referred to, and if so, translate it. procedure end name;

label restart , exit ; var t: packed array [1 . . file name size] of char ;

i: pool pointer ; len: signed halfword ; begin restart : if (str pool [str start [str ptr ] + area delimiter ] = si ( )) ∧

(pool ptr = str start [str ptr ] + area delimiter + 1) then begin cur area ← make string ; len ← length(cur area) − 1; { don’t include the colon } for i ← 1 to len do t[i] ← xchr [so(str pool [str start [cur area] + i − 1])]; if ¬translate(t, len) then

begin cur ext ← ; cur name ← ; { silly case } return; end;

flush string ; { needn’t remember logical name in cur area } begin name; for i ← 1 to len do

if ¬more name(xord [t[i]]) then goto restart ; goto restart ; { heavy! } end;

if str ptr + 3 > max strings then overflow ( ␣ ␣ , max strings − init str ptr ); if area delimiter = 0 then cur area ← else begin cur area ← str ptr ; str start [str ptr + 1] ← str start [str ptr ] + area delimiter ; incr (str ptr );

end; if ext delimiter = 0 then

begin cur ext ← ; cur name ← make string ; end

else begin cur name ← str ptr ; str start [str ptr + 1] ← str start [str ptr ] + ext delimiter − area delimiter − 1; incr (str ptr ); cur ext ← make string ; end;

exit : end; 520* . A messier routine is also needed, since format file names must be scanned before TEX’s string mechanism has been initialized. We shall use the global variable TEX format default to supply the text for default system areas and extensions related to format files.

We want to be able to load the name of the area where formats live from an argument on the command line (actually, this will work like the and qualifiers mentioned above, except that here, the qualifier will be read by both TEX and . Also, things are a little simpler since we don’t deal with the string pool ourselves. On the other hand some constants will be changed to variables since we cannot know at compile time how long the argument to will be. We also will take this opportunity to set the value for pool name since we need the value given by to construct it.

define format name length = 9 { length of ´ ´ }

define format ext length = 4 { length of its ‘ ’ part }

define format extension = { the extension, as a constant }

define pool name length ≡ \underline{\overline{␣}} (pool f name) ⟨ Global variables 13 ⟩ +≡ TEX f name default : packed array [1 . . format name length] of char ;

{ abbreviated name for conflict considerations }

TEX format default : packed array [1 . . file name size] of char ; pool name: packed array [1 . . file name size] of char ; format area length: file size; { length of the area part } format default length: integer ; { length of the whole mess upon construction }

521* . ⟨ Set initial values of key variables 21 ⟩ +≡ TEX f name default ← ´ ´ ; VAX cli get value(´ ´ , TEX format default , format area length); pool name ← TEX format default ; for i ← 1 to pool name length do pool name[i + format area length] ← pool f name[i]; for i ← 1 to format name length do

TEX format default [i + format area length] ← TEX f name default [i]; format default length ← format area length + format name length;

522* . There used to be a consistency check here, but since the value it checked wouldn’t be set until after the consistency checking, we’ve deleted it. Besides, our code will automatically guarantee consistancy simply by the way TEX format default is defined.

525* . The VMS operating system is able to determine the exact name (and version number) of a file that has been opened through use of the user action parameter of the open routine. The following routine makes a TEX string from the value of last name[1 . . last length], which is the full specification of the most recently opened file.

This routine might be called after string memory has overflowed, hence we dare not use ‘str room’. function make name string : str number ;

var k: 1 . . file name size; { index into name of file } begin if (pool ptr + last length > pool size) ∨ (str ptr = max strings ) ∨ (cur length > 0) then

make name string ← else begin for k ← 1 to last length do append char (xord [last name[k]]);

make name string ← make string ;

end; end;

function a make name string (var f : alpha file): str number ; begin a make name string ← make name string ; end;

function b make name string (var f : byte file): str number ; begin b make name string ← make name string ; end;

function w make name string (var f : word file): str number ; begin w make name string ← make name string ; end;

529* . Here is a routine that manufactures the output file names, assuming that job name ≠ 0. It ignores and changes the current settings of cur area and cur ext .

Similarly, pack default name extracts a (possibly partial) file specification from the appropriate command line qualifier, if used, and creates a string which may be used to provide defaults for part of a file specification when opening certain auxiliary files. The routine clear default name is also provided to ensure that no defaults are applied on successive calls of open.

define pack cur name ≡ pack file name(cur name, cur area, cur ext ) procedure pack job name(s : str number ); { s = , , , format extension }

begin cur area ← ; cur ext ← s; cur name ← job name; pack cur name; end;

function pack default name(qual : boolean; df name : packed array [l1 . . u1 : integer ] of char ; df len: file size): boolean; var k: integer ; begin for k ← 1 to file name size do default name[k] ← name of file[k]; deflt length ← name length;

if qual then

begin name of file ← df name; name length ← df len; if name length < file name size then

for k ← name length + 1 to file name size do name of file[k] ← ´ ␣´ ; end;

pack default name ← qual ; { Result is whether file wanted } end;

procedure clear default name; var k: integer ; begin for k ← 1 to file name size do default name[k] ← ´ ␣´ ; end; 530* . If some trouble arises when TEX tries to open a file, the following routine calls upon the user to supply another file name. Parameter s is used in the error message to identify the type of file; parameter e is the default extension if none is given. Upon exit from the routine, variables cur name, cur area, cur ext , and name of file are ready for another attempt at file opening.

Because this procedure invokes the print err macro, but does not terminate the “error” (by invoking error ), we have to take special measures to prevent everything from here onwards being written to the temp file used for diagnostics. It does this by resetting the temp file. procedure prompt file name(s, e : str number );

label done; var k: 0 . . buf size; { index into buffer } begin if interaction = scroll mode then wake up terminal ; if s = ␣ ␣ then print err ( ␣ ´ ␣ ␣ ␣` ) else print err ( ␣ ´ ␣ ␣ ␣ ␣` ); print file name(cur name, cur area, cur ext ); print ( ´ ); if e = then show context ; print nl ( ␣ ␣ ␣ ); print (s); if interaction < scroll mode then fatal error ( ␣ ␣ ␣ ␣ ␣ ␣ ␣ ); clear terminal ; prompt input ( ␣ ); ⟨ Ensure temp file not in use 1604* ⟩; ⟨ Scan file name in the buffer 531 ⟩; if cur ext = then cur ext ← e; pack cur name; end;

532* . Here’s an example of how these conventions are used. Whenever it is time to ship out a box of stuff, we shall use the macro ensure dvi open.

define ensure dvi open ≡

if output file name = 0 then begin if job name = 0 then open log file; pack job name( ); if pack default name(dvi qual , dvif name, dvif len) then

begin while ¬b open out (dvi file) do

prompt file name( ␣ ␣ ␣ , ); output file name ← b make name string (dvi file); end

else output file name ← ;

clear default name;

end

⟨ Global variables 13 ⟩ +≡ dvi file: byte file; { the device-independent output goes here } output file name: str number ; { full name of the output file } log name: str number ; { full name of the log file } 534* . The open log file routine is used to open the transcript file and to help it catch up to what has previously been printed on the terminal.

⟨ Declare the open diag file procedure 1615* ⟩ procedure open log file;

var old setting : 0 . . max selector ; { previous selector setting } k: 0 . . buf size; { index into months and buffer } l: 0 . . buf size; { end of first input line } months : packed array [1 . . 36] of char ; { abbreviations of month names }

begin old setting ← selector ; if job name = 0 then job name ← ; pack job name( ); if pack default name(log qual , logf name, logf len) then

begin while ¬a open out (log file) do ⟨ Try to get a different log file name 535* ⟩; log name ← a make name string (log file); end

else log name ← ; clear default name; open diag file; selector ← log only ; log opened ← true; ⟨ Print the banner line, including the date and time 536* ⟩; input stack [input ptr ] ← cur input ; { make sure bottom level is in memory } print nl ( ); l ← input stack [0].limit field ; { last position of first line } if buffer [l] = end line char then decr (l); for k ← 1 to l do print (buffer [k]); print ln; { now the transcript file contains the first line of input } selector ← old setting + 2; { log only or term and log } end;

535* . Sometimes open log file is called at awkward moments when TEX is unable to print error messages or even to show context . The prompt file name routine can result in a fatal error , but the error routine will not be invoked because log opened will be false.

The normal idea of batch mode is that nothing at all should be written on the terminal. However, in the unusual case that no log file could be opened, we make an exception and allow an explanatory message to be seen.

Incidentally, the program always refers to the log file as a ‘ ’, because some systems cannot use the extension ‘ ’ for this file. ⟨ Try to get a different log file name 535* ⟩ ≡

begin selector ← term only ; prompt file name( ␣ ␣ , ); end

This code is used in section 534*.

536* . ⟨ Print the banner line, including the date and time 536* ⟩ ≡ begin wlog (eTeX banner ); slow print (format ident ); print ( ␣␣ ); print int (day ); print char ( ␣ ); months ← ´ ´ ; for k ← 3 ∗ month − 2 to 3 ∗ month do wlog (months [k]); print char ( ␣ ); print int (year ); print char ( ␣ ); print two(time div 60); print char ( ); print two(time mod 60);

if eTeX ex then

begin ; wlog cr ; wlog (´ ␣ ␣ ´ );

end; end

This code is used in section 534*.

537* . Let’s turn now to the procedure that is used to initiate file reading when an ‘ ’ command is being processed.

As originally used by TEX82 under VMS, this procedure discarded the current file name (as returned to it by the operating system) after it had been printed. However, with this version of TEX, with its capability of writing diagnostic files for use by LSEdit’s review mode, we need to be able to report the full file specifications of any files that may be involved in show context ; therefore, we do not call flush string here.

Here, x open in, a modified version of a open in, is inserted. This function is located here (and not next to a open in) to eliminate the neccessity of a forward declaration for the pack file name function.

The new function x open in is intended to replace the calls to a open in in the procedures start input and open or close in. It extends the file opening functionality of a open in by a second try to open the file using the TEX area path specification, when no explicit path was specified. The code needed for this purpose has been moved out of the start input procedure. This change unifies the file search behaviour of the and commands, a useful modification of TEX recommended by the new edition of the L^{A}TEX macro package. The original function a open in is still used to read the TEX pool file.

When start input decides to initiate the transcript file (this can only happen when start input is called the first time!), the cur name string get updated with the contents of last basename. This string is the base name part of the file opened the previous x open in call. This modification reveals the correct job name when the primary input file specification contained wildcard characters in the base name part. function x open in(var f : alpha file): boolean;

begin open(f, name of file, VAX readonly , VAX user action ← user reset , VAX ignore error ); if status (f) > 0 then

begin if cur area = then begin pack file name(cur name, TEX area, cur ext ); open(f, name of file, VAX readonly , VAX user action ← user reset , VAX ignore error ); end; end;

if status (f) > 0 then x open in ← false

else begin reset (f, VAX ignore error ); x open in ← status (f) ≤ 0;

end; end;

procedure start input ; { TEX will something } label done; var k: integer ; begin scan file name; { set cur name to desired file name } if cur ext = then cur ext ← ; pack cur name; loop begin begin file reading ; { set up cur file and new level of input }

if x open in(cur file) then goto done;

end file reading ; { remove the level that didn’t work }

prompt file name( ␣ ␣ , );

end; done: name ← a make name string (cur file);

if job name = 0 then

begin if last basenam len = length(cur name) then

begin for k ← 1 to last basenam len do

str pool [str start [cur name] + k − 1] ← si (xord [last basename[k]]); end

else if (pool ptr + last basenam len ≤ pool size) ∧ (str ptr ≠ max strings ) ∧ (cur length ≤ 0) then begin for k ← 1 to last basenam len do append char (xord [last basename[k]]); cur name ← make string ; end;

job name ← cur name; open log file;

end; { open log file doesn’t show context , so limit and loc needn’t be set to meaningful values yet } if term offset + length(name) > max print line − 2 then print ln else if (term offset > 0) ∨ (file offset > 0) then print char ( ␣ ); print char ( ); incr (open parens ); slow print (name); update terminal ; state ← new line; ⟨ Read the first line of the new file 538 ⟩; end;

92  PART 30: FONT METRIC DATA  ε-TEX 3.14159 [PD VMS 3.6] changes §539

563* . ⟨ Open tfm file for input 563* ⟩ ≡ file opened ← false; if aire = then pack file name(nom, TEX font area, ) else pack file name(nom, aire, ); if ¬b open in(tfm file) then abort ; tfm count ← 0; file opened ← true

This code is used in section 562.

564* . Note: A malformed file might be shorter than it claims to be; thus eof (tfm file) might be true when read font info refers to tfm file↑ or when it says get (tfm file). If such circumstances cause system error messages, you will have to defeat them somehow, for example by defining fget to be ‘begin get (tfm file); if eof (tfm file) then abort ; end’.

define fget ≡ begin incr (tfm count ); if tfm count = VAX block length then

begin get (tfm file, VAX ignore error ); tfm count ← 0; end end

define fbyte ≡ tfm file↑[tfm count ] define read sixteen(#) ≡

begin # ← fbyte;

if # > 127 then abort ; fget ; # ← # ∗ ´ 400 + fbyte; end

define store four quarters (#) ≡ begin fget ; a ← fbyte; qw .b0 ← qi (a); fget ; b ← fbyte; qw .b1 ← qi (b); fget ; c ← fbyte; qw .b2 ← qi (c); fget ; d ← fbyte; qw .b3 ← qi (d); # ← qw ; end

575* . We check to see that the file doesn’t end prematurely; but no error message is given for files having more than lf words. ⟨ Read font parameters 575* ⟩ ≡

begin for k ← 1 to np do

if k = 1 then { the slant parameter is a pure number } begin fget ; sw ← fbyte; if sw > 127 then sw ← sw − 256; fget ; sw ← sw ∗ ´ 400 + fbyte; fget ; sw ← sw ∗ ´ 400 + fbyte; fget ; font info[param base[f]].sc ← (sw ∗ ´ 20 ) + (fbyte div ´ 20 ); end

else store scaled (font info[param base[f] + k − 1].sc); if status (tfm file) ≠ 0 then abort ; for k ← np + 1 to 7 do font info[param base[f] + k − 1].sc ← 0; end

This code is used in section 562.

§581 ε-TEX 3.14159 [PD VMS 3.6] changes PART 30: FONT METRIC DATA 93

581* . When TEX wants to typeset a character that doesn’t exist, the character node is not created; thus the output routine can assume that characters exist when it sees them. The following procedure prints a warning message unless the user has suppressed it. procedure char warning (f : internal font number ; c : eight bits );

var old setting : integer ; { saved value of tracing online } begin if tracing lost chars > 0 then

begin old setting ← tracing online; if eTeX ex ∧ (tracing lost chars > 1) then tracing online ← 1; begin begin diagnostic; print nl ( ␣ ␣ ␣ ␣ ␣ ); print ASCII (c); print ( ␣ ␣ ␣ ); slow print (font name[f]); print char ( ); end diagnostic(false); end; tracing online ← old setting ; end;

94  PART 32: SHIPPING PAGES OUT  ε-TEX 3.14159 [PD VMS 3.6] changes §583

end; 595* . Some systems may find it more efficient to make dvi buf a packed array, since output of four bytes at once may be facilitated. On VMS, we get even more complicated than that, for efficiency.

define dvi buf ≡ d buffer .b { buffer for output } ⟨ Global variables 13 ⟩ +≡ d buffer : [VAX volatile, VAX aligned (9)] packed record case boolean of

false: (b : packed array [dvi index ] of eight bits ); true: (l : byte block ; r : byte block ; j : eight bits ); end;

half buf : dvi index ; { half of dvi buf size } dvi limit : dvi index ; { end of the current half buffer } dvi ptr : dvi index ; { the next available buffer address } dvi offset : integer ; { dvi buf size times the number of times the output buffer has been fully emptied } dvi gone: integer ; { the number of bytes already output to dvi file }

597* . The actual output of dvi buf [a . . b] to dvi file is performed by calling write on the other variant of the dvi buf record. Thus, we have to be sure that things line up properly, by padding out with “signature” bytes. ⟨ Check the “constant” values for consistency 14 ⟩ +≡

if dvi buf size ≠ 2 ∗ VAX block length then bad ← 223;

598* . To put a byte in the buffer without paying the cost of invoking a procedure each time, we use the macro dvi out .

define dvi out (#) ≡ begin dvi buf [dvi ptr ] ← #; incr (dvi ptr ); if dvi ptr = dvi limit then dvi swap; end

procedure dvi swap; { outputs half of the buffer }

begin if dvi limit = dvi buf size then begin if dvi qual then write(dvi file, d buffer .l); dvi limit ← half buf ; dvi offset ← dvi offset + dvi buf size; dvi ptr ← 0; end

else begin if dvi qual then write(dvi file, d buffer .r); dvi limit ← dvi buf size; end;

dvi gone ← dvi gone + half buf ;

end;

599* . Here is how we clean out the buffer when TEX is all through; dvi ptr will be a multiple of 4. ⟨ Empty the last bytes out of dvi buf 599* ⟩ ≡

if (dvi limit = half buf ) ∧ dvi qual then write(dvi file, d buffer .r); for k ← dvi ptr to dvi buf size do dvi buf [k] ← 223; if (dvi ptr > 0) ∧ dvi qual then write(dvi file, d buffer .l); if (dvi ptr > half buf ) ∧ dvi qual then write(dvi file, d buffer .r);

This code is used in section 642*.

§616 ε-TEX 3.14159 [PD VMS 3.6] changes PART 32: SHIPPING PAGES OUT 95

616* . The actual distances by which we want to move might be computed as the sum of several separate movements. For example, there might be several glue nodes in succession, or we might want to move right by the width of some box plus some amount of glue. More importantly, the baselineskip distances are computed in terms of glue together with the depth and height of adjacent boxes, and we want the file to lump these three quantities together into a single motion.

Therefore, TEX maintains two pairs of global variables: dvi h and dvi v are the h and v coordinates corresponding to the commands actually output to the file, while cur h and cur v are the coordinates corresponding to the current state of the output routines. Coordinate changes will accumulate in cur h and cur v without being reflected in the output, until such a change becomes necessary or desirable; we can call the movement procedure whenever we want to make dvi h = cur h or dvi v = cur v .

The current font reflected in the output is called dvi f ; there is no need for a ‘cur f ’ variable.

The depth of nesting of hlist out and vlist out is called cur s ; this is essentially the depth of push commands in the output.

For mixed direction text (TEX-����) the current text direction is called cur dir . As the box being shipped out will never be used again and soon be recycled, we can simply reverse any R-text (i.e., right-to-left) segments of hlist nodes as well as complete hlist nodes embedded in such segments. Moreover this can be done iteratively rather than recursively. There are, however, two complications related to leaders that require some additional bookkeeping: (1) One and the same hlist node might be used more than once (but never inside both L- and R-text); and (2) leader boxes inside hlists must be aligned with respect to the left edge of the original hlist.

A math node is changed into a kern node whenever the text direction remains the same, it is replaced by an edge node if the text direction changes; the subtype of an an hlist node inside R-text is changed to reversed once its hlist has been reversed.

define reversed = min quarterword + 1 { subtype for an hlist node whose hlist has been reversed } define dlist = min quarterword + 2 { subtype for an hlist node from display math mode } define left to right = 0 define right to left = 1 define reflected ≡ 1 − cur dir { the opposite of cur dir } define synch h ≡

if cur h ≠ dvi h then begin movement (cur h − dvi h, right1 ); dvi h ← cur h; end

define synch v ≡

if cur v ≠ dvi v then begin movement (cur v − dvi v , down1 ); dvi v ← cur v ; end

⟨ Global variables 13 ⟩ +≡ dvi h, dvi v : scaled ; { a reader program thinks we are here } cur h, cur v : scaled ; { TEX thinks we are here } dvi f : internal font number ; { the current font } cur s : integer ; { current depth of output box nesting, initially −1 } 619* . The recursive procedures hlist out and vlist out each have local variables save h and save v to hold the values of dvi h and dvi v just before entering a new level of recursion. In effect, the values of save h and save v on TEX’s run-time stack correspond to the values of h and v that a -reading program will push onto its coordinate stack.

define move past = 13 { go to this label when advancing past glue or a rule } define fin rule = 14 { go to this label to finish processing a rule } define next p = 15 { go to this label when finished with node p }

⟨ Declare procedures needed in hlist out , vlist out 1368 ⟩ procedure hlist out ; { output an hlist node box }

label reswitch, move past , fin rule, next p; var base line: scaled ; { the baseline coordinate for this box }

left edge: scaled ; { the left coordinate for this box } save h, save v : scaled ; { what dvi h and dvi v should pop to } this box : pointer ; { pointer to containing box } g sign: normal . . shrinking ; { selects type of glue } p: pointer ; { current position in the hlist } save loc: integer ; { byte location upon entry } leader box : pointer ; { the leader box being replicated } leader wd : scaled ; { width of leader box being replicated } lx : scaled ; { extra space between leader boxes } outer doing leaders : boolean; { were we doing leaders? } edge: scaled ; { right edge of sub-box or leader space } prev p: pointer ; { one step behind p }

begin this box ← temp ptr ; g sign ← glue sign(this box ); p ← list ptr (this box ); incr (cur s ); if cur s > 0 then dvi out (push); if cur s > max push then max push ← cur s ; save loc ← dvi offset + dvi ptr ; base line ← cur v ; prev p ← this box + list offset ;

if eTeX ex then

begin ⟨ Initialize the LR stack 1446* ⟩; if subtype(this box ) = dlist then

if cur dir = right to left then begin cur dir ← left to right ; cur h ← cur h − width(this box ); end

else subtype(this box ) ← min quarterword ; if (cur dir = right to left ) ∧ (subtype(this box ) ≠ reversed ) then

⟨ Reverse the complete hlist and set the subtype to reversed 1454* ⟩; end;

left edge ← cur h; while p ≠ null do ⟨ Output node p for hlist out and move to the next node, maintaining the condition

cur v = base line 620* ⟩;

if eTeX ex then

begin ⟨ Check for LR anomalies at the end of hlist out 1451* ⟩; if subtype(this box ) = dlist then cur dir ← right to left ; end;

prune movements (save loc); if cur s > 0 then dvi pop(save loc); decr (cur s ); end; 620* . We ought to give special care to the efficiency of one part of hlist out , since it belongs to TEX’s inner loop. When a char node is encountered, we save a little time by processing several nodes in succession until reaching a non-char node. The program uses the fact that set char 0 = 0. ⟨ Output node p for hlist out and move to the next node, maintaining the condition cur v = base line 620* ⟩ ≡ reswitch: if is char node(p) then

begin synch h; synch v ;

repeat f ← font (p); c ← character (p); if f ≠ dvi f then ⟨ Change font dvi f to f 621 ⟩; if c ≥ qi (128) then dvi out (set1 ); dvi out (qo(c)); cur h ← cur h + char width(f)(char info(f)(c)); prev p ← link (prev p);

{ N.B.: not prev p ← p, p might be lig trick } p ← link (p);

until ¬is char node(p);

dvi h ← cur h;

end else ⟨ Output the non-char node p for hlist out and move to the next node 622* ⟩

This code is used in section 619*.

622* . ⟨ Output the non-char node p for hlist out and move to the next node 622* ⟩ ≡ begin case type(p) of hlist node, vlist node: ⟨ Output a box in an hlist 623* ⟩; rule node: begin rule ht ← height (p); rule dp ← depth(p); rule wd ← width(p); goto fin rule;

end; whatsit node: ⟨ Output the whatsit node p in an hlist 1367 ⟩; glue node: ⟨ Move right or output leaders 625* ⟩; kern node: cur h ← cur h + width(p); math node: begin if eTeX ex then ⟨ Adjust the LR stack for the hlist out routine; if necessary reverse

an hlist segment and goto reswitch 1450* ⟩; cur h ← cur h + width(p); end;

ligature node: ⟨ Make node p look like a char node and goto reswitch 652 ⟩;

⟨ Cases of hlist out that arise in mixed direction text only 1453* ⟩

othercases do nothing

endcases; goto next p;

fin rule: ⟨ Output a rule in an hlist 624 ⟩; move past : cur h ← cur h + rule wd ; next p: prev p ← p; p ← link (p);

end

This code is used in section 620*.

623* . ⟨ Output a box in an hlist 623* ⟩ ≡ if list ptr (p) = null then cur h ← cur h + width(p) else begin save h ← dvi h; save v ← dvi v ; cur v ← base line + shift amount (p);

{ shift the box down } temp ptr ← p; edge ← cur h + width(p); if cur dir = right to left then cur h ← edge; if type(p) = vlist node then vlist out else hlist out ; dvi h ← save h; dvi v ← save v ; cur h ← edge; cur v ← base line; end

This code is used in section 622*.

625* . define vet glue(#) ≡ glue temp ← #; if glue temp > float constant (1000000000) then glue temp ← float constant (1000000000) else if glue temp < −float constant (1000000000) then glue temp ← −float constant (1000000000)

⟨ Move right or output leaders 625* ⟩ ≡ begin g ← glue ptr (p); rule wd ← width(g); if g sign ≠ normal then add glue(rule wd ); if subtype(p) ≥ a leaders then

⟨ Output leaders in an hlist, goto fin rule if a rule or to next p if done 626* ⟩; goto move past ; end

This code is used in section 622*.

626* . ⟨ Output leaders in an hlist, goto fin rule if a rule or to next p if done 626* ⟩ ≡ begin leader box ← leader ptr (p); if type(leader box ) = rule node then

begin rule ht ← height (leader box ); rule dp ← depth(leader box ); goto fin rule;

end; leader wd ← width(leader box ); if (leader wd > 0) ∧ (rule wd > 0) then

begin rule wd ← rule wd + 10; { compensate for floating-point rounding }

if cur dir = right to left then cur h ← cur h − 10;

edge ← cur h + rule wd ; lx ← 0; ⟨ Let cur h be the position of the first box, and set leader wd + lx to

the spacing between corresponding parts of boxes 627 ⟩; while cur h + leader wd ≤ edge do

⟨ Output a leader box at cur h, then advance cur h by leader wd + lx 628* ⟩; if cur dir = right to left then cur h ← edge else cur h ← edge − 10; goto next p; end;

end

This code is used in section 625*.

628* . The ‘synch’ operations here are intended to decrease the number of bytes needed to specify horizontal and vertical motion in the output. ⟨ Output a leader box at cur h, then advance cur h by leader wd + lx 628* ⟩ ≡

begin cur v ← base line + shift amount (leader box ); synch v ; save v ← dvi v ; synch h; save h ← dvi h; temp ptr ← leader box ; if cur dir = right to left then cur h ← cur h + leader wd ; outer doing leaders ← doing leaders ; doing leaders ← true; if type(leader box ) = vlist node then vlist out else hlist out ; doing leaders ← outer doing leaders ; dvi v ← save v ; dvi h ← save h; cur v ← base line; cur h ← save h + leader wd + lx ; end

This code is used in section 626*.

629* . The vlist out routine is similar to hlist out , but a bit simpler. procedure vlist out ; { output a vlist node box }

label move past , fin rule, next p; var left edge: scaled ; { the left coordinate for this box }

top edge: scaled ; { the top coordinate for this box } save h, save v : scaled ; { what dvi h and dvi v should pop to } this box : pointer ; { pointer to containing box } g sign: normal . . shrinking ; { selects type of glue } p: pointer ; { current position in the vlist } save loc: integer ; { byte location upon entry } leader box : pointer ; { the leader box being replicated } leader ht : scaled ; { height of leader box being replicated } lx : scaled ; { extra space between leader boxes } outer doing leaders : boolean; { were we doing leaders? } edge: scaled ; { bottom boundary of leader space }

begin this box ← temp ptr ; g sign ← glue sign(this box ); p ← list ptr (this box ); incr (cur s ); if cur s > 0 then dvi out (push); if cur s > max push then max push ← cur s ; save loc ← dvi offset + dvi ptr ; left edge ← cur h; cur v ← cur v − height (this box ); top edge ← cur v ; while p ≠ null do ⟨ Output node p for vlist out and move to the next node, maintaining the condition

cur h = left edge 630 ⟩; prune movements (save loc); if cur s > 0 then dvi pop(save loc); decr (cur s ); end;

632* . The synch v here allows the output to use one-byte commands for adjusting v in most cases, since the baselineskip distance will usually be constant. ⟨ Output a box in a vlist 632* ⟩ ≡

if list ptr (p) = null then cur v ← cur v + height (p) + depth(p) else begin cur v ← cur v + height (p); synch v ; save h ← dvi h; save v ← dvi v ;

if cur dir = right to left then cur h ← left edge − shift amount (p) else cur h ← left edge + shift amount (p); { shift the box right } temp ptr ← p; if type(p) = vlist node then vlist out else hlist out ; dvi h ← save h; dvi v ← save v ; cur v ← save v + depth(p); cur h ← left edge; end

This code is used in section 631.

633* . ⟨ Output a rule in a vlist, goto next p 633* ⟩ ≡ if is running (rule wd ) then rule wd ← width(this box ); rule ht ← rule ht + rule dp; { this is the rule thickness } cur v ← cur v + rule ht ; if (rule ht > 0) ∧ (rule wd > 0) then { we don’t output empty rules }

begin if cur dir = right to left then cur h ← cur h − rule wd ; synch h; synch v ; dvi out (put rule); dvi four (rule ht ); dvi four (rule wd ); cur h ← left edge; end;

goto next p

This code is used in section 631.

634* . ⟨ Move down or output leaders 634* ⟩ ≡ begin g ← glue ptr (p); rule ht ← width(g); if g sign ≠ normal then add glue(rule ht ); if subtype(p) ≥ a leaders then

⟨ Output leaders in a vlist, goto fin rule if a rule or to next p if done 635 ⟩; goto move past ; end

This code is used in section 631.

637* . When we reach this part of the program, cur v indicates the top of a leader box, not its baseline. ⟨ Output a leader box at cur v , then advance cur v by leader ht + lx 637* ⟩ ≡

begin if cur dir = right to left then cur h ← left edge − shift amount (leader box ) else cur h ← left edge + shift amount (leader box ); synch h; save h ← dvi h; cur v ← cur v + height (leader box ); synch v ; save v ← dvi v ; temp ptr ← leader box ; outer doing leaders ← doing leaders ; doing leaders ← true; if type(leader box ) = vlist node then vlist out else hlist out ; doing leaders ← outer doing leaders ; dvi v ← save v ; dvi h ← save h; cur h ← left edge; cur v ← save v − height (leader box ) + leader ht + lx ; end

This code is used in section 635.

638* . The hlist out and vlist out procedures are now complete, so we are ready for the ship out routine that gets them started in the first place. procedure ship out (p : pointer ); { output the box p }

label done; var page loc: integer ; { location of the current bop }

j, k: 0 . . 9; { indices to first ten count registers }

s: pool pointer ; { index into str pool }

old setting : 0 . . max selector ; { saved selector setting } begin if tracing output > 0 then

begin print nl ( ); print ln; print ( ␣ ␣ ␣ ␣ ); end;

if term offset > max print line − 9 then print ln else if (term offset > 0) ∨ (file offset > 0) then print char ( ␣ ); print char ( ); j ← 9; while (count (j) = 0) ∧ (j > 0) do decr (j); for k ← 0 to j do

begin print int (count (k));

if k < j then print char ( );

end; update terminal ; if tracing output > 0 then

begin print char ( ); begin diagnostic; show box (p); end diagnostic(true); end;

⟨ Ship box p out 640 ⟩; if eTeX ex then ⟨ Check for LR anomalies at the end of ship out 1463* ⟩; if tracing output ≤ 0 then print char ( ); dead cycles ← 0; update terminal ; { progress report } ⟨ Flush the box from memory, showing statistics if requested 639 ⟩; end; 642* . At the end of the program, we must finish things off by writing the postamble. If total pages = 0, the file was never opened. If total pages ≥ 65536, the file will lie.

An integer variable k will be declared for use by this routine. ⟨ Finish the file 642* ⟩ ≡

while cur s > −1 do begin if cur s > 0 then dvi out (pop) else begin dvi out (eop); incr (total pages );

end; decr (cur s ); end;

if total pages = 0 then print nl ( ␣ ␣ ␣ ) else begin dvi out (post ); { beginning of the postamble }

dvi four (last bop); last bop ← dvi offset + dvi ptr − 5; { post location } dvi four (25400000); dvi four (473628672); { conversion ratio for sp } prepare mag ; dvi four (mag ); { magnification factor } dvi four (max v ); dvi four (max h); dvi out (max push div 256); dvi out (max push mod 256); dvi out ((total pages div 256) mod 256); dvi out (total pages mod 256); ⟨ Output the font definitions for all fonts that were used 643 ⟩; dvi out (post post ); dvi four (last bop); dvi out (id byte); k ← 4 + ((dvi buf size − dvi ptr ) mod 4); { the number of 223’s } while k > 0 do

begin dvi out (223); decr (k);

end; ⟨ Empty the last bytes out of dvi buf 599* ⟩;

if dvi qual then

begin b close(dvi file); print nl ( ␣ ␣ ␣ ); slow print (output file name); end

else print nl ( ␣ ␣ ␣ ␣ ␣ ␣ ); print ( ␣ ); print int (total pages ); print ( ␣ ); if total pages ≠ 1 then print char ( ); print ( ␣ ); print int (dvi offset + dvi ptr ); print ( ␣ ); end

This code is used in section 1333*.

102  PART 33: PACKAGING  ε-TEX 3.14159 [PD VMS 3.6] changes §644

649* . Here now is hpack , which contains few if any surprises. function hpack (p : pointer ; w : scaled ; m : small number ): pointer ;

label reswitch, common ending , exit ; var r: pointer ; { the box node that will be returned }

q: pointer ; { trails behind p } h, d, x: scaled ; { height, depth, and natural width } s: scaled ; { shift amount } g: pointer ; { points to a glue specification } o: glue ord ; { order of infinity } f: internal font number ; { the font in a char node } i: four quarters ; { font information about a char node } hd : eight bits ; { height and depth indices for a character }

begin last badness ← 0; r ← get node(box node size); type(r) ← hlist node; subtype(r) ← min quarterword ; shift amount (r) ← 0; q ← r + list offset ; link (q) ← p; h ← 0; ⟨ Clear dimensions to zero 650 ⟩; if TeXXeT en then ⟨ Initialize the LR stack 1446* ⟩; while p ≠ null do ⟨ Examine node p in the hlist, taking account of its effect on the dimensions of the

new box, or moving it to the adjustment list; then advance p to the next node 651* ⟩; if adjust tail ≠ null then link (adjust tail ) ← null ; height (r) ← h; depth(r) ← d; ⟨ Determine the value of width(r) and the appropriate glue setting; then return or goto

common ending 657 ⟩;

common ending : ⟨ Finish issuing a diagnostic message for an overfull or underfull hbox 663 ⟩; exit : if TeXXeT en then ⟨ Check for LR anomalies at the end of hpack 1448* ⟩;

hpack ← r; end;

651* . ⟨ Examine node p in the hlist, taking account of its effect on the dimensions of the new box, or

moving it to the adjustment list; then advance p to the next node 651* ⟩ ≡ begin reswitch: while is char node(p) do ⟨ Incorporate character dimensions into the dimensions of the

hbox that will contain it, then move to the next node 654 ⟩; if p ≠ null then

begin case type(p) of hlist node, vlist node, rule node, unset node: ⟨ Incorporate box dimensions into the dimensions of the

hbox that will contain it 653 ⟩; ins node, mark node, adjust node: if adjust tail ≠ null then

⟨ Transfer node p to the adjustment list 655 ⟩; whatsit node: ⟨ Incorporate a whatsit node into an hbox 1360 ⟩; glue node: ⟨ Incorporate glue into the horizontal totals 656 ⟩; kern node: x ← x + width(p); math node: begin x ← x + width(p);

if TeXXeT en then ⟨ Adjust the LR stack for the hpack routine 1447* ⟩; end;

ligature node: ⟨ Make node p look like a char node and goto reswitch 652 ⟩;

othercases do nothing

endcases; p ← link (p); end;

end

This code is used in section 649*.

§680 ε-TEX 3.14159 [PD VMS 3.6] changes PART 34: DATA STRUCTURES FOR MATH MODE 103

687* . A few more kinds of noads will complete the set: An under noad has its nucleus underlined; an over noad has it overlined. An accent noad places an accent over its nucleus; the accent character appears as fam(accent chr (p)) and character (accent chr (p)). A vcenter noad centers its nucleus vertically with respect to the axis of the formula; in such noads we always have math type(nucleus (p)) = sub box .

And finally, we have left noad and right noad types, to implement TEX’s  and  as well as
ε-TEX’s  . The nucleus of such noads is replaced by a delimiter field; thus, for example, ‘  ’

produces a left noad such that delimiter (p) holds the family and character codes for all left parentheses. A left noad never appears in an mlist except as the first element, and a right noad never appears in an mlist except as the last element; furthermore, we either have both a left noad and a right noad , or neither one is present. The subscr and supscr fields are always empty in a left noad and a right noad .

define under noad = fraction noad + 1 { type of a noad for underlining } define over noad = under noad + 1 { type of a noad for overlining } define accent noad = over noad + 1 { type of a noad for accented subformulas } define accent noad size = 5 { number of mem words in an accent noad } define accent chr (#) ≡ # + 4 { the accent chr field of an accent noad } define vcenter noad = accent noad + 1 { type of a noad for } define left noad = vcenter noad + 1 { type of a noad for } define right noad = left noad + 1 { type of a noad for } define delimiter ≡ nucleus { delimiter field in left and right noads } define middle noad ≡ 1 { subtype of right noad representing } define scripts allowed (#) ≡ (type(#) ≥ ord noad ) ∧ (type(#) < left noad )

104  PART 34: DATA STRUCTURES FOR MATH MODE  ε-TEX 3.14159 [PD VMS 3.6] changes §696

696* . ⟨ Display normal noad p 696* ⟩ ≡ begin case type(p) of ord noad : print esc( ); op noad : print esc( ); bin noad : print esc( ); rel noad : print esc( ); open noad : print esc( ); close noad : print esc( ); punct noad : print esc( ); inner noad : print esc( ); over noad : print esc( ); under noad : print esc( ); vcenter noad : print esc( ); radical noad : begin print esc( ); print delimiter (left delimiter (p));

end; accent noad : begin print esc( ); print fam and char (accent chr (p));

end; left noad : begin print esc( ); print delimiter (nucleus (p));

end; right noad : begin if subtype(p) = normal then print esc( )

else print esc( );

print delimiter (nucleus (p));

end; end; if type(p) < left noad then

begin if subtype(p) ≠ normal then if subtype(p) = limits then print esc( ) else print esc( );

print subsidiary data(nucleus (p), ); end;

print subsidiary data(supscr (p), ); print subsidiary data(subscr (p), ); end

This code is used in section 690.

§699 ε-TEX 3.14159 [PD VMS 3.6] changes PART 36: TYPESETTING MATH FORMULAS 105

727* . We use the fact that no character nodes appear in an mlist, hence the field type(q) is always present. ⟨ Process node-or-noad q as much as possible in preparation for the second pass of mlist to hlist , then move

to the next item in the mlist 727* ⟩ ≡ begin ⟨ Do first-pass processing based on type(q); goto done with noad if a noad has been fully

processed, goto check dimensions if it has been translated into new hlist (q), or goto done with node if a node has been fully processed 728 ⟩;

check dimensions : z ← hpack (new hlist (q), natural ); if height (z) > max h then max h ← height (z); if depth(z) > max d then max d ← depth(z); free node(z, box node size);

done with noad : r ← q; r type ← type(r);

if r type = right noad then begin r type ← left noad ; cur style ← style; ⟨ Set up the values of cur size and cur mu, based on cur style 703 ⟩; end;

done with node: q ← link (q);

end

This code is used in section 726.

760* . We have now tied up all the loose ends of the first pass of mlist to hlist . The second pass simply goes through and hooks everything together with the proper glue and penalties. It also handles the left noad and right noad that might be present, since max h and max d are now known. Variable p points to a node at the current end of the final hlist. ⟨ Make a second pass over the mlist, removing all noads and inserting the proper spacing and

penalties 760* ⟩ ≡ p ← temp head ; link (p) ← null ; q ← mlist ; r type ← 0; cur style ← style; ⟨ Set up the values of cur size and cur mu, based on cur style 703 ⟩; while q ≠ null do

begin ⟨ If node q is a style node, change the style and goto delete q ; otherwise if it is not a noad, put it into the hlist, advance q, and goto done; otherwise set s to the size of noad q, set t to the associated type (ord noad . . inner noad ), and set pen to the associated penalty 761 ⟩;

⟨ Append inter-element spacing based on r type and t 766 ⟩;

⟨ Append any new hlist entries for q, and any appropriate penalties 767 ⟩;

if type(q) = right noad then t ← open noad ;

r type ← t; delete q : r ← q; q ← link (q); free node(r, s); done: end

This code is used in section 726.

106  PART 36: TYPESETTING MATH FORMULAS  ε-TEX 3.14159 [PD VMS 3.6] changes §762

762* . The make left right function constructs a left or right delimiter of the required size and returns the value open noad or close noad . The right noad and left noad will both be based on the original style, so they will have consistent sizes.

We use the fact that right noad − left noad = close noad − open noad . ⟨ Declare math construction procedures 734 ⟩ +≡ function make left right (q : pointer ; style : small number ; max d , max h : scaled ): small number ;

§768 ε-TEX 3.14159 [PD VMS 3.6] changes PART 37: ALIGNMENT 107

var delta, delta1 , delta2 : scaled ; { dimensions used in the calculation } begin cur style ← style; ⟨ Set up the values of cur size and cur mu, based on cur style 703 ⟩; delta2 ← max d + axis height (cur size); delta1 ← max h + max d − delta2 ; if delta2 > delta1 then delta1 ← delta2 ; { delta1 is max distance from axis } delta ← (delta1 div 500) ∗ delimiter factor ; delta2 ← delta1 + delta1 − delimiter shortfall ; if delta < delta2 then delta ← delta2 ; new hlist (q) ← var delimiter (delimiter (q), cur size, delta); make left right ← type(q) − (left noad − open noad ); { open noad or close noad } end; 785* . The tricky part about alignments is getting the templates into the scanner at the right time, and recovering control when a row or column is finished.

We usually begin a row after each has been sensed, unless that is followed by or by the right brace that terminates the alignment. The align peek routine is used to look ahead and do the right thing; it either gets a new row started, or gets a started, or finishes off the alignment. ⟨ Declare the procedure called align peek 785* ⟩ ≡ procedure align peek ;

label restart ; begin restart : align state ← 1000000; repeat get x or protected ; until cur cmd ≠ spacer ; if cur cmd = no align then

begin scan left brace; new save level (no align group);

if mode = −vmode then normal paragraph;

end else if cur cmd = right brace then fin align

else if (cur cmd = car ret ) ∧ (cur chr = cr cr code) then goto restart { ignore }

else begin init row ; { start a new row } init col ; { start a new column and replace what we peeked at } end;

end;

This code is used in section 800.

108  PART 37: ALIGNMENT  ε-TEX 3.14159 [PD VMS 3.6] changes §791

791* . When the endv command at the end of a ⟨v_{j}⟩ template comes through the scanner, things really start to happen; and it is the fin col routine that makes them happen. This routine returns true if a row as well as a column has been finished. function fin col : boolean;

label exit ; var p: pointer ; { the alignrecord after the current one }

q, r: pointer ; { temporary pointers for list manipulation }

s: pointer ; { a new span node }

u: pointer ; { a new unset box }

w: scaled ; { natural width }

o: glue ord ; { order of infinity }

n: halfword ; { span counter } begin if cur align = null then confusion( ); q ← link (cur align); if q = null then confusion( ); if align state < 500000 then fatal error ( ␣ ␣ ␣ ␣ ␣ ); p ← link (q); ⟨ If the preamble list has been traversed, check that the row has ended 792 ⟩; if extra info(cur align) ≠ span code then

begin unsave; new save level (align group);

⟨ Package an unset box for the current column and record its width 796 ⟩; ⟨ Copy the tabskip glue between columns 795 ⟩; if extra info(cur align) ≥ cr code then

begin fin col ← true; return; end;

init span(p);

end; align state ← 1000000; repeat get x or protected ; until cur cmd ≠ spacer ; cur align ← p; init col ; fin col ← false;

exit : end;

807* . The unset box q represents a row that contains one or more unset boxes, depending on how soon occurred in that row. ⟨ Set the unset box q and the unset boxes in it 807* ⟩ ≡

begin if mode = −vmode then begin type(q) ← hlist node; width(q) ← width(p); if nest [nest ptr − 1].mode field = mmode then subtype(q) ← dlist ; { for ship out } end

else begin type(q) ← vlist node; height (q) ← height (p);

end; glue order (q) ← glue order (p); glue sign(q) ← glue sign(p); glue set (q) ← glue set (p); shift amount (q) ← o; r ← link (list ptr (q)); s ← link (list ptr (p)); repeat ⟨ Set the glue in node r and change it from an unset node 808* ⟩;

r ← link (link (r)); s ← link (link (s)); until r = null ; end

This code is used in section 805.

808* . A box made from spanned columns will be followed by tabskip glue nodes and by empty boxes as if there were no spanning. This permits perfect alignment of subsequent entries, and it prevents values that depend on floating point arithmetic from entering into the dimensions of any boxes. ⟨ Set the glue in node r and change it from an unset node 808* ⟩ ≡

n ← span count (r); t ← width(s); w ← t; u ← hold head ; subtype(r) ← min quarterword ;

{ for ship out } while n > min quarterword do

begin decr (n); ⟨ Append tabskip glue and an empty box to list u, and update s and t as the prototype

nodes are passed 809 ⟩; end;

if mode = −vmode then

⟨ Make the unset node r into an hlist node of width w, setting the glue as if the width were t 810 ⟩ else ⟨ Make the unset node r into a vlist node of height w, setting the glue as if the height were t 811 ⟩; shift amount (r) ← 0; if u ≠ hold head then { append blank boxes to account for spanned nodes }

begin link (u) ← link (r); link (r) ← link (hold head ); r ← u;

end

This code is used in section 807*.

110  PART 38: BREAKING PARAGRAPHS INTO LINES  ε-TEX 3.14159 [PD VMS 3.6] changes §813

814* . The line break procedure should be invoked only in horizontal mode; it leaves that mode and places its output into the current vlist of the enclosing vertical mode (or internal vertical mode). There is one explicit parameter: d is true for partial paragraphs preceding display math mode; in this case the amount of additional penalty inserted before the final line is display widow penalty instead of widow penalty .

There are also a number of implicit parameters: The hlist to be broken starts at link (head ), and it is nonempty. The value of prev graf in the enclosing semantic level tells where the paragraph should begin in the sequence of line numbers, in case hanging indentation or are in use; prev graf is zero unless this paragraph is being continued after a displayed formula. Other implicit parameters, such as the par shape ptr and various penalties to use for hyphenation, etc., appear in eqtb.

After line break has acted, it will have updated the current vlist and the value of prev graf . Furthermore, the global variable just box will point to the final box created by line break , so that the width of this line can be ascertained when it is necessary to decide whether to use above display skip or above display short skip before a displayed formula. ⟨ Global variables 13 ⟩ +≡ just box : pointer ; { the hlist node for the last line of the new paragraph }

815* . Since line break is a rather lengthy procedure—sort of a small world unto itself—we must build it up little by little, somewhat more cautiously than we have done with the simpler procedures of TEX. Here is the general outline. ⟨ Declare subprocedures for line break 826 ⟩ procedure line break (d : boolean);

label done, done1 , done2 , done3 , done4 , done5 , continue;

var ⟨ Local variables for line breaking 862 ⟩

begin pack begin line ← mode line; { this is for over/underfull box messages }

⟨ Get ready to start line breaking 816* ⟩;

⟨ Find optimal breakpoints 863* ⟩;

⟨ Break the paragraph at the chosen breakpoints, justify the resulting lines to the correct widths, and

append them to the current vertical list 876* ⟩; ⟨ Clean up the memory by removing the break nodes 865 ⟩; pack begin line ← 0; end;

⟨ Declare ε-TEX procedures for use by main control 1390* ⟩

816* . The first task is to move the list from head to temp head and go into the enclosing semantic level. We also append the glue to the end of the paragraph, removing a space (or other glue node) if it was there, since spaces usually precede blank lines and instances of ‘$$’. The par fill skip is preceded by an infinite penalty, so it will never be considered as a potential breakpoint.

This code assumes that a glue node and a penalty node occupy the same number of mem words. ⟨ Get ready to start line breaking 816* ⟩ ≡

link (temp head ) ← link (head );

if is char node(tail ) then tail append (new penalty (inf penalty ))

else if type(tail ) ≠ glue node then tail append (new penalty (inf penalty ))

else begin type(tail ) ← penalty node; delete glue ref (glue ptr (tail )); flush node list (leader ptr (tail )); penalty (tail ) ← inf penalty ; end;

link (tail ) ← new param glue(par fill skip code); last line fill ← link (tail );

init cur lang ← prev graf mod ´ 200000 ; init l hyf ← prev graf div ´ 20000000 ;

init r hyf ← (prev graf div ´ 200000 ) mod ´ 100 ; pop nest ;

See also sections 827*, 834, and 848. This code is used in section 815*.

§819 ε-TEX 3.14159 [PD VMS 3.6] changes PART 38: BREAKING PARAGRAPHS INTO LINES 111

819* . An active node for a given breakpoint contains six fields: link points to the next node in the list of active nodes; the last active node has link = last active. break node points to the passive node associated with this breakpoint. line number is the number of the line that follows this breakpoint. fitness is the fitness classification of the line ending at this breakpoint. type is either hyphenated or unhyphenated , depending on whether this breakpoint is a disc node. total demerits is the minimum possible sum of demerits over all lines leading from the beginning of the

paragraph to this breakpoint. The value of link (active) points to the first active node on a linked list of all currently active nodes. This list is in order by line number , except that nodes with line number > easy line may be in any order relative to each other.

define active node size normal = 3 { number of words in normal active nodes } define fitness ≡ subtype { very loose fit . . tight fit on final line for this break } define break node ≡ rlink { pointer to the corresponding passive node } define line number ≡ llink { line that begins at this breakpoint } define total demerits (#) ≡ mem[# + 2].int { the quantity that TEX minimizes } define unhyphenated = 0 { the type of a normal active break node } define hyphenated = 1 { the type of an active node that breaks at a disc node } define last active ≡ active { the active list ends where it begins }

827* . ⟨ Get ready to start line breaking 816* ⟩ +≡ no shrink error yet ← true; check shrinkage(left skip); check shrinkage(right skip); q ← left skip; r ← right skip; background [1] ← width(q) + width(r); background [2] ← 0; background [3] ← 0; background [4] ← 0; background [5] ← 0; background [2 + stretch order (q)] ← stretch(q); background [2 + stretch order (r)] ← background [2 + stretch order (r)] + stretch(r); background [6] ← shrink (q) + shrink (r); ⟨ Check for special treatment of last line of paragraph 1576* ⟩; 829* . The heart of the line-breaking procedure is ‘try break ’, a subroutine that tests if the current breakpoint cur p is feasible, by running through the active list to see what lines of text can be made from active nodes to cur p. If feasible breaks are possible, new break nodes are created. If cur p is too far from an active node, that node is deactivated.

The parameter pi to try break is the penalty associated with a break at cur p; we have pi = eject penalty if the break is forced, and pi = inf penalty if the break is illegal.

The other parameter, break type, is set to hyphenated or unhyphenated , depending on whether or not the current break is at a disc node. The end of a paragraph is also regarded as ‘hyphenated ’; this case is distinguishable by the condition cur p = null .

define copy to cur active(#) ≡ cur active width[#] ← active width[#] define deactivate = 60 { go here when node r should be deactivated }

⟨ Declare subprocedures for line break 826 ⟩ +≡ procedure try break (pi : integer ; break type : small number );

label exit , done, done1 , continue, deactivate, found , not found ; var r: pointer ; { runs through the active list }

prev r : pointer ; { stays a step behind r }

old l : halfword ; { maximum line number in current equivalence class of lines }

no break yet : boolean; { have we found a feasible break at cur p? }

⟨ Other local variables for try break 830 ⟩ begin ⟨ Make sure that pi is in the proper range 831 ⟩; no break yet ← true; prev r ← active; old l ← 0; do all six (copy to cur active); loop begin continue: r ← link (prev r ); ⟨ If node r is of type delta node, update cur active width, set

prev r and prev prev r , then goto continue 832 ⟩; ⟨ If a line number class has ended, create new active nodes for the best feasible breaks in that class;

then return if r = last active, otherwise compute the new line width 835 ⟩; ⟨ Consider the demerits for a line from r to cur p; deactivate node r if it should no longer be active;

then goto continue if a line from r to cur p is infeasible, otherwise record a new feasible break 851* ⟩;

end; exit : stat ⟨ Update the value of printed node for symbolic displays 858 ⟩ tats

end;

845* . When we create an active node, we also create the corresponding passive node. ⟨ Insert a new active node from best place[fit class ] to cur p 845* ⟩ ≡

begin q ← get node(passive node size); link (q) ← passive; passive ← q; cur break (q) ← cur p; stat incr (pass number ); serial (q) ← pass number ; tats prev break (q) ← best place[fit class ]; q ← get node(active node size); break node(q) ← passive; line number (q) ← best pl line[fit class ] + 1; fitness (q) ← fit class ; type(q) ← break type; total demerits (q) ← minimal demerits [fit class ]; if do last line fit then ⟨ Store additional data in the new active node 1584* ⟩; link (q) ← r; link (prev r ) ← q; prev r ← q; stat if tracing paragraphs > 0 then ⟨ Print a symbolic description of the new break node 846* ⟩; tats end

This code is used in section 836.

846* . ⟨ Print a symbolic description of the new break node 846* ⟩ ≡ begin print nl ( ); print int (serial (passive)); print ( ␣ ␣ ); print int (line number (q) − 1); print char ( ); print int (fit class ); if break type = hyphenated then print char ( ); print ( ␣ ); print int (total demerits (q)); if do last line fit then ⟨ Print additional data in the new active node 1585* ⟩; print ( ␣ ␣ ); if prev break (passive) = null then print char ( ) else print int (serial (prev break (passive))); end

This code is used in section 845*.

851* . The remaining part of try break deals with the calculation of demerits for a break from r to cur p.

The first thing to do is calculate the badness, b. This value will always be between zero and inf bad + 1; the latter value occurs only in the case of lines from r to cur p that cannot shrink enough to fit the necessary width. In such cases, node r will be deactivated. We also deactivate node r when a break at cur p is forced, since future breaks must go through a forced break. ⟨ Consider the demerits for a line from r to cur p; deactivate node r if it should no longer be active; then

goto continue if a line from r to cur p is infeasible, otherwise record a new feasible break 851* ⟩ ≡ begin artificial demerits ← false; shortfall ← line width − cur active width[1]; { we’re this much too short } if shortfall > 0 then

⟨ Set the value of b to the badness for stretching the line, and compute the corresponding fit class 852* ⟩ else ⟨ Set the value of b to the badness for shrinking the line, and compute the corresponding fit class 853 ⟩; if do last line fit then ⟨ Adjust the additional data for last line 1582* ⟩;

found : if (b > inf bad ) ∨ (pi = eject penalty ) then ⟨ Prepare to deactivate node r, and goto deactivate

unless there is a reason to consider lines of text from r to cur p 854 ⟩ else begin prev r ← r;

if b > threshold then goto continue;

node r stays active ← true;

end; ⟨ Record a new feasible break 855* ⟩; if node r stays active then goto continue; { prev r has been set to r }

deactivate: ⟨ Deactivate node r 860 ⟩;

end

This code is used in section 829*.

852* . When a line must stretch, the available stretchability can be found in the subarray cur active width[2 . . 5], in units of points, fil, fill, and filll.

The present section is part of TEX’s inner loop, and it is most often performed when the badness is infinite; therefore it is worth while to make a quick test for large width excess and small stretchability, before calling the badness subroutine. ⟨ Set the value of b to the badness for stretching the line, and compute the corresponding fit class 852* ⟩ ≡

if (cur active width[3] ≠ 0) ∨ (cur active width[4] ≠ 0) ∨ (cur active width[5] ≠ 0) then

begin if do last line fit then

begin if cur p = null then { the last line of a paragraph } ⟨ Perform computations for last line and goto found 1579* ⟩;

shortfall ← 0;

end; b ← 0; fit class ← decent fit ; { infinite stretch } end

else begin if shortfall > 7230584 then

if cur active width[2] < 1663497 then begin b ← inf bad ; fit class ← very loose fit ; goto done1 ; end;

b ← badness (shortfall , cur active width[2]);

if b > 12 then if b > 99 then fit class ← very loose fit else fit class ← loose fit else fit class ← decent fit ;

done1 : end

This code is used in section 851*.

855* . When we get to this part of the code, the line from r to cur p is feasible, its badness is b, and its fitness classification is fit class . We don’t want to make an active node for this break yet, but we will compute the total demerits and record them in the minimal demerits array, if such a break is the current champion among all ways to get to cur p in a given line-number class and fitness class. ⟨ Record a new feasible break 855* ⟩ ≡

if artificial demerits then d ← 0

else ⟨ Compute the demerits, d, from r to cur p 859 ⟩;

stat if tracing paragraphs > 0 then ⟨ Print a symbolic description of this feasible break 856 ⟩; tats d ← d + total demerits (r); { this is the minimum total demerits from the beginning to cur p via r } if d ≤ minimal demerits [fit class ] then

begin minimal demerits [fit class ] ← d; best place[fit class ] ← break node(r); best pl line[fit class ] ← l; if do last line fit then ⟨ Store additional data for this feasible break 1583* ⟩; if d < minimum demerits then minimum demerits ← d; end

This code is used in section 851*.

§862 ε-TEX 3.14159 [PD VMS 3.6] changesPART 39: BREAKING PARAGRAPHS INTO LINES, CONTINUED 115

863* . The ‘loop’ in the following code is performed at most thrice per call of line break , since it is actually a pass over the entire paragraph. ⟨ Find optimal breakpoints 863* ⟩ ≡

threshold ← pretolerance; if threshold ≥ 0 then

begin stat if tracing paragraphs > 0 then

begin begin diagnostic; print nl ( ); end; tats second pass ← false; final pass ← false; end

else begin threshold ← tolerance; second pass ← true; final pass ← (emergency stretch ≤ 0); stat if tracing paragraphs > 0 then begin diagnostic; tats end;

loop begin if threshold > inf bad then threshold ← inf bad ; if second pass then ⟨ Initialize for hyphenating a paragraph 891* ⟩; ⟨ Create an active breakpoint representing the beginning of the paragraph 864* ⟩; cur p ← link (temp head ); auto breaking ← true; prev p ← cur p; { glue at beginning is not a legal breakpoint } while (cur p ≠ null ) ∧ (link (active) ≠ last active) do ⟨ Call try break if cur p is a legal breakpoint;

on the second pass, also try to hyphenate the next word, if cur p is a glue node; then advance cur p to the next node of the paragraph that could possibly be a legal breakpoint 866* ⟩;

if cur p = null then ⟨ Try the final line break at the end of the paragraph, and goto done if the

desired breakpoints have been found 873 ⟩; ⟨ Clean up the memory by removing the break nodes 865 ⟩; if ¬second pass then

begin stat if tracing paragraphs > 0 then print nl ( ); tats threshold ← tolerance; second pass ← true; final pass ← (emergency stretch ≤ 0); end { if at first you don’t succeed, … }

else begin stat if tracing paragraphs > 0 then print nl ( ); tats background [2] ← background [2] + emergency stretch; final pass ← true; end;

end; done: stat if tracing paragraphs > 0 then

begin end diagnostic(true); normalize selector ; end;

tats if do last line fit then ⟨ Adjust the final line of the paragraph 1586* ⟩;

This code is used in section 815*.

864* . The active node that represents the starting point does not need a corresponding passive node.

define store background (#) ≡ active width[#] ← background [#] ⟨ Create an active breakpoint representing the beginning of the paragraph 864* ⟩ ≡

q ← get node(active node size); type(q) ← unhyphenated ; fitness (q) ← decent fit ; link (q) ← last active; break node(q) ← null ; line number (q) ← prev graf + 1; total demerits (q) ← 0; link (active) ← q; if do last line fit then ⟨ Initialize additional fields of the first active node 1578* ⟩; do all six (store background ); passive ← null ; printed node ← temp head ; pass number ← 0; font in short display ← null font

This code is used in section 863*.

116 PART 39: BREAKING PARAGRAPHS INTO LINES, CONTINUEDε-TEX 3.14159 [PD VMS 3.6] changes §866

866* . Here is the main switch in the line break routine, where legal breaks are determined. As we move through the hlist, we need to keep the active width array up to date, so that the badness of individual lines is readily calculated by try break . It is convenient to use the short name act width for the component of active width that represents real width as opposed to glue.

define act width ≡ active width[1] { length from first active node to current node } define kern break ≡

begin if ¬is char node(link (cur p)) ∧ auto breaking then

if type(link (cur p)) = glue node then try break (0, unhyphenated ); act width ← act width + width(cur p); end

⟨ Call try break if cur p is a legal breakpoint; on the second pass, also try to hyphenate the next word, if cur p is a glue node; then advance cur p to the next node of the paragraph that could possibly be a legal breakpoint 866* ⟩ ≡

begin if is char node(cur p) then

⟨ Advance cur p to the node following the present string of characters 867 ⟩; case type(cur p) of hlist node, vlist node, rule node: act width ← act width + width(cur p); whatsit node: ⟨ Advance past a whatsit node in the line break loop 1362 ⟩; glue node: begin ⟨ If node cur p is a legal breakpoint, call try break ; then update the active widths by

including the glue in glue ptr (cur p) 868 ⟩; if second pass ∧ auto breaking then ⟨ Try to hyphenate the following word 894 ⟩; end;

kern node: if subtype(cur p) = explicit then kern break

else act width ← act width + width(cur p); ligature node: begin f ← font (lig char (cur p));

act width ← act width + char width(f)(char info(f)(character (lig char (cur p)))); end;

disc node: ⟨ Try to break after a discretionary fragment, then goto done5 869 ⟩; math node: begin if subtype(cur p) < L code then auto breaking ← end LR(cur p);

kern break ;

end; penalty node: try break (penalty (cur p), unhyphenated ); mark node, ins node, adjust node: do nothing ; othercases confusion( ) endcases; prev p ← cur p; cur p ← link (cur p);

done5 : end

This code is used in section 863*.

876* . Once the best sequence of breakpoints has been found (hurray), we call on the procedure post line break to finish the remainder of the work. (By introducing this subprocedure, we are able to keep line break from getting extremely long.) ⟨ Break the paragraph at the chosen breakpoints, justify the resulting lines to the correct widths, and

append them to the current vertical list 876* ⟩ ≡ post line break (d)

This code is used in section 815*.

877* . The total number of lines that will be set by post line break is best line − prev graf − 1. The last breakpoint is specified by break node(best bet ), and this passive node points to the other breakpoints via the prev break links. The finishing-up phase starts by linking the relevant passive nodes in forward order, changing prev break to next break . (The next break fields actually reside in the same memory space as the prev break fields did, but we give them a new name because of their new significance.) Then the lines are justified, one by one.

define next break ≡ prev break { new name for prev break after links are reversed } ⟨ Declare subprocedures for line break 826 ⟩ +≡ procedure post line break (d : boolean);

label done, done1 ; var q, r, s: pointer ; { temporary registers for list manipulation }

disc break : boolean; { was the current break at a discretionary node? } post disc break : boolean; { and did it have a nonempty post-break part? } cur width: scaled ; { width of line number cur line } cur indent : scaled ; { left margin of line number cur line } t: quarterword ; { used for replacement counts in discretionary nodes } pen: integer ; { use when calculating penalties between lines } cur line: halfword ; { the current line number being justified } LR ptr : pointer ; { stack of LR codes }

begin LR ptr ← LR save; ⟨ Reverse the links of the relevant passive nodes, setting cur p to the first breakpoint 878 ⟩; cur line ← prev graf + 1; repeat ⟨ Justify the line ending at breakpoint cur p, and append it to the current vertical list, together

with associated penalties and other insertions 880* ⟩; incr (cur line); cur p ← next break (cur p); if cur p ≠ null then

if ¬post disc break then ⟨ Prune unwanted nodes at the beginning of the next line 879* ⟩; until cur p = null ; if (cur line ≠ best line) ∨ (link (temp head ) ≠ null ) then confusion( ␣ ); prev graf ← best line − 1; LR save ← LR ptr ; end; 879* . Glue and penalty and kern and math nodes are deleted at the beginning of a line, except in the anomalous case that the node to be deleted is actually one of the chosen breakpoints. Otherwise the pruning done here is designed to match the lookahead computation in try break , where the break width values are computed for non-discretionary breakpoints. ⟨ Prune unwanted nodes at the beginning of the next line 879* ⟩ ≡

begin r ← temp head ;

loop begin q ← link (r);

if q = cur break (cur p) then goto done1 ; { cur break (cur p) is the next breakpoint }

{ now q cannot be null } if is char node(q) then goto done1 ; if non discardable(q) then goto done1 ; if type(q) = kern node then

if subtype(q) ≠ explicit then goto done1 ; r ← q; { now type(q) = glue node, kern node, math node or penalty node } if type(q) = math node then

if TeXXeT en then ⟨ Adjust the LR stack for the post line break routine 1442* ⟩; end;

done1 : if r ≠ temp head then begin link (r) ← null ; flush node list (link (temp head )); link (temp head ) ← q; end;

end

This code is used in section 877*.

880* . The current line to be justified appears in a horizontal list starting at link (temp head ) and ending at cur break (cur p). If cur break (cur p) is a glue node, we reset the glue to equal the right skip glue; otherwise we append the right skip glue at the right. If cur break (cur p) is a discretionary node, we modify the list so that the discretionary break is compulsory, and we set disc break to true. We also append the left skip glue at the left of the line, unless it is zero. ⟨ Justify the line ending at breakpoint cur p, and append it to the current vertical list, together with

associated penalties and other insertions 880* ⟩ ≡ if TeXXeT en then ⟨ Insert LR nodes at the beginning of the current line and adjust the LR stack based

on LR nodes in this line 1441* ⟩; ⟨ Modify the end of the line to reflect the nature of the break and to include ; also set the

proper value of disc break 881* ⟩; if TeXXeT en then ⟨ Insert LR nodes at the end of the current line 1443* ⟩; ⟨ Put the glue at the left and detach this line 887 ⟩; ⟨ Call the packaging subroutine, setting just box to the justified box 889 ⟩; ⟨ Append the new box to the current vertical list, followed by the list of special nodes taken out of the

box by the packager 888 ⟩; ⟨ Append a penalty node, if a nonzero penalty is appropriate 890* ⟩

This code is used in section 877*.

881* . At the end of the following code, q will point to the final node on the list about to be justified. ⟨ Modify the end of the line to reflect the nature of the break and to include ; also set the

proper value of disc break 881* ⟩ ≡ q ← cur break (cur p); disc break ← false; post disc break ← false; if q ≠ null then { q cannot be a char node }

if type(q) = glue node then begin delete glue ref (glue ptr (q)); glue ptr (q) ← right skip; subtype(q) ← right skip code + 1; add glue ref (right skip); goto done; end

else begin if type(q) = disc node then

⟨ Change discretionary to compulsory and set disc break ← true 882 ⟩ else if type(q) = kern node then width(q) ← 0

else if type(q) = math node then begin width(q) ← 0; if TeXXeT en then ⟨ Adjust the LR stack for the post line break routine 1442* ⟩; end;

end else begin q ← temp head ;

while link (q) ≠ null do q ← link (q); end;

⟨ Put the glue after node q 886 ⟩; done:

This code is used in section 880*.

890* . Penalties between the lines of a paragraph come from club and widow lines, from the inter line penalty parameter, and from lines that end at discretionary breaks. Breaking between lines of a two-line paragraph gets both club-line and widow-line penalties. The local variable pen will be set to the sum of all relevant penalties for the current line, except that the final line is never penalized. ⟨ Append a penalty node, if a nonzero penalty is appropriate 890* ⟩ ≡

if cur line + 1 ≠ best line then begin q ← inter line penalties ptr ; if q ≠ null then

begin r ← cur line; if r > penalty (q) then r ← penalty (q); pen ← penalty (q + r); end

else pen ← inter line penalty ; q ← club penalties ptr ; if q ≠ null then

begin r ← cur line − prev graf ; if r > penalty (q) then r ← penalty (q); pen ← pen + penalty (q + r); end

else if cur line = prev graf + 1 then pen ← pen + club penalty ; if d then q ← display widow penalties ptr else q ← widow penalties ptr ; if q ≠ null then

begin r ← best line − cur line − 1; if r > penalty (q) then r ← penalty (q); pen ← pen + penalty (q + r); end

else if cur line + 2 = best line then if d then pen ← pen + display widow penalty else pen ← pen + widow penalty ;

if disc break then pen ← pen + broken penalty ; if pen ≠ 0 then

begin r ← new penalty (pen); link (tail ) ← r; tail ← r; end;

end

This code is used in section 880*.

§891 ε-TEX 3.14159 [PD VMS 3.6] changes PART 40: PRE-HYPHENATION 121

891* . Pre-hyphenation. When the line-breaking routine is unable to find a feasible sequence of breakpoints, it makes a second pass over the paragraph, attempting to hyphenate the hyphenatable words. The goal of hyphenation is to insert discretionary material into the paragraph so that there are more potential places to break.

The general rules for hyphenation are somewhat complex and technical, because we want to be able to hyphenate words that are preceded or followed by punctuation marks, and because we want the rules to work for languages other than English. We also must contend with the fact that hyphens might radically alter the ligature and kerning structure of a word.

A sequence of characters will be considered for hyphenation only if it belongs to a “potentially hyphenatable part” of the current paragraph. This is a sequence of nodes p_{0}p_{1} … p_{m} where p_{0} is a glue node, p_{1} … p_{m−1} are either character or ligature or whatsit or implicit kern nodes, and p_{m} is a glue or penalty or insertion or adjust or mark or whatsit or explicit kern node. (Therefore hyphenation is disabled by boxes, math formulas, and discretionary nodes already inserted by the user.) The ligature nodes among p_{1} … p_{m−1} are effectively expanded into the original non-ligature characters; the kern nodes and whatsits are ignored. Each character c is now classified as either a nonletter (if lc code(c) = 0), a lowercase letter (if lc code(c) = c), or an uppercase letter (otherwise); an uppercase letter is treated as if it were lc code(c) for purposes of hyphenation. The characters generated by p_{1} … p_{m−1} may begin with nonletters; let c_{1} be the first letter that is not in the middle of a ligature. Whatsit nodes preceding c_{1} are ignored; a whatsit found after c_{1} will be the terminating node p_{m}. All characters that do not have the same font as c_{1} will be treated as nonletters. The hyphen char for that font must be between 0 and 255, otherwise hyphenation will not be attempted. TEX looks ahead for as many consecutive letters c_{1} … c_{n} as possible; however, n must be less than 64, so a character that would otherwise be c_{64} is effectively not a letter. Furthermore c_{n} must not be in the middle of a ligature. In this way we obtain a string of letters c_{1} … c_{n} that are generated by nodes p_{a} … p_{b}, where 1 ≤ a ≤ b + 1 ≤ m. If n ≥ l hyf + r hyf , this string qualifies for hyphenation; however, uc hyph must be positive, if c_{1} is uppercase.

The hyphenation process takes place in three stages. First, the candidate sequence c_{1} … c_{n} is found; then potential positions for hyphens are determined by referring to hyphenation tables; and finally, the nodes p_{a} … p_{b} are replaced by a new sequence of nodes that includes the discretionary breaks found.

Fortunately, we do not have to do all this calculation very often, because of the way it has been taken out of TEX’s inner loop. For example, when the second edition of the author’s 700-page book Seminumerical Algorithms was typeset by TEX, only about 1.2 hyphenations needed to be tried per paragraph, since the line breaking algorithm needed to use two passes on only about 5 per cent of the paragraphs. ⟨ Initialize for hyphenating a paragraph 891* ⟩ ≡

begin init if trie not ready then init trie;

tini

cur lang ← init cur lang ; l hyf ← init l hyf ; r hyf ← init r hyf ; set hyph index ;

end

This code is used in section 863*.

122  PART 40: PRE-HYPHENATION  ε-TEX 3.14159 [PD VMS 3.6] changes §896

896* . The first thing we need to do is find the node ha just before the first letter. ⟨ Skip to node ha, or goto done1 if no hyphenation should be attempted 896* ⟩ ≡

loop begin if is char node(s) then begin c ← qo(character (s)); hf ← font (s); end

else if type(s) = ligature node then if lig ptr (s) = null then goto continue else begin q ← lig ptr (s); c ← qo(character (q)); hf ← font (q);

end else if (type(s) = kern node) ∧ (subtype(s) = normal ) then goto continue

else if type(s) = whatsit node then begin ⟨ Advance past a whatsit node in the pre-hyphenation loop 1363* ⟩; goto continue; end

else goto done1 ; set lc code(c); if hc[0] ≠ 0 then

if (hc[0] = c) ∨ (uc hyph > 0) then goto done2 else goto done1 ;

continue: prev s ← s; s ← link (prev s );

end; done2 : hyf char ← hyphen char [hf ];

if hyf char < 0 then goto done1 ; if hyf char > 255 then goto done1 ; ha ← prev s

This code is used in section 894.

897* . The word to be hyphenated is now moved to the hu and hc arrays. ⟨ Skip to node hb, putting letters into hu and hc 897* ⟩ ≡

hn ← 0; loop begin if is char node(s) then

begin if font (s) ≠ hf then goto done3 ; hyf bchar ← character (s); c ← qo(hyf bchar ); set lc code(c); if hc[0] = 0 then goto done3 ; if hn = 63 then goto done3 ; hb ← s; incr (hn); hu[hn] ← c; hc[hn] ← hc[0]; hyf bchar ← non char ; end

else if type(s) = ligature node then ⟨ Move the characters of a ligature node to hu and hc; but goto

done3 if they are not all letters 898* ⟩ else if (type(s) = kern node) ∧ (subtype(s) = normal ) then

begin hb ← s; hyf bchar ← font bchar [hf ]; end

else goto done3 ; s ← link (s); end;

done3 :

This code is used in section 894.

898* . We let j be the index of the character being stored when a ligature node is being expanded, since we do not want to advance hn until we are sure that the entire ligature consists of letters. Note that it is possible to get to done3 with hn = 0 and hb not set to any value. ⟨ Move the characters of a ligature node to hu and hc; but goto done3 if they are not all letters 898* ⟩ ≡

begin if font (lig char (s)) ≠ hf then goto done3 ; j ← hn; q ← lig ptr (s); if q > null then hyf bchar ← character (q); while q > null do

begin c ← qo(character (q)); set lc code(c); if hc[0] = 0 then goto done3 ; if j = 63 then goto done3 ; incr (j); hu[j] ← c; hc[j] ← hc[0]; q ← link (q); end;

hb ← s; hn ← j; if odd (subtype(s)) then hyf bchar ← font bchar [hf ] else hyf bchar ← non char ; end

This code is used in section 897*.

124  PART 42: HYPHENATION  ε-TEX 3.14159 [PD VMS 3.6] changes §900

934* . We have now completed the hyphenation routine, so the line break procedure is finished at last. Since the hyphenation exception table is fresh in our minds, it’s a good time to deal with the routine that adds new entries to it.

When TEX has scanned ‘ ’, it calls on a procedure named new hyph exceptions to do the right thing.

define set cur lang ≡ if language ≤ 0 then cur lang ← 0 else if language > 255 then cur lang ← 0

else cur lang ← language

procedure new hyph exceptions ; { enters new exceptions } label reswitch, exit , found , not found , not found1 ; var n: 0 . . 64; { length of current word; not always a small number }

j: 0 . . 64; { an index into hc } h: hyph pointer ; { an index into hyph word and hyph list } k: str number ; { an index into str start } p: pointer ; { head of a list of hyphen positions } q: pointer ; { used when creating a new node for list p } s, t: str number ; { strings being compared or stored } u, v: pool pointer ; { indices into str pool }

begin scan left brace; { a left brace must follow } set cur lang ;

init if trie not ready then

begin hyph index ← 0; goto not found1 ; end;

tini set hyph index ;

not found1 : ⟨ Enter as many hyphenation exceptions as are listed, until coming to a right brace; then

return 935 ⟩;

exit : end;

937* . ⟨ Append a new letter or hyphen 937* ⟩ ≡ if cur chr = then ⟨ Append the value n to list p 938 ⟩ else begin set lc code(cur chr );

if hc[0] = 0 then

begin print err (  ␣ ␣  );
help2 (  ␣  ␣           ␣     ␣    ␣    ␣  )
(  ␣ ´ ␣      ␣   ␣         ␣ ␣    ␣  ); error ;

end else if n < 63 then

begin incr (n); hc[n] ← hc[0]; end;

end

This code is used in section 935.

§942 ε-TEX 3.14159 [PD VMS 3.6] changes PART 43: INITIALIZING THE HYPHENATION TABLES 125

952* . Here is how the trie-compression data structures are initialized. If storage is tight, it would be possible to overlap trie op hash, trie op lang , and trie op val with trie, trie hash, and trie taken, because we finish with the former just before we need the latter. ⟨ Get ready to compress the trie 952* ⟩ ≡

⟨ Sort the hyphenation op tables into proper order 945 ⟩; for p ← 0 to trie size do trie hash[p] ← 0; hyph root ← compress trie(hyph root ); trie root ← compress trie(trie root );

{ identify equivalent subtries } for p ← 0 to trie ptr do trie ref [p] ← 0; for p ← 0 to 255 do trie min[p] ← p + 1; trie link (0) ← 1; trie max ← 0

This code is used in section 966*.

958* . When the whole trie has been allocated into the sequential table, we must go through it once again so that trie contains the correct information. Null pointers in the linked trie will be represented by the value 0, which properly implements an “empty” family. ⟨ Move the data into trie 958* ⟩ ≡

h.rh ← 0; h.b0 ← min quarterword ; h.b1 ← min quarterword ;

{ trie link ← 0, trie op ← min quarterword , trie char ← qi (0) } if trie max = 0 then { no patterns were given }

begin for r ← 0 to 256 do trie[r] ← h;

trie max ← 256;

end else begin if hyph root > 0 then trie fix (hyph root );

if trie root > 0 then trie fix (trie root ); { this fixes the non-holes in trie } r ← 0; { now we will zero out all the holes } repeat s ← trie link (r); trie[r] ← h; r ← s; until r > trie max ; end;

trie char (0) ← qi ( ); { make trie char (c) ≠ c for all c }

This code is used in section 966*.

126  PART 43: INITIALIZING THE HYPHENATION TABLES  ε-TEX 3.14159 [PD VMS 3.6] changes §960

960* . Now let’s go back to the easier problem, of building the linked trie. When has scanned the ‘ ’ control sequence, it calls on new patterns to do the right thing. ⟨ Declare procedures for preprocessing hyphenation patterns 944 ⟩ +≡ procedure new patterns ; { initializes the hyphenation pattern data }

label done, done1 ; var k, l: 0 . . 64; { indices into hc and hyf ; not always in small number range }

digit sensed : boolean; { should the next digit be treated as a letter? } v: quarterword ; { trie op code } p, q: trie pointer ; { nodes of trie traversed during insertion } first child : boolean; { is p = trie l [q]? } c: ASCII code; { character being inserted }

begin if trie not ready then

begin set cur lang ; scan left brace; { a left brace must follow } ⟨ Enter all of the patterns into a linked trie, until coming to a right brace 961 ⟩; if saving hyph codes > 0 then ⟨ Store hyphenation codes for current language 1588* ⟩; end

else begin print err (  ␣    ␣   ␣ ); print esc(  );
help1 (  ␣        ␣    ␣  ␣     ␣      ␣          ␣  ); error ;

link (garbage) ← scan toks (false, false); flush list (def ref ); end;

end;

966* . Finally we put everything together: Here is how the trie gets to its final, efficient form. The following packing routine is rigged so that the root of the linked tree gets mapped into location 1 of trie, as required by the hyphenation algorithm. This happens because the first call of first fit will “take” location 1. ⟨ Declare procedures for preprocessing hyphenation patterns 944 ⟩ +≡ procedure init trie;

var p: trie pointer ; { pointer for initialization } j, k, t: integer ; { all-purpose registers for initialization } r, s: trie pointer ; { used to clean up the packed trie } h: two halves ; { template used to zero out trie’s holes }

begin ⟨ Get ready to compress the trie 952* ⟩; if trie root ≠ 0 then

begin first fit (trie root ); trie pack (trie root ); end;

if hyph root ≠ 0 then ⟨ Pack all stored hyph codes 1590* ⟩; ⟨ Move the data into trie 958* ⟩; trie not ready ← false; end;

§967 ε-TEX 3.14159 [PD VMS 3.6] changes PART 44: BREAKING VERTICAL LISTS INTO PAGES 127

968* . A subroutine called prune page top takes a pointer to a vlist and returns a pointer to a modified vlist in which all glue, kern, and penalty nodes have been deleted before the first box or rule node. However, the first box or rule is actually preceded by a newly created glue node designed so that the topmost baseline will be at distance split top skip from the top, whenever this is possible without backspacing.

When the second argument s is false the deleted nodes are destroyed, otherwise they are collected in a list starting at split disc.

In this routine and those that follow, we make use of the fact that a vertical list contains no character nodes, hence the type field exists for each node in the list. function prune page top(p : pointer ; s : boolean): pointer ; { adjust top after page break }

var prev p: pointer ; { lags one step behind p }

q, r: pointer ; { temporary variables for list manipulation } begin prev p ← temp head ; link (temp head ) ← p; while p ≠ null do

case type(p) of

hlist node, vlist node, rule node: ⟨ Insert glue for split top skip and set p ← null 969 ⟩; whatsit node, mark node, ins node: begin prev p ← p; p ← link (prev p);

end; glue node, kern node, penalty node: begin q ← p; p ← link (q); link (q) ← null ; link (prev p) ← p;

if s then

begin if split disc = null then split disc ← q else link (r) ← q; r ← q; end

else flush node list (q); end;

othercases confusion( )

endcases; prune page top ← link (temp head ); end;

128  PART 44: BREAKING VERTICAL LISTS INTO PAGES  ε-TEX 3.14159 [PD VMS 3.6] changes §977

977* . Now we are ready to consider vsplit itself. Most of its work is accomplished by the two subroutines that we have just considered.

Given the number of a vlist box n, and given a desired page height h, the vsplit function finds the best initial segment of the vlist and returns a box for a page of height h. The remainder of the vlist, if any, replaces the original box, after removing glue and penalties and adjusting for split top skip. Mark nodes in the split-off box are used to set the values of split first mark and split bot mark ; we use the fact that split first mark = null if and only if split bot mark = null .

The original box becomes “void” if and only if it has been entirely extracted. The extracted box is “void” if and only if the original box was void (or if it was, erroneously, an hlist box). ⟨ Declare the function called do marks 1558* ⟩ function vsplit (n : halfword ; h : scaled ): pointer ; { extracts a page of height h from box n }

label exit , done; var v: pointer ; { the box to be split }

p: pointer ; { runs through the vlist }

q: pointer ; { points to where the break occurs } begin cur val ← n; fetch box (v); flush node list (split disc); split disc ← null ; if sa mark ≠ null then

if do marks (vsplit init , 0, sa mark ) then sa mark ← null ; if split first mark ≠ null then

begin delete token ref (split first mark ); split first mark ← null ; delete token ref (split bot mark ); split bot mark ← null ; end;

⟨ Dispense with trivial cases of void or bad boxes 978 ⟩; q ← vert break (list ptr (v), h, split max depth); ⟨ Look at all the marks in nodes before the break, and set the final link to null at the break 979* ⟩; q ← prune page top(q, saving vdiscards > 0); p ← list ptr (v); free node(v, box node size); if q ≠ null then q ← vpack (q, natural ); change box (q); { the eq level of the box stays the same } vsplit ← vpackage(p, h, exactly , split max depth);

exit : end;

979* . It’s possible that the box begins with a penalty node that is the “best” break, so we must be careful to handle this special case correctly. ⟨ Look at all the marks in nodes before the break, and set the final link to null at the break 979* ⟩ ≡

p ← list ptr (v); if p = q then list ptr (v) ← null else loop begin if type(p) = mark node then

if mark class (p) ≠ null then ⟨ Update the current marks for vsplit 1560* ⟩ else if split first mark = null then

begin split first mark ← mark ptr (p); split bot mark ← split first mark ; token ref count (split first mark ) ← token ref count (split first mark ) + 2; end

else begin delete token ref (split bot mark ); split bot mark ← mark ptr (p); add token ref (split bot mark ); end; if link (p) = q then

begin link (p) ← null ; goto done;

end; p ← link (p); end;

done:

This code is used in section 977*.

§980 ε-TEX 3.14159 [PD VMS 3.6] changes PART 45: THE PAGE BUILDER 129

982* . An array page so far records the heights and depths of everything on the current page. This array contains six scaled numbers, like the similar arrays already considered in line break and vert break ; and it also contains page goal and page depth, since these values are all accessible to the user via set page dimen commands. The value of page so far [1] is also called page total . The stretch and shrink components of the corrections for each insertion are included in page so far , but the natural space components of these corrections are not, since they have been subtracted from page goal .

The variable page depth records the depth of the current page; it has been adjusted so that it is at most page max depth. The variable last glue points to the glue specification of the most recent node contributed from the contribution list, if this was a glue node; otherwise last glue = max halfword . (If the contribution list is nonempty, however, the value of last glue is not necessarily accurate.) The variables last penalty , last kern, and last node type are similar. And finally, insert penalties holds the sum of the penalties associated with all split and floating insertions.

define page goal ≡ page so far [0] { desired height of information on page being built }

define page total ≡ page so far [1] { height of the current page }

define page shrink ≡ page so far [6] { shrinkability of the current page }

define page depth ≡ page so far [7] { depth of the current page } ⟨ Global variables 13 ⟩ +≡ page so far : array [0 . . 7] of scaled ; { height and glue of the current page } last glue: pointer ; { used to implement } last penalty : integer ; { used to implement } last kern: scaled ; { used to implement } last node type: integer ; { used to implement } insert penalties : integer ; { sum of the penalties for held-over insertions }

991* . The page builder is ready to start a fresh page if we initialize the following state variables. (However, the page insertion list is initialized elsewhere.) ⟨ Start a new current page 991* ⟩ ≡

page contents ← empty ; page tail ← page head ; link (page head ) ← null ;

last glue ← max halfword ; last penalty ← 0; last kern ← 0; last node type ← −1; page depth ← 0; page max depth ← 0

This code is used in sections 215* and 1017.

996* . ⟨ Update the values of last glue, last penalty , and last kern 996* ⟩ ≡ if last glue ≠ max halfword then delete glue ref (last glue); last penalty ← 0; last kern ← 0; last node type ← type(p) + 1; if type(p) = glue node then

begin last glue ← glue ptr (p); add glue ref (last glue); end

else begin last glue ← max halfword ; if type(p) = penalty node then last penalty ← penalty (p) else if type(p) = kern node then last kern ← width(p); end

This code is used in section 994.

130  PART 45: THE PAGE BUILDER  ε-TEX 3.14159 [PD VMS 3.6] changes §999

999* . ⟨ Recycle node p 999* ⟩ ≡ link (contrib head ) ← link (p); link (p) ← null ; if saving vdiscards > 0 then

begin if page disc = null then page disc ← p else link (tail page disc) ← p; tail page disc ← p; end

else flush node list (p)

This code is used in section 997.

1012* . When the page builder has looked at as much material as could appear before the next page break, it makes its decision. The break that gave minimum badness will be used to put a completed “page” into box 255, with insertions appended to their other boxes.

We also set the values of top mark , first mark , and bot mark . The program uses the fact that bot mark ≠ null implies first mark ≠ null ; it also knows that bot mark = null implies top mark = first mark = null .

The fire up subroutine prepares to output the current page at the best place; then it fires up the user’s output routine, if there is one, or it simply ships out the page. There is one parameter, c, which represents the node that was being contributed to the page when the decision to force an output was made. ⟨ Declare the procedure called fire up 1012* ⟩ ≡ procedure fire up(c : pointer );

label exit ; var p, q, r, s: pointer ; { nodes being examined and/or changed }

prev p: pointer ; { predecessor of p } n: min quarterword . . 255; { insertion box number } wait : boolean; { should the present insertion be held over? } save vbadness : integer ; { saved value of vbadness } save vfuzz : scaled ; { saved value of vfuzz } save split top skip: pointer ; { saved value of split top skip }

begin ⟨ Set the value of output penalty 1013 ⟩; if sa mark ≠ null then

if do marks (fire up init , 0, sa mark ) then sa mark ← null ; if bot mark ≠ null then

begin if top mark ≠ null then delete token ref (top mark ); top mark ← bot mark ; add token ref (top mark ); delete token ref (first mark ); first mark ← null ; end;

⟨ Put the optimal current page into box 255, update first mark and bot mark , append insertions to their

boxes, and put the remaining nodes back on the contribution list 1014* ⟩; if sa mark ≠ null then

if do marks (fire up done, 0, sa mark ) then sa mark ← null ; if (top mark ≠ null ) ∧ (first mark = null ) then

begin first mark ← top mark ; add token ref (top mark ); end;

if output routine ≠ null then

if dead cycles ≥ max dead cycles then

⟨ Explain that too many dead cycles have occurred in a row 1024 ⟩ else ⟨ Fire up the user’s output routine and return 1025 ⟩;

⟨ Perform the default output routine 1023* ⟩; exit : end;

This code is used in section 994.

1014* . As the page is finally being prepared for output, pointer p runs through the vlist, with prev p trailing behind; pointer q is the tail of a list of insertions that are being held over for a subsequent page. ⟨ Put the optimal current page into box 255, update first mark and bot mark , append insertions to their

boxes, and put the remaining nodes back on the contribution list 1014* ⟩ ≡ if c = best page break then best page break ← null ; { c not yet linked in } ⟨ Ensure that box 255 is empty before output 1015 ⟩; insert penalties ← 0; { this will count the number of insertions held over } save split top skip ← split top skip; if holding inserts ≤ 0 then ⟨ Prepare all the boxes involved in insertions to act as queues 1018 ⟩; q ← hold head ; link (q) ← null ; prev p ← page head ; p ← link (prev p); while p ≠ best page break do

begin if type(p) = ins node then

begin if holding inserts ≤ 0 then ⟨ Either insert the material specified by node p into the

appropriate box, or hold it for the next page; also delete node p from the current page 1020 ⟩; end

else if type(p) = mark node then if mark class (p) ≠ null then ⟨ Update the current marks for fire up 1563* ⟩ else ⟨ Update the values of first mark and bot mark 1016 ⟩;

prev p ← p; p ← link (prev p);

end; split top skip ← save split top skip; ⟨ Break the current page at node p, put it in box 255, and put the

remaining nodes on the contribution list 1017 ⟩; ⟨ Delete the page-insertion nodes 1019 ⟩

This code is used in section 1012*.

1021* . ⟨ Wrap up the box specified by node r, splitting node p if called for; set wait ← true if node p

holds a remainder after splitting 1021* ⟩ ≡ begin if type(r) = split up then

if (broken ins (r) = p) ∧ (broken ptr (r) ≠ null ) then begin while link (s) ≠ broken ptr (r) do s ← link (s); link (s) ← null ; split top skip ← split top ptr (p); ins ptr (p) ← prune page top(broken ptr (r), false); if ins ptr (p) ≠ null then

begin temp ptr ← vpack (ins ptr (p), natural ); height (p) ← height (temp ptr ) + depth(temp ptr ); free node(temp ptr , box node size); wait ← true; end; end;

best ins ptr (r) ← null ; n ← qo(subtype(r)); temp ptr ← list ptr (box (n)); free node(box (n), box node size); box (n) ← vpack (temp ptr , natural ); end

This code is used in section 1020.

1023* . The list of heldover insertions, running from link (page head ) to page tail , must be moved to the contribution list when the user has specified no output routine. ⟨ Perform the default output routine 1023* ⟩ ≡

begin if link (page head ) ≠ null then

begin if link (contrib head ) = null then

if nest ptr = 0 then tail ← page tail else contrib tail ← page tail else link (page tail ) ← link (contrib head ); link (contrib head ) ← link (page head ); link (page head ) ← null ; page tail ← page head ; end;

flush node list (page disc); page disc ← null ; ship out (box (255)); box (255) ← null ; end

This code is used in section 1012*.

1026* . When the user’s output routine finishes, it has constructed a vlist in internal vertical mode, and TEX will do the following: ⟨ Resume the page builder after an output routine has come to an end 1026* ⟩ ≡

begin if (loc ≠ null ) ∨ ((token type ≠ output text ) ∧ (token type ≠ backed up)) then

⟨ Recover from an unbalanced output routine 1027 ⟩; end token list ; { conserve stack space in case more outputs are triggered } end graf ; unsave; output active ← false; insert penalties ← 0; ⟨ Ensure that box 255 is empty after output 1028 ⟩; if tail ≠ head then { current list goes after heldover insertions }

begin link (page tail ) ← link (head ); page tail ← tail ;

end; if link (page head ) ≠ null then { and both go before heldover contributions }

begin if link (contrib head ) = null then contrib tail ← page tail ;

link (page tail ) ← link (contrib head ); link (contrib head ) ← link (page head ); link (page head ) ← null ; page tail ← page head ; end;

flush node list (page disc); page disc ← null ; pop nest ; build page; end

This code is used in section 1100.

§1029 ε-TEX 3.14159 [PD VMS 3.6] changes PART 47: BUILDING BOXES AND LISTS 133

1070* . Here is where we clear the parameters that are supposed to revert to their default values after every paragraph and when internal vertical mode is entered. ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure normal paragraph;

begin if looseness ≠ 0 then eq word define(int base + looseness code, 0); if hang indent ≠ 0 then eq word define(dimen base + hang indent code, 0); if hang after ≠ 1 then eq word define(int base + hang after code, 1); if par shape ptr ≠ null then eq define(par shape loc, shape ref , null ); if inter line penalties ptr ≠ null then eq define(inter line penalties loc, shape ref , null ); end;

1071* . Now let’s turn to the question of how is treated. We actually need to consider also a slightly larger context, since constructions like ‘ ’ and ‘ ’ and ‘ ’ are supposed to invoke quite different actions after the box has been packaged. Conversely, constructions like ‘ ’ can be followed by a variety of different kinds of boxes, and we would like to encode such things in an efficient way.

In other words, there are two problems: To represent the context of a box, and to represent its type. The first problem is solved by putting a “context code” on the save stack , just below the two entries

that give the dimensions produced by scan spec. The context code is either a (signed) shift amount, or it is a large integer ≥ box flag , where box flag = 2^{30}. Codes box flag through global box flag − 1

represent ‘  ’ through ‘  ’; codes global box flag through ship out flag − 1 represent
‘  ’ through ‘  ’; code ship out flag represents ‘  ’; and codes
leader flag through leader flag + 2 represent ‘  ’, ‘  ’, and ‘  ’.

The second problem is solved by giving the command code make box to all control sequences that produce a box, and by using the following chr code values to distinguish between them: box code, copy code, last box code, vsplit code, vtop code, vtop code + vmode, and vtop code + hmode, where the latter two are used denote and , respectively.

define box flag ≡ ´ 10000000000 { context code for ‘ ’ } define global box flag ≡ ´ 10000100000 { context code for ‘ ’ } define ship out flag ≡ ´ 10000200000 { context code for ‘ ’ } define leader flag ≡ ´ 10000200001 { context code for ‘ ’ } define box code = 0 { chr code for ‘ ’ } define copy code = 1 { chr code for ‘ ’ } define last box code = 2 { chr code for ‘ ’ } define vsplit code = 3 { chr code for ‘ ’ } define vtop code = 4 { chr code for ‘ ’ }

⟨ Put each of TEX’s primitives into the hash table 226 ⟩ +≡

primitive(  , hmove, 1); primitive(  , hmove, 0);
primitive(  , vmove, 1); primitive(  , vmove, 0);
primitive(  , make box , box code); primitive(  , make box , copy code);
primitive(  , make box , last box code); primitive(  , make box , vsplit code);

134  PART 47: BUILDING BOXES AND LISTS  ε-TEX 3.14159 [PD VMS 3.6] changes §1075

primitive( , make box , vtop code); primitive( , make box , vtop code + vmode); primitive( , make box , vtop code + hmode); primitive( , leader ship, a leaders − 1); { ship out flag = leader flag − 1 } primitive( , leader ship, a leaders ); primitive( , leader ship, c leaders ); primitive( , leader ship, x leaders ); 1075* . The box end procedure does the right thing with cur box , if box context represents the context as explained above. ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure box end (box context : integer );

var p: pointer ; { ord noad for new box in math mode }

a: small number ; { global prefix } begin if box context < box flag then

⟨ Append box cur box to the current list, shifted by box context 1076 ⟩ else if box context < ship out flag then ⟨ Store cur box in a box register 1077* ⟩

else if cur box ≠ null then if box context > ship out flag then ⟨ Append a new leader node that uses cur box 1078 ⟩ else ship out (cur box );

end;

1077* . ⟨ Store cur box in a box register 1077* ⟩ ≡

begin if box context < global box flag then begin cur val ← box context − box flag ; a ← 0; end

else begin cur val ← box context − global box flag ; a ← 4;

end; if cur val < 256 then define(box base + cur val , box ref , cur box ) else sa def box ; end

This code is used in section 1075*.

1079* . Now that we can see what eventually happens to boxes, we can consider the first steps in their creation. The begin box routine is called when box context is a context specification, cur chr specifies the type of box desired, and cur cmd = make box . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure begin box (box context : integer );

label exit , done; var p, q: pointer ; { run through the current list }

m: quarterword ; { the length of a replacement list }

k: halfword ; { 0 or vmode or hmode }

n: halfword ; { a box number }

begin case cur chr of

box code: begin scan register num; fetch box (cur box ); change box (null );

{ the box becomes void, at the same level } end;

copy code: begin scan register num; fetch box (q); cur box ← copy node list (q);

end; last box code: ⟨ If the current list ends with a box node, delete it from the list and make cur box point to

it; otherwise set cur box ← null 1080* ⟩; vsplit code: ⟨ Split off part of a vertical box, make cur box point to it 1082* ⟩; othercases ⟨ Initiate the construction of an hbox or vbox, then return 1083 ⟩ endcases; box end (box context ); { in simple cases, we use the box immediately }

exit : end; 1080* . Note that the condition ¬is char node(tail ) implies that head ≠ tail , since head is a one-word node. A final node is temporarily removed. ⟨ If the current list ends with a box node, delete it from the list and make cur box point to it; otherwise set

cur box ← null 1080* ⟩ ≡

begin cur box ← null ; if abs (mode) = mmode then

begin you cant ; help1 ( ␣ ␣ ␣ ␣ ␣ ); error ; end

else if (mode = vmode) ∧ (head = tail ) then

begin you cant ; help2 (  ␣       ␣   ´ ␣    ␣      ␣    ␣   ␣       ␣  )
(  ␣        ␣    ␣         ␣  ␣  ); error ;

end else begin if ¬is char node(tail ) then

begin if (type(tail ) = math node) ∧ (subtype(tail ) = end M code) then remove end M ; if (type(tail ) = hlist node) ∨ (type(tail ) = vlist node) then

⟨ Remove the last box, unless it’s part of a discretionary 1081 ⟩; if LR temp ≠ null then insert end M ; end;

end; end

This code is used in section 1079*.

1082* . Here we deal with things like ‘ ’. ⟨ Split off part of a vertical box, make cur box point to it 1082* ⟩ ≡

begin scan register num; n ← cur val ; if ¬scan keyword ( ) then

begin print err (  ␣`   ´ ␣  );

help2 ( ´ ␣       ␣  ␣` ␣       ␣  ␣  ´  )

(  ␣    ␣   ␣   ␣       ␣  ); error ;

end; scan normal dimen; cur box ← vsplit (n, cur val ); end

This code is used in section 1079*.

1096* . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure end graf ;

begin if mode = hmode then begin if head = tail then pop nest { null paragraphs are ignored } else line break (false); if LR save ≠ null then

begin flush list (LR save); LR save ← null ;

end; normal paragraph; error count ← 0; end;

end; 1101* . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure make mark ;

var p: pointer ; { new node }

c: halfword ; { the mark class } begin if cur chr = 0 then c ← 0 else begin scan register num; c ← cur val ;

end; p ← scan toks (false, true); p ← get node(small node size); mark class (p) ← c; type(p) ← mark node; subtype(p) ← 0; { the subtype is not used } mark ptr (p) ← def ref ; link (tail ) ← p; tail ← p; end;

1105* . When delete last is called, cur chr is the type of node that will be deleted, if present. A final node is temporarily removed. ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure delete last ;

label exit ; var p, q: pointer ; { run through the current list }

m: quarterword ; { the length of a replacement list } begin if (mode = vmode) ∧ (tail = head ) then

⟨ Apologize for inability to do the operation now, unless follows non-glue 1106 ⟩ else begin if ¬is char node(tail ) then

begin if (type(tail ) = math node) ∧ (subtype(tail ) = end M code) then remove end M ; if type(tail ) = cur chr then

begin q ← head ; repeat p ← q;

if ¬is char node(q) then

if type(q) = disc node then begin for m ← 1 to replace count (q) do p ← link (p); if p = tail then return; end; q ← link (p); until q = tail ; link (p) ← null ; flush node list (tail ); tail ← p; end;

if LR temp ≠ null then insert end M ;

end; end;

exit : end;

1108* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ remove item: if chr code = glue node then print esc( )

else if chr code = kern node then print esc( )

else print esc( ); un hbox : if chr code = copy code then print esc( )

else print esc( ); un vbox : if chr code = copy code then print esc( ) ⟨ Cases of un vbox for print cmd chr 1595* ⟩

else print esc( ); 1110* . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure unpackage;

label done, exit ;

var p: pointer ; { the box }

c: box code . . copy code; { should we copy? } begin if cur chr > copy code then ⟨ Handle saved items and goto done 1596* ⟩; c ← cur chr ; scan register num; fetch box (p); if p = null then return; if (abs (mode) = mmode) ∨ ((abs (mode) = vmode) ∧ (type(p) ≠ vlist node)) ∨

((abs (mode) = hmode) ∧ (type(p) ≠ hlist node)) then

begin print err (  ␣    ␣   ´ ␣  ␣  );
help3 (  ␣        ␣    ␣      ␣  )

    ( ␣      ␣  ␣     ␣  ␣     ␣  ␣        ␣    ␣  ␣    ␣  )
    (  ␣ ␣   ´ ␣    ␣   ␣     ␣  ␣    ␣  );

error ; return;

end; if c = copy code then link (tail ) ← copy node list (list ptr (p)) else begin link (tail ) ← list ptr (p); change box (null ); free node(p, box node size);

end; done: while link (tail ) ≠ null do tail ← link (tail ); exit : end;

1130* . We’ve now covered most of the abuses of  and  . Let’s take a look at what happens

when they are used correctly. ⟨ Cases of main control that build boxes and lists 1056 ⟩ +≡ vmode + halign: init align; hmode + valign: ⟨ Cases of main control for hmode + valign 1437* ⟩

init align; mmode + halign: if privileged then

if cur group = math shift group then init align

138  PART 48: BUILDING MATH LISTS  ε-TEX 3.14159 [PD VMS 3.6] changes §1136

else off save; vmode + endv , hmode + endv : do endv ; 1138* . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ ⟨ Declare subprocedures for init math 1466* ⟩ procedure init math;

label reswitch, found , not found , done; var w: scaled ; { new or partial pre display size }

j: pointer ; { prototype box for display }

x: integer ; { new pre display direction }

l: scaled ; { new display width }

s: scaled ; { new display indent }

p: pointer ; { current node when calculating pre display size }

q: pointer ; { glue specification when calculating pre display size }

f: internal font number ; { font in current char node }

n: integer ; { scope of paragraph shape specification }

v: scaled ; { w plus possible glue amount }

d: scaled ; { increment to v } begin get token; { get x token would fail on ! } if (cur cmd = math shift ) ∧ (mode > 0) then ⟨ Go into display math mode 1145* ⟩ else begin back input ; ⟨ Go into ordinary math mode 1139 ⟩;

end; end;

1145* . When we enter display math mode, we need to call line break to process the partial paragraph that has just been interrupted by the display. Then we can set the proper values of display width and display indent and pre display size. ⟨ Go into display math mode 1145* ⟩ ≡

begin j ← null ; w ← −max dimen; if head = tail then { ‘ $$ ’ or ‘$$ $$’ }

⟨ Prepare for display after an empty paragraph 1465* ⟩ else begin line break (true);

⟨ Calculate the natural width, w, by which the characters of the final line extend to the right of the reference point, plus two ems; or set w ← max dimen if the non-blank information on that line is affected by stretching or shrinking 1146* ⟩;

end; { Now we are in vertical mode, working on the list that will contain the display } ⟨ Calculate the length, l, and the shift amount, s, of the display lines 1149 ⟩; push math(math shift group); mode ← mmode; eq word define(int base + cur fam code, −1); eq word define(dimen base + pre display size code, w); LR box ← j; if eTeX ex then eq word define(int base + pre display direction code, x); eq word define(dimen base + display width code, l); eq word define(dimen base + display indent code, s); if every display ≠ null then begin token list (every display , every display text ); if nest ptr = 1 then build page; end

This code is used in section 1138*.

§1146 ε-TEX 3.14159 [PD VMS 3.6] changes PART 48: BUILDING MATH LISTS 139

1146* . ⟨ Calculate the natural width, w, by which the characters of the final line extend to the right of the reference point, plus two ems; or set w ← max dimen if the non-blank information on that line is affected by stretching or shrinking 1146* ⟩ ≡

⟨ Prepare for display after a non-empty paragraph 1467* ⟩; while p ≠ null do

begin ⟨ Let d be the natural width of node p; if the node is “visible,” goto found ; if the node is glue

that stretches or shrinks, set v ← max dimen 1147* ⟩; if v < max dimen then v ← v + d; goto not found ;

found : if v < max dimen then begin v ← v + d; w ← v; end

else begin w ← max dimen; goto done;

end; not found : p ← link (p);

end; done: ⟨ Finish the natural width computation 1468* ⟩

This code is used in section 1145*.

1147* . ⟨ Let d be the natural width of node p; if the node is “visible,” goto found ; if the node is glue that

stretches or shrinks, set v ← max dimen 1147* ⟩ ≡ reswitch: if is char node(p) then

begin f ← font (p); d ← char width(f)(char info(f)(character (p))); goto found ;

end; case type(p) of hlist node, vlist node, rule node: begin d ← width(p); goto found ;

end; ligature node: ⟨ Make node p look like a char node and goto reswitch 652 ⟩; kern node: d ← width(p); ⟨ Cases of ‘Let d be the natural width’ that need special treatment 1469* ⟩ glue node: ⟨ Let d be the natural width of this glue; if stretching or shrinking, set v ← max dimen; goto

found in the case of leaders 1148 ⟩; whatsit node: ⟨ Let d be the width of the whatsit p 1361 ⟩; othercases d ← 0 endcases

This code is used in section 1146*.

1185* . ⟨ Compleat the incompleat noad 1185* ⟩ ≡ begin math type(denominator (incompleat noad )) ← sub mlist ; info(denominator (incompleat noad )) ← link (head ); if p = null then q ← incompleat noad else begin q ← info(numerator (incompleat noad ));

if (type(q) ≠ left noad ) ∨ (delim ptr = null ) then confusion( );

info(numerator (incompleat noad )) ← link (delim ptr ); link (delim ptr ) ← incompleat noad ; link (incompleat noad ) ← p; end;

end

This code is used in section 1184.

1189* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ left right : if chr code = left noad then print esc( )

⟨ Cases of left right for print cmd chr 1432* ⟩ else print esc( );

1191* . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure math left right ;

var t: small number ; { left noad or right noad } p: pointer ; { new noad } q: pointer ; { resulting mlist }

begin t ← cur chr ; if (t ≠ left noad ) ∧ (cur group ≠ math left group) then ⟨ Try to recover from mismatched 1192* ⟩ else begin p ← new noad ; type(p) ← t; scan delimiter (delimiter (p), false);

if t = middle noad then begin type(p) ← right noad ; subtype(p) ← middle noad ; end;

if t = left noad then q ← p else begin q ← fin mlist (p); unsave; { end of math left group }

end; if t ≠ right noad then

begin push math(math left group); link (head ) ← q; tail ← p; delim ptr ← p;

end else begin tail append (new noad ); type(tail ) ← inner noad ; math type(nucleus (tail )) ← sub mlist ;

info(nucleus (tail )) ← q;

end; end;

end;

1192* . ⟨ Try to recover from mismatched 1192* ⟩ ≡

begin if cur group = math shift group then begin scan delimiter (garbage, false); print err ( ␣ ); if t = middle noad then

begin print esc( ); help1 ( ´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ); end

else begin print esc( ); help1 ( ´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ );

end; error ; end

else off save; end

This code is used in section 1191*.

1194* . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ ⟨ Declare subprocedures for after math 1477* ⟩ procedure after math;

var l: boolean; { ‘ ’ instead of ‘ ’ } danger : boolean; { not enough symbol fonts are present } m: integer ; { mmode or −mmode } p: pointer ; { the formula } a: pointer ; { box containing equation number } ⟨ Local variables for finishing a displayed formula 1198 ⟩

begin danger ← false; ⟨ Retrieve the prototype box 1475* ⟩; ⟨ Check that the necessary fonts for math symbols are present; if not, flush the current math lists and set

danger ← true 1195 ⟩;

m ← mode; l ← false; p ← fin mlist (null ); { this pops the nest } if mode = −m then { end of equation number }

begin ⟨ Check that another $ follows 1197 ⟩; cur mlist ← p; cur style ← text style; mlist penalties ← false; mlist to hlist ; a ← hpack (link (temp head ), natural ); subtype(a) ← dlist ; unsave; decr (save ptr );

{ now cur group = math shift group } if saved (0) = 1 then l ← true; danger ← false; ⟨ Retrieve the prototype box 1475* ⟩; ⟨ Check that the necessary fonts for math symbols are present; if not, flush the current math lists and

set danger ← true 1195 ⟩; m ← mode; p ← fin mlist (null ); end

else a ← null ; if m < 0 then ⟨ Finish math in text 1196 ⟩ else begin if a = null then ⟨ Check that another $ follows 1197 ⟩;

⟨ Finish displayed math 1199* ⟩; end;

end; 1199* . At this time p points to the mlist for the formula; a is either null or it points to a box containing the equation number; and we are in vertical mode (or internal vertical mode). ⟨ Finish displayed math 1199* ⟩ ≡

cur mlist ← p; cur style ← display style; mlist penalties ← false; mlist to hlist ; p ← link (temp head ); adjust tail ← adjust head ; b ← hpack (p, natural ); p ← list ptr (b); t ← adjust tail ; adjust tail ← null ; w ← width(b); z ← display width; s ← display indent ; if pre display direction < 0 then s ← −s − z; if (a = null ) ∨ danger then

begin e ← 0; q ← 0;

end else begin e ← width(a); q ← e + math quad (text size);

end; if w + q > z then ⟨ Squeeze the equation as much as possible; if there is an equation number that should

go on a separate line by itself, set e ← 0 1201 ⟩; ⟨ Determine the displacement, d, of the left edge of the equation, with respect to the line size z, assuming

that l = false 1202* ⟩; ⟨ Append the glue or equation number preceding the display 1203* ⟩; ⟨ Append the display and perhaps also the equation number 1204* ⟩; ⟨ Append the glue or equation number following the display 1205* ⟩; ⟨ Flush the prototype box 1476* ⟩; resume after display

This code is used in section 1194*.

1202* . We try first to center the display without regard to the existence of the equation number. If that would make it too close (where “too close” means that the space between display and equation number is less than the width of the equation number), we either center it in the remaining space or move it as far from the equation number as possible. The latter alternative is taken only if the display begins with glue, since we assume that the user put glue there to control the spacing precisely. ⟨ Determine the displacement, d, of the left edge of the equation, with respect to the line size z, assuming

that l = false 1202* ⟩ ≡ subtype(b) ← dlist ; d ← half (z − w); if (e > 0) ∧ (d < 2 ∗ e) then { too close }

begin d ← half (z − w − e); if p ≠ null then

if ¬is char node(p) then

if type(p) = glue node then d ← 0; end

This code is used in section 1199*.

1203* . If the equation number is set on a line by itself, either before or after the formula, we append an infinite penalty so that no page break will separate the display from its number; and we use the same size and displacement for all three potential lines of the display, even though ‘ ’ may specify them differently. ⟨ Append the glue or equation number preceding the display 1203* ⟩ ≡

tail append (new penalty (pre display penalty )); if (d + s ≤ pre display size) ∨ l then { not enough clearance }

begin g1 ← above display skip code; g2 ← below display skip code; end

else begin g1 ← above display short skip code; g2 ← below display short skip code;

end; if l ∧ (e = 0) then { it follows that type(a) = hlist node }

begin app display (j, a, 0); tail append (new penalty (inf penalty )); end

else tail append (new param glue(g1 ))

This code is used in section 1199*.

1204* . ⟨ Append the display and perhaps also the equation number 1204* ⟩ ≡

if e ≠ 0 then begin r ← new kern(z − w − e − d);

if l then

begin link (a) ← r; link (r) ← b; b ← a; d ← 0; end

else begin link (b) ← r; link (r) ← a;

end; b ← hpack (b, natural ); end;

app display (j, b, d)

This code is used in section 1199*.

1205* . ⟨ Append the glue or equation number following the display 1205* ⟩ ≡

if (a ≠ null ) ∧ (e = 0) ∧ ¬l then begin tail append (new penalty (inf penalty )); app display (j, a, z − width(a)); g2 ← 0; end;

if t ≠ adjust head then { migrating material comes after equation number } begin link (tail ) ← link (adjust head ); tail ← t; end;

tail append (new penalty (post display penalty )); if g2 > 0 then tail append (new param glue(g2 ))

This code is used in section 1199*.

1206* . When appears in a display, the alignment routines operate essentially as they do in vertical mode. Then the following program is activated, with p and q pointing to the beginning and end of the resulting list, and with aux save holding the prev depth value. ⟨ Finish an alignment in a display 1206* ⟩ ≡

begin do assignments ; if cur cmd ≠ math shift then ⟨ Pontificate about improper alignment in display 1207 ⟩ else ⟨ Check that another $ follows 1197 ⟩; flush node list (LR box ); pop nest ; tail append (new penalty (pre display penalty )); tail append (new param glue(above display skip code)); link (tail ) ← p; if p ≠ null then tail ← q; tail append (new penalty (post display penalty )); tail append (new param glue(below display skip code)); prev depth ← aux save.sc; resume after display ; end

This code is used in section 812.

§1208 ε-TEX 3.14159 [PD VMS 3.6] changes PART 49: MODE-INDEPENDENT PROCESSING 145

1208* . Mode-independent processing. The long main control procedure has now been fully specified, except for certain activities that are independent of the current mode. These activities do not change the current vlist or hlist or mlist; if they change anything, it is the value of a parameter or the meaning of a control sequence.

Assignments to values in eqtb can be global or local. Furthermore, a control sequence can be defined to be

‘  ’, ‘  ’, or ‘  ’, and it might or might not be expanded. The prefixes ‘  ’, ‘  ’,
‘  ’, and ‘  ’ can occur in any order. Therefore we assign binary numeric codes, making it

possible to accumulate the union of all specified prefixes by adding the corresponding codes. (Pascal’s set operations could also have been used.) ⟨ Put each of TEX’s primitives into the hash table 226 ⟩ +≡

primitive(  , prefix , 1); primitive(  , prefix , 2); primitive(  , prefix , 4);
primitive(  , def , 0); primitive(  , def , 1); primitive(  , def , 2); primitive(  , def , 3);

1209* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ prefix : if chr code = 1 then print esc( )

else if chr code = 2 then print esc( )

⟨ Cases of prefix for print cmd chr 1504* ⟩ else print esc( ); def : if chr code = 0 then print esc( )

else if chr code = 1 then print esc( )

else if chr code = 2 then print esc( )

else print esc( );

1211* . If the user says, e.g., ‘ ’, the redundancy is silently accepted. ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ ⟨ Declare subprocedures for prefixed command 1215 ⟩ procedure prefixed command ;

label done, exit ;

var a: small number ; { accumulated prefix codes so far } f: internal font number ; { identifies a font } j: halfword ; { index into a specification } k: font index ; { index into font info } p, q: pointer ; { for temporary short-term use } n: integer ; { ditto } e: boolean; { should a definition be expanded? or was not done? }

begin a ← 0;

while cur cmd = prefix do begin if ¬odd (a div cur chr ) then a ← a + cur chr ; ⟨ Get the next non-blank non-relax non-call token 404 ⟩; if cur cmd ≤ max non prefixed command then ⟨ Discard erroneous prefixes and return 1212 ⟩; if tracing commands > 2 then

if eTeX ex then show cur cmd chr ; end;

⟨ Discard the prefixes and if they are irrelevant 1213* ⟩;

⟨ Adjust for the setting of 1214 ⟩;

case cur cmd of

⟨ Assignments 1217 ⟩

othercases confusion( )

endcases; done: ⟨ Insert a token saved by , if any 1269 ⟩; exit : end;

146  PART 49: MODE-INDEPENDENT PROCESSING  ε-TEX 3.14159 [PD VMS 3.6] changes §1213
1213* . ⟨ Discard the prefixes  and  if they are irrelevant 1213* ⟩ ≡

if a ≥ 8 then begin j ← protected token; a ← a − 8; end

else j ← 0; if (cur cmd ≠ def ) ∧ ((a mod 4 ≠ 0) ∨ (j ≠ 0)) then

begin print err ( ␣ ´ ␣ ␣` ); print esc( ); print ( ´ ␣ ␣` ); print esc( ); print ( ´ ␣ ␣` ); print cmd chr (cur cmd , cur chr ); print char ( ´ ); help1 ( ´ ␣ ␣ ␣ ´ ␣ ␣ ␣ ␣ ␣ ); error ; end

This code is used in section 1211*.

1218* . When a def command has been scanned, cur chr is odd if the definition is supposed to be global, and cur chr ≥ 2 if the definition is supposed to be expanded. ⟨ Assignments 1217 ⟩ +≡ def : begin if odd (cur chr ) ∧ ¬global ∧ (global defs ≥ 0) then a ← a + 4;

e ← (cur chr ≥ 2); get r token; p ← cur cs ; q ← scan toks (true, e); if j ≠ 0 then

begin q ← get avail ; info(q) ← j; link (q) ← link (def ref ); link (def ref ) ← q;

end; define(p, call + (a mod 4), def ref ); end;

1224* . We temporarily define p to be relax , so that an occurrence of p while scanning the definition will simply stop the scanning instead of producing an “undefined control sequence” error or expanding the previous meaning. This allows, for instance, ‘ ’. ⟨ Assignments 1217 ⟩ +≡ shorthand def : begin n ← cur chr ; get r token; p ← cur cs ; define(p, relax , 256); scan optional equals ;

case n of

char def code: begin scan char num; define(p, char given, cur val );

end; math char def code: begin scan fifteen bit int ; define(p, math given, cur val );

end; othercases begin scan register num;

if cur val > 255 then begin j ← n − count def code; { int val . . box val } if j > mu val then j ← tok val ; { int val . . mu val or tok val } find sa element (j, cur val , true); add sa ref (cur ptr ); if j = tok val then j ← toks register else j ← register ; define(p, j, cur ptr ); end

else case n of

count def code: define(p, assign int , count base + cur val ); dimen def code: define(p, assign dimen, scaled base + cur val ); skip def code: define(p, assign glue, skip base + cur val ); mu skip def code: define(p, assign mu glue, mu skip base + cur val ); toks def code: define(p, assign toks , toks base + cur val ); end; { there are no other cases }

end endcases; end; 1225* . ⟨ Assignments 1217 ⟩ +≡ read to cs : begin j ← cur chr ; scan int ; n ← cur val ;

if ¬scan keyword ( ) then

begin print err (  ␣`   ´ ␣  );
help2 (  ␣      ␣    ␣    ␣` ␣  ␣ ´  )

( ´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ); error ;

end; get r token; p ← cur cs ; read toks (n, p, j); define(p, call , cur val ); end;

1226* . The token-list parameters,  and  , etc., receive their values in the following way.

(For safety’s sake, we place an enclosing pair of braces around an list.) ⟨ Assignments 1217 ⟩ +≡ toks register , assign toks : begin q ← cur cs ; e ← false;

{ just in case, will be set true for sparse array elements } if cur cmd = toks register then

if cur chr = mem bot then begin scan register num; if cur val > 255 then

begin find sa element (tok val , cur val , true); cur chr ← cur ptr ; e ← true; end

else cur chr ← toks base + cur val ;

end else e ← true;

p ← cur chr ; { p = every par loc or output routine loc or … } scan optional equals ; ⟨ Get the next non-blank non-relax non-call token 404 ⟩; if cur cmd ≠ left brace then ⟨ If the right-hand side is a token parameter or token register, finish the

assignment and goto done 1227* ⟩; back input ; cur cs ← q; q ← scan toks (false, false); if link (def ref ) = null then { empty list: revert to the default }

begin sa define(p, null )(p, undefined cs , null ); free avail (def ref ); end

else begin if (p = output routine loc) ∧ ¬e then { enclose in curlies } begin link (q) ← get avail ; q ← link (q); info(q) ← right brace token + ; q ← get avail ; info(q) ← left brace token + ; link (q) ← link (def ref ); link (def ref ) ← q; end;

sa define(p, def ref )(p, call , def ref );

end; end; 1227* . ⟨ If the right-hand side is a token parameter or token register, finish the assignment and goto

done 1227* ⟩ ≡

if (cur cmd = toks register ) ∨ (cur cmd = assign toks ) then

begin if cur cmd = toks register then

if cur chr = mem bot then begin scan register num; if cur val < 256 then q ← equiv (toks base + cur val ) else begin find sa element (tok val , cur val , false);

if cur ptr = null then q ← null else q ← sa ptr (cur ptr ); end; end

else q ← sa ptr (cur ptr ) else q ← equiv (cur chr ); if q = null then sa define(p, null )(p, undefined cs , null ) else begin add token ref (q); sa define(p, q)(p, call , q);

end; goto done; end

This code is used in section 1226*.

1236* . We use the fact that register < advance < multiply < divide. ⟨ Declare subprocedures for prefixed command 1215 ⟩ +≡ procedure do register command (a : small number );

label found , exit ; var l, q, r, s: pointer ; { for list manipulation }

p: int val . . mu val ; { type of register involved } e: boolean; { does l refer to a sparse array element? } w: integer ; { integer or dimen value of l }

begin q ← cur cmd ; e ← false; { just in case, will be set true for sparse array elements } ⟨ Compute the register location l and its type p; but return if invalid 1237* ⟩; if q = register then scan optional equals else if scan keyword ( ) then do nothing ; { optional ‘ ’ } arith error ← false; if q < multiply then ⟨ Compute result of register or advance, put it in cur val 1238* ⟩ else ⟨ Compute result of multiply or divide, put it in cur val 1240* ⟩;

if arith error then
begin print err (  ␣  );

help2 ( ␣   ´ ␣     ␣   ␣    ␣             ␣  ␣  )

(  ␣   ␣      ␣  ␣   ␣  ␣  ); error ; return;

end; if p < glue val then sa word define(l, cur val ) else begin trap zero glue; sa define(l, cur val )(l, glue ref , cur val );

end; exit : end; 1237* . Here we use the fact that the consecutive codes int val …mu val and assign int . . assign mu glue correspond to each other nicely. ⟨ Compute the register location l and its type p; but return if invalid 1237* ⟩ ≡

begin if q ≠ register then begin get x token; if (cur cmd ≥ assign int ) ∧ (cur cmd ≤ assign mu glue) then

begin l ← cur chr ; p ← cur cmd − assign int ; goto found ;

end; if cur cmd ≠ register then

begin print err ( ␣ ´ ␣ ␣` ); print cmd chr (cur cmd , cur chr ); print ( ´ ␣ ␣ ); print cmd chr (q, 0); help1 ( ´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ); error ; return; end;

end; if (cur chr < mem bot ) ∨ (cur chr > lo mem stat max ) then

begin l ← cur chr ; p ← sa type(l); e ← true; end

else begin p ← cur chr − mem bot ; scan register num;

if cur val > 255 then begin find sa element (p, cur val , true); l ← cur ptr ; e ← true; end

else case p of

int val : l ← cur val + count base;

dimen val : l ← cur val + scaled base;

glue val : l ← cur val + skip base;

mu val : l ← cur val + mu skip base;

end; { there are no other cases } end;

end; found : if p < glue val then if e then w ← sa int (l) else w ← eqtb[l].int

else if e then s ← sa ptr (l) else s ← equiv (l)

This code is used in section 1236*.

1238* . ⟨ Compute result of register or advance, put it in cur val 1238* ⟩ ≡

if p < glue val then begin if p = int val then scan int else scan normal dimen; if q = advance then cur val ← cur val + w; end

else begin scan glue(p); if q = advance then ⟨ Compute the sum of two glue specs 1239* ⟩; end

This code is used in section 1236*.

1239* . ⟨ Compute the sum of two glue specs 1239* ⟩ ≡ begin q ← new spec(cur val ); r ← s; delete glue ref (cur val ); width(q) ← width(q) + width(r); if stretch(q) = 0 then stretch order (q) ← normal ; if stretch order (q) = stretch order (r) then stretch(q) ← stretch(q) + stretch(r) else if (stretch order (q) < stretch order (r)) ∧ (stretch(r) ≠ 0) then

begin stretch(q) ← stretch(r); stretch order (q) ← stretch order (r);

end; if shrink (q) = 0 then shrink order (q) ← normal ; if shrink order (q) = shrink order (r) then shrink (q) ← shrink (q) + shrink (r) else if (shrink order (q) < shrink order (r)) ∧ (shrink (r) ≠ 0) then

begin shrink (q) ← shrink (r); shrink order (q) ← shrink order (r);

end; cur val ← q; end

This code is used in section 1238*.

1240* . ⟨ Compute result of multiply or divide, put it in cur val 1240* ⟩ ≡ begin scan int ; if p < glue val then

if q = multiply then if p = int val then cur val ← mult integers (w, cur val ) else cur val ← nx plus y (w, cur val , 0)

else cur val ← x over n(w, cur val ) else begin r ← new spec(s);

if q = multiply then begin width(r) ← nx plus y (width(s), cur val , 0); stretch(r) ← nx plus y (stretch(s), cur val , 0); shrink (r) ← nx plus y (shrink (s), cur val , 0); end

else begin width(r) ← x over n(width(s), cur val ); stretch(r) ← x over n(stretch(s), cur val ); shrink (r) ← x over n(shrink (s), cur val ); end;

cur val ← r;

end; end

This code is used in section 1236*.

1241* . The processing of boxes is somewhat different, because we may need to scan and create an entire box before we actually change the value of the old one. ⟨ Assignments 1217 ⟩ +≡ set box : begin scan register num;

if global then n ← global box flag + cur val else n ← box flag + cur val ; scan optional equals ; if set box allowed then scan box (n)

else begin print err (  ␣ ); print esc(  );

  help2 (  ␣       ␣  ␣   ␣       ␣     ␣       ␣  ␣ ␣  )

( ␣ ␣ ␣ ␣ ␣ ␣ ); error ;

end; end; 1246* . ⟨ Declare subprocedures for prefixed command 1215 ⟩ +≡ procedure alter integer ;

var c: small number ; { 0 for , 1 for , etc. } begin c ← cur chr ; scan optional equals ; scan int ; if c = 0 then dead cycles ← cur val ⟨ Cases for alter integer 1430* ⟩

else insert penalties ← cur val ; end;

1247* . ⟨ Declare subprocedures for prefixed command 1215 ⟩ +≡ procedure alter box dimen;

var c: small number ; { width offset or height offset or depth offset }

b: pointer ; { box register } begin c ← cur chr ; scan register num; fetch box (b); scan optional equals ; scan normal dimen; if b ≠ null then mem[b + c].sc ← cur val ; end;

1248* . Paragraph shapes are set up in the obvious way. ⟨ Assignments 1217 ⟩ +≡ set shape: begin q ← cur chr ; scan optional equals ; scan int ; n ← cur val ;

if n ≤ 0 then p ← null else if q > par shape loc then

begin n ← (cur val div 2) + 1; p ← get node(2 ∗ n + 1); info(p) ← n; n ← cur val ; mem[p + 1].int ← n; { number of penalties } for j ← p + 2 to p + n + 1 do

begin scan int ; mem[j].int ← cur val ; { penalty values }

end; if ¬odd (n) then mem[p + n + 2].int ← 0; { unused } end

else begin p ← get node(2 ∗ n + 1); info(p) ← n;

for j ← 1 to n do begin scan normal dimen; mem[p + 2 ∗ j − 1].sc ← cur val ; { indentation } scan normal dimen; mem[p + 2 ∗ j].sc ← cur val ; { width } end; end;

define(q, shape ref , p); end;

1252* . ⟨ Assignments 1217 ⟩ +≡ hyph data: if cur chr = 1 then

begin Init new patterns ; goto done; Tini

print err ( ␣ ␣ ␣ ␣ ␣ ␣ ); help0 ; error ; repeat get token; until cur cmd = right brace; { flush the patterns } return; end

else begin new hyph exceptions ; goto done; end; 1275* . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure open or close in;

var c: 0 . . 1; { 1 for , 0 for }

n: 0 . . 15; { stream number } begin c ← cur chr ; scan four bit int ; n ← cur val ; if read open[n] ≠ closed then

begin a close(read file[n]); read open[n] ← closed ; end;

if c ≠ 0 then begin scan optional equals ; scan file name; if cur ext = then cur ext ← ; pack cur name; if x open in(read file[n]) then read open[n] ← just open; end;

end;

1292* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ xray : case chr code of

show box code: print esc( ); show the code: print esc( ); show lists : print esc( );

⟨ Cases of xray for print cmd chr 1410* ⟩ othercases print esc( ) endcases; 1293* . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ procedure show whatever ;

label common ending ; var p: pointer ; { tail of a token list to show }

t: small number ; { type of conditional being shown } m: normal . . or code; { upper bound on fi or else codes } l: integer ; { line where that conditional began } n: integer ; { level of nesting }

begin ⟨ Clear out the temp file 1614* ⟩;

case cur chr of

show lists : begin begin diagnostic; show activities ;

end; show box code: ⟨ Show the current contents of a box 1296* ⟩; show code: ⟨ Show the current meaning of a token, then goto common ending 1294 ⟩;

⟨ Cases for show whatever 1411* ⟩ othercases ⟨ Show the current value of some parameter or register, then goto common ending 1297 ⟩ endcases; ⟨ Complete a potentially long command 1298 ⟩;

common ending : if interaction < error stop mode then begin help0 ; decr (error count ); end

else if tracing online > 0 then begin

    help3 (  ␣   ´ ␣  ␣     ␣        ␣ ´ ␣    ␣        ␣  )
    (  ␣`          ´ ␣  ␣    ␣    ␣      ␣  )

(  ␣           ␣  );

end

else begin

    help5 (  ␣   ´ ␣  ␣     ␣        ␣ ´ ␣    ␣        ␣  )
    (  ␣`          ´ ␣  ␣    ␣    ␣      ␣  )
    (  ␣           ␣  )
    (  ␣    ␣`                         ´ ␣  ␣    ␣     ␣  )
    (  ␣  ␣    ␣        ␣  ␣    ␣  ␣  ␣   ␣          ␣  );

end; error ; end;

1295* . ⟨ Cases of print cmd chr for symbolic printing of primitives 227 ⟩ +≡ undefined cs : print ( ); call , long call , outer call , long outer call : begin n ← cmd − call ;

if info(link (chr code)) = protected token then n ← n + 4; if odd (n div 4) then print esc( ); if odd (n) then print esc( ); if odd (n div 2) then print esc( ); if n > 0 then print char ( ␣ ); print ( ); end;

end template: print esc(  ␣  );

1296* . ⟨ Show the current contents of a box 1296* ⟩ ≡ begin scan register num; fetch box (p); begin diagnostic; print nl ( ␣ ); print int (cur val ); print char ( ); if p = null then print ( ) else show box (p); end

This code is used in section 1293*.

§1299 ε-TEX 3.14159 [PD VMS 3.6] changes PART 50: DUMPING AND UNDUMPING THE TABLES 155

1305* . Format files consist of memory word items, and we use the following macros to dump words of different types:

define fmt put ≡ begin incr (fmt count ); if fmt count = VAX block length then

begin put (fmt file, VAX ignore error ); fmt count ← 0; end end

define fmt word ≡ fmt file↑[fmt count ] define dump wd (#) ≡

begin fmt word ← #; fmt put ; end

define dump int (#) ≡

begin fmt word .int ← #; fmt put ; end

define dump hh(#) ≡

begin fmt word .hh ← #; fmt put ; end

define dump qqqq (#) ≡

begin fmt word .qqqq ← #; fmt put ; end

⟨ Global variables 13 ⟩ +≡ fmt file: word file; { for input or output of format information }

1306* . The inverse macros are slightly more complicated, since we need to check the range of the values we are reading in. We say ‘undump(a)(b)(x)’ to read an integer value x that is supposed to be in the range a ≤ x ≤ b.

define fmt get ≡ begin incr (fmt count ); if fmt count = VAX block length then

begin get (fmt file, VAX ignore error ); fmt count ← 0; end end

define undump wd (#) ≡

begin fmt get ; # ← fmt word ; end

define undump int (#) ≡

begin fmt get ; # ← fmt word .int ; end

define undump hh(#) ≡

begin fmt get ; # ← fmt word .hh; end

define undump qqqq (#) ≡

begin fmt get ; # ← fmt word .qqqq ; end

define undump end end (#) ≡ # ← x; end define undump end (#) ≡ (x > #) then goto bad fmt else undump end end define undump(#) ≡

begin undump int (x); if (x < #) ∨ undump end

define undump size end end (#) ≡ too small (#) else undump end end define undump size end (#) ≡

if x > # then undump size end end

156  PART 50: DUMPING AND UNDUMPING THE TABLES  ε-TEX 3.14159 [PD VMS 3.6] changes §1307

define undump size(#) ≡ begin undump int (x); if x < # then goto bad fmt ; undump size end 1307* . The next few sections of the program should make it clear how we use the dump/undump macros. ⟨ Dump constants for consistency check 1307* ⟩ ≡

dump int ( $); ⟨ Dump the ε-TEX state 1388* ⟩ dump int (mem bot ); dump int (mem top); dump int (eqtb size); dump int (hash prime); dump int (hyph size)

This code is used in section 1302.

1308* . Sections of a program that are “commented out” still contribute strings to the string pool; therefore and TEX will have the same strings. (And it is, of course, a good thing that they do.) ⟨ Undump constants for consistency check 1308* ⟩ ≡

x ← fmt word .int ; if x ≠ $ then goto bad fmt ; { check that strings are the same } ⟨ Undump the ε-TEX state 1389* ⟩ undump int (x); if x ≠ mem bot then goto bad fmt ; undump int (x); if x ≠ mem top then goto bad fmt ; undump int (x); if x ≠ eqtb size then goto bad fmt ; undump int (x); if x ≠ hash prime then goto bad fmt ; undump int (x); if x ≠ hyph size then goto bad fmt

This code is used in section 1303.

1311* . By sorting the list of available spaces in the variable-size portion of mem, we are usually able to get by without having to dump very much of the dynamic memory.

We recompute var used and dyn used , so that dumps valid information even when it has not been gathering statistics. ⟨ Dump the dynamic memory 1311* ⟩ ≡

sort avail ; var used ← 0; dump int (lo mem max ); dump int (rover );

if eTeX ex then

for k ← int val to tok val do dump int (sa root [k]); p ← mem bot ; q ← rover ; x ← 0; repeat for k ← p to q + 1 do dump wd (mem[k]);

x ← x + q + 2 − p; var used ← var used + q − p; p ← q + node size(q); q ← rlink (q); until q = rover ; var used ← var used + lo mem max − p; dyn used ← mem end + 1 − hi mem min; for k ← p to lo mem max do dump wd (mem[k]); x ← x + lo mem max + 1 − p; dump int (hi mem min); dump int (avail ); for k ← hi mem min to mem end do dump wd (mem[k]); x ← x + mem end + 1 − hi mem min; p ← avail ; while p ≠ null do

begin decr (dyn used ); p ← link (p);

end; dump int (var used ); dump int (dyn used ); print ln; print int (x); print ( ␣ ␣ ␣ ␣ ␣ ␣ ␣ ); print int (var used ); print char ( ); print int (dyn used )

This code is used in section 1302.

1312* . ⟨ Undump the dynamic memory 1312* ⟩ ≡ undump(lo mem stat max + 1000)(hi mem stat min − 1)(lo mem max ); undump(lo mem stat max + 1)(lo mem max )(rover );

if eTeX ex then

for k ← int val to tok val do undump(null )(lo mem max )(sa root [k]); p ← mem bot ; q ← rover ; repeat for k ← p to q + 1 do undump wd (mem[k]);

p ← q + node size(q);

if (p > lo mem max ) ∨ ((q ≥ rlink (q)) ∧ (rlink (q) ≠ rover )) then goto bad fmt ; q ← rlink (q);

until q = rover ; for k ← p to lo mem max do undump wd (mem[k]); if mem min < mem bot − 2 then { make more low memory available }

begin p ← llink (rover ); q ← mem min + 1; link (mem min) ← null ; info(mem min) ← null ;

{ we don’t use the bottom word } rlink (p) ← q; llink (rover ) ← q; rlink (q) ← rover ; llink (q) ← p; link (q) ← empty flag ; node size(q) ← mem bot − q; end;

undump(lo mem max + 1)(hi mem stat min)(hi mem min); undump(null )(mem top)(avail ); mem end ← mem top; for k ← hi mem min to mem end do undump wd (mem[k]); undump int (var used ); undump int (dyn used )

This code is used in section 1303.

1324* . ⟨ Dump the hyphenation tables 1324* ⟩ ≡ dump int (hyph count ); for k ← 0 to hyph size do

if hyph word [k] ≠ 0 then begin dump int (k); dump int (hyph word [k]); dump int (hyph list [k]); end;

print ln; print int (hyph count ); print ( ␣ ␣ ); if hyph count ≠ 1 then print char ( ); if trie not ready then init trie; dump int (trie max ); dump int (hyph start ); for k ← 0 to trie max do dump hh(trie[k]); dump int (trie op ptr ); for k ← 1 to trie op ptr do

begin dump int (hyf distance[k]); dump int (hyf num[k]); dump int (hyf next [k]); end;

print nl ( ␣ ␣ ␣ ␣ ); print int (trie max ); print ( ␣ ␣ ); print int (trie op ptr ); print ( ␣ ); if trie op ptr ≠ 1 then print char ( ); print ( ␣ ␣ ␣ ); print int (trie op size); for k ← 255 downto 0 do

if trie used [k] > min quarterword then begin print nl ( ␣␣ ); print int (qo(trie used [k])); print ( ␣ ␣ ␣ ); print int (k); dump int (k); dump int (qo(trie used [k])); end

This code is used in section 1302.

1325* . Only “nonempty” parts of op start need to be restored. ⟨ Undump the hyphenation tables 1325* ⟩ ≡

undump(0)(hyph size)(hyph count ); for k ← 1 to hyph count do

begin undump(0)(hyph size)(j); undump(0)(str ptr )(hyph word [j]);

undump(min halfword )(max halfword )(hyph list [j]);

end; undump size(0)(trie size)(´ ␣ ´ )(j); init trie max ← j; tiniundump(0)(j)(hyph start ); for k ← 0 to j do undump hh(trie[k]); undump size(0)(trie op size)(´ ␣ ␣ ´ )(j); init trie op ptr ← j; tini for k ← 1 to j do

begin undump(0)(63)(hyf distance[k]); { a small number }

undump(0)(63)(hyf num[k]); undump(min quarterword )(max quarterword )(hyf next [k]); end;

init for k ← 0 to 255 do trie used [k] ← min quarterword ; tini k ← 256; while j > 0 do

begin undump(0)(k − 1)(k); undump(1)(j)(x); init trie used [k] ← qi (x); tini j ← j − x; op start [k] ← qo(j); end;

init trie not ready ← false tini

This code is used in section 1303.

1329* . ⟨ Close the format file 1329* ⟩ ≡ while fmt count > 0 do dump int (0); { flush out the buffer } w close(fmt file)

This code is used in section 1302.

160  PART 51: THE MAIN PROGRAM  ε-TEX 3.14159 [PD VMS 3.6] changes §1330

1331* . We have noted that there are two versions of TEX82. One, called , has to be run first; it initializes everything from scratch, without reading a format file, and it has the capability of dumping a format file. The other one is called ‘ ’; it is a “virgin” program that needs to input a format file in order to get started. typically has more memory capacity than , because it does not need the space consumed by the auxiliary hyphenation tables and the numerous calls on primitive, etc.

The program cannot read a format file instantaneously, of course; the best implementations therefore allow for production versions of TEX that not only avoid the loading routine for Pascal object code, they also have a format file pre-loaded. This is impossible to do if we stick to standard Pascal; but there is a simple way to fool many systems into avoiding the initialization, as follows: (1) We declare a global integer variable called ready already . The probability is negligible that this variable holds any particular value like 314159 when is first loaded. (2) After we have read in a format file and initialized everything, we set ready already ← 314159. (3) Soon will print ‘ ’, waiting for more input; and at this point we interrupt the program and save its core image in some form that the operating system can reload speedily. (4) When that core image is activated, the program starts again at the beginning; but now ready already = 314159 and all the other global variables have their initial values too. The former chastity has vanished!

In other words, if we allow ourselves to test the condition ready already = 314159, before ready already has been assigned a value, we can avoid the lengthy initialization. Dirty tricks rarely pay off so handsomely.

On systems that allow such preloading, the standard program called should be the one that has format preloaded, since that agrees with The TEXbook. Other versions, e.g., , should also be provided for commonly used formats. ⟨ Global variables 13 ⟩ +≡

init init flag : boolean;

§1332 ε-TEX 3.14159 [PD VMS 3.6] changes PART 51: THE MAIN PROGRAM 161

tini 1332* . Now this is really it: TEX starts and ends here.

The initial test involving ready already should be deleted if the Pascal runtime system is smart enough to detect such a “mistake” and in fact it has been deleted. We also take this opportunity to find out if we’re supposed to be TEX or . (As an interesting note, Knuth simply uses for everything now. The performance difference is too minimal on his machine to make it worth maintaining two copies of TEX.)

Since all files are opened with a disposition ← delete clause, they will be deleted automatically if the program does not complete properly. However, if a fatal error occurs, the jumpout procedure also causes termination of the program without closing the files, therefore we ensure that at least the log file gets closed so that the fatal error can be examined!

begin { start here } history ← fatal error stop; { in case we quit during initialization } t open out ; { open the terminal for output } if ¬odd (init cli (eTeX CLD table, ´ ´ , ´ ´ )) then

begin wterm ln(´ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ´ ); goto final end ; end;

init init flag ← odd (VAX cli present (´ ´ )); tini⟨ Check the “constant” values for consistency 14 ⟩ if bad > 0 then

begin wterm ln(´ ␣ ␣ ␣ ␣ ␣ ´ , ´ ␣´ , bad : 1); goto final end ; end;

initialize; { set global variables to their starting values } eight qual ← odd (VAX cli present (´ ´ )); Init if ¬get strings started then goto final end ; init prim; { call primitive for each primitive } init str ptr ← str ptr ; init pool ptr ← pool ptr ; fix date and time; Tini

start of TEX : ⟨ Extract command-line and qualifiers 1617* ⟩; ⟨ Initialize the output routines 55 ⟩; ⟨ Get the first line of input and prepare to start 1337* ⟩; history ← spotless ; { ready to go! } main control ; { come to life } final cleanup; { prepare for death }

end of TEX : close files and terminate; final end : if log opened then

begin wlog cr ; a close(log file); selector ← selector − 2;

if selector = term only then

begin if log qual then

begin print nl ( ␣ ␣ ␣ ); slow print (log name); print char ( ); end

else print nl ( ␣ ␣ ); end;

end; ⟨ Exit to operating system with final status 1600* ⟩; end.

1333* . Here we do whatever is needed to complete TEX’s job gracefully on the local operating system. The code here might come into play after a fatal error; it must therefore consist entirely of “safe” operations that cannot produce error messages. For example, it would be a mistake to call str room or make string at this time, because a call on overflow might lead to an infinite loop.

Actually there’s one way to get error messages, via prepare mag ; but that can’t cause infinite recursion. This program doesn’t bother to close the input files that may still be open.

⟨ Last-minute procedures 1333* ⟩ ≡ procedure close files and terminate;

var k: integer ; { all-purpose index } begin ⟨ Finish the extensions 1378 ⟩; stat if tracing stats > 0 then ⟨ Output statistics about this job 1334 ⟩; tats wake up terminal ; ⟨ Finish the file 642* ⟩;

if diag qual then

begin wdiag cr ; wdiag ln(´ ␣ ´ ); a close(diag file);

print nl ( ␣ ␣ ␣ ); slow print (diag name); print char ( ); end;

end;

See also sections 1335*, 1336*, 1338, 1601*, 1620*, 1621*, and 1651*. This code is used in section 1330.

1335* . We get to the final cleanup routine when  or  has been scanned and its all over.

⟨ Last-minute procedures 1333* ⟩ +≡ procedure final cleanup;

label exit ; var c: small number ; { 0 for , 1 for } begin c ← cur chr ; if job name = 0 then open log file; while input ptr > 0 do

if state = token list then end token list else end file reading ; while open parens > 0 do

begin print ( ␣ ); decr (open parens ); end;

if cur level > level one then begin print nl ( ); print esc( ␣ ␣ ); print ( ␣ ␣ ␣ ␣ ␣ ); print int (cur level − level one); print char ( ); if eTeX ex then show save groups ; end;

while cond ptr ≠ null do begin print nl ( ); print esc( ␣ ␣ ); print ( ␣ ); print cmd chr (if test , cur if ); if if line ≠ 0 then

begin print ( ␣ ␣ ␣ ); print int (if line);

end; print ( ␣ ␣ ); if line ← if line field (cond ptr ); cur if ← subtype(cond ptr ); temp ptr ← cond ptr ; cond ptr ← link (cond ptr ); free node(temp ptr , if node size); end;

if history ≠ spotless then

if ((history = warning issued ) ∨ (interaction < error stop mode)) then

if selector = term and log then begin selector ← term only ; print nl ( ␣ ␣ ␣ ␣ ␣ ␣ ); selector ← term and log ; end;

if c = 1 then

begin Init for c ← top mark code to split bot mark code do

if cur mark [c] ≠ null then delete token ref (cur mark [c]); if sa mark ≠ null then

if do marks (destroy marks , 0, sa mark ) then sa mark ← null ; for c ← last box code to vsplit code do flush node list (disc ptr [c]); store fmt file; return; Tini print nl ( ␣ ␣ ␣ ␣ ␣ ); return; end;

exit : end;

1336* . ⟨ Last-minute procedures 1333* ⟩ +≡ init procedure init prim; { initialize all the primitives } begin no new control sequence ← false; first ← 0; ⟨ Put each of TEX’s primitives into the hash table 226 ⟩; no new control sequence ← true; end; tini 1337* . When we begin the following code, TEX’s tables may still contain garbage; the strings might not even be present. Thus we must proceed cautiously to get bootstrapped in.

But when we finish this part of the program, TEX is ready to call on the main control routine to do its work. ⟨ Get the first line of input and prepare to start 1337* ⟩ ≡

begin ⟨ Initialize the input routines 331* ⟩; ⟨ Enable ε-TEX, if requested 1379* ⟩ if (format ident = 0) ∨ (buffer [loc] = ) then

begin if format ident ≠ 0 then initialize; { erase preloaded format } if ¬open fmt file then goto final end ; if ¬load fmt file then

begin w close(fmt file); goto final end ; end;

w close(fmt file);

while (loc < limit ) ∧ (buffer [loc] = ␣ ) do incr (loc);

end; if eTeX ex then wterm ln(´ ␣ ␣ ´ ); if end line char inactive then decr (limit ) else buffer [limit ] ← end line char ; fix date and time; ⟨ Compute the magic offset 765 ⟩; ⟨ Initialize the print selector based on interaction 75 ⟩; ⟨ Read the values of and and put them into the string pool 514* ⟩; if (loc < limit ) ∧ (cat code(buffer [loc]) ≠ escape) then start input ; { assumed } end

This code is used in section 1332*.

§1338 ε-TEX 3.14159 [PD VMS 3.6] changes PART 53: EXTENSIONS 165

1348* . ⟨ Declare action procedures for use by main control 1043 ⟩ +≡ ⟨ Declare procedures needed in do extension 1349 ⟩ procedure do extension;

var k: integer ; { all-purpose integers }

p: pointer ; { all-purpose pointers }

begin case cur chr of

open node: ⟨ Implement 1351 ⟩; write node: ⟨ Implement 1352 ⟩; close node: ⟨ Implement 1353 ⟩; special node: ⟨ Implement 1354 ⟩; immediate code: ⟨ Implement 1375 ⟩; set language code: ⟨ Implement 1377 ⟩; othercases confusion( ) endcases; end;

1363* . ⟨ Advance past a whatsit node in the pre-hyphenation loop 1363* ⟩ ≡ if subtype(s) = language node

then begin cur lang ← what lang (s); l hyf ← what lhm(s); r hyf ← what rhm(s); set hyph index ; end

This code is used in section 896*.

166  PART 53a: THE EXTENDED FEATURES OF ε-TEX  ε-TEX 3.14159 [PD VMS 3.6] changes §1379

1379* . The extended features of ε-TEX. The program has two modes of operation: (1) In TEX compatibility mode it fully deserves the name TEX and there are neither extended features nor additional primitive commands. There are, however, a few modifications that would be legitimate in any implementation of TEX such as, e.g., preventing inadequate results of the glue to unit conversion during ship out . (2) In extended mode there are additional primitive commands and the extended features of ε-TEX are available.

The distinction between these two modes of operation initially takes place when a ‘virgin’ starts without reading a format file. Later on the values of all ε-TEX state variables are inherited when (or ) reads a format file.

The code below is designed to work for cases where ‘init … tini’ is a run-time switch. ⟨ Enable ε-TEX, if requested 1379* ⟩ ≡

init if (buffer [loc] = ) ∧ (format ident = ␣ ) then begin no new control sequence ← false; ⟨ Generate all ε-TEX primitives 1380* ⟩ incr (loc); eTeX mode ← 1; { enter extended mode } ⟨ Initialize variables for ε-TEX extended mode 1546* ⟩ end;

tini

if ¬no new control sequence then { just entered extended mode ? }

no new control sequence ← true else

This code is used in section 1337*.

1380* . The ε-TEX features available in extended mode are grouped into two categories: (1) Some of them are permanently enabled and have no semantic effect as long as none of the additional primitives are executed.

(2) The remaining ε-TEX features are optional and can be individually enabled and disabled. For each optional feature there is an ε-TEX state variable named ; the feature is enabled, resp. disabled by assigning a positive, resp. non-positive value to that integer.

define eTeX state base = int base + eTeX state code

define eTeX state(#) ≡ eqtb[eTeX state base + #].int { an ε-TEX state variable }

define eTeX version code = eTeX int { code for }

define eTeX revision code = 6 { command code for } ⟨ Generate all ε-TEX primitives 1380* ⟩ ≡

primitive( , last item, last node type code);

primitive( , last item, eTeX version code);

primitive( , convert , eTeX revision code);

See also sections 1391*, 1397*, 1400*, 1403*, 1406*, 1409*, 1418*, 1420*, 1423*, 1426*, 1431*, 1435*, 1480*, 1492*, 1495*,

1503*, 1511*, 1534*, 1538*, 1542*, 1594*, and 1597*. This code is used in section 1379*.

1381* . ⟨ Cases of last item for print cmd chr 1381* ⟩ ≡ last node type code: print esc( ); eTeX version code: print esc( );

See also sections 1398*, 1401*, 1404*, 1407*, 1512*, 1535*, and 1539*. This code is used in section 417*.

1382* . ⟨ Cases for fetching an integer value 1382* ⟩ ≡ eTeX version code: cur val ← eTeX version;

See also sections 1399*, 1402*, and 1536*. This code is used in section 424*.

1383* . ⟨ Cases of convert for print cmd chr 1383* ⟩ ≡ eTeX revision code: print esc( );

This code is used in section 469*.

§1384 ε-TEX 3.14159 [PD VMS 3.6] changes PART 53a: THE EXTENDED FEATURES OF ε-TEX 167

1384* . ⟨ Cases of ‘Scan the argument for command c’ 1384* ⟩ ≡ eTeX revision code: do nothing ;

This code is used in section 471*.

1385* . ⟨ Cases of ‘Print the result of command c’ 1385* ⟩ ≡ eTeX revision code: print (eTeX revision);

This code is used in section 472*.

1386* . define eTeX ex ≡ (eTeX mode = 1) { is this extended mode? } ⟨ Global variables 13 ⟩ +≡ eTeX mode: 0 . . 1; { identifies compatibility and extended mode }

1387* . ⟨ Initialize table entries (done by only) 164 ⟩ +≡ eTeX mode ← 0; { initially we are in compatibility mode } ⟨ Initialize variables for ε-TEX compatibility mode 1545* ⟩

1388* . ⟨ Dump the ε-TEX state 1388* ⟩ ≡ dump int (eTeX mode); for j ← 0 to eTeX states − 1 do eTeX state(j) ← 0; { disable all enhancements }

See also section 1491*. This code is used in section 1307*.

1389* . ⟨ Undump the ε-TEX state 1389* ⟩ ≡ undump(0)(1)(eTeX mode);

if eTeX ex then

begin ⟨ Initialize variables for ε-TEX extended mode 1546* ⟩

end else begin ⟨ Initialize variables for ε-TEX compatibility mode 1545* ⟩

end;

This code is used in section 1308*.

1390* . The eTeX enabled function simply returns its first argument as result. This argument is true if an optional ε-TEX feature is currently enabled; otherwise, if the argument is false, the function gives an error message. ⟨ Declare ε-TEX procedures for use by main control 1390* ⟩ ≡ function eTeX enabled (b : boolean; j : quarterword ; k : halfword ): boolean;

begin if ¬b then begin print err ( ␣ ); print cmd chr (j, k); help1 ( ␣ ␣ ␣ ␣ ␣ ␣ ␣ ); error ; end;

eTeX enabled ← b;

end;

See also sections 1413* and 1429*. This code is used in section 815*.

1391* . First we implement the additional ε-TEX parameters in the table of equivalents. ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , assign toks , every eof loc);

primitive( , assign int , int base + tracing assigns code); primitive( , assign int , int base + tracing groups code); primitive( , assign int , int base + tracing ifs code); primitive( , assign int , int base + tracing scan tokens code); primitive( , assign int , int base + tracing nesting code); primitive( , assign int , int base + pre display direction code); primitive( , assign int , int base + last line fit code); primitive( , assign int , int base + saving vdiscards code); primitive( , assign int , int base + saving hyph codes code);

1392* . define every eof ≡ equiv (every eof loc) ⟨ Cases of assign toks for print cmd chr 1392* ⟩ ≡ every eof loc: print esc( );

This code is used in section 231*.

1393* . ⟨ Cases for print param 1393* ⟩ ≡ tracing assigns code: print esc( ); tracing groups code: print esc( ); tracing ifs code: print esc( ); tracing scan tokens code: print esc( ); tracing nesting code: print esc( ); pre display direction code: print esc( ); last line fit code: print esc( ); saving vdiscards code: print esc( ); saving hyph codes code: print esc( );

See also section 1434*. This code is used in section 237*.

1394* . In order to handle we need an array eof seen of boolean variables. ⟨ Global variables 13 ⟩ +≡ eof seen: array [1 . . max in open] of boolean; { has eof been seen? } 1395* . The print group procedure prints the current level of grouping and the name corresponding to cur group. ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure print group(e : boolean);

label exit ;

begin case cur group of

bottom level : begin print ( ␣ ); return;

end; simple group, semi simple group: begin if cur group = semi simple group then print ( ␣ );

print ( );

end; hbox group, adjusted hbox group: begin if cur group = adjusted hbox group then print ( ␣ );

print ( );

end; vbox group: print ( ); vtop group: print ( ); align group, no align group: begin if cur group = no align group then print ( ␣ );

print ( );

end; output group: print ( ); disc group: print ( ); insert group: print ( ); vcenter group: print ( ); math group, math choice group, math shift group, math left group: begin print ( );

if cur group = math choice group then print ( ␣ )

else if cur group = math shift group then print ( ␣ )

else if cur group = math left group then print ( ␣ ); end;

end; { there are no other cases } print ( ␣ ␣ ␣ ); print int (qo(cur level )); print char ( ); if saved (−1) ≠ 0 then

begin if e then print ( ␣ ␣ ␣ ␣ )

else print ( ␣ ␣ ␣ );

print int (saved (−1));

end; exit : end;

1396* . The group trace procedure is called when a new level of grouping begins (e = false) or ends (e = true) with saved (−1) containing the line number. ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡

stat procedure group trace(e : boolean); begin begin diagnostic; print char ( ); if e then print ( ␣ ) else print ( ␣ ); print group(e); print char ( ); end diagnostic(false); end; tats

1397* . The  and  commands return the current level of grouping

and the type of the current group respectively.

define current group level code = eTeX int + 1 { code for } define current group type code = eTeX int + 2 { code for }

⟨ Generate all ε-TEX primitives 1380* ⟩ +≡ primitive( , last item, current group level code); primitive( , last item, current group type code);

1398* . ⟨ Cases of last item for print cmd chr 1381* ⟩ +≡ current group level code: print esc( ); current group type code: print esc( );

1399* . ⟨ Cases for fetching an integer value 1382* ⟩ +≡ current group level code: cur val ← cur level − level one; current group type code: cur val ← cur group;

1400* . The  ,  , and  commands return the current

level of conditionals and the type and branch of the current conditional.

define current if level code = eTeX int + 3 { code for } define current if type code = eTeX int + 4 { code for } define current if branch code = eTeX int + 5 { code for }

⟨ Generate all ε-TEX primitives 1380* ⟩ +≡ primitive( , last item, current if level code); primitive( , last item, current if type code); primitive( , last item, current if branch code);

1401* . ⟨ Cases of last item for print cmd chr 1381* ⟩ +≡ current if level code: print esc( ); current if type code: print esc( ); current if branch code: print esc( );

1402* . ⟨ Cases for fetching an integer value 1382* ⟩ +≡ current if level code: begin q ← cond ptr ; cur val ← 0;

while q ≠ null do begin incr (cur val ); q ← link (q); end;

end; current if type code: if cond ptr = null then cur val ← 0

else if cur if < unless code then cur val ← cur if + 1

else cur val ← −(cur if − unless code + 1); current if branch code: if (if limit = or code) ∨ (if limit = else code) then cur val ← 1

else if if limit = fi code then cur val ← −1 else cur val ← 0;

1403* . The  ,  ,  , and  commands return information

about a character in a font.

define font char wd code = eTeX dim { code for } define font char ht code = eTeX dim + 1 { code for } define font char dp code = eTeX dim + 2 { code for } define font char ic code = eTeX dim + 3 { code for }

⟨ Generate all ε-TEX primitives 1380* ⟩ +≡ primitive( , last item, font char wd code); primitive( , last item, font char ht code); primitive( , last item, font char dp code); primitive( , last item, font char ic code);

1404* . ⟨ Cases of last item for print cmd chr 1381* ⟩ +≡ font char wd code: print esc( ); font char ht code: print esc( ); font char dp code: print esc( ); font char ic code: print esc( );

1405* . ⟨ Cases for fetching a dimension value 1405* ⟩ ≡ font char wd code, font char ht code, font char dp code, font char ic code: begin scan font ident ;

q ← cur val ; scan char num; if (font bc[q] ≤ cur val ) ∧ (font ec[q] ≥ cur val ) then

begin i ← char info(q)(qi (cur val ));

case m of

font char wd code: cur val ← char width(q)(i);

font char ht code: cur val ← char height (q)(height depth(i)); font char dp code: cur val ← char depth(q)(height depth(i)); font char ic code: cur val ← char italic(q)(i); end; { there are no other cases } end

else cur val ← 0; end;

See also sections 1408* and 1537*. This code is used in section 424*.

1406* . The  ,  , and  commands return the indent and

length parameters of the current specification.

define par shape length code = eTeX dim + 4 { code for } define par shape indent code = eTeX dim + 5 { code for } define par shape dimen code = eTeX dim + 6 { code for }

⟨ Generate all ε-TEX primitives 1380* ⟩ +≡ primitive( , last item, par shape length code); primitive( , last item, par shape indent code); primitive( , last item, par shape dimen code);

1407* . ⟨ Cases of last item for print cmd chr 1381* ⟩ +≡ par shape length code: print esc( ); par shape indent code: print esc( ); par shape dimen code: print esc( ); 1408* . ⟨ Cases for fetching a dimension value 1405* ⟩ +≡ par shape length code, par shape indent code, par shape dimen code: begin

q ← cur chr − par shape length code; scan int ; if (par shape ptr = null ) ∨ (cur val ≤ 0) then cur val ← 0 else begin if q = 2 then

begin q ← cur val mod 2; cur val ← (cur val + q) div 2; end;

if cur val > info(par shape ptr ) then cur val ← info(par shape ptr ); cur val ← mem[par shape ptr + 2 ∗ cur val − q].sc; end;

cur val level ← dimen val ;

end;

1409* . The command displays all currently active grouping levels.

define show groups = 4 { } ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , xray , show groups );

1410* . ⟨ Cases of xray for print cmd chr 1410* ⟩ ≡ show groups : print esc( );

See also sections 1419* and 1424*. This code is used in section 1292*.

1411* . ⟨ Cases for show whatever 1411* ⟩ ≡ show groups : begin begin diagnostic; show save groups ;

end;

See also section 1425*. This code is used in section 1293*.

1412* . ⟨ Types in the outer block 18 ⟩ +≡ save pointer = 0 . . save size; { index into save stack } 1413* . The modifications of TEX required for the display produced by the show save groups procedure were first discussed by Donald E. Knuth in TUGboat 11, 165–170 and 499–511, 1990.

In order to understand a group type we also have to know its mode. Since unrestricted horizontal modes are not associated with grouping, they are skipped when traversing the semantic nest.

⟨ Declare ε-TEX procedures for use by main control 1390* ⟩ +≡ procedure show save groups ;

label found1 , found2 , found , done; var p: 0 . . nest size; { index into nest }

m: −mmode . . mmode; { mode } v: save pointer ; { saved value of save ptr } l: quarterword ; { saved value of cur level } c: group code; { saved value of cur group } a: −1 . . 1; { to keep track of alignments } i: integer ; j: quarterword ; s: str number ;

begin p ← nest ptr ; nest [p] ← cur list ; { put the top level into the array } v ← save ptr ; l ← cur level ; c ← cur group; save ptr ← cur boundary ; decr (cur level ); a ← 1; print nl ( ); print ln; loop begin print nl ( ###␣ ); print group(true);

if cur group = bottom level then goto done; repeat m ← nest [p].mode field ;

if p > 0 then decr (p)

else m ← vmode; until m ≠ hmode; print ( ␣ );

case cur group of

simple group: begin incr (p); goto found2 ;

end; hbox group, adjusted hbox group: s ← ; vbox group: s ← ; vtop group: s ← ; align group: if a = 0 then

begin if m = −vmode then s ← else s ← ; a ← 1; goto found1 ; end

else begin if a = 1 then print ( ␣ ) else print esc( ); if p ≥ a then p ← p − a; a ← 0; goto found ; end;

no align group: begin incr (p); a ← −1; print esc( ); goto found2 ;

end; output group: begin print esc( ); goto found ;

end; math group: goto found2 ; disc group, math choice group: begin if cur group = disc group then print esc( )

else print esc( );

for i ← 1 to 3 do

if i ≤ saved (−2) then print ( ); goto found2 ; end;

insert group: begin if saved (−2) = 255 then print esc( ) else begin print esc( ); print int (saved (−2));

end; goto found2 ; end;

vcenter group: begin s ← ; goto found1 ;

end; semi simple group: begin incr (p); print esc( ); goto found ;

end; math shift group: begin if m = mmode then print char ( $ )

else if nest [p].mode field = mmode then begin print cmd chr (eq no, saved (−2)); goto found ; end;

print char ( $ ); goto found ;

end; math left group: begin if type(nest [p + 1].eTeX aux field ) = left noad then print esc( )

else print esc( );

goto found ;

end; end; { there are no other cases } ⟨ Show the box context 1415* ⟩;

found1 : print esc(s); ⟨ Show the box packaging info 1414* ⟩; found2 : print char ( ); found : print char ( ); decr (cur level ); cur group ← save level (save ptr );

save ptr ← save index (save ptr ) end;

done: save ptr ← v; cur level ← l; cur group ← c; end;

1414* . ⟨ Show the box packaging info 1414* ⟩ ≡

if saved (−2) ≠ 0 then begin print char ( ␣ ); if saved (−3) = exactly then print ( ) else print ( ); print scaled (saved (−2)); print ( ); end

This code is used in section 1413*.

1415* . ⟨ Show the box context 1415* ⟩ ≡ i ← saved (−4); if i ≠ 0 then

if i < box flag then begin if abs (nest [p].mode field ) = vmode then j ← hmove else j ← vmove; if i > 0 then print cmd chr (j, 0) else print cmd chr (j, 1); print scaled (abs (i)); print ( ); end

else if i < ship out flag then

begin if i ≥ global box flag then begin print esc( ); i ← i − (global box flag − box flag ); end;

print esc( ); print int (i − box flag ); print char ( ); end

else print cmd chr (leader ship, i − (leader flag − a leaders ))

This code is used in section 1413*.

1416* . The scan general text procedure is much like scan toks (false, false), but will be invoked via expand , i.e., recursively. ⟨ Declare ε-TEX procedures for scanning 1416* ⟩ ≡ procedure scan general text ; forward ;

See also sections 1444*, 1445*, 1505*, 1514*, and 1519*. This code is used in section 409*.

1417* . The token list (balanced text) created by scan general text begins at link (temp head ) and ends at cur val . (If cur val = temp head , the list is empty.) ⟨ Declare ε-TEX procedures for token lists 1417* ⟩ ≡ procedure scan general text ;

label found ;

var s: normal . . absorbing ; { to save scanner status } w: pointer ; { to save warning index } d: pointer ; { to save def ref } p: pointer ; { tail of the token list being built } q: pointer ; { new node being added to the token list via store new token } unbalance: halfword ; { number of unmatched left braces }

begin s ← scanner status ; w ← warning index ; d ← def ref ; scanner status ← absorbing ; warning index ← cur cs ; def ref ← get avail ; token ref count (def ref ) ← null ; p ← def ref ; scan left brace; { remove the compulsory left brace } unbalance ← 1; loop begin get token;

if cur tok < right brace limit then if cur cmd < right brace then incr (unbalance) else begin decr (unbalance);

if unbalance = 0 then goto found ; end;

store new token(cur tok );

end; found : q ← link (def ref ); free avail (def ref ); { discard reference count }

if q = null then cur val ← temp head else cur val ← p;

link (temp head ) ← q; scanner status ← s; warning index ← w; def ref ← d;

end;

See also section 1486*. This code is used in section 464*.

1418* . The command displays a token list.

define show tokens = 5 { , must be odd! } ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , xray , show tokens );

1419* . ⟨ Cases of xray for print cmd chr 1410* ⟩ +≡ show tokens : print esc( );

1420* . The  primitive prevents expansion of tokens much as the result from  applied to

a token variable. The primitive converts a token list into a list of character tokens much as if the token list were written to a file. We use the fact that the command modifiers for and are odd whereas those for and are even. ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , the, 1);

primitive( , the, show tokens );

1421* . ⟨ Cases of the for print cmd chr 1421* ⟩ ≡ else if chr code = 1 then print esc( )

else print esc( )

This code is used in section 266*.

1422* . ⟨ Handle  or  and return 1422* ⟩ ≡

if odd (cur chr ) then begin c ← cur chr ; scan general text ; if c = 1 then the toks ← cur val else begin old setting ← selector ; selector ← new string ; b ← pool ptr ; p ← get avail ; link (p) ← link (temp head ); token show (p); flush list (p); selector ← old setting ; the toks ← str toks (b); end; return; end

This code is used in section 465*.

1423* . The command displays all currently active conditionals.

define show ifs = 6 { } ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , xray , show ifs );

1424* . ⟨ Cases of xray for print cmd chr 1410* ⟩ +≡ show ifs : print esc( );

1425* .

define print if line(#) ≡

if # ≠ 0 then begin print ( ␣ ␣ ␣ ␣ ); print int (#); end

⟨ Cases for show whatever 1411* ⟩ +≡ show ifs : begin begin diagnostic; print nl ( ); print ln;

if cond ptr = null then begin print nl ( ###␣ ); print ( ␣ ␣ ); end

else begin p ← cond ptr ; n ← 0; repeat incr (n); p ← link (p); until p = null ; p ← cond ptr ; t ← cur if ; l ← if line; m ← if limit ; repeat print nl ( ###␣ ␣ ); print int (n); print ( ␣ ); print cmd chr (if test , t);

if m = fi code then print esc( );

print if line(l); decr (n); t ← subtype(p); l ← if line field (p); m ← type(p); p ← link (p); until p = null ; end;

end;

1426* . The primitive allows to query and set the interaction mode. ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , set page int , 2);

1427* . ⟨ Cases of set page int for print cmd chr 1427* ⟩ ≡ else if chr code = 2 then print esc( )

This code is used in section 417*.

1428* . ⟨ Cases for ‘Fetch the dead cycles or the insert penalties ’ 1428* ⟩ ≡ else if m = 2 then cur val ← interaction

This code is used in section 419*.

1429* . ⟨ Declare ε-TEX procedures for use by main control 1390* ⟩ +≡ procedure new interaction; forward ;

1430* . ⟨ Cases for alter integer 1430* ⟩ ≡ else if c = 2 then

begin if (cur val < batch mode) ∨ (cur val > error stop mode) then

begin print err (  ␣          ␣  );
help2 (  ␣   ␣        ␣          ␣         ␣  )
(  ␣        ␣   ␣ ´ ␣      ␣    ␣  ); int error (cur val );

end else begin cur chr ← cur val ; new interaction;

end; end

This code is used in section 1246*.

1431* . The middle feature of ε-TEX allows one ore several delimiters to appear between and . ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , left right , middle noad );

1432* . ⟨ Cases of left right for print cmd chr 1432* ⟩ ≡ else if chr code = middle noad then print esc( )

This code is used in section 1189*.

1433* . In constructions such as

the stretch components of  and  compensate; in standard TEX they may get modified in order

to prevent arithmetic overflow during ship out when each of them is multiplied by a large glue set value.

In ε-TEX the conversion from stretch or shrink components of glue to units is performed by the do glue function defined below.

In extended mode the do glue function adds up the relevant stretch (or shrink) components of consecutive glue nodes and converts the glue nodes into equivalent kern nodes; during this process glue specifications may be recycled. The accumulated stretch or shrink is then multiplied by glue set (this box ) and returned as result. Since one and the same box may be used several times inside leaders the result is also added to the width of the first or only kern node; the subtype of the glue node(s) remains unchanged. The consecutive glue nodes may be separated by insert, mark, adjust, kern, and penalty nodes.

define add glue(#) ≡ # ← # + do glue(this box , p)

define add stretch shrink ≡ { accumulate stretch or shrink amount }

if g sign = stretching then begin if stretch order (g) = g order then s ← s + stretch(g); end

else begin if shrink order (g) = g order then s ← s − shrink (g);

end

⟨ Declare procedures needed in hlist out , vlist out 1368 ⟩ +≡ function do glue(this box , p : pointer ): scaled ;

label continue, next p, done;

var q: pointer ; { list traverser } g order : glue ord ; { applicable order of infinity for glue } g sign: normal . . shrinking ; { selects type of glue } s: scaled ; { accumulated stretch or shrink } glue temp: real ; { glue value before rounding }

begin g order ← glue order (this box ); g sign ← glue sign(this box ); s ← 0; add stretch shrink ; if ¬eTeX ex ∨ (subtype(p) ≥ a leaders ) then goto done; q ← p;

continue: type(q) ← kern node; width(q) ← width(g); fast delete glue ref (g); next p: q ← link (q);

if (q ≠ null ) ∧ ¬is char node(q) then case type(q) of ins node, mark node, adjust node, kern node, penalty node: goto next p; glue node: if subtype(q) < a leaders then

begin g ← glue ptr (q); add stretch shrink ; goto continue; end;

othercases do nothing

endcases; done: if s ≠ 0 then

begin vet glue(float (glue set (this box )) ∗ s); s ← round (glue temp); if type(p) = kern node then width(p) ← width(p) + s; end;

do glue ← s;

end; 1434* . The optional TeXXeT feature of ε-TEX contains the code for mixed left-to-right and right-to-left typesetting. This code is inspired by but different from TEX-��� as presented by Donald E. Knuth and Pierre MacKay in TUGboat 8, 14–25, 1987.

In order to avoid confusion with TEX-��� the present implementation of mixed direction typesetting is called TEX-����. It differs from TEX-��� in several important aspects: (1) Right-to-left text is reversed explicitely by the ship out routine and is written to a normal file without any begin reflect or end reflect commands; (2) a math node is (ab)used instead of a whatsit node to record the , , , and text direction primitives in order to keep the influence on the line breaking algorithm for pure leftto-right text as small as possible; (3) right-to-left text interrupted by a displayed equation is automatically resumed after that equation; and (4) the valign command code with a non-zero command modifier is (ab)used for the text direction primitives.

Nevertheless there is a subtle difference between TEX and TEX-���� that may influence the line breaking algorithm for pure left-to-right text. When a paragraph containing math mode material is broken into lines TEX may generate lines where math mode material is not enclosed by properly nested and nodes. Unboxing such lines as part of a new paragraph may have the effect that hyphenation is attempted for ‘words’ originating from math mode or that hyphenation is inhibited for words originating from horizontal mode.

In TEX-���� additional  , resp.  math nodes are supplied at the start, resp. end of lines such
that math mode material inside a horizontal list always starts with either  or  and ends with
or  . These additional nodes are transparent to operations such as  ,  ,

or but they do have the effect that hyphenation is never attempted for ‘words’ originating from math mode and is never inhibited for words originating from horizontal mode.

define TeXXeT state ≡ eTeX state(TeXXeT code)

define TeXXeT en ≡ (TeXXeT state > 0) { is TEX-���� enabled? } ⟨ Cases for print param 1393* ⟩ +≡ eTeX state code + TeXXeT code: print esc( );

1435* . ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡ primitive( , assign int , eTeX state base + TeXXeT code);

primitive(  , valign, begin L code); primitive(  , valign, end L code);
primitive(  , valign, begin R code); primitive(  , valign, end R code);

1436* . ⟨ Cases of valign for print cmd chr 1436* ⟩ ≡

else case chr code of

begin L code: print esc( );

end L code: print esc( );

begin R code: print esc( );

othercases print esc( )

endcases

This code is used in section 266*.

1437* . ⟨ Cases of main control for hmode + valign 1437* ⟩ ≡

if cur chr > 0 then begin if eTeX enabled (TeXXeT en, cur cmd , cur chr ) then tail append (new math(0, cur chr )); end

else

This code is used in section 1130*.

1438* . An hbox with subtype dlist will never be reversed, even when embedded in right-to-left text. ⟨ Display if this box is never to be reversed 1438* ⟩ ≡

if (type(p) = hlist node) ∧ (subtype(p) = dlist ) then print ( ␣ )

This code is used in section 184*.

1439* . A number of routines are based on a stack of one-word nodes whose info fields contain end M code, end L code, or end R code. The top of the stack is pointed to by LR ptr .

When the stack manipulation macros of this section are used below, variable LR ptr might be the global variable declared here for hpack and ship out , or might be local to post line break .

define put LR(#) ≡ begin temp ptr ← get avail ; info(temp ptr ) ← #; link (temp ptr ) ← LR ptr ; LR ptr ← temp ptr ; end

define push LR(#) ≡ put LR(end LR type(#))

define pop LR ≡ begin temp ptr ← LR ptr ; LR ptr ← link (temp ptr ); free avail (temp ptr ); end

⟨ Global variables 13 ⟩ +≡ LR temp: pointer ; { holds a temporarily removed node } LR ptr : pointer ; { stack of LR codes for hpack , ship out , and init math } LR problems : integer ; { counts missing begins and ends } cur dir : small number ; { current text direction }

1440* . ⟨ Set initial values of key variables 21 ⟩ +≡ LR temp ← null ; LR ptr ← null ; LR problems ← 0; cur dir ← left to right ;

1441* . ⟨ Insert LR nodes at the beginning of the current line and adjust the LR stack based on LR nodes

in this line 1441* ⟩ ≡ begin q ← link (temp head ); if LR ptr ≠ null then

begin temp ptr ← LR ptr ; r ← q;

repeat s ← new math(0, begin LR type(info(temp ptr ))); link (s) ← r; r ← s;

temp ptr ← link (temp ptr ); until temp ptr = null ; link (temp head ) ← r; end;

while q ≠ cur break (cur p) do

begin if ¬is char node(q) then

if type(q) = math node then ⟨ Adjust the LR stack for the post line break routine 1442* ⟩; q ← link (q); end;

end

This code is used in section 880*.

1442* . ⟨ Adjust the LR stack for the post line break routine 1442* ⟩ ≡

if end LR(q) then

begin if LR ptr ≠ null then

if info(LR ptr ) = end LR type(q) then pop LR; end

else push LR(q)

This code is used in sections 879*, 881*, and 1441*.

1443* . We use the fact that q now points to the node with glue. ⟨ Insert LR nodes at the end of the current line 1443* ⟩ ≡

if LR ptr ≠ null then begin s ← temp head ; r ← link (s); while r ≠ q do

begin s ← r; r ← link (s);

end; r ← LR ptr ; while r ≠ null do

begin temp ptr ← new math(0, info(r)); link (s) ← temp ptr ; s ← temp ptr ; r ← link (r); end; link (s) ← q; end

This code is used in section 880*.

1444* . Special  and  nodes are inserted in cases where math nodes are discarded during

line breaking or end up in different lines. When the current lists ends with an node that node is temporarily removed and later reinserted when the last node is to be inspected or removed. A final preceded by a char node will not be removed. ⟨ Declare ε-TEX procedures for scanning 1416* ⟩ +≡ procedure remove end M ;

var p: pointer ; { runs through the current list } begin p ← head ; while link (p) ≠ tail do p ← link (p); if ¬is char node(p) then

begin LR temp ← tail ; link (p) ← null ; tail ← p;

end; end;

1445* . ⟨ Declare ε-TEX procedures for scanning 1416* ⟩ +≡ procedure insert end M ;

label done;

var p: pointer ; { runs through the current list } begin if ¬is char node(tail ) then

if (type(tail ) = math node) ∧ (subtype(tail ) = begin M code) then begin free node(LR temp, small node size); p ← head ; while link (p) ≠ tail do p ← link (p); free node(tail , small node size); link (p) ← null ; tail ← p; goto done; end;

link (tail ) ← LR temp; tail ← LR temp; done: LR temp ← null ;

end;

1446* . ⟨ Initialize the LR stack 1446* ⟩ ≡

put LR(before) { this will never match }

This code is used in sections 619*, 649*, and 1467*.

1447* . ⟨ Adjust the LR stack for the hpack routine 1447* ⟩ ≡

if end LR(p) then if info(LR ptr ) = end LR type(p) then pop LR else begin incr (LR problems ); type(p) ← kern node; subtype(p) ← explicit ;

end else push LR(p)

This code is used in section 651*.

1448* . ⟨ Check for LR anomalies at the end of hpack 1448* ⟩ ≡

begin if info(LR ptr ) ≠ before then begin while link (q) ≠ null do q ← link (q); repeat temp ptr ← q; q ← new math(0, info(LR ptr )); link (temp ptr ) ← q;

LR problems ← LR problems + 10000; pop LR; until info(LR ptr ) = before; end;

if LR problems > 0 then begin ⟨ Report LR problems 1449* ⟩; goto common ending ; end;

pop LR; if LR ptr ≠ null then confusion( ); end

This code is used in section 649*.

1449* . ⟨ Report LR problems 1449* ⟩ ≡ begin print ln; print nl ( ␣ ␣ ␣ ␣ ); print int (LR problems div 10000); print ( ␣ ␣ ); print int (LR problems mod 10000); print ( ␣ ); LR problems ← 0; end

This code is used in sections 1448* and 1463*.

1450* . Breaking a paragraph into lines while TEX-���� is disabled may result in lines whith unpaired math nodes. Such hlists are silently accepted in the absence of text direction directives.

define LR dir (#) ≡ (subtype(#) div R code) { text direction of a ‘math node’ } ⟨ Adjust the LR stack for the hlist out routine; if necessary reverse an hlist segment and goto

reswitch 1450* ⟩ ≡

begin if end LR(p) then if info(LR ptr ) = end LR type(p) then pop LR else begin if subtype(p) > L code then incr (LR problems );

end else begin push LR(p);

if LR dir (p) ≠ cur dir then ⟨ Reverse an hlist segment and goto reswitch 1455* ⟩; end;

type(p) ← kern node; end

This code is used in section 622*.

1451* . ⟨ Check for LR anomalies at the end of hlist out 1451* ⟩ ≡

begin while info(LR ptr ) ≠ before do begin if info(LR ptr ) > L code then LR problems ← LR problems + 10000; pop LR; end;

pop LR; end

This code is used in section 619*.

1452* . define edge node = style node { a style node does not occur in hlists } define edge node size = style node size { number of words in an edge node } define edge dist (#) ≡ depth(#)

{ new left edge position relative to cur h (after width has been taken into account) }

⟨ Declare procedures needed in hlist out , vlist out 1368 ⟩ +≡ function new edge(s : small number ; w : scaled ): pointer ; { create an edge node }

var p: pointer ; { the new node } begin p ← get node(edge node size); type(p) ← edge node; subtype(p) ← s; width(p) ← w; edge dist (p) ← 0; { the edge dist field will be set later } new edge ← p; end;

1453* . ⟨ Cases of hlist out that arise in mixed direction text only 1453* ⟩ ≡ edge node: begin cur h ← cur h + width(p); left edge ← cur h + edge dist (p); cur dir ← subtype(p);

end;

This code is used in section 622*.

1454* . We detach the hlist, start a new one consisting of just one kern node, append the reversed list, and set the width of the kern node. ⟨ Reverse the complete hlist and set the subtype to reversed 1454* ⟩ ≡

begin save h ← cur h; temp ptr ← p; p ← new kern(0); link (prev p) ← p; cur h ← 0; link (p) ← reverse(this box , null ); width(p) ← −cur h; cur h ← save h; subtype(this box ) ← reversed ; end

This code is used in section 619*.

1455* . We detach the remainder of the hlist, replace the math node by an edge node, and append the reversed hlist segment to it; the tail of the reversed segment is another edge node and the remainder of the original list is attached to it. ⟨ Reverse an hlist segment and goto reswitch 1455* ⟩ ≡

begin save h ← cur h; temp ptr ← link (p); rule wd ← width(p); free node(p, small node size); cur dir ← reflected ; p ← new edge(cur dir , rule wd ); link (prev p) ← p; cur h ← cur h − left edge + rule wd ; link (p) ← reverse(this box , new edge(reflected , 0)); edge dist (p) ← cur h; cur dir ← reflected ; cur h ← save h; goto reswitch; end

This code is used in section 1450*.

1456* . The reverse function defined here is responsible to reverse the nodes of an hlist (segment). The first parameter this box is the enclosing hlist node, the second parameter t is to become the tail of the reversed list, and the global variable temp ptr is the head of the list to be reversed. We remove nodes from the original list and add them to the head of the new one. ⟨ Declare procedures needed in hlist out , vlist out 1368 ⟩ +≡ function reverse(this box , t : pointer ): pointer ;

label reswitch, next p, done; var l: pointer ; { the new list }

p: pointer ; { the current node }

q: pointer ; { the next node }

g sign: normal . . shrinking ; { selects type of glue }

m, n: halfword ; { count of unmatched math nodes } begin g sign ← glue sign(this box ); l ← t; p ← temp ptr ; m ← min halfword ; n ← min halfword ; loop begin while p ≠ null do ⟨ Move node p to the new list and go to the next node; or goto done if

the end of the reflected segment has been reached 1457* ⟩; if (t = null ) ∧ (m = min halfword ) ∧ (n = min halfword ) then goto done; p ← new math(0, info(LR ptr )); LR problems ← LR problems + 10000;

{ manufacture one missing math node } end;

done: reverse ← l; end;

1457* . ⟨ Move node p to the new list and go to the next node; or goto done if the end of the reflected

segment has been reached 1457* ⟩ ≡ reswitch: if is char node(p) then

repeat f ← font (p); c ← character (p); cur h ← cur h + char width(f)(char info(f)(c)); q ← link (p);

link (p) ← l; l ← p; p ← q; until ¬is char node(p)

else ⟨ Move the non-char node p to the new list 1458* ⟩

This code is used in section 1456*.

1458* . ⟨ Move the non-char node p to the new list 1458* ⟩ ≡ begin q ← link (p); case type(p) of hlist node, vlist node, rule node, kern node: rule wd ← width(p); ⟨ Cases of reverse that need special treatment 1459* ⟩ edge node: confusion( );

othercases goto next p

endcases; cur h ← cur h + rule wd ;

next p: link (p) ← l;

if type(p) = kern node then

if (rule wd = 0) ∨ (l = null ) then begin free node(p, small node size); p ← l; end;

l ← p; p ← q; end

This code is used in section 1457*.

1459* . Here we have to remember that add glue may have converted the glue node into a kern node. If this is not the case we try to covert the glue node into a rule node. ⟨ Cases of reverse that need special treatment 1459* ⟩ ≡ glue node: begin g ← glue ptr (p); rule wd ← width(g);

if g sign ≠ normal then add glue(rule wd );

if subtype(p) ≥ a leaders then begin temp ptr ← leader ptr (p); if type(temp ptr ) = rule node then

begin delete glue ref (g); free node(p, small node size); p ← temp ptr ; width(p) ← rule wd ; end; end;

end;

See also sections 1460* and 1461*. This code is used in section 1458*.

1460* . A ligature node is replaced by a char node. ⟨ Cases of reverse that need special treatment 1459* ⟩ +≡ ligature node: begin flush node list (lig ptr (p)); temp ptr ← p; p ← get avail ;

mem[p] ← mem[lig char (temp ptr )]; link (p) ← q; free node(temp ptr , small node size); goto reswitch; end;

1461* . Math nodes in an inner reflected segment are modified, those at the outer level are changed into kern nodes. ⟨ Cases of reverse that need special treatment 1459* ⟩ +≡ math node: begin rule wd ← width(p);

if end LR(p) then

if info(LR ptr ) ≠ end LR type(p) then begin type(p) ← kern node; incr (LR problems ); end

else begin pop LR;

if n > min halfword then begin decr (n); decr (subtype(p)); { change after into before } end

else begin type(p) ← kern node; if m > min halfword then decr (m) else ⟨ Finish the reversed hlist segment and goto done 1462* ⟩; end; end

else begin push LR(p);

if (n > min halfword ) ∨ (LR dir (p) ≠ cur dir ) then begin incr (n); incr (subtype(p)); { change before into after } end

else begin type(p) ← kern node; incr (m);

end; end;

end; 1462* . Finally we have found the end of the hlist segment to be reversed; the final math node is released and the remaining list attached to the edge node terminating the reversed segment. ⟨ Finish the reversed hlist segment and goto done 1462* ⟩ ≡

begin free node(p, small node size); link (t) ← q; width(t) ← rule wd ; edge dist (t) ← −cur h − rule wd ; goto done; end

This code is used in section 1461*.

1463* . ⟨ Check for LR anomalies at the end of ship out 1463* ⟩ ≡

begin if LR problems > 0 then begin ⟨ Report LR problems 1449* ⟩; print char ( ); print ln; end;

if (LR ptr ≠ null ) ∨ (cur dir ≠ left to right ) then confusion( ); end

This code is used in section 638*.

1464* . Some special actions are required for displayed equation in paragraphs with mixed direction texts. First of all we have to set the text direction preceding the display. ⟨ Set the value of x to the text direction before the display 1464* ⟩ ≡

if LR save = null then x ← 0 else if info(LR save) ≥ R code then x ← −1 else x ← 1

This code is used in sections 1465* and 1467*.

1465* . ⟨ Prepare for display after an empty paragraph 1465* ⟩ ≡ begin pop nest ; ⟨ Set the value of x to the text direction before the display 1464* ⟩; end

This code is used in section 1145*.

1466* . When calculating the natural width, w, of the final line preceding the display, we may have to copy all or part of its hlist. We copy, however, only those parts of the original list that are relevant for the computation of pre display size. ⟨ Declare subprocedures for init math 1466* ⟩ ≡ procedure just copy (p, h, t : pointer );

label found , not found ; var r: pointer ; { current node being fabricated for new list }

words : 0 . . 5; { number of words remaining to be copied } begin while p ≠ null do

begin words ← 1; { this setting occurs in more branches than any other } if is char node(p) then r ← get avail else case type(p) of

hlist node, vlist node: begin r ← get node(box node size); mem[r + 6] ← mem[p + 6]; mem[r + 5] ← mem[p + 5]; { copy the last two words } words ← 5; list ptr (r) ← null ; { this affects mem[r + 5] } end;

rule node: begin r ← get node(rule node size); words ← rule node size;

end; ligature node: begin r ← get avail ; { only font and character are needed }

mem[r] ← mem[lig char (p)]; goto found ;

end; kern node, math node: begin r ← get node(small node size); words ← small node size;

end; glue node: begin r ← get node(small node size); add glue ref (glue ptr (p));

glue ptr (r) ← glue ptr (p); leader ptr (r) ← null ;

end; whatsit node: ⟨ Make a partial copy of the whatsit node p and make r point to it; set words to the

number of initial words not yet copied 1357 ⟩;

othercases goto not found

endcases; while words > 0 do

begin decr (words ); mem[r + words ] ← mem[p + words ]; end;

found : link (h) ← r; h ← r; not found : p ← link (p);

end; link (h) ← t; end;

See also section 1471*. This code is used in section 1138*.

1467* . When the final line ends with R-text, the value w refers to the line reflected with respect to the left edge of the enclosing vertical list. ⟨ Prepare for display after a non-empty paragraph 1467* ⟩ ≡

if eTeX ex then ⟨ Let j be the prototype box for the display 1473* ⟩; v ← shift amount (just box ); ⟨ Set the value of x to the text direction before the display 1464* ⟩; if x ≥ 0 then

begin p ← list ptr (just box ); link (temp head ) ← null ;

end else begin v ← −v − width(just box ); p ← new math(0, begin L code); link (temp head ) ← p;

just copy (list ptr (just box ), p, new math(0, end L code)); cur dir ← right to left ; end;

v ← v + 2 ∗ quad (cur font ); if TeXXeT en then ⟨ Initialize the LR stack 1446* ⟩

This code is used in section 1146*.

1468* . ⟨ Finish the natural width computation 1468* ⟩ ≡

if TeXXeT en then

begin while LR ptr ≠ null do pop LR;

if LR problems ≠ 0 then begin w ← max dimen; LR problems ← 0; end;

end; cur dir ← left to right ; flush node list (link (temp head ))

This code is used in section 1146*.

1469* . In the presence of text direction directives we assume that any LR problems have been fixed by the hpack routine. If the final line contains, however, text direction directives while TEX-���� is disabled, then we set w ← max dimen. ⟨ Cases of ‘Let d be the natural width’ that need special treatment 1469* ⟩ ≡ math node: begin d ← width(p);

if TeXXeT en then ⟨ Adjust the LR stack for the init math routine 1470* ⟩ else if subtype(p) ≥ L code then

begin w ← max dimen; goto done;

end; end;

edge node: begin d ← width(p); cur dir ← subtype(p);

end;

This code is used in section 1147*.

1470* . ⟨ Adjust the LR stack for the init math routine 1470* ⟩ ≡

if end LR(p) then begin if info(LR ptr ) = end LR type(p) then pop LR else if subtype(p) > L code then

begin w ← max dimen; goto done; end

end else begin push LR(p);

if LR dir (p) ≠ cur dir then begin just reverse(p); p ← temp head ; end;

end

This code is used in section 1469*.

1471* . ⟨ Declare subprocedures for init math 1466* ⟩ +≡ procedure just reverse(p : pointer );

label found , done; var l: pointer ; { the new list }

t: pointer ; { tail of reversed segment } q: pointer ; { the next node } m, n: halfword ; { count of unmatched math nodes }

begin m ← min halfword ; n ← min halfword ; if link (temp head ) = null then

begin just copy (link (p), temp head , null ); q ← link (temp head ); end

else begin q ← link (p); link (p) ← null ; flush node list (link (temp head ));

end; t ← new edge(cur dir , 0); l ← t; cur dir ← reflected ; while q ≠ null do

if is char node(q) then repeat p ← q; q ← link (p); link (p) ← l; l ← p; until ¬is char node(q)

else begin p ← q; q ← link (p); if type(p) = math node then ⟨ Adjust the LR stack for the just reverse routine 1472* ⟩; link (p) ← l; l ← p; end;

goto done; found : width(t) ← width(p); link (t) ← q; free node(p, small node size); done: link (temp head ) ← l;

end; 1472* . ⟨ Adjust the LR stack for the just reverse routine 1472* ⟩ ≡

if end LR(p) then

if info(LR ptr ) ≠ end LR type(p) then begin type(p) ← kern node; incr (LR problems ); end

else begin pop LR;

if n > min halfword then begin decr (n); decr (subtype(p)); { change after into before } end

else begin if m > min halfword then decr (m) else goto found ; type(p) ← kern node; end; end

else begin push LR(p);

if (n > min halfword ) ∨ (LR dir (p) ≠ cur dir ) then begin incr (n); incr (subtype(p)); { change before into after } end

else begin type(p) ← kern node; incr (m);

end; end

This code is used in section 1471*.

1473* . The prototype box is an hlist node with the width, glue set, and shift amount of just box , i.e., the last line preceding the display. Its hlist reflects the current and . ⟨ Let j be the prototype box for the display 1473* ⟩ ≡

begin if right skip = zero glue then j ← new kern(0) else j ← new param glue(right skip code); if left skip = zero glue then p ← new kern(0) else p ← new param glue(left skip code); link (p) ← j; j ← new null box ; width(j) ← width(just box ); shift amount (j) ← shift amount (just box ); list ptr (j) ← p; glue order (j) ← glue order (just box ); glue sign(j) ← glue sign(just box ); glue set (j) ← glue set (just box ); end

This code is used in section 1467*.

1474* . At the end of a displayed equation we retrieve the prototype box. ⟨ Local variables for finishing a displayed formula 1198 ⟩ +≡ j: pointer ; { prototype box }

1475* . ⟨ Retrieve the prototype box 1475* ⟩ ≡

if mode = mmode then j ← LR box

This code is used in section 1194*.

1476* . ⟨ Flush the prototype box 1476* ⟩ ≡

flush node list (j)

This code is used in section 1199*.

1477* . The app display procedure used to append the displayed equation and/or equation number to the current vertical list has three parameters: the prototype box, the hbox to be appended, and the displacement of the hbox in the display line. ⟨ Declare subprocedures for after math 1477* ⟩ ≡ procedure app display (j, b : pointer ; d : scaled );

var z: scaled ; { width of the line } s: scaled ; { move the line right this much } e: scaled ; { distance from right edge of box to end of line } x: integer ; { pre display direction } p, q, r, t, u: pointer ; { for list manipulation }

begin s ← display indent ; x ← pre display direction; if x = 0 then shift amount (b) ← s + d else begin z ← display width; p ← b; ⟨ Set up the hlist for the display line 1478* ⟩;

⟨ Package the display line 1479* ⟩; end;

append to vlist (b); end;

This code is used in section 1194*.

1478* . Here we construct the hlist for the display, starting with node p and ending with node q. We also set d and e to the amount of kerning to be added before and after the hlist (adjusted for the prototype box). ⟨ Set up the hlist for the display line 1478* ⟩ ≡

if x > 0 then e ← z − d − width(p) else begin e ← d; d ← z − e − width(p);

end; if j ≠ null then

begin b ← copy node list (j); height (b) ← height (p); depth(b) ← depth(p); s ← s − shift amount (b); d ← d + s; e ← e + width(b) − z − s; end;

if subtype(p) = dlist then q ← p { display or equation number } else begin { display and equation number }

r ← list ptr (p); free node(p, box node size); if r = null then confusion( ); if x > 0 then

begin p ← r;

repeat q ← r; r ← link (r); { find tail of list }

until r = null ;

end else begin p ← null ; q ← r;

repeat t ← link (r); link (r) ← p; p ← r; r ← t; { reverse list } until r = null ; end;

end

This code is used in section 1477*.

1479* . In the presence of a prototype box we use its shift amount and width to adjust the values of kerning and add these values to the glue nodes inserted to cancel the and . If there is no prototype box (because the display is preceded by an empty paragraph), or if the skip parameters are zero, we just add kerns.

The cancel glue macro creates and links a glue node that is, together with another glue node, equivalent to a given amount of kerning. We can use j as temporary pointer, since all we need is j ≠ null .

define cancel glue(#) ≡ j ← new skip param(#); cancel glue cont define cancel glue cont (#) ≡ link (#) ← j; cancel glue cont cont define cancel glue cont cont (#) ≡ link (j) ← #; cancel glue end define cancel glue end (#) ≡ j ← glue ptr (#); cancel glue end end define cancel glue end end (#) ≡ stretch order (temp ptr ) ← stretch order (j);

shrink order (temp ptr ) ← shrink order (j); width(temp ptr ) ← # − width(j); stretch(temp ptr ) ← −stretch(j); shrink (temp ptr ) ← −shrink (j)

⟨ Package the display line 1479* ⟩ ≡

if j = null then begin r ← new kern(0); t ← new kern(0); { the widths will be set later } end

else begin r ← list ptr (b); t ← link (r);

end; u ← new math(0, end M code); if type(t) = glue node then { t is glue }

begin cancel glue(right skip code)(q)(u)(t)(e); link (u) ← t;

end else begin width(t) ← e; link (t) ← u; link (q) ← t;

end; u ← new math(0, begin M code); if type(r) = glue node then { r is glue }

begin cancel glue(left skip code)(u)(p)(r)(d); link (r) ← u;

end else begin width(r) ← d; link (r) ← p; link (u) ← r;

if j = null then begin b ← hpack (u, natural ); shift amount (b) ← s; end

else list ptr (b) ← u;

end

This code is used in section 1477*.

1480* . The scan tokens feature of ε-TEX defines the primitive. ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , input , 2);

1481* . ⟨ Cases of input for print cmd chr 1481* ⟩ ≡ else if chr code = 2 then print esc( )

This code is used in section 377*.

1482* . ⟨ Cases for input 1482* ⟩ ≡ else if cur chr = 2 then pseudo start

This code is used in section 378*.

1483* . The global variable pseudo files is used to maintain a stack of pseudo files. The info field of each pseudo file points to a linked list of variable size nodes representing lines not yet processed: the info field of the first word contains the size of this node, all the following words contain ASCII codes. ⟨ Global variables 13 ⟩ +≡ pseudo files : pointer ; { stack of pseudo files }

1484* . ⟨ Set initial values of key variables 21 ⟩ +≡ pseudo files ← null ;

1485* . The pseudo start procedure initiates reading from a pseudo file. ⟨ Declare ε-TEX procedures for expanding 1485* ⟩ ≡ procedure pseudo start ; forward ;

See also sections 1543*, 1548*, and 1552*. This code is used in section 366*.

1486* . ⟨ Declare ε-TEX procedures for token lists 1417* ⟩ +≡ procedure pseudo start ;

var old setting : 0 . . max selector ; { holds selector setting } s: str number ; { string to be converted into a pseudo file } l, m: pool pointer ; { indices into str pool } p, q, r: pointer ; { for list construction } w: four quarters ; { four ASCII codes } nl , sz : integer ;

begin scan general text ; old setting ← selector ; selector ← new string ; token show (temp head ); selector ← old setting ; flush list (link (temp head )); str room(1); s ← make string ; ⟨ Convert string s into a new pseudo file 1487* ⟩; flush string ; ⟨ Initiate input from new pseudo file 1488* ⟩; end; 1487* . ⟨ Convert string s into a new pseudo file 1487* ⟩ ≡

str pool [pool ptr ] ← si ( ␣ ); l ← str start [s]; nl ← si (new line char ); p ← get avail ; q ← p; while l < pool ptr do

begin m ← l; while (l < pool ptr ) ∧ (str pool [l] ≠ nl ) do incr (l); sz ← (l − m + 7) div 4; if sz = 1 then sz ← 2; r ← get node(sz ); link (q) ← r; q ← r; info(q) ← hi (sz ); while sz > 2 do

begin decr (sz ); incr (r); w.b0 ← qi (so(str pool [m])); w.b1 ← qi (so(str pool [m + 1])); w.b2 ← qi (so(str pool [m + 2])); w.b3 ← qi (so(str pool [m + 3])); mem[r].qqqq ← w; m ← m + 4; end;

w.b0 ← qi ( ␣ ); w.b1 ← qi ( ␣ ); w.b2 ← qi ( ␣ ); w.b3 ← qi ( ␣ ); if l > m then

begin w.b0 ← qi (so(str pool [m]));

if l > m + 1 then begin w.b1 ← qi (so(str pool [m + 1])); if l > m + 2 then

begin w.b2 ← qi (so(str pool [m + 2]));

if l > m + 3 then w.b3 ← qi (so(str pool [m + 3])); end; end;

end; mem[r + 1].qqqq ← w; if str pool [l] = nl then incr (l); end;

info(p) ← link (p); link (p) ← pseudo files ; pseudo files ← p

This code is used in section 1486*.

1488* . ⟨ Initiate input from new pseudo file 1488* ⟩ ≡ begin file reading ; { set up cur file and new level of input } line ← 0; limit ← start ; loc ← limit + 1; { force line read } if tracing scan tokens > 0 then

begin if term offset > max print line − 3 then print ln else if (term offset > 0) ∨ (file offset > 0) then print char ( ␣ ); name ← 19; print ( ␣ ); incr (open parens ); update terminal ; end

else name ← 18

This code is used in section 1486*.

1489* . Here we read a line from the current pseudo file into buffer . ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ function pseudo input : boolean; { inputs the next line or returns false }

var p: pointer ; { current line from pseudo file } sz : integer ; { size of node p } w: four quarters ; { four ASCII codes } r: pointer ; { loop index }

begin last ← first ; { cf. Matthew 19 : 30 } p ← info(pseudo files ); if p = null then pseudo input ← false else begin info(pseudo files ) ← link (p); sz ← ho(info(p));

if 4 ∗ sz − 3 ≥ buf size − last then ⟨ Report overflow of the input buffer, and abort 35 ⟩; last ← first ; for r ← p + 1 to p + sz − 1 do

begin w ← mem[r].qqqq ; buffer [last ] ← w.b0 ; buffer [last + 1] ← w.b1 ; buffer [last + 2] ← w.b2 ; buffer [last + 3] ← w.b3 ; last ← last + 4; end;

if last ≥ max buf stack then max buf stack ← last + 1;

while (last > first ) ∧ (buffer [last − 1] = ␣ ) do decr (last );

free node(p, sz ); pseudo input ← true;

end; end;

1490* . When we are done with a pseudo file we ‘close’ it. ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure pseudo close; { close the top level pseudo file }

var p, q: pointer ; begin p ← link (pseudo files ); q ← info(pseudo files ); free avail (pseudo files ); pseudo files ← p; while q ≠ null do

begin p ← q; q ← link (p); free node(p, ho(info(p)));

end; end;

1491* . ⟨ Dump the ε-TEX state 1388* ⟩ +≡ while pseudo files ≠ null do pseudo close; { flush pseudo files }

1492* . ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡ primitive( , read to cs , 1);

1493* . ⟨ Cases of read for print cmd chr 1493* ⟩ ≡ else print esc( )

This code is used in section 266*.

1494* . ⟨ Handle and goto done 1494* ⟩ ≡

if j = 1 then

begin while loc ≤ limit do { current line not yet finished } begin cur chr ← buffer [loc]; incr (loc); if cur chr = ␣ then cur tok ← space token else cur tok ← cur chr + other token; store new token(cur tok ); end;

goto done;

end

This code is used in section 483*.

1495* . Here we define the additional conditionals of ε-TEX as well as the prefix.

define if def code = 17 { ‘ ’ } define if cs code = 18 { ‘ ’ } define if font char code = 19 { ‘ ’ }

⟨ Generate all ε-TEX primitives 1380* ⟩ +≡ primitive( , expand after , 1); primitive( , if test , if def code); primitive( , if test , if cs code); primitive( , if test , if font char code);

1496* . ⟨ Cases of expandafter for print cmd chr 1496* ⟩ ≡ else print esc( )

This code is used in section 266*.

1497* . ⟨ Cases of if test for print cmd chr 1497* ⟩ ≡ if def code: print esc( ); if cs code: print esc( ); if font char code: print esc( );

This code is used in section 488*.

1498* . The result of a boolean condition is reversed when the conditional is preceded by . ⟨ Negate a boolean conditional and goto reswitch 1498* ⟩ ≡

begin get token; if (cur cmd = if test ) ∧ (cur chr ≠ if case code) then

begin cur chr ← cur chr + unless code; goto reswitch; end;

print err ( ␣ ´ ␣ ␣` ); print esc( ); print ( ´ ␣ ␣` ); print cmd chr (cur cmd , cur chr ); print char ( ´ ); help1 ( ␣ ␣ ´ ␣ ␣ ␣ ␣ ␣ ); back error ; end

This code is used in section 367*.

1499* . The conditional tests if a control sequence is defined.

We need to reset scanner status , since control sequences are allowed, but we might be scanning a macro definition or preamble. ⟨ Cases for conditional 1499* ⟩ ≡ if def code: begin save scanner status ← scanner status ; scanner status ← normal ; get next ;

b ← (cur cmd ≠ undefined cs ); scanner status ← save scanner status ; end;

See also sections 1500* and 1502*. This code is used in section 501*.

1500* . The conditional  is equivalent to  ,

except that no new control sequence will be entered into the hash table (once all tokens preceding the mandatory have been expanded). ⟨ Cases for conditional 1499* ⟩ +≡ if cs code: begin n ← get avail ; p ← n; { head of the list of characters }

repeat get x token;

if cur cs = 0 then store new token(cur tok ); until cur cs ≠ 0; if cur cmd ≠ end cs name then ⟨ Complain about missing 373 ⟩; ⟨ Look up the characters of list n in the hash table, and set cur cs 1501* ⟩; flush list (n); b ← (eq type(cur cs ) ≠ undefined cs ); end;

1501* . ⟨ Look up the characters of list n in the hash table, and set cur cs 1501* ⟩ ≡ m ← first ; p ← link (n); while p ≠ null do

begin if m ≥ max buf stack then begin max buf stack ← m + 1; if max buf stack = buf size then overflow ( ␣ , buf size); end;

buffer [m] ← info(p) mod ´ 400 ; incr (m); p ← link (p);

end; if m > first + 1 then cur cs ← id lookup(first , m − first ) { no new control sequence is true } else if m = first then cur cs ← null cs { the list is empty }

else cur cs ← single base + buffer [first ] { the list has length one }

This code is used in section 1500*.

1502* . The conditional tests the existence of a character in a font. ⟨ Cases for conditional 1499* ⟩ +≡ if font char code: begin scan font ident ; n ← cur val ; scan char num;

if (font bc[n] ≤ cur val ) ∧ (font ec[n] ≥ cur val ) then b ← char exists (char info(n)(qi (cur val )))

else b ← false;

end;

1503* . The protected feature of ε-TEX defines the prefix command for macro definitions. Such macros are protected against expansions when lists of expanded tokens are built, e.g., for or during . ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , prefix , 8);

1504* . ⟨ Cases of prefix for print cmd chr 1504* ⟩ ≡ else if chr code = 8 then print esc( )

This code is used in section 1209*.

1505* . The get x or protected procedure is like get x token except that protected macros are not expanded. ⟨ Declare ε-TEX procedures for scanning 1416* ⟩ +≡ procedure get x or protected ; { sets cur cmd , cur chr , cur tok , and expands non-protected macros }

label exit ;

begin loop begin get token; if cur cmd ≤ max command then return; if (cur cmd ≥ call ) ∧ (cur cmd < end template) then if info(link (cur chr )) = protected token then return;

expand ; end;

exit : end;

1506* . A group entered (or a conditional started) in one file may end in a different file. Such slight anomalies, although perfectly legitimate, may cause errors that are difficult to locate. In order to be able to give a warning message when such anomalies occur, ε-TEX uses the grp stack and if stack arrays to record the initial cur boundary and cond ptr values for each input file. ⟨ Global variables 13 ⟩ +≡ grp stack : array [0 . . max in open] of save pointer ; { initial cur boundary } if stack : array [0 . . max in open] of pointer ; { initial cond ptr }

1507* . When a group ends that was apparently entered in a different input file, the group warning procedure is invoked in order to update the grp stack . If moreover is positive we want to give a warning message. The situation is, however, somewhat complicated by two facts: (1) There may be grp stack elements without a corresponding file or pseudo file (e.g., error insertions from the terminal); and (2) the relevant information is recorded in the name field of the input stack only loosely synchronized with the in open variable indexing grp stack . ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure group warning ;

var i: 0 . . max in open; { index into grp stack }

w: boolean; { do we need a warning? } begin base ptr ← input ptr ; input stack [base ptr ] ← cur input ; { store current state } i ← in open; w ← false; while (grp stack [i] = cur boundary ) ∧ (i > 0) do

begin ⟨ Set variable w to indicate if this case should be reported 1508* ⟩;

grp stack [i] ← save index (save ptr ); decr (i);

end;

if w then

begin print nl ( ␣ ␣ ␣ ); print group(true); print ( ␣ ␣ ␣ ␣ ); print ln; if tracing nesting > 1 then show context ; if history = spotless then history ← warning issued ; end;

end;

1508* . This code scans the input stack in order to determine the type of the current input file. ⟨ Set variable w to indicate if this case should be reported 1508* ⟩ ≡

if tracing nesting > 0 then

begin while (input stack [base ptr ].state field = token list ) ∨ (input stack [base ptr ].index field > i) do

decr (base ptr ); if input stack [base ptr ].name field > 17 then w ← true; end

This code is used in sections 1507* and 1509*.

1509* . When a conditional ends that was apparently started in a different input file, the if warning procedure is invoked in order to update the if stack . If moreover is positive we want to give a warning message (with the same complications as above). ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure if warning ;

var i: 0 . . max in open; { index into if stack }

w: boolean; { do we need a warning? } begin base ptr ← input ptr ; input stack [base ptr ] ← cur input ; { store current state } i ← in open; w ← false; while if stack [i] = cond ptr do

begin ⟨ Set variable w to indicate if this case should be reported 1508* ⟩; if stack [i] ← link (cond ptr ); decr (i); end;

if w then

begin print nl ( ␣ ␣ ␣ ); print cmd chr (if test , cur if ); print if line(if line); print ( ␣ ␣ ␣ ␣ ); print ln; if tracing nesting > 1 then show context ; if history = spotless then history ← warning issued ; end;

end;

1510* . Conversely, the file warning procedure is invoked when a file ends and some groups entered or conditionals started while reading from that file are still incomplete. ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure file warning ;

var p: pointer ; { saved value of save ptr or cond ptr } l: quarterword ; { saved value of cur level or if limit } c: quarterword ; { saved value of cur group or cur if } i: integer ; { saved value of if line }

begin p ← save ptr ; l ← cur level ; c ← cur group; save ptr ← cur boundary ; while grp stack [in open] ≠ save ptr do

begin decr (cur level ); print nl ( ␣ ␣ ␣ ␣ ␣ ); print group(true); print ( ␣ ␣ ); cur group ← save level (save ptr ); save ptr ← save index (save ptr ) end;

save ptr ← p; cur level ← l; cur group ← c; { restore old values } p ← cond ptr ; l ← if limit ; c ← cur if ; i ← if line; while if stack [in open] ≠ cond ptr do

begin print nl ( ␣ ␣ ␣ ␣ ␣ ); print cmd chr (if test , cur if ); if if limit = fi code then print esc( ); print if line(if line); print ( ␣ ␣ ); if line ← if line field (cond ptr ); cur if ← subtype(cond ptr ); if limit ← type(cond ptr ); cond ptr ← link (cond ptr ); end;

cond ptr ← p; if limit ← l; cur if ← c; if line ← i; { restore old values } print ln; if tracing nesting > 1 then show context ; if history = spotless then history ← warning issued ; end; 1511* . Here are the additional ε-TEX primitives for expressions. ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , last item, eTeX expr − int val + int val ); primitive( , last item, eTeX expr − int val + dimen val ); primitive( , last item, eTeX expr − int val + glue val ); primitive( , last item, eTeX expr − int val + mu val );

1512* . ⟨ Cases of last item for print cmd chr 1381* ⟩ +≡ eTeX expr − int val + int val : print esc( ); eTeX expr − int val + dimen val : print esc( ); eTeX expr − int val + glue val : print esc( ); eTeX expr − int val + mu val : print esc( );

1513* . This code for reducing cur val level and/or negating the result is similar to the one for all the other cases of scan something internal , with the difference that scan expr has already increased the reference count of a glue specification. ⟨ Process an expression and return 1513* ⟩ ≡

begin if m < eTeX mu then

begin case m of

⟨ Cases for fetching a glue value 1540* ⟩ end; { there are no other cases } cur val level ← glue val ; end

else if m < eTeX expr then

begin case m of

⟨ Cases for fetching a mu value 1541* ⟩ end; { there are no other cases } cur val level ← mu val ; end

else begin cur val level ← m − eTeX expr + int val ; scan expr ;

end; while cur val level > level do

begin if cur val level = glue val then begin m ← cur val ; cur val ← width(m); delete glue ref (m); end

else if cur val level = mu val then mu error ;

decr (cur val level );

end;

if negative then

if cur val level ≥ glue val then begin m ← cur val ; cur val ← new spec(m); delete glue ref (m); ⟨ Negate all three glue components of cur val 431 ⟩; end

else negate(cur val ); return; end

This code is used in section 424*.

1514* . ⟨ Declare ε-TEX procedures for scanning 1416* ⟩ +≡ procedure scan expr ; forward ; 1515* . The scan expr procedure scans and evaluates an expression. ⟨ Declare procedures needed for expressions 1515* ⟩ ≡ ⟨ Declare subprocedures for scan expr 1526* ⟩ procedure scan expr ; { scans and evaluates an expression }

label restart , continue, found ; var a, b: boolean; { saved values of arith error }

l: small number ; { type of expression } r: small number ; { state of expression so far } s: small number ; { state of term so far } o: small number ; { next operation or type of next factor } e: integer ; { expression so far } t: integer ; { term so far } f: integer ; { current factor } n: integer ; { numerator of combined multiplication and division } p: pointer ; { top of expression stack } q: pointer ; { for stack manipulations }

begin l ← cur val level ; a ← arith error ; b ← false; p ← null ; ⟨ Scan and evaluate an expression e of type l 1516* ⟩;

if b then
begin print err (  ␣  ); help2 ( ␣   ´ ␣        ␣    ␣  )
(  ␣   ␣      ␣  ␣   ␣  ␣  ); error ;

if l ≥ glue val then begin delete glue ref (e); e ← zero glue; add glue ref (e); end

else e ← 0; end;

arith error ← a; cur val ← e; cur val level ← l; end;

See also section 1520*. This code is used in section 461*.

1516* . Evaluating an expression is a recursive process: When the left parenthesis of a subexpression is scanned we descend to the next level of recursion; the previous level is resumed with the matching right parenthesis.

define expr none = 0 { seen, or ⟨expr⟩ seen } define expr add = 1 { ⟨expr⟩ seen } define expr sub = 2 { ⟨expr⟩ seen } define expr mult = 3 { ⟨term⟩ seen } define expr div = 4 { ⟨term⟩ seen } define expr scale = 5 { ⟨term⟩ ⟨factor⟩ seen }

⟨ Scan and evaluate an expression e of type l 1516* ⟩ ≡ restart : r ← expr none; e ← 0; s ← expr none; t ← 0; n ← 0; continue: if s = expr none then o ← l else o ← int val ;

⟨ Scan a factor f of type o or start a subexpression 1518* ⟩; found : ⟨ Scan the next operator and set o 1517* ⟩;

arith error ← b; ⟨ Make sure that f is in the proper range 1523* ⟩;

case s of

⟨ Cases for evaluation of the current term 1524* ⟩ end; { there are no other cases } if o > expr sub then s ← o else ⟨ Evaluate the current expression 1525* ⟩; b ← arith error ; if o ≠ expr none then goto continue; if p ≠ null then ⟨ Pop the expression stack and goto found 1522* ⟩

This code is used in section 1515*.

1517* . ⟨ Scan the next operator and set o 1517* ⟩ ≡ ⟨ Get the next non-blank non-call token 406 ⟩; if cur tok = other token + then o ← expr add else if cur tok = other token + then o ← expr sub

else if cur tok = other token + then o ← expr mult

else if cur tok = other token + then o ← expr div

else begin o ← expr none;

if p = null then begin if cur cmd ≠ relax then back input ; end

else if cur tok ≠ other token + then

begin print err (  ␣ ␣        ␣   ␣  );

           help1 ( ␣   ␣         ␣  ␣   ␣`  ´ ␣`  ´ ␣`  ´ ␣`  ´ ␣  ␣`  ´ ␣  ´  ); back error ;

end; end

This code is used in section 1516*.

1518* . ⟨ Scan a factor f of type o or start a subexpression 1518* ⟩ ≡ ⟨ Get the next non-blank non-call token 406 ⟩; if cur tok = other token + then ⟨ Push the expression stack and goto restart 1521* ⟩; back input ; if o = int val then scan int else if o = dimen val then scan normal dimen

else if o = glue val then scan normal glue

else scan mu glue; f ← cur val

This code is used in section 1516*.

1519* . ⟨ Declare ε-TEX procedures for scanning 1416* ⟩ +≡ procedure scan normal glue; forward ; procedure scan mu glue; forward ;

1520* . Here we declare to trivial procedures in order to avoid mutually recursive procedures with parameters. ⟨ Declare procedures needed for expressions 1515* ⟩ +≡ procedure scan normal glue;

begin scan glue(glue val );

end; procedure scan mu glue;

begin scan glue(mu val );

end;

1521* . Parenthesized subexpressions can be inside expressions, and this nesting has a stack. Seven local variables represent the top of the expression stack: p points to pushed-down entries, if any; l specifies the type of expression currently beeing evaluated; e is the expression so far and r is the state of its evaluation; t is the term so far and s is the state of its evaluation; finally n is the numerator for a combined multiplication and division, if any.

define expr node size = 4 { number of words in stack entry for subexpressions }

define expr e field (#) ≡ mem[# + 1].int { saved expression so far }

define expr t field (#) ≡ mem[# + 2].int { saved term so far }

define expr n field (#) ≡ mem[# + 3].int { saved numerator } ⟨ Push the expression stack and goto restart 1521* ⟩ ≡

begin q ← get node(expr node size); link (q) ← p; type(q) ← l; subtype(q) ← 4 ∗ s + r;

expr e field (q) ← e; expr t field (q) ← t; expr n field (q) ← n; p ← q; l ← o; goto restart ; end

This code is used in section 1518*.

1522* . ⟨ Pop the expression stack and goto found 1522* ⟩ ≡ begin f ← e; q ← p; e ← expr e field (q); t ← expr t field (q); n ← expr n field (q); s ← subtype(q) div 4; r ← subtype(q) mod 4; l ← type(q); p ← link (q); free node(q, expr node size); goto found ; end

This code is used in section 1516*.

1523* . We want to make sure that each term and (intermediate) result is in the proper range. Integer values must not exceed infinity (2^{31} −1) in absolute value, dimensions must not exceed max dimen (2^{30} −1). We avoid the absolute value of an integer, because this might fail for the value −2^{31} using 32-bit arithmetic.

define num error (#) ≡ { clear a number or dimension and set arith error } begin arith error ← true; # ← 0; end

define glue error (#) ≡ { clear a glue spec and set arith error } begin arith error ← true; delete glue ref (#); # ← new spec(zero glue); end

⟨ Make sure that f is in the proper range 1523* ⟩ ≡

if (l = int val ) ∨ (s > expr sub) then begin if (f > infinity ) ∨ (f < −infinity ) then num error (f); end

else if l = dimen val then begin if abs (f) > max dimen then num error (f); end

else begin if (abs (width(f)) > max dimen) ∨ (abs (stretch(f)) > max dimen) ∨

(abs (shrink (f)) > max dimen) then glue error (f); end

This code is used in section 1516*.

1524* . Applying the factor f to the partial term t (with the operator s) is delayed until the next operator o has been scanned. Here we handle the first factor of a partial term. A glue spec has to be copied unless the next operator is a right parenthesis; this allows us later on to simply modify the glue components.

define normalize glue(#) ≡

if stretch(#) = 0 then stretch order (#) ← normal ; if shrink (#) = 0 then shrink order (#) ← normal

⟨ Cases for evaluation of the current term 1524* ⟩ ≡ expr none: if (l ≥ glue val ) ∧ (o ≠ expr none) then

begin t ← new spec(f); delete glue ref (f); normalize glue(t);

end else t ← f;

See also sections 1528*, 1529*, and 1531*. This code is used in section 1516*.

1525* . When a term t has been completed it is copied to, added to, or subtracted from the expression e. define expr add sub(#) ≡ add or sub(#, r = expr sub) define expr a(#) ≡ expr add sub(#, max dimen)

⟨ Evaluate the current expression 1525* ⟩ ≡ begin s ← expr none; if r = expr none then e ← t else if l = int val then e ← expr add sub(e, t, infinity )

else if l = dimen val then e ← expr a(e, t)

else ⟨ Compute the sum or difference of two glue specs 1527* ⟩; r ← o; end

This code is used in section 1516*.

1526* . The function add or sub(x, y, max answer , negative) computes the sum (for negative = false) or difference (for negative = true) of x and y, provided the absolute value of the result does not exceed max answer . ⟨ Declare subprocedures for scan expr 1526* ⟩ ≡ function add or sub(x, y, max answer : integer ; negative : boolean): integer ;

var a: integer ; { the answer } begin if negative then negate(y); if x ≥ 0 then

if y ≤ max answer − x then a ← x + y else num error (a) else if y ≥ −max answer − x then a ← x + y else num error (a); add or sub ← a; end;

See also sections 1530* and 1532*. This code is used in section 1515*.

1527* . We know that stretch order (e) > normal implies stretch(e) ≠ 0 and shrink order (e) > normal implies shrink (e) ≠ 0. ⟨ Compute the sum or difference of two glue specs 1527* ⟩ ≡

begin width(e) ← expr a(width(e), width(t)); if stretch order (e) = stretch order (t) then stretch(e) ← expr a(stretch(e), stretch(t)) else if (stretch order (e) < stretch order (t)) ∧ (stretch(t) ≠ 0) then

begin stretch(e) ← stretch(t); stretch order (e) ← stretch order (t); end;

if shrink order (e) = shrink order (t) then shrink (e) ← expr a(shrink (e), shrink (t)) else if (shrink order (e) < shrink order (t)) ∧ (shrink (t) ≠ 0) then

begin shrink (e) ← shrink (t); shrink order (e) ← shrink order (t); end;

delete glue ref (t); normalize glue(e); end

This code is used in section 1525*.

1528* . If a multiplication is followed by a division, the two operations are combined into a ‘scaling’ operation. Otherwise the term t is multiplied by the factor f.

define expr m(#) ≡ # ← nx plus y (#, f, 0) ⟨ Cases for evaluation of the current term 1524* ⟩ +≡ expr mult : if o = expr div then

begin n ← f; o ← expr scale;

end else if l = int val then t ← mult integers (t, f)

else if l = dimen val then expr m(t)

else begin expr m(width(t)); expr m(stretch(t)); expr m(shrink (t)); end;

1529* . Here we divide the term t by the factor f.

define expr d (#) ≡ # ← quotient (#, f) ⟨ Cases for evaluation of the current term 1524* ⟩ +≡ expr div : if l < glue val then expr d (t)

else begin expr d (width(t)); expr d (stretch(t)); expr d (shrink (t)); end; 1530* . The function quotient (n, d) computes the rounded quotient q = ⌊n/d+ \frac{1}{2}⌋, when n and d are positive. ⟨ Declare subprocedures for scan expr 1526* ⟩ +≡ function quotient (n, d : integer ): integer ;

var negative: boolean; { should the answer be negated? }

a: integer ; { the answer } begin if d = 0 then num error (a) else begin if d > 0 then negative ← false

else begin negate(d); negative ← true;

end; if n < 0 then

begin negate(n); negative ← ¬negative; end;

a ← n div d; n ← n − a ∗ d; d ← n − d; { avoid certain compiler optimizations! } if d + n ≥ 0 then incr (a); if negative then negate(a); end;

quotient ← a; end;

1531* . Here the term t is multiplied by the quotient n/f.

define expr s (#) ≡ # ← fract (#, n, f, max dimen) ⟨ Cases for evaluation of the current term 1524* ⟩ +≡ expr scale: if l = int val then t ← fract (t, n, f, infinity )

else if l = dimen val then expr s (t)

else begin expr s (width(t)); expr s (stretch(t)); expr s (shrink (t)); end; 1532* . Finally, the function fract (x, n, d, max answer ) computes the integer q = ⌊xn/d + \frac{1}{2}⌋, when x, n, and d are positive and the result does not exceed max answer . We can’t use floating point arithmetic since the routine must produce identical results in all cases; and it would be too dangerous to multiply by n and then divide by d, in separate operations, since overflow might well occur. Hence this subroutine simulates double precision arithmetic, somewhat analogous to ’s make fraction and take fraction routines.

define too big = 88 { go here when the result is too big } ⟨ Declare subprocedures for scan expr 1526* ⟩ +≡ function fract (x, n, d, max answer : integer ): integer ;

label found , found1 , too big , done; var negative: boolean; { should the answer be negated? }

a: integer ; { the answer }

f: integer ; { a proper fraction }

h: integer ; { smallest integer such that 2 ∗ h ≥ d } r: integer ; { intermediate remainder } t: integer ; { temp variable }

begin if d = 0 then goto too big ; a ← 0; if d > 0 then negative ← false else begin negate(d); negative ← true;

end; if x < 0 then

begin negate(x); negative ← ¬negative;

end else if x = 0 then goto done; if n < 0 then

begin negate(n); negative ← ¬negative;

end; t ← n div d; if t > max answer div x then goto too big ; a ← t ∗ x; n ← n − t ∗ d; if n = 0 then goto found ; t ← x div d; if t > (max answer − a) div n then goto too big ; a ← a + t ∗ n; x ← x − t ∗ d; if x = 0 then goto found ; if x < n then

begin t ← x; x ← n; n ← t;

end; { now 0 < n ≤ x < d } ⟨ Compute f = ⌊xn/d + \frac{1}{2}⌋ 1533* ⟩ if f > (max answer − a) then goto too big ; a ← a + f;

found : if negative then negate(a);

goto done; too big : num error (a); done: fract ← a;

end; 1533* . The loop here preserves the following invariant relations between f, x, n, and r: (i) f + ⌊(xn + (r + d))/d⌋ = ⌊x_{0}n_{0}/d + \frac{1}{2}⌋; (ii) −d ≤ r < 0 < n ≤ x < d, where x_{0}, n_{0} are the original values of x and n.

Notice that the computation specifies (x − d) + x instead of (x + x) − d, because the latter could overflow. ⟨ Compute f = ⌊xn/d + \frac{1}{2}⌋ 1533* ⟩ ≡

f ← 0; r ← (d div 2) − d; h ← −r; loop begin if odd (n) then

begin r ← r + x; if r ≥ 0 then

begin r ← r − d; incr (f);

end; end;

n ← n div 2;

if n = 0 then goto found1 ;

if x < h then x ← x + x

else begin t ← x − d; x ← t + x; f ← f + n;

if x < n then begin if x = 0 then goto found1 ; t ← x; x ← n; n ← t; end; end;

end; found1 :

This code is used in section 1532*.

1534* . The  ,  ,  , and  commands return

the stretch and shrink components and their orders of “infinity” of a glue specification.

define glue stretch order code = eTeX int + 6 { code for } define glue shrink order code = eTeX int + 7 { code for } define glue stretch code = eTeX dim + 7 { code for } define glue shrink code = eTeX dim + 8 { code for }

⟨ Generate all ε-TEX primitives 1380* ⟩ +≡ primitive( , last item, glue stretch order code); primitive( , last item, glue shrink order code); primitive( , last item, glue stretch code); primitive( , last item, glue shrink code);

1535* . ⟨ Cases of last item for print cmd chr 1381* ⟩ +≡ glue stretch order code: print esc( ); glue shrink order code: print esc( ); glue stretch code: print esc( ); glue shrink code: print esc( );

1536* . ⟨ Cases for fetching an integer value 1382* ⟩ +≡ glue stretch order code, glue shrink order code: begin scan normal glue; q ← cur val ;

if m = glue stretch order code then cur val ← stretch order (q) else cur val ← shrink order (q); delete glue ref (q); end; 1537* . ⟨ Cases for fetching a dimension value 1405* ⟩ +≡ glue stretch code, glue shrink code: begin scan normal glue; q ← cur val ;

if m = glue stretch code then cur val ← stretch(q)

else cur val ← shrink (q);

delete glue ref (q);

end;

1538* . The  and  commands convert “math” glue into normal glue and vice versa;

they allow to manipulate math glue with etc.

define mu to glue code = eTeX glue { code for }

define glue to mu code = eTeX mu { code for } ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive(  , last item, mu to glue code); primitive(  , last item, glue to mu code);

1539* . ⟨ Cases of last item for print cmd chr 1381* ⟩ +≡ mu to glue code: print esc( ); glue to mu code: print esc( );

1540* . ⟨ Cases for fetching a glue value 1540* ⟩ ≡ mu to glue code: scan mu glue;

This code is used in section 1513*.

1541* . ⟨ Cases for fetching a mu value 1541* ⟩ ≡ glue to mu code: scan normal glue;

This code is used in section 1513*.

1542* . ε-TEX (in extended mode) supports 32768 (i.e., 2^{15}) count, dimen, skip, muskip, box, and token registers. As in TEX the first 256 registers of each kind are realized as arrays in the table of equivalents; the additional registers are realized as tree structures built from variable-size nodes with individual registers existing only when needed. Default values are used for nonexistent registers: zero for count and dimen values, zero glue for glue (skip and muskip) values, void for boxes, and null for token lists (and current marks discussed below).

Similarly there are 32768 mark classes; the command n creates a mark node for a given mark class 0 ≤ n ≤ 32767 (where is synonymous to ). The page builder (actually the fire up routine) and the vsplit routine maintain the current values of top mark , first mark , bot mark , split first mark , and split bot mark for each mark class. They are accessed as n etc., and is again synonymous to . As in TEX the five current marks for mark class zero are realized as cur mark array. The additional current marks are again realized as tree structure with individual mark classes existing only when needed. ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , mark , marks code);

primitive( , top bot mark , top mark code + marks code);

primitive( , top bot mark , first mark code + marks code);

primitive( , top bot mark , bot mark code + marks code);

primitive( , top bot mark , split first mark code + marks code);

primitive( , top bot mark , split bot mark code + marks code);

1543* . The scan register num procedure scans a register number that must not exceed 255 in compatibility mode resp. 32767 in extended mode. ⟨ Declare ε-TEX procedures for expanding 1485* ⟩ +≡ procedure scan register num; forward ; 1544* . ⟨ Declare procedures that scan restricted classes of integers 433 ⟩ +≡ procedure scan register num;

begin scan int ;

if (cur val < 0) ∨ (cur val > max reg num) then begin print err ( ␣ ␣ ); help2 (max reg help line)( ␣ ␣ ␣ ␣ ␣ ); int error (cur val ); cur val ← 0; end;

end;

1545* . ⟨ Initialize variables for ε-TEX compatibility mode 1545* ⟩ ≡

max reg num ← 255; max reg help line ← ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ;

This code is used in sections 1387* and 1389*.

1546* . ⟨ Initialize variables for ε-TEX extended mode 1546* ⟩ ≡

max reg num ← 32767; max reg help line ← ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ;

This code is used in sections 1379* and 1389*.

1547* . ⟨ Global variables 13 ⟩ +≡ max reg num: halfword ; { largest allowed register number } max reg help line: str number ; { first line of help message } 1548* . There are seven almost identical doubly linked trees, one for the sparse array of the up to 32512 additional registers of each kind and one for the sparse array of the up to 32767 additional mark classes. The root of each such tree, if it exists, is an index node containing 16 pointers to subtrees for 4096 consecutive array elements. Similar index nodes are the starting points for all nonempty subtrees for 4096, 256, and 16 consecutive array elements. These four levels of index nodes are followed by a fifth level with nodes for the individual array elements.

Each index node is nine words long. The pointers to the 16 possible subtrees or are kept in the info and link fields of the last eight words. (It would be both elegant and efficient to declare them as array, unfortunately Pascal doesn’t allow this.)

The fields in the first word of each index node and in the nodes for the array elements are closely related. The link field points to the next lower index node and the sa index field contains four bits (one hexadecimal digit) of the register number or mark class. For the lowest index node the link field is null and the sa index field indicates the type of quantity (int avl , dimen val , glue val , mu val , box val , tok val , or mark val ). The sa used field in the index nodes counts how many of the 16 pointers are non-null.

The sa index field in the nodes for array elements contains the four bits plus 16 times the type. Therefore such a node represents a count or dimen register if and only if sa index < dimen val limit ; it represents a skip or muskip register if and only if dimen val limit ≤ sa index < mu val limit ; it represents a box register if and only if mu val limit ≤ sa index < box val limit ; it represents a token list register if and only if box val limit ≤ sa index < tok val limit ; finally it represents a mark class if and only if tok val limit ≤ sa index .

The new index procedure creates an index node (returned in cur ptr ) having given contents of the sa index and link fields.

define box val ≡ 4 { the additional box registers }

define mark val = 6 { the additional mark classes }

define dimen val limit = ˝ 20 { 2^{4} · (dimen val + 1) }

define mu val limit = ˝ 40 { 2^{4} · (mu val + 1) }

define box val limit = ˝ 50 { 2^{4} · (box val + 1) }

define tok val limit = ˝ 60 { 2^{4} · (tok val + 1) }

define index node size = 9 { size of an index node }

define sa index ≡ type { a four-bit address or a type or both }

define sa used ≡ subtype { count of non-null pointers } ⟨ Declare ε-TEX procedures for expanding 1485* ⟩ +≡ procedure new index (i : quarterword ; q : pointer );

var k: small number ; { loop index }

begin cur ptr ← get node(index node size); sa index (cur ptr ) ← i; sa used (cur ptr ) ← 0; link (cur ptr ) ← q; for k ← 1 to index node size − 1 do { clear all 16 pointers }

mem[cur ptr + k] ← sa null ; end;

1549* . The roots of the seven trees for the additional registers and mark classes are kept in the sa root array. The first six locations must be dumped and undumped; the last one is also known as sa mark .

define sa mark ≡ sa root [mark val ] { root for mark classes } ⟨ Global variables 13 ⟩ +≡ sa root : array [int val . . mark val ] of pointer ; { roots of sparse arrays } cur ptr : pointer ; { value returned by new index and find sa element } sa null : memory word ; { two null pointers }

1550* . ⟨ Set initial values of key variables 21 ⟩ +≡ sa mark ← null ; sa null .hh.lh ← null ; sa null .hh.rh ← null ;

§1551 ε-TEX 3.14159 [PD VMS 3.6] changes PART 53a: THE EXTENDED FEATURES OF ε-TEX 213

1551* . ⟨ Initialize table entries (done by only) 164 ⟩ +≡ for i ← int val to tok val do sa root [i] ← null ; 1552* . Given a type t and a sixteen-bit number n, the find sa element procedure returns (in cur ptr ) a pointer to the node for the corresponding array element, or null when no such element exists. The third parameter w is set true if the element must exist, e.g., because it is about to be modified. The procedure has two main branches: one follows the existing tree structure, the other (only used when w is true) creates the missing nodes.

We use macros to extract the four-bit pieces from a sixteen-bit register number or mark class and to fetch or store one of the 16 pointers from an index node.

define if cur ptr is null then return or goto(#) ≡ { some tree element is missing }

begin if cur ptr = null then

if w then goto # else return; end

define hex dig1 (#) ≡ # div 4096 { the fourth lowest hexadecimal digit } define hex dig2 (#) ≡ (# div 256) mod 16 { the third lowest hexadecimal digit } define hex dig3 (#) ≡ (# div 16) mod 16 { the second lowest hexadecimal digit } define hex dig4 (#) ≡ # mod 16 { the lowest hexadecimal digit }

define get sa ptr ≡ if odd (i) then cur ptr ← link (q + (i div 2) + 1) else cur ptr ← info(q + (i div 2) + 1)

{ set cur ptr to the pointer indexed by i from index node q }

define put sa ptr (#) ≡ if odd (i) then link (q + (i div 2) + 1) ← # else info(q + (i div 2) + 1) ← # { store the pointer indexed by i in index node q }

define add sa ptr ≡ begin put sa ptr (cur ptr ); incr (sa used (q)); end { add cur ptr as the pointer indexed by i in index node q }

define delete sa ptr ≡ begin put sa ptr (null ); decr (sa used (q)); end { delete the pointer indexed by i in index node q }

⟨ Declare ε-TEX procedures for expanding 1485* ⟩ +≡ procedure find sa element (t : small number ; n : halfword ; w : boolean);

{ sets cur val to sparse array element location or null } label not found , not found1 , not found2 , not found3 , not found4 , exit ; var q: pointer ; { for list manipulations }

i: small number ; { a four bit index } begin cur ptr ← sa root [t]; if cur ptr is null then return or goto(not found ); q ← cur ptr ; i ← hex dig1 (n); get sa ptr ; if cur ptr is null then return or goto(not found1 ); q ← cur ptr ; i ← hex dig2 (n); get sa ptr ; if cur ptr is null then return or goto(not found2 ); q ← cur ptr ; i ← hex dig3 (n); get sa ptr ; if cur ptr is null then return or goto(not found3 ); q ← cur ptr ; i ← hex dig4 (n); get sa ptr ; if (cur ptr = null ) ∧ w then goto not found4 ; return;

not found : new index (t, null ); { create first level index node }

sa root [t] ← cur ptr ; q ← cur ptr ; i ← hex dig1 (n); not found1 : new index (i, q); { create second level index node }

add sa ptr ; q ← cur ptr ; i ← hex dig2 (n); not found2 : new index (i, q); { create third level index node }

add sa ptr ; q ← cur ptr ; i ← hex dig3 (n); not found3 : new index (i, q); { create fourth level index node }

add sa ptr ; q ← cur ptr ; i ← hex dig4 (n); not found4 : ⟨ Create a new array element of type t with index i 1553* ⟩;

link (cur ptr ) ← q; add sa ptr ; exit : end;

1553* . The array elements for registers are subject to grouping and have an sa lev field (quite analogous to eq level ) instead of sa used . Since saved values as well as shorthand definitions (created by e.g., ) refer to the location of the respective array element, we need a reference count that is kept in the sa ref field. An array element can be deleted (together with all references to it) when its sa ref value is null and its value is the default value.

Skip, muskip, box, and token registers use two word nodes, their values are stored in the sa ptr field. Count and dimen registers use three word nodes, their values are stored in the sa int resp. sa dim field in the third word; the sa ptr field is used under the name sa num to store the register number. Mark classes use four word nodes. The last three words contain the five types of current marks

define sa lev ≡ sa used { grouping level for the current value } define pointer node size = 2 { size of an element with a pointer value } define sa type(#) ≡ (sa index (#) div 16) { type part of combined type/index } define sa ref (#) ≡ info(# + 1) { reference count of a sparse array element } define sa ptr (#) ≡ link (# + 1) { a pointer value } define word node size = 3 { size of an element with a word value } define sa num ≡ sa ptr { the register number } define sa int (#) ≡ mem[# + 2].int { an integer } define sa dim(#) ≡ mem[# + 2].sc { a dimension (a somewhat esotheric distinction) } define mark class node size = 4 { size of an element for a mark class } define fetch box (#) ≡ { fetch box (cur val ) }

if cur val < 256 then # ← box (cur val )

else begin find sa element (box val , cur val , false); if cur ptr = null then # ← null else # ← sa ptr (cur ptr ); end

⟨ Create a new array element of type t with index i 1553* ⟩ ≡

if t = mark val then { a mark class } begin cur ptr ← get node(mark class node size); mem[cur ptr + 1] ← sa null ; mem[cur ptr + 2] ← sa null ; mem[cur ptr + 3] ← sa null ; end

else begin if t ≤ dimen val then { a count or dimen register } begin cur ptr ← get node(word node size); sa int (cur ptr ) ← 0; sa num(cur ptr ) ← n; end

else begin cur ptr ← get node(pointer node size);

if t ≤ mu val then { a skip or muskip register } begin sa ptr (cur ptr ) ← zero glue; add glue ref (zero glue); end

else sa ptr (cur ptr ) ← null ; { a box or token list register }

end; sa ref (cur ptr ) ← null ; { all registers have a reference count } end;

sa index (cur ptr ) ← 16 ∗ t + i; sa lev (cur ptr ) ← level one

This code is used in section 1552*.

1554* . The delete sa ref procedure is called when a pointer to an array element representing a register is being removed; this means that the reference count should be decreased by one. If the reduced reference count is null and the register has been (globally) assigned its default value the array element should disappear, possibly together with some index nodes. This procedure will never be used for mark class nodes.

define add sa ref (#) ≡ incr (sa ref (#)) { increase reference count } define change box (#) ≡ { change box (cur val ), the eq level stays the same }

if cur val < 256 then box (cur val ) ← # else set sa box (#) define set sa box (#) ≡

begin find sa element (box val , cur val , false); if cur ptr ≠ 0 then

begin sa ptr (cur ptr ) ← #; add sa ref (cur ptr ); delete sa ref (cur ptr ); end; end

⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure delete sa ref (q : pointer ); { reduce reference count }

label exit ; var p: pointer ; { for list manipulations }

i: small number ; { a four bit index }

s: small number ; { size of a node } begin decr (sa ref (q)); if sa ref (q) ≠ null then return; if sa index (q) < dimen val limit then

if sa int (q) = 0 then s ← word node size

else return

else begin if sa index (q) < mu val limit then if sa ptr (q) = zero glue then delete glue ref (zero glue)

else return

else if sa ptr (q) ≠ null then return;

s ← pointer node size;

end; repeat i ← hex dig4 (sa index (q)); p ← q; q ← link (p); free node(p, s);

if q = null then { the whole tree has been freed } begin sa root [i] ← null ; return; end;

delete sa ptr ; s ← index node size; { node q is an index node } until sa used (q) > 0;

exit : end;

1555* . The print sa num procedure prints the register number corresponding to an array element. ⟨ Basic printing procedures 56* ⟩ +≡ procedure print sa num(q : pointer ); { print register number }

var n: halfword ; { the register number } begin if sa index (q) < dimen val limit then n ← sa num(q) { the easy case } else begin n ← hex dig4 (sa index (q)); q ← link (q); n ← n + 16 ∗ sa index (q); q ← link (q);

n ← n + 256 ∗ (sa index (q) + 16 ∗ sa index (link (q)));

end; print int (n); end; 1556* . Here is a procedure that displays the contents of an array element symbolically. It is used under similar circumstances as is restore trace (together with show eqtb) for the quantities kept in the eqtb array. ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡

stat procedure show sa(p : pointer ; s : str number ); var t: small number ; { the type of element } begin begin diagnostic; print char ( ); print (s); print char ( ␣ ); if p = null then print char ( ) { this can’t happen } else begin t ← sa type(p);

if t < box val then print cmd chr (register , p)

else if t = box val then begin print esc( ); print sa num(p); end

else if t = tok val then print cmd chr (toks register , p) else print char ( ); { this can’t happen either }

print char ( );

if t = int val then print int (sa int (p))

else if t = dimen val then begin print scaled (sa dim(p)); print ( ); end

else begin p ← sa ptr (p); if t = glue val then print spec(p, ) else if t = mu val then print spec(p, )

else if t = box val then if p = null then print ( ) else begin depth threshold ← 0; breadth max ← 1; show node list (p);

end else if t = tok val then

begin if p ≠ null then show token list (link (p), null , 32); end

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

end; print char ( ); end diagnostic(false); end; tats

1557* . Here we compute the pointer to the current mark of type t and mark class cur val . ⟨ Compute the mark pointer for mark type t and class cur val 1557* ⟩ ≡

begin find sa element (mark val , cur val , false); if cur ptr ≠ null then

if odd (t) then cur ptr ← link (cur ptr + (t div 2) + 1)

else cur ptr ← info(cur ptr + (t div 2) + 1); end

This code is used in section 386*.

1558* . The current marks for all mark classes are maintained by the vsplit and fire up routines and are finally destroyed (for only) by the final cleanup routine. Apart from updating the current marks when mark nodes are encountered, these routines perform certain actions on all existing mark classes. The recursive do marks procedure walks through the whole tree or a subtree of existing mark class nodes and preforms certain actions indicted by its first parameter a, the action code. The second parameter l indicates the level of recursion (at most four); the third parameter points to a nonempty tree or subtree. The result is true if the complete tree or subtree has been deleted.

define vsplit init ≡ 0 { action code for vsplit initialization } define fire up init ≡ 1 { action code for fire up initialization } define fire up done ≡ 2 { action code for fire up completion } define destroy marks ≡ 3 { action code for final cleanup } define sa top mark (#) ≡ info(# + 1) { n } define sa first mark (#) ≡ link (# + 1) { n } define sa bot mark (#) ≡ info(# + 2) { n } define sa split first mark (#) ≡ link (# + 2) { n } define sa split bot mark (#) ≡ info(# + 3) { n }

⟨ Declare the function called do marks 1558* ⟩ ≡ function do marks (a, l : small number ; q : pointer ): boolean;

var i: small number ; { a four bit index } begin if l < 4 then { q is an index node }

begin for i ← 0 to 15 do begin get sa ptr ; if cur ptr ≠ null then

if do marks (a, l + 1, cur ptr ) then delete sa ptr ; end;

if sa used (q) = 0 then begin free node(q, index node size); q ← null ; end;

end else { q is the node for a mark class }

begin case a of

⟨ Cases for do marks 1559* ⟩ end; { there are no other cases } if sa bot mark (q) = null then

if sa split bot mark (q) = null then begin free node(q, mark class node size); q ← null ; end;

end; do marks ← (q = null ); end;

This code is used in section 977*.

1559* . At the start of the vsplit routine the existing split fist mark and split bot mark are discarded. ⟨ Cases for do marks 1559* ⟩ ≡ vsplit init : if sa split first mark (q) ≠ null then

begin delete token ref (sa split first mark (q)); sa split first mark (q) ← null ; delete token ref (sa split bot mark (q)); sa split bot mark (q) ← null ; end;

See also sections 1561*, 1562*, and 1564*. This code is used in section 1558*.

1560* . We use again the fact that split first mark = null if and only if split bot mark = null . ⟨ Update the current marks for vsplit 1560* ⟩ ≡

begin find sa element (mark val , mark class (p), true); if sa split first mark (cur ptr ) = null then

begin sa split first mark (cur ptr ) ← mark ptr (p); add token ref (mark ptr (p)); end

else delete token ref (sa split bot mark (cur ptr )); sa split bot mark (cur ptr ) ← mark ptr (p); add token ref (mark ptr (p)); end

This code is used in section 979*.

1561* . At the start of the fire up routine the old top mark and first mark are discarded, whereas the old bot mark becomes the new top mark . An empty new top mark token list is, however, discarded as well in order that mark class nodes can eventually be released. We use again the fact that bot mark ≠ null implies first mark ≠ null ; it also knows that bot mark = null implies top mark = first mark = null . ⟨ Cases for do marks 1559* ⟩ +≡ fire up init : if sa bot mark (q) ≠ null then

begin if sa top mark (q) ≠ null then delete token ref (sa top mark (q)); delete token ref (sa first mark (q)); sa first mark (q) ← null ; if link (sa bot mark (q)) = null then { an empty token list }

begin delete token ref (sa bot mark (q)); sa bot mark (q) ← null ; end

else add token ref (sa bot mark (q)); sa top mark (q) ← sa bot mark (q); end;

1562* . ⟨ Cases for do marks 1559* ⟩ +≡ fire up done: if (sa top mark (q) ≠ null ) ∧ (sa first mark (q) = null ) then

begin sa first mark (q) ← sa top mark (q); add token ref (sa top mark (q)); end;

1563* . ⟨ Update the current marks for fire up 1563* ⟩ ≡ begin find sa element (mark val , mark class (p), true); if sa first mark (cur ptr ) = null then

begin sa first mark (cur ptr ) ← mark ptr (p); add token ref (mark ptr (p)); end;

if sa bot mark (cur ptr ) ≠ null then delete token ref (sa bot mark (cur ptr )); sa bot mark (cur ptr ) ← mark ptr (p); add token ref (mark ptr (p)); end

This code is used in section 1014*.

1564* . Here we use the fact that the five current mark pointers in a mark class node occupy the same locations as the the first five pointers of an index node. For systems using a run-time switch to distinguish between and , the codewords ‘init … tini’ surrounding the following piece of code should be removed. ⟨ Cases for do marks 1559* ⟩ +≡

init destroy marks : for i ← top mark code to split bot mark code do begin get sa ptr ; if cur ptr ≠ null then

begin delete token ref (cur ptr ); put sa ptr (null ); end; end;

tini

1565* . The command code register is used for ‘  ’, ‘  ’, etc., as well as for references to sparse

array elements defined by ‘ ’, etc. ⟨ Cases of register for print cmd chr 1565* ⟩ ≡

begin if (chr code < mem bot ) ∨ (chr code > lo mem stat max ) then cmd ← sa type(chr code)

else begin cmd ← chr code − mem bot ; chr code ← null ;

end; if cmd = int val then print esc( ) else if cmd = dimen val then print esc( )

else if cmd = glue val then print esc( )

else print esc( ); if chr code ≠ null then print sa num(chr code); end

This code is used in section 412*.

1566* . Similarly the command code toks register is used for ‘ ’ as well as for references to sparse array elements defined by ‘ ’. ⟨ Cases of toks register for print cmd chr 1566* ⟩ ≡

begin print esc( );

if chr code ≠ mem bot then print sa num(chr code);

end

This code is used in section 266*.

1567* . When a shorthand definition for an element of one of the sparse arrays is destroyed, we must reduce the reference count. ⟨ Cases for eq destroy 1567* ⟩ ≡ toks register , register : if (equiv field (w) < mem bot ) ∨ (equiv field (w) > lo mem stat max ) then

delete sa ref (equiv field (w));

This code is used in section 275*.

1568* . The task to maintain (change, save, and restore) register values is essentially the same when the register is realized as sparse array element or entry in eqtb. The global variable sa chain is the head of a linked list of entries saved at the topmost level sa level ; the lists for lowel levels are kept in special save stack entries. ⟨ Global variables 13 ⟩ +≡ sa chain: pointer ; { chain of saved sparse array entries } sa level : quarterword ; { group level for sa chain } 1569* . ⟨ Set initial values of key variables 21 ⟩ +≡

sa chain ← null ; sa level ← level zero;

1570* . The individual saved items are kept in pointer or word nodes similar to those used for the array elements: a word node with value zero is, however, saved as pointer node with the otherwise impossible sa index value tok val limit .

define sa loc ≡ sa ref { location of saved item } ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure sa save(p : pointer ); { saves value of p }

var q: pointer ; { the new save node }

i: quarterword ; { index field of node } begin if cur level ≠ sa level then

begin check full save stack ; save type(save ptr ) ← restore sa; save level (save ptr ) ← sa level ; save index (save ptr ) ← sa chain; incr (save ptr ); sa chain ← null ; sa level ← cur level ; end;

i ← sa index (p); if i < dimen val limit then

begin if sa int (p) = 0 then begin q ← get node(pointer node size); i ← tok val limit ; end

else begin q ← get node(word node size); sa int (q) ← sa int (p);

end; sa ptr (q) ← null ; end

else begin q ← get node(pointer node size); sa ptr (q) ← sa ptr (p);

end; sa loc(q) ← p; sa index (q) ← i; sa lev (q) ← sa lev (p); link (q) ← sa chain; sa chain ← q; add sa ref (p); end;

1571* . ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure sa destroy (p : pointer ); { destroy value of p }

begin if sa index (p) < mu val limit then delete glue ref (sa ptr (p)) else if sa ptr (p) ≠ null then

if sa index (p) < box val limit then flush node list (sa ptr (p))

else delete token ref (sa ptr (p)); end; 1572* . The procedure sa def assigns a new value to sparse array elements, and saves the former value if appropriate. This procedure is used only for skip, muskip, box, and token list registers. The counterpart of sa def for count and dimen registers is called sa w def .

define sa define(#) ≡

if e then

if global then gsa def (#) else sa def (#)

else define

define sa def box ≡ { assign cur box to box (cur val ) } begin find sa element (box val , cur val , true); if global then gsa def (cur ptr , cur box ) else sa def (cur ptr , cur box ); end

define sa word define(#) ≡

if e then

if global then gsa w def (#) else sa w def (#) else word define(#)

⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure sa def (p : pointer ; e : halfword ); { new data for sparse array elements }

begin add sa ref (p); if sa ptr (p) = e then

begin stat if tracing assigns > 0 then show sa(p, ); tats sa destroy (p); end

else begin stat if tracing assigns > 0 then show sa(p, ); tats if sa lev (p) = cur level then sa destroy (p) else sa save(p); sa lev (p) ← cur level ; sa ptr (p) ← e; stat if tracing assigns > 0 then show sa(p, ); tats end;

delete sa ref (p); end;

procedure sa w def (p : pointer ; w : integer ); begin add sa ref (p); if sa int (p) = w then

begin stat if tracing assigns > 0 then show sa(p, ); tats end

else begin stat if tracing assigns > 0 then show sa(p, ); tats if sa lev (p) ≠ cur level then sa save(p); sa lev (p) ← cur level ; sa int (p) ← w; stat if tracing assigns > 0 then show sa(p, ); tats end;

delete sa ref (p); end; 1573* . The sa def and sa w def routines take care of local definitions. Global definitions are done in almost the same way, but there is no need to save old values, and the new value is associated with level one. ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure gsa def (p : pointer ; e : halfword ); { global sa def }

begin add sa ref (p); stat if tracing assigns > 0 then show sa(p, ␣ ); tats sa destroy (p); sa lev (p) ← level one; sa ptr (p) ← e; stat if tracing assigns > 0 then show sa(p, ); tats delete sa ref (p); end;

procedure gsa w def (p : pointer ; w : integer ); { global sa w def } begin add sa ref (p); stat if tracing assigns > 0 then show sa(p, ␣ ); tats sa lev (p) ← level one; sa int (p) ← w; stat if tracing assigns > 0 then show sa(p, ); tats delete sa ref (p); end;

1574* . The sa restore procedure restores the sparse array entries pointed at by sa chain ⟨ Declare ε-TEX procedures for tracing and input 284* ⟩ +≡ procedure sa restore;

var p: pointer ; { sparse array element } begin repeat p ← sa loc(sa chain);

if sa lev (p) = level one then begin if sa index (p) ≥ dimen val limit then sa destroy (sa chain); stat if tracing restores > 0 then show sa(p, ); tats end

else begin if sa index (p) < dimen val limit then if sa index (sa chain) < dimen val limit then sa int (p) ← sa int (sa chain) else sa int (p) ← 0

else begin sa destroy (p); sa ptr (p) ← sa ptr (sa chain);

end; sa lev (p) ← sa lev (sa chain); stat if tracing restores > 0 then show sa(p, ); tats end;

delete sa ref (p); p ← sa chain; sa chain ← link (p);

if sa index (p) < dimen val limit then free node(p, word node size)

else free node(p, pointer node size); until sa chain = null ; end; 1575* . When the value of last line fit is positive, the last line of a (partial) paragraph is treated in a special way and we need additional fields in the active nodes.

define active node size extended = 5 { number of words in extended active nodes } define active short (#) ≡ mem[# + 3].sc { shortfall of this line } define active glue(#) ≡ mem[# + 4].sc { corresponding glue stretch or shrink }

⟨ Global variables 13 ⟩ +≡ last line fill : pointer ; { the par fill skip glue node of the new paragraph } do last line fit : boolean; { special algorithm for last line of paragraph? } active node size: small number ; { number of words in active nodes } fill width: array [0 . . 2] of scaled ; { infinite stretch components of par fill skip } best pl short : array [very loose fit . . tight fit ] of scaled ; { shortfall corresponding to minimal demerits } best pl glue: array [very loose fit . . tight fit ] of scaled ; { corresponding glue stretch or shrink }

1576* . The new algorithm for the last line requires that the stretchability par fill skip is infinite and the stretchability of left skip plus right skip is finite. ⟨ Check for special treatment of last line of paragraph 1576* ⟩ ≡

do last line fit ← false; active node size ← active node size normal ; { just in case } if last line fit > 0 then

begin q ← glue ptr (last line fill );

if (stretch(q) > 0) ∧ (stretch order (q) > normal ) then

if (background [3] = 0) ∧ (background [4] = 0) ∧ (background [5] = 0) then begin do last line fit ← true; active node size ← active node size extended ; fill width[0] ← 0; fill width[1] ← 0; fill width[2] ← 0; fill width[stretch order (q) − 1] ← stretch(q); end;

end

This code is used in section 827*.

1577* . ⟨ Other local variables for try break 830 ⟩ +≡ g: scaled ; { glue stretch or shrink of test line, adjustment for last line }

1578* . Here we initialize the additional fields of the first active node representing the beginning of the paragraph. ⟨ Initialize additional fields of the first active node 1578* ⟩ ≡

begin active short (q) ← 0; active glue(q) ← 0;

end

This code is used in section 864*.

1579* . Here we compute the adjustment g and badness b for a line from r to the end of the paragraph. When any of the criteria for adjustment is violated we fall through to the normal algorithm.

The last line must be too short, and have infinite stretch entirely due to par fill skip. ⟨ Perform computations for last line and goto found 1579* ⟩ ≡

begin if (active short (r) = 0) ∨ (active glue(r) ≤ 0) then goto not found ;

{ previous line was neither stretched nor shrunk, or was infinitely bad } if (cur active width[3] ≠ fill width[0]) ∨ (cur active width[4] ≠ fill width[1]) ∨

(cur active width[5] ≠ fill width[2]) then goto not found ; { infinite stretch of this line not entirely due to par fill skip }

if active short (r) > 0 then g ← cur active width[2] else g ← cur active width[6]; if g ≤ 0 then goto not found ; { no finite stretch resp. no shrink } arith error ← false; g ← fract (g, active short (r), active glue(r), max dimen); if last line fit < 1000 then g ← fract (g, last line fit , 1000, max dimen);

if arith error then

if active short (r) > 0 then g ← max dimen else g ← −max dimen; if g > 0 then ⟨ Set the value of b to the badness of the last line for stretching, compute the corresponding

fit class , ∧goto found 1580* ⟩ else if g < 0 then ⟨ Set the value of b to the badness of the last line for shrinking, compute the

corresponding fit class , ∧goto found 1581* ⟩;

not found : end

This code is used in section 852*.

1580* . These badness computations are rather similar to those of the standard algorithm, with the adjustment amount g replacing the shortfall . ⟨ Set the value of b to the badness of the last line for stretching, compute the corresponding fit class , ∧goto

found 1580* ⟩ ≡ begin if g > shortfall then g ← shortfall ; if g > 7230584 then

if cur active width[2] < 1663497 then begin b ← inf bad ; fit class ← very loose fit ; goto found ; end;

b ← badness (g, cur active width[2]); if b > 12 then

if b > 99 then fit class ← very loose fit

else fit class ← loose fit else fit class ← decent fit ; goto found ; end

This code is used in section 1579*.

1581* . ⟨ Set the value of b to the badness of the last line for shrinking, compute the corresponding

fit class , ∧goto found 1581* ⟩ ≡ begin if −g > cur active width[6] then g ← −cur active width[6]; b ← badness (−g, cur active width[6]); if b > 12 then fit class ← tight fit else fit class ← decent fit ; goto found ; end

This code is used in section 1579*.

1582* . Vanishing values of shortfall and g indicate that the last line is not adjusted. ⟨ Adjust the additional data for last line 1582* ⟩ ≡

begin if cur p = null then shortfall ← 0; if shortfall > 0 then g ← cur active width[2] else if shortfall < 0 then g ← cur active width[6]

else g ← 0; end

This code is used in section 851*.

1583* . For each feasible break we record the shortfall and glue stretch or shrink (or adjustment). ⟨ Store additional data for this feasible break 1583* ⟩ ≡

begin best pl short [fit class ] ← shortfall ; best pl glue[fit class ] ← g; end

This code is used in section 855*.

1584* . Here we save these data in the active node representing a potential line break. ⟨ Store additional data in the new active node 1584* ⟩ ≡

begin active short (q) ← best pl short [fit class ]; active glue(q) ← best pl glue[fit class ]; end

This code is used in section 845*.

1585* . ⟨ Print additional data in the new active node 1585* ⟩ ≡ begin print ( ␣ ); print scaled (active short (q)); if cur p = null then print ( ␣ ) else print ( ␣ ); print scaled (active glue(q)); end

This code is used in section 846*.

1586* . Here we either reset do last line fit or adjust the par fill skip glue. ⟨ Adjust the final line of the paragraph 1586* ⟩ ≡

if active short (best bet ) = 0 then do last line fit ← false else begin q ← new spec(glue ptr (last line fill )); delete glue ref (glue ptr (last line fill ));

width(q) ← width(q) + active short (best bet ) − active glue(best bet ); stretch(q) ← 0; glue ptr (last line fill ) ← q; end

This code is used in section 863*.

1587* . When reading  while  is positive the current lc code values are stored

together with the hyphenation patterns for the current language. They will later be used instead of the lc code values for hyphenation purposes.

The lc code values are stored in the linked trie analogous to patterns p_{1} of length 1, with hyph root = trie r [0] replacing trie root and lc code(p 1 ) replacing the trie op code. This allows to compress and pack them together with the patterns with minimal changes to the existing code.

define hyph root ≡ trie r [0] { root of the linked trie for hyph codes } ⟨ Initialize table entries (done by only) 164 ⟩ +≡

hyph root ← 0; hyph start ← 0; 1588* . ⟨ Store hyphenation codes for current language 1588* ⟩ ≡

begin c ← cur lang ; first child ← false; p ← 0; repeat q ← p; p ← trie r [q]; until (p = 0) ∨ (c ≤ so(trie c[p])); if (p = 0) ∨ (c < so(trie c[p])) then ⟨ Insert a new trie node between q and p, and make p point to it 964 ⟩; q ← p; { now node q represents cur lang } ⟨ Store all current lc code values 1589* ⟩; end

This code is used in section 960*.

1589* . We store all nonzero lc code values, overwriting any previously stored values (and possibly wasting a few trie nodes that were used previously and are not needed now). We always store at least one lc code value such that hyph index (defined below) will not be zero. ⟨ Store all current lc code values 1589* ⟩ ≡

p ← trie l [q]; first child ← true; for c ← 0 to 255 do

if (lc code(c) > 0) ∨ ((c = 255) ∧ first child ) then begin if p = 0 then ⟨ Insert a new trie node between q and p, and make p point to it 964 ⟩ else trie c[p] ← si (c); trie o[p] ← qi (lc code(c)); q ← p; p ← trie r [q]; first child ← false; end;

if first child then trie l [q] ← 0 else trie r [q] ← 0

This code is used in section 1588*.

1590* . We must avoid to “take” location 1, in order to distinguish between lc code values and patterns. ⟨ Pack all stored hyph codes 1590* ⟩ ≡

begin if trie root = 0 then

for p ← 0 to 255 do trie min[p] ← p + 2; first fit (hyph root ); trie pack (hyph root ); hyph start ← trie ref [hyph root ]; end

This code is used in section 966*.

1591* . The global variable hyph index will point to the hyphenation codes for the current language.

define set hyph index ≡ { set hyph index for current language }

if trie char (hyph start + cur lang ) ≠ qi (cur lang ) then hyph index ← 0

{ no hyphenation codes for cur lang } else hyph index ← trie link (hyph start + cur lang )

define set lc code(#) ≡ { set hc[0] to hyphenation or lc code for # } if hyph index = 0 then hc[0] ← lc code(#) else if trie char (hyph index + #) ≠ qi (#) then hc[0] ← 0

else hc[0] ← qo(trie op(hyph index + #))

⟨ Global variables 13 ⟩ +≡ hyph start : trie pointer ; { root of the packed trie for hyph codes } hyph index : trie pointer ; { pointer to hyphenation codes for cur lang } 1592* . When saving vdiscards is positive then the glue, kern, and penalty nodes removed by the page builder or by from the top of a vertical list are saved in special lists instead of being discarded.

define tail page disc ≡ disc ptr [copy code] { last item removed by page builder } define page disc ≡ disc ptr [last box code] { first item removed by page builder } define split disc ≡ disc ptr [vsplit code] { first item removed by }

⟨ Global variables 13 ⟩ +≡ disc ptr : array [copy code . . vsplit code] of pointer ; { list pointers }

1593* . ⟨ Set initial values of key variables 21 ⟩ +≡ page disc ← null ; split disc ← null ;

1594* . The  and  commands share the command code un vbox with

and , they are distinguished by their chr code values last box code and vsplit code. These chr code values are larger than box code and copy code. ⟨ Generate all ε-TEX primitives 1380* ⟩ +≡

primitive( , un vbox , last box code);

primitive( , un vbox , vsplit code);

1595* . ⟨ Cases of un vbox for print cmd chr 1595* ⟩ ≡ else if chr code = last box code then print esc( )

else if chr code = vsplit code then print esc( )

This code is used in section 1108*.

1596* . ⟨ Handle saved items and goto done 1596* ⟩ ≡ begin link (tail ) ← disc ptr [cur chr ]; disc ptr [cur chr ] ← null ; goto done; end

This code is used in section 1110*.

1597* . The  ,  ,  , and

commands allow to define arrays of penalty values to be used instead of the corresponding single values. define inter line penalties ptr ≡ equiv (inter line penalties loc) define club penalties ptr ≡ equiv (club penalties loc) define widow penalties ptr ≡ equiv (widow penalties loc) define display widow penalties ptr ≡ equiv (display widow penalties loc)

⟨ Generate all ε-TEX primitives 1380* ⟩ +≡ primitive( , set shape, inter line penalties loc); primitive( , set shape, club penalties loc); primitive( , set shape, widow penalties loc); primitive( , set shape, display widow penalties loc);

1598* . ⟨ Cases of set shape for print cmd chr 1598* ⟩ ≡ inter line penalties loc: print esc( ); club penalties loc: print esc( ); widow penalties loc: print esc( ); display widow penalties loc: print esc( );

This code is used in section 266*.

1599* . ⟨ Fetch a penalties array element 1599* ⟩ ≡ begin scan int ; if (equiv (m) = null ) ∨ (cur val < 0) then cur val ← 0 else begin if cur val > penalty (equiv (m)) then cur val ← penalty (equiv (m));

cur val ← penalty (equiv (m) + cur val ); end;

end

This code is used in section 423*.

230  PART 54: SYSTEM-DEPENDENT CHANGES  ε-TEX 3.14159 [PD VMS 3.6] changes §1600

1600* . System-dependent changes. Here are the remaining changes to the program that are necessary to make TEX work on VMS. Note that especial care has been taken not to introduce any new sections; therefore, everything up to this point has had the same section numbers as the canonical versions in “TEX: The Program”.

Firstly, putting the cart before the horse, this is how we can return the final status of TEX to the operating system, in such a way that DCL command procedures and the like can determine whether the run of TEX was successfull or not. We use the $ system service; the value of its parameter is given by an appropriate symbolic constant taken from the library. We also take this opportunity to call the symbol jobname routine (defined below).

define VAX exit ≡ \underline{\overline{$}} define VAX ss normal ≡ \underline{\overline{␣ $ ␣}} define VAX ss ignore ≡ \underline{\overline{␣ $ ␣}} define VAX ss warning ≡ \underline{\overline{␣ $ $ ␣}} define VAX ss error ≡ \underline{\overline{␣ $ $ ␣}} define VAX ss fatal ≡ \underline{\overline{␣ $ $ ␣}}

⟨ Exit to operating system with final status 1600* ⟩ ≡ symbol jobname; case history of { Issue an appropriate VAX exit status } spotless : VAX exit (VAX ss normal ); { Everything OK! } warning issued : VAX exit (VAX ss warning ); error message issued : VAX exit (VAX ss error ); fatal error stop: VAX exit (VAX ss fatal ) endcases

This code is used in section 1332*.

1601* . symbol jobname is a routine which takes the job name string and the numeric portion of the extension of the output file and writes that information to the DCL symbol given by . The code here is based on code donated by Jim Walker of South Carolina University.

define VAX set symbol ≡ \underline{\overline{␣ $ ␣}} ⟨ Last-minute procedures 1333* ⟩ +≡ procedure VAX set symbol (VAX immed symbol : descr ptr ; VAX immed value string : descr ptr ;

tbl ind : integer ← VAX immed 0); external ;

procedure symbol jobname; var tmp descr : descr ptr ; begin tmp descr ← nil;

if job qual then

begin str to descr (job name, tmp descr ); VAX set symbol (VAX stdescr l jobname, tmp descr , 2); end;

§1602 ε-TEX 3.14159 [PD VMS 3.6] changes PART 54: SYSTEM-DEPENDENT CHANGES 231

end; 1602* . Support is provided for the mode of DEC’s Language-sensitive editor, by generating a file. Any output sent via this routine is also repeated to that file if the global copy err is print it : if the characters are being “repeated” to produce a for a directive, then characters will only be copied if no more than label max have been output; this is controlled by label size. Negative values for this variable always permit printing.

Since TEX produces its error messages by many separate calls to various printing routines, we accumulate the full text in the Pascal internal file temp file when copy err is set to save it . This file can later be reset and “played back” by standard Pascal routines.

define label max = 14 ⟨ Save printed character for diagnostic messages 1602* ⟩ ≡

case copy err of

print it : begin if label size ≠ 0 then diag char (s); if label size > 0 then decr (label size) end;

ignore it : do nothing ;

save it : temp char (s)

endcases

This code is used in section 58*.

1603* . We introduce here variables which control the action of error reporting routines. When error message display is commenced, the variable copy err is set to save it : this causes parts of the error message to be saved in the internal file temp file, which is rewound at this point. Certain parts of the error message are not so saved (copy err = ignore it ). This variable is also used to cause messages to be written (copy err = print it ) to the diagnostics file diag file. Since VAX-Pascal supports proper enumeration types, we don’t bother with defining numeric constants for this.

When information is being written to the diag file, we restrict the “label” portion of a diagnostic message to label max characters, to preserve on-screen alignment in LSEdit’s buffer. Characters are only output through to the diag file if label size is non-zero, and this variable is decremented after each character has been output if it is positive. Thus negative values of label size do not impose any restriction on the amount of text that may be output to the diag file. ⟨ Global variables 13 ⟩ +≡ copy err : (ignore it , print it , save it ); label size: −1 . . label max ; { Restricts “printing” in the file }

1604* . After the terminating period has been written, copy err is reset to prevent further output to temp file, which is also reset, ready to be “replayed” into the diagnostics file itself.

This code is also used during initialization, and also before prompting for a new file name when TEX has been unable to find a users’ file. ⟨ Ensure temp file not in use 1604* ⟩ ≡

copy err ← ignore it ; reset (temp file) { Full TEX message in temp file }

This code is used in sections 82* and 530*.

1605* . Every error message that TEX creates is “wrapped” into a environment for use by LSE’s mode.

This is the text generated for the start of such an environment. ⟨ Commence an LSE diagnostic report 1605* ⟩ ≡

wdiag ln(´ ´ ); wdiag ln(´ ␣␣ ␣ ´ )

This code is used in section 311*.

1606* . And this finishes off the environment: we copy into it the informational part of TEX’s own error message. ⟨ Terminate an LSE diagnostic report 1606* ⟩ ≡

  wdiag (´ ␣␣␣␣␣␣       ␣ %              ␣´ );

while ¬eof (temp file) do begin wdiag (temp file↑); get (temp file) end;

wdiag ln(´ ´ ); wdiag ln(´ ␣␣ ␣ ´ )

This code is used in section 311*.

1607* . If the error report arises within the expansion of a macro, TEX will report the expansions of all macros and arguments involved: each such line of information is used in the diagnostics file as a (in the terminology of LSE’s mode). This is how we start it off, and ensure that no more than label max characters are printed, thus preserving alignment of the text within the $ buffer. ⟨ Output the location to the diagnostics file 1607* ⟩ ≡

wdiag (´ ␣␣␣␣ ´ ); copy err ← print it ; label size ← label max

This code is used in section 313*.

1608* . The rest of the context (display of macro expansions, or whatever) forms the remainder of the diagnostic region label. ⟨ Prepare to copy tokens to the diagnostic region 1608* ⟩ ≡

copy err ← ignore it ; wdiag (´ ␣ ´ )

This code is used in sections 313* and 314*.

1609* . On the other hand, if TEX’s error report specifies a location within a source file, the diagnostic region generated in the diagnostics file reports that location thus: ⟨ Report location within source file to diagnostics 1609* ⟩ ≡

wdiag (´ ␣␣␣␣ ␣´ ); diag print (name); wdiag ln(´ ␣ ´ );

{ Continuation line follows }

wdiag ln(´ ␣␣␣␣␣␣␣␣␣␣  ´ , line : 1, ´  ´ )

This code is used in section 313*.

1610* . Whenever show context involves printing out a token list, we arrange to capture the printed tokens for our diagnostic file. ⟨ Include token report within diagnostics file 1610* ⟩ ≡

wdiag (´ ␣␣␣␣ ´ ); copy err ← print it ; label size ← label max

This code is used in section 314*.

1611* . As we write out the second line of the original source, split at the point of error detection, we don’t want to include within the diagnostic file the newline nor the leading spaces. This looks like horrible duplication of code, but remember that copy err = print it only if a diagnostic file is being generated. ⟨ Split the context line display 1611* ⟩ ≡

if copy err = print it then begin copy err ← ignore it ; print ln; for q ← 1 to n do print char ( ␣ ); { print n spaces to begin line 2 } copy err ← print it end

else begin print ln; for q ← 1 to n do print char ( ␣ ); { print n spaces to begin line 2 } end

This code is used in section 317*.

1612* . After we’ve completed the display of the error context, we are able to complete the diagnostic region within the diagnostics file. ⟨ Indicate offending character 1612* ⟩ ≡

if copy err = print it then begin wdiag (´ ´ ); n ← n − l; wdiag ln(n + 1 : 1, ´ ´ ); copy err ← ignore it ; end

else wdiag ln(´ ␣␣␣␣ ´ , loc − start + 1 : 1)

This code is used in section 317*.

1613* . When we are writing the remainder of the context to the terminal and/or transcript file, we need to ensure that it is also all copied to the diagnostics file.

The diagnostic is completed by “playing back” the contents of the temp file, which contains TEX’s error message. ⟨ Copy remainder of context to diagnostic file 1613* ⟩ ≡

begin copy err ← print it ; label size ← −1

end

This code is used in sections 318* and 319*.

1614* . When the primitive is used, it will later involve the display of a token; the latter would cause output to be written to the temp file used for accumulating error messages for the diagnostics file, so we ensure here that the file will not be overfilled. ⟨ Clear out the temp file 1614* ⟩ ≡

copy err ← ignore it ; rewrite(temp file); { Internal file will later be reset }

This code is used in section 1293*.

1615* . The open diag file routine is used to open a file into which error diagnostics are written to support DEC’s Language-sensitive Editor (LSEdit). These may be used by the latter to locate the editor at the position within the source file at which an error has been detected. ⟨ Declare the open diag file procedure 1615* ⟩ ≡ procedure open diag file;

begin pack job name( );

if pack default name(diag qual , diagf name, diagf len) then begin while ¬a open out (diag file) do prompt file name( ␣ ␣ , ); diag name ← a make name string (diag file); wdiag ln(´ ␣ ´ ); end

else diag name ← ;

clear default name;

end;

This code is used in section 534*.

1616* . Here are a number of variables used during the initial extraction of the command line and its qualifiers. Firstly, we require separate flags for each of the possible qualifiers.

We also need to declare those variables associated with support for the diagnostics file, utilized by LSEdit. When TEX is producing error messages, they are created in “dribs and drabs”; we utilize a Pascal ‘internal’ file temp file to accumulate the whole message for transfer to the diagnostics file.

This mechanism is also used to create a command line by means of which an editor can be invoked by the user answering ‘ ’ in response to TEX’s error prompt. Since such invocation of an editor will disrupt access to the values associated with any qualifiers on the command, we have to provide storage space for any values provided with those qualifiers, so that they may be read during the initialization phase, in preparation for use later (in some cases, much later) in the program. For each such piece of text, we need somewhere to save it, and somewhere else to record its length, for use with pack default name. ⟨ Global variables 13 ⟩ +≡ format qual , dvi qual , cmd line present , continue qual , eight qual , job qual , batch qual , log qual , diag qual ,

edit qual : boolean; diag file: alpha file; diag name: str number ; temp file: alpha file; logf name, diagf name, edit name, l jobname, dvif name: packed array [1 . . file name size] of char ; logf len, diagf len, edit len, l len name, dvif len: file size;

1617* . Since we provide a command-line qualifier which will “preload” a format file, it would be best to extract all the qualifiers before the banner gets printed, so that the correct preloaded format can be displayed (it will never really be preloaded, but a VAX doesn’t take long to read a file!) In fact, it is essential that all command-line qualifiers be read at this stage; the reader might imagine that extraction of qualifiers and their values could be deferred until the point at which the qualifier is used, but any intervening activation of another image (for example, an editor) results in the information being wiped out.

The cmd line present flag will later avoid clearing the buffer if a command-line has already been “read” into it. We can control TEX’s operation in batch mode through the qualifier.

At this point, we also initialize copy err , which controls the insertion into the diagnostics file of text being (pseudo)printed in traditional TEX error message. ⟨ Extract command-line and qualifiers 1617* ⟩ ≡

diag name ← 0; get command line;

if batch qual then interaction ← batch mode;

copy err ← ignore it

This code is used in section 1332*.

1618* . For interacting with a user-supplied command line, we need to call the VAX standard library routines $ , $ , $ and $ . This is a definition of their external interfaces: note the application of the ‘external’ attribute, and use of the extern directive.

define VAX external ≡ \underline{\overline{␣}} define VAX asynchronous ≡ \underline{\overline{␣}} define VAX cli dcl parse ≡ \underline{\overline{␣ $}} define VAX lib get foreign ≡ \underline{\overline{␣ $}} define VAX lib sig to ret ≡ \underline{\overline{␣ $}} define VAX establish ≡ \underline{\overline{␣}}

⟨ VMS procedures 34* ⟩ +≡

[VAX external ] function VAX cli present (VAX stdescr entity : [VAX volatile, VAX readonly ]

packed array [l1 . . u1 : integer ] of char ← VAX immed 0): integer ; extern;

[VAX external ] function VAX cli get value (

VAX stdescr entity : [VAX volatile, VAX readonly ] packed array [l1 . . u1 : integer ] of

char ← VAX immed 0; VAX stdescr returns : [VAX volatile] packed array [l2 . . u2 : integer ] of char ← VAX immed 0; var retlen: [VAX volatile]sixteen bits ← VAX immed 0 ) : integer ;

extern; [VAX external ]

function VAX cli dcl parse(VAX stdescr cmdline: [VAX volatile, VAX readonly ]

packed array [l1 . . u1 : integer ] of char ← VAX immed 0; VAX immed cld table: [VAX volatile, VAX readonly ]VAX unsigned ← VAX immed 0): integer ;

extern; [VAX external ]

function VAX lib get foreign ( VAX stdescr cmdlin: [VAX volatile] packed array [l1 . . u1 : integer ] of char ← VAX immed 0; VAX stdescr prompt : [VAX volatile] packed array [l2 . . u2 : integer ] of char ← VAX immed 0; var len: [VAX volatile]sixteen bits ← VAX immed 0; var flag : [VAX volatile]integer ← VAX immed 0 ) : integer ;

extern; [VAX external , VAX asynchronous ]

function VAX lib sig to ret (VAX ref signal args : [VAX volatile, VAX unsafe] array [l1 . . u1 : integer ] of

[VAX byte]eight bits ; VAX ref mechan args : [VAX volatile, VAX unsafe] array [l2 . . u2 : integer ] of

[VAX byte]eight bits ): integer ; extern;

1619* . The following global symbol is used to refer to the command definition table linked into the TEX program

define eTeX CLD table ≡ \underline{\overline{}} ⟨ Global variables 13 ⟩ +≡ eTeX CLD table: [VAX external , VAX readonly ]VAX unsigned ; 1620* . The init cli function is invoked right at the beginning of TEX, only preceded by the terminal output initialization. Its purpose is to make sure that the DCL command interface is available.

This function checks, if the program was invoked by the DCL command specified through verb name and that a command qualifier specified by qual name is present (or defaulted) in the command description. For the second test, a small subroutine check cli is needed, because of the ”caller–callee” dependence required by the user error handler facility. The verb name string supplied to init cli by the caller must not exceed a length of 4, otherwise the comparison with the ”last DCL command” does never succeed, because the DCL parser truncates commands to a length of 4! The test item qual name should be a specific, non-negatable command qualifier for the verb verb name, which is set by default in the command description.

If either of these two tests fail, it can be assumed that the program was invoked as a foreign command (or started by the RUN command). If this case, the command line tail is fetched with the $ runtime functions and parsed internally, using the $ utility routine and the command table linked into the program executable, whose name is supplied by the table formal parameter. ⟨ Last-minute procedures 1333* ⟩ +≡ function init cli (var table : [VAX readonly ]VAX unsigned ; verb name : [VAX readonly ]

packed array [l1 . . u1 : integer ] of char ; qual name: [VAX readonly ] packed array [l2 . . u2 : integer ] of char ): integer ; label exit ; var command line: packed array [1 . . 256] of char ;

len: sixteen bits ; sts : integer ; function check cli (unique def qual : [VAX readonly ] packed array [l1 . . u1 : integer ] of

char ): integer ; begin VAX establish(VAX lib sig to ret ); check cli ← VAX cli present (unique def qual ); end;

begin sts ← VAX cli get value(´ $ ´ , command line, len);

if (odd (sts ) ∧ (len > 0)) then

if (VAX substr (command line, 1, len) = verb name) then

if (odd (check cli (qual name))) then begin init cli ← 1; return; end;

VAX lib get foreign(command line, , len); { prepend verb name plus a blank to command line } command line ← verb name + ´ ␣´ + VAX substr (command line, 1, len); init cli ← VAX cli dcl parse(command line, VAX address of (table));

exit : end; 1621* . Logically, the following procedure belongs with init terminal ; however, we can’t declare it there because it calls functions which don’t get declared until later, so we’ll stuff it in just before the main program starts.

If an editor is invoked later, its use of the command-line interface parsing routines will “disable communications”, so we’d better extract any values associated with qualifiers now. The various flags are set or cleared according as to whether the associated qualifier is or is not present. ⟨ Last-minute procedures 1333* ⟩ +≡ procedure get command line;

var qual argument : packed array [1 . . 256] of char ;

len: sixteen bits ; i: integer ; j: 0 . . buf size; begin cmd line present ← odd (VAX cli present (´ ´ )); edit qual ← odd (VAX cli present (´ ´ )); if edit qual then VAX cli get value(´ ´ , edit name, edit len); job qual ← odd (VAX cli present (´ ´ )); if job qual then VAX cli get value(´ ´ , l jobname, l len name); continue qual ← odd (VAX cli present (´ ´ )); batch qual ← odd (VAX cli present (´ ´ )); dvi qual ← odd (VAX cli present (´ ´ )); if dvi qual then VAX cli get value(´ ´ , dvif name, dvif len); log qual ← odd (VAX cli present (´ ´ )); if log qual then VAX cli get value(´ ´ , logf name, logf len); diag qual ← odd (VAX cli present (´ ´ )); if diag qual then VAX cli get value(´ ´ , diagf name, diagf len); format qual ← odd (VAX cli present (´ ´ ));

if format qual then

begin VAX cli get value(´ ´ , qual argument , len); loc ← 0; buffer [0] ← xord [´ ´ ]; j ← 1; for i ← 1 to len do

begin buffer [j] ← xord [qual argument [i]]; incr (j)

end; buffer [j] ← xord [´ ␣´ ]; { open fmt file requires space after name } if format ident ≠ 0 then initialize; if ¬open fmt file then goto final end ; if ¬load fmt file then

begin w close(fmt file); goto final end ;

end; w close(fmt file); end;

end;

1622* . Here are the things we need for byte file and word file files: ⟨ Global variables 13 ⟩ +≡ tfm count : 0 . . VAX block length; fmt count : 0 . . VAX block length; 1623* . Here’s the interrupt stuff.

At this point, we define some attributes for specifying particular sizes and alignments of numerical quantities in VAX-Pascal.

define VAX word ≡ \underline{\overline{␣ ␣}} define VAX longword ≡ \underline{\overline{␣ ␣}} define VAX byte ≡ \underline{\overline{␣ ␣}} define VAX unsigned ≡ \underline{\overline{␣ ␣}}

⟨ Types in the outer block 18 ⟩ +≡ signed halfword = [VAX word ] − 32768 . . 32767; sixteen bits = [VAX word ]0 . . 65535; file size = [VAX word ]0 . . file name size; VAX F float = packed record { Bit pattern layout of F-Floating Reals }

Frac1 : 0 . . 127; { the 7 MSBits of the mantissa } Expo: 0 . . 255; { 8 bit exponent } Sign: boolean; { 1 sign bit } Frac: 0 . . 65535; { the 16 lower bits of the mantissa } end;

1624* . ⟨ Global variables 13 ⟩ +≡ res : [VAX volatile]integer ; tt chan: [VAX volatile]signed halfword ;

1625* . ⟨ VMS procedures 34* ⟩ +≡ [VAX asynchronous ] procedure ctrlc rout ;

begin interrupt ← 1; enable control C ;

end;

1626* . Here is the stuff for magic file operations.

define VAX FAB type ≡ \underline{\overline{␣ $ ␣}} define VAX RAB type ≡ \underline{\overline{␣ $ ␣}} define VAX NAM type ≡ \underline{\overline{␣ $ ␣}}

⟨ Types in the outer block 18 ⟩ +≡ unsafe file = [VAX unsafe] file of char ; FAB ptr = ↑VAX FAB type; RAB ptr = ↑VAX RAB type; NAM ptr = ↑VAX NAM type; chrptr = ↑char ; 1627* . We supply the following two routines to be used (in a call of the VAX-Pascal open procedure) as a user action function. When called from within the open routine, the addresses of the FAB and RAB allocated to the file are passed to such a function, along with the file variable; the latter is tagged as ‘unsafe’ to prevent undesirable compiler optimizations.

The user reset function, used to open files for reading, performs wild card expansion on the file specification and opens the first matching file.

Both user action functions copy the fully qualified name of the file that was actually opened into the global variable last name. Additionally, the basename part of the filename is available in the string variable last basename. The latter string is converted to lowercase; to comply with normal usage on other (casesensitive) operating systems.

The two external functions VAX PAS FAB and VAX PAS RAB permit access by the program to these structures after the file has been opened.

define VAX rms parse ≡ \underline{\overline{$}} define VAX rms search ≡ \underline{\overline{$}} define VAX rms create ≡ \underline{\overline{$}} define VAX rms connect ≡ \underline{\overline{$}} define VAX rms open ≡ \underline{\overline{$}}

define VAX FAB V NAM ≡ \underline{\overline{$}} define VAX FAB L NAM ≡ \underline{\overline{$}} define VAX NAM B RSL ≡ \underline{\overline{$}} define VAX NAM L RSA ≡ \underline{\overline{$}} define VAX NAM B NAME ≡ \underline{\overline{$}} define VAX NAM L NAME ≡ \underline{\overline{$}}

⟨ VMS procedures 34* ⟩ +≡ function user reset (var FAB : VAX FAB type; var RAB : VAX RAB type; var F : unsafe file): integer ;

label done; var sts : integer ; NAM : NAM ptr ; p: chrptr ; i: integer ; ichr : integer ; begin last length ← 0; sts ← VAX rms parse(FAB ); if ¬odd (sts ) then goto done; sts ← VAX rms search(FAB ); if odd (sts ) then FAB .VAX FAB V NAM ← true; { Use NAM block in VAX rms open call! } sts ← VAX rms open(FAB ); if ¬odd (sts ) then goto done; sts ← VAX rms connect (RAB ); if ¬odd (sts ) then goto done; NAM ← FAB .VAX FAB L NAM :: NAM ptr ; if NAM = nil then goto done; last length ← NAM ↑.VAX NAM B RSL; for i ← 1 to last length do

begin p ← (NAM ↑.VAX NAM L RSA :: integer + i − 1) :: chrptr ; last name[i] ← p↑; end;

last basenam len ← NAM ↑.VAX NAM B NAME ; for i ← 1 to last basenam len do

begin p ← (NAM ↑.VAX NAM L NAME :: integer + i − 1) :: chrptr ; ichr ← ord (p↑); if (ichr > 64) ∧ (ichr < 91) then ichr ← ichr + 32; last basename[i] ← chr (ichr ); end;

done: user reset ← sts ;

end; function user rewrite(var FAB : VAX FAB type; var RAB : VAX RAB type; var F : unsafe file): integer ; label done; var sts : integer ; NAM : NAM ptr ; p: chrptr ; i: integer ; ichr : integer ; begin sts ← VAX rms create(FAB ); if ¬odd (sts ) then goto done; sts ← VAX rms connect (RAB ); if ¬odd (sts ) then goto done; NAM ← FAB .VAX FAB L NAM :: NAM ptr ; if NAM = nil then goto done; last length ← NAM ↑.VAX NAM B RSL; for i ← 1 to last length do

begin p ← (NAM ↑.VAX NAM L RSA :: integer + i − 1) :: chrptr ; last name[i] ← p↑; end;

last basenam len ← NAM ↑.VAX NAM B NAME ; for i ← 1 to last basenam len do

begin p ← (NAM ↑.VAX NAM L NAME :: integer + i − 1) :: chrptr ; ichr ← ord (p↑); if (ichr > 64) ∧ (ichr < 91) then ichr ← ichr + 32; last basename[i] ← chr (ichr ); end;

done: user rewrite ← sts ;

end; function VAX PAS FAB (var foobar : unsafe file): FAB ptr ; extern; function VAX PAS RAB (var foobar : unsafe file): RAB ptr ; extern;

1628* . ⟨ Global variables 13 ⟩ +≡ in FAB , out FAB : FAB ptr ; in RAB , out RAB : RAB ptr ; last length: integer ; last name: packed array [1 . . file name size] of char ; last basenam len: integer ; last basename: packed array [1 . . file name size] of char ; 1629* . The following procedure is used to translate any logical name that may appear as its parameter into its equivalence string and makes use of the $ system service in place of the obsolete $ . If the content of the buffer is a logical name, it is replaced by its equivalence string and the routine returns true. If no translation can be found, the result is false, and the original string is left unchanged.

The VAX-Pascal procedure substr is used to extract a substring into the varying array which is passed to the system service, whilst another VAX-specific function iaddress is used to obtain the address of various data items to fill in the item list .

define VAX trnlnm ≡ \underline{\overline{␣$}}

define VAX lnm case blind ≡ \underline{\overline{␣ $ ␣}}

define VAX lnm string ≡ \underline{\overline{␣ $ ␣}}

define VAX substr ≡ \underline{\overline{␣}}

define VAX address of ≡ \underline{\overline{␣}} ⟨ VMS procedures 34* ⟩ +≡ function translate ( var t : packed array [l1 . . u1 : integer ] of char ;

var len: signed halfword ) : boolean;

var s: varying [file name size] of char ; trnlnm return: integer ; { what did the $ return? } return length: [VAX volatile]integer ; attributes : unsigned ; item list : [VAX volatile] array [0 . . 1] of

VMS item list ; begin s ← VAX substr (t, 1, len); attributes ← VAX lnm case blind ; return length ← 0; with item list [0] do

begin buffer length ← file name size; item code ← VAX lnm string ;

buffer addr ← VAX address of (t); ret len addr ← VAX address of (return length); end;

item list [1].next item ← 0;

trnlnm return ← VAX trnlnm(attributes , ´ $ ´ , s, , item list ); len ← return length; translate ← trnlnm return = VAX ss normal ; end;

1630* . Here is a new type introduced to support $ . Many VMS system services make use of an item list to pass information in and out. An item list consists of a number of item list elements, with each element containing the following fields:

Name  Type  Usage
buffer length 16-bit word  Size of buffer
item code  unsigned 16-bit word Code for desired operation
buffer address Pointer to char  Address of buffer
ret len addr Pointer to integer To receive length of translation

This structure is overlaid with a single 32-bit integer whose use is solely to hold the value zero indicating the end of the list. ⟨ Types in the outer block 18 ⟩ +≡

VMS item list = packed record case boolean of

true: (buffer length : sixteen bits ; item code : sixteen bits ; buffer addr : [VAX longword ]integer ;

ret len addr : [VAX longword ]integer ); false: (next item : [VAX longword ]integer ) end; 1631* . If the user, in response to TEX’s error message, elects to edit the source file, then we have to find some method of invoking an editor. The simplest solution, under VMS, is simply to spawn a sub-process, but this is expensive in terms of image activation and might leave the sub-process short of page file quota, since the latter is shared by all processes in the current ‘job’.

Therefore, where possible, we invoke a “callable” editor, which merely requires that we find the relevant editor’s entry point in an installed shareable image. However, the library routine which can perform this trick returns the entry point as an address, and yet we want the Pascal code to think that it’s invoking the editor through a procedure call, passing appropriate parameter(s).

The callable versions of LSEdit and TPU each require a single parameter which is a string similar to the DCL command that could be used to invoke the non-callable versions. In the case of EDT and TECO, the first parameter gives the name of the file to be edited, the second (if used) names the output file, whilst the third can specify the name of a command file. Both editors can also take further parameters, and their meanings differ, but luckily we don’t need any of these other parameters!

Unfortunately, Pascal provides no mechanism by which a routine, which has amongst its formal parameters one which is in turn another routine, may be called with anything but the name of an actual routine (with congruent parameters) substitued for that formal parameter. Therefore, it is not permissible to pass the address of the routine instead and yet that is all that we have available!

We therefore provide a procedure which calls, in turn, the actual editor “procedure”, and resorting to subterfuge, invoke a rather useful VAX Library Routine:

define VAX lib callg ≡ \underline{\overline{␣ $}} ⟨ VMS procedures 34* ⟩ +≡

[VAX external ] function VAX lib callg (VAX immed arg list : [VAX longword ]integer ;

VAX immed user proc: [VAX longword ]integer ): integer ; extern; function call editor (proc : [VAX longword ]integer ; param 1 , param 3 : [VAX volatile]descr ptr ): integer ;

var call G descriptor : packed array [1 . . 4] of [VAX longword ]integer ;

begin call G descriptor [1] ← 1; { Number of arguments }

call G descriptor [2] ← param 1 :: integer ; { DCL-like command line or name of file to be edited } if param 3 ≠ nil then

begin call G descriptor [1] ← 3; { EDT and TECO require more arguments } call G descriptor [3] ← 0; { Default the output file name } call G descriptor [4] ← param 3 :: integer ; { Editor command file } end;

call editor ← VAX lib callg (VAX address of (call G descriptor ), proc)

end; 1632* . Here is the interface to two routines from the run-time library to handle dynamic strings. Also, we declare here the interface to the $ library function, because we don’t have much else to fall back on if an error crops up whilst allocating strings!

define str allocate ≡ \underline{\overline{␣ $}} define str release ≡ \underline{\overline{␣ $}} define lib signal ≡ \underline{\overline{␣ $}} define VAX char string ≡ \underline{\overline{␣ $ ␣}} define VAX class S ≡ \underline{\overline{␣ $ ␣}} define VAX class D ≡ \underline{\overline{␣ $ ␣}}

⟨ VMS procedures 34* ⟩ +≡

[VAX external , VAX asynchronous ] function str allocate(VAX ref alloc: [VAX readonly ]sixteen bits ;

VAX immed descrp: descr ptr ): integer ; extern; [VAX external , VAX asynchronous ]

function str release(VAX immed descrp: descr ptr ): integer ; extern;

[VAX external , VAX asynchronous ] procedure lib signal (VAX immed cond code: integer ;

VAX immed num of args : integer ← VAX immed 0; VAX immed fao argument : [ \underline{\overline{}}]integer ); extern;

1633* . Some editors require either command or file specifications to be passed to them as parameters, which in turn requires that they be passed in the form of string descriptors. Many of the strings that we have to deal with are held within TEX’s string pool.

This routine converts a -type string (from the pool) into an appropriate VAX-Pascal string descriptor. Any existing string described by dynam str is returned to the operating system and a new string allocated to reflect the actual length of the string in pool string . ⟨ VMS procedures 34* ⟩ +≡ procedure str to descr (pool string : str number ; var dynam str : [VAX volatile]descr ptr );

var ch ptr , str stat : integer ; str size: sixteen bits ; ch ctr : chrptr ; begin if dynam str = nil then

begin new (dynam str );

with dynam str ↑ do begin len ← 0; desc type ← VAX char string ; desc class ← VAX class D ; string ← 0 end;

end else if dynam str ↑.len ≠ 0 then

begin str stat ← str release(dynam str ); if ¬odd (str stat ) then lib signal (str stat ) end;

ch ptr ← str start [pool string ]; str size ← str start [pool string + 1] − str start [pool string ]; str stat ← str allocate(str size, dynam str ); if ¬odd (str stat ) then lib signal (str stat ); ch ctr ← dynam str ↑.string :: chrptr ; while str size > 0 do

begin ch ctr ↑ ← xchr [so(str pool [ch ptr ])]; ch ctr ← (ch ctr :: integer + 1) :: chrptr ; incr (ch ptr ); decr (str size) end;

end; 1634* . Here is where we declare a structure to hold a VMS Descriptor. We could just have used one of the definitions in the library that we’ve inherited, but declaring it here is an aid to understanding.

Name  Type  Usage
len  16-bit word  Elements in the array
desc type unsigned 8-bit byte Type of items in array
desc class unsigned 8-bit byte e.g. Fixed, Varying, Dynamic
string Pointer to char Address of first item in array

It also makes life much easier, when passing dynamic strings as parameters, especially to system services and library routines which expect to be passed the address of such a descriptor, to have a type which is a pointer to such a descriptor, and then pass the pointer’s value by immediate parameter-passing mechanism. ⟨ Types in the outer block 18 ⟩ +≡

descr type = packed record { A VAX-descriptor object } len: sixteen bits ; desc type: eight bits ; desc class : eight bits ; string : [VAX longword ]integer ; end;

descr ptr = ↑descr type;

1635* . Here is a procedure to dispose of dynamically-allocated strings when they are no longer required. ⟨ VMS procedures 34* ⟩ +≡ procedure release(string : descr ptr );

var str stat : integer ;

begin if string ≠ nil then begin str stat ← str release(string ); if ¬odd (str stat ) then lib signal (str stat ); dispose(string ); string ← nil; end;

end;

1636* . This version of TEX supports various editors; that required by the user must be specified by the

qualifier  which is set by default to  (which should be defined as a VMS logical name, in
analogy with  $  —in fact some system managers may want to set the default in the CLD file to be
$  ). If this qualifier specifies one of the strings ‘  ’, ‘  ’, ‘  or

‘ ’ (or a logical name translating to one of those strings), the appropriate editor is invoked from its callable shared image. Any other value for is treated as a DCL command, and a sub-process is spawned in which the command is executed; the name of the file to be edited, together with the location of the error, are passed as parameters to this DCL command, which will most usefully, therefore, be defined to invoke a command procedure. Because the original version of this change file simply used directly and this is the default value, the remainder of this exposition will simply refer to the value of as .

Here is a data structure which holds details of the supported callable editors: ⟨ Types in the outer block 18 ⟩ +≡

editor ident = record cmd offset : integer ; image, entry , quitting , exiting , cmd text : str number ; start qual , EDT like: boolean; logical : packed array [1 . . file name size] of char ; end; 1637* . We need a suitably sized array of such structures:

define max editor = 4 define LSE editor = 1 define TPU editor = 2 define EDT editor = 3 define TECO editor = 4

⟨ Global variables 13 ⟩ +≡ editor : packed array [1 . . max editor ] of editor ident ;

1638* . And we needs must initialize them: ⟨ Set initial values of key variables 21 ⟩ +≡

with editor [LSE editor ] do

begin logical ← ´  ´ ; image ←  ; entry ←  $  ;
quitting ←  $  ; exiting ←  $  ; cmd text ←  ; cmd offset ← 0;

start qual ← true; EDT like ← false; end;

with editor [TPU editor ] do

begin logical ← ´  ´ ; image ←  ; entry ←  $  ;
quitting ←  $  ; exiting ←  $  ; cmd text ←  ; cmd offset ← 5;

{ Actual command expected by $ omits } start qual ← true; EDT like ← false; end;

with editor [EDT editor ] do begin logical ← ´ ´ ; image ← ; entry ← $ ; quitting ← 0; exiting ← 0; cmd text ← ; cmd offset ← 0; start qual ← false; EDT like ← true; end;

with editor [TECO editor ] do begin logical ← ´ ´ ; image ← ; entry ← $ ; quitting ← 0; exiting ← 0; cmd text ← ; cmd offset ← 0; start qual ← false; EDT like ← true; end;

1639* . When we invoke an editor, there are three (possibly more?) potential outcomes: (1) The editor cannot be invoked — perhaps we should find some other method; (2) The user makes no change to the file (quits); (3) The use produces a new version of the file. This type allows us to discriminate between these outcomes: ⟨ Types in the outer block 18 ⟩ +≡

edit result = (failed , quit , edited ); 1640* . If the user elects to edit the relevant input file in response to an error message, we prefer to use an editor provided as a “callable image”, since this saves the overhead of spawning a sub-process. DEC provide callable versions of EDT, TPU, LSEdit (the language-sensitive editor, highly recommended for L^{A}TEX), and even for that editor beloved of many, TECO.

To activate such a callable image, we need to load it into the process’s space, and determine its entry point before transferring control to it with appropriate parameters.

If it proves impossible to load a suitable callable image, we can adopt the expedient of spawning a new (DCL) sub-process, and pass to it the command to be executed. When such a spawned sub-process is given a single command to execute, the exit status of that command is passed back to the parent process when the sub-process exits. In most useful applications of such a sub-process, the “command” to be executed will be a DCL command procedure; the code below will accept an exit status of 1 as indicating that an edit has taken place, the value 0 (which is of warning severity level) as showing that the edit was aborted (the user quit), and any other value will be interpreted as indicative of a failure of the sub-process to perform editing.

The official definition of $ has about a dozen parameters, but since all of them are optional, and we only need to pass a command (which is the first parameter) and get back the completion status (which is the seventh), we’ll pretend that it only takes seven parameters.

define VAX find image ≡ \underline{\overline{␣ $}} define VAX lib spawn ≡ \underline{\overline{␣ $}}

⟨ VMS procedures 34* ⟩ +≡

[VAX external ] function VAX find image(VAX immed filenm: descr ptr ;

VAX immed symbol : descr ptr ; VAX ref symbol value: [VAX volatile, VAX longword ]integer ; VAX immed image name: descr ptr ← VAX immed 0): integer ;

extern;

[VAX external ] function VAX lib spawn(VAX immed cmd : descr ptr ;

VAX immed sys input : descr ptr ← VAX immed 0; VAX immed sys output : descr ptr ← VAX immed 0; VAX ref flags : [VAX longword ]integer ← VAX immed 0; VAX immed prcnm: descr ptr ← VAX immed 0; VAX ref pid : [VAX longword ]integer ← VAX immed 0; VAX ref status : [VAX longword ]integer ← VAX immed 0): integer ;

extern;

function Edit (filenm, cmd file : str number ; editor : editor ident ): edit result ;

var edit command line: descr ptr ; char ct : sixteen bits ; editor entry : integer ; editor status , str stat : integer ; ch ptr : chrptr ; quit status , exit status : integer ; image symbol , entry point , bad symbol , good symbol : descr ptr ; edit file, edit cmd : descr ptr ;

begin ⟨ Determine length of the editor command 1647* ⟩; edit command line ← nil; ⟨ Copy editor command into dynamic string 1648* ⟩; edit file ← nil; edit cmd ← nil; if editor .EDT like then { Such editors take filenames as parameters }

begin str to descr (filenm, edit file); str to descr (cmd file, edit cmd );

end; Edit ← failed ; { Assume the worst! } editor status ← 4; { Neither edited nor quitted } quit status ← 0; { Users’ command procedures can return this for quitting } exit status ← VAX ss normal ; ⟨ Create names of symbols to be sought 1641* ⟩; if editor .image ≠ 0 then { Possibly callable }

begin if VAX find image(image symbol , entry point , editor entry ) = VAX ss normal then ⟨ Load shareable image and call the editor 1642* ⟩ else editor .image ← 0 { Indicate inability to invoke shareable image } end;

if editor .image = 0 then { Use non-shareable-image editing }

str stat ← VAX lib spawn(cmd ← edit command line, status ← editor status ); ⟨ Dispose of dynamic strings used by Edit 1643* ⟩; ⟨ Interpret exit status of editor 1644* ⟩ end;

1641* . The data structure editor contains pool strings giving the name of the required shareable image and the names of symbols which are to be sought for in it. This is where we translate those strings into dynamic ones to be passed to $ ⟨ Create names of symbols to be sought 1641* ⟩ ≡

image symbol ← nil; entry point ← nil; bad symbol ← nil; good symbol ← nil; str to descr (editor .image, image symbol ); str to descr (editor .entry , entry point ); str to descr (editor .quitting , bad symbol ); str to descr (editor .exiting , good symbol )

This code is used in section 1640*.

1642* . If we’re to invoke a callable editor, we have now obtained its entry point, which will have caused its image to be loaded into the process’s space. Now we find within the image the values associated with the symbols which indicate whether the editor was used to create a new file or whether the use quit without creating a new file (only possible for LSEdit and TPU; with EDT and TECO, we assume that any successful exit resulted in the creation of a new file). ⟨ Load shareable image and call the editor 1642* ⟩ ≡

begin ⟨ Preset anticipated exit statuses of the called editor 1645* ⟩;

if editor .EDT like then editor status ← call editor (editor entry , edit file, edit cmd )

else ⟨ Invoke callable LSEdit or TPU 1646* ⟩;

end

This code is used in section 1640*.

1643* . Just to keep things tidy, we dispose of all dynamic strings used by Edit before exit; this ensures that repeated invocation of an editor will not result in the “eating up” of virtual memory. ⟨ Dispose of dynamic strings used by Edit 1643* ⟩ ≡

release(image symbol ); release(entry point ); release(bad symbol ); release(good symbol ); release(edit command line); release(edit file); release(edit cmd );

This code is used in section 1640*.

1644* . After the editor, whether running in a spawned sub-process or as a callable version in a shared image, has returned control to TEX, we attempt to interpret its exit status. Having removed any flag instructing the CLI to ignore the error status (because the editor will have reported such an error already), we attempt to match the exit status against the values which we have preset as indicating normal exit or quit from the editor. Any other value will leave the value failed to be returned by Edit : this should cause TEX to inform the user that the edit will have to be performed “off-line”. ⟨ Interpret exit status of editor 1644* ⟩ ≡

if editor status ≥ VAX ss ignore then editor status ← editor status − VAX ss ignore; if editor status = exit status then Edit ← edited else if editor status = quit status then Edit ← quit

This code is used in section 1640*.

1645* . As well as containing the entry point at which the callable editor should be entered, its image file may also contain global symbols which give the exit status which will be returned by the editor if the user exits successfully, having written a new file, or quits without writing a new file. We extract the values of these symbols so that this status can be interpreted on exit from this procedure Edit . ⟨ Preset anticipated exit statuses of the called editor 1645* ⟩ ≡

if editor .quitting ≠ 0 then

if ¬odd (VAX find image(image symbol , bad symbol , quit status )) then quit status ← VAX ss normal ; if editor .exiting ≠ 0 then

if ¬odd (VAX find image(image symbol , good symbol , exit status )) then exit status ← VAX ss normal

This code is used in section 1642*.

1646* . If we’re invoking the callable version of TPU, we have to remove the ‘  ’ from the ‘  ’

command that we’ve constructed in edit command line. This code removes the first editor .cmd offset characters of the command by overwriting with spaces, which achieves the desired effect.

We then invoke the editor through call editor . ⟨ Invoke callable LSEdit or TPU 1646* ⟩ ≡

begin ch ptr ← edit command line↑.string :: chrptr ;

for char ct ← 1 to editor .cmd offset do begin ch ptr ↑ ← ´ ␣´ ; { Expunge the first cmd offset characters } ch ptr ← (ch ptr :: integer + 1) :: chrptr end;

editor status ← call editor (editor entry , edit command line, nil); end

This code is used in section 1642*.

1647* . So far, we’ve managed to construct in the temp file a command to be passed to the callable editor (through appropriate diversion to that Pascal internal file during the analysis of the logical ). So that we can allocate an appropriately sized dynamic string and its descriptor to be passed to the callable image, we need initially to determine how long that command really is: ⟨ Determine length of the editor command 1647* ⟩ ≡

reset (temp file); char ct ← 1;

while ¬eof (temp file) do begin get (temp file); incr (char ct ) end

This code is used in section 1640*.

1648* . Now we can allocate the dynamic string to hold the editor command, and copy the latter into it. Perhaps it might be thought that this could be simplified, because we could “replay” the command from the temp file into a pool string by setting selector to new string and then using str to descr : however, I’m not sure that this would be safe if in so doing we exceeded the allocated string pool, so we’re going to do a bit more work! ⟨ Copy editor command into dynamic string 1648* ⟩ ≡

new (edit command line);

with edit command line↑ do begin len ← 0; desc type ← VAX char string ; desc class ← VAX class D ; string ← 0 end;

str stat ← str allocate(char ct , edit command line);

if ¬odd (str stat ) then lib signal (str stat );

ch ptr ← edit command line↑.string :: chrptr ; reset (temp file);

while ¬eof (temp file) do begin ch ptr ↑ ← temp file↑; get (temp file); ch ptr ← (ch ptr :: integer + 1) :: chrptr end

This code is used in section 1640*.

1649* . Certain VAX callable editors ( and ) accept a qualifier which may be used to specify the row and column number at which the editor’s cursor is to be positioned. This routine adds suitable characters to the editor command line currently under construction in temp file. ⟨ Basic printing procedures 56* ⟩ +≡ procedure edit locate(line, col : integer );

begin print ( ); print int (line); print char ( ); print int (col ); print ( ␣ )

end;

1650* . The function edit file is called from the error reporting routine with the context of an input file and the line number as parameters. It forms a command for the desired editor (making using of temp file and various of the error printing routines).

The function returns true if it was able to invoke an editor. If false is returned, the user-interface routine should tell the user what and where to edit, and exit from TEX.

First of all, we need to make a forward declaration in order that the code which interprets the user’s response can be compiled to call this procedure. ⟨ Basic printing procedures 56* ⟩ +≡ function edit file(stack item : in state record ; line : integer ): boolean; forward ; 1651* . But the function itself needs to follow all those declared in modules, so we put it just before the main program itself.

To determine what name to use in invoking the editor, this function attempts to translate the value of ; if the translation is recognized, then we’ll use that as the value, otherwise, we’ll use the value given by . If the editing of the file has (or could have) created a new version of the source file, then steps are taken to ensure that further edits all access the newly created file(s) rather than the original. ⟨ Last-minute procedures 1333* ⟩ +≡ function edit file; { (stack item : in state record ; line : integer ): boolean }

var equivalence: packed array [1 . . file name size] of char ; equv len: signed halfword ; old setting : integer ; edit status : edit result ; edit ctr : integer ; edit found : integer ; ⟨ Variables for edit file 1657* ⟩

begin old setting ← selector ; selector ← log only ; edit file ← false; edit status ← failed ;

{ Assume the worst! } equivalence ← edit name; equv len ← edit len;

if edit qual then

if equivalence[equv len] = ´ ´ then begin equivalence[equv len] ← ´ ␣´ ; decr (equv len); edit qual ← translate(equivalence, equv len); end;

if edit qual then ⟨ Attempt to invoke desired editor 1652* ⟩; if edit status ≠ failed then

begin edit file ← true;

if edit status = edited then ⟨ Remove version number from file specification 1662* ⟩ end;

selector ← old setting ; end;

1652* . If the logical has a suitable translation, we attempt to identify the “preferred” editors (preferred in the sense that they can be invoked from a shareable image, without the overhead of spawning a new process). ⟨ Attempt to invoke desired editor 1652* ⟩ ≡

begin print nl ( ␣ ␣ ␣ ); ⟨ Upcase the equivalence string 1653* ⟩; ⟨ Attempt to recognize name of editor 1654* ⟩; if edit found ≠ 0 then ⟨ Invoke callable editor 1655* ⟩ else ⟨ Invoke editor in a sub-process 1664* ⟩; copy err ← ignore it ; selector ← old setting ; end

This code is used in section 1651*.

1653* . The equivalence string for needs to be converted to upper-case, to ensure that it may be matched to the names of the preferred editors. ⟨ Upcase the equivalence string 1653* ⟩ ≡

for edit ctr ← 1 to equv len do

if equivalence[edit ctr ] ∈ [´ ´ . . ´ ´ ] then

equivalence[edit ctr ] ← xchr [xord [equivalence[edit ctr ]] + − ]

This code is used in section 1652*.

1654* . Now that we have the equivalence string in upper-case, we attempt to match it with the names of the preferred editors in the data structure editor .

For testing equality between two strings, we use VAX-Pascal’s index function. define VAX index ≡ \underline{\overline{␣}}

⟨ Attempt to recognize name of editor 1654* ⟩ ≡ edit ctr ← 1; edit found ← 0; while (edit ctr ≤ max editor ) ∧ (edit found = 0) do

begin if VAX index (editor [edit ctr ].logical , equivalence) = 1 then edit found ← edit ctr ; incr (edit ctr ) end;

This code is used in section 1652*.

1655* . Well, we now know that the user wishes to use one of the supported callable editors. So the next move is to construct suitable command strings and invoke the editor from the appropriate shareable image. ⟨ Invoke callable editor 1655* ⟩ ≡

with editor [edit found ] do begin rewrite(temp file); copy err ← save it ; print nl (cmd text );

if start qual then

with stack item do edit locate(line, loc field − start field + 1); if edit found = EDT editor then ⟨ Create command file 1656* ⟩; if edit found = TECO editor then ⟨ Create command file 1658* ⟩; print (stack item.name field ); copy err ← ignore it ; selector ← old setting ;

if EDT like then

begin edit status ← Edit (stack item.name field , cmd file, editor [edit found ]); ⟨ Delete an editor command file 1661* ⟩ end

else edit status ← Edit (0, 0, editor [edit found ]); end

This code is used in section 1652*.

1656* . The common-or-garden editor doesn’t have a qualifier to specify the starting position, so we create a small command file, and specify its name on the qualifier for

The command file contains line-mode commands to position the cursor appropriately. Strictly speaking, it is illegal to issue a command (which is the only one that accepts no-keypad commands to position the cursor) except from a terminal, and will display a message about this when it executes the command from the command file; however, it does honour the command correctly, so the end does justify the means!

It seemed too complicated to try to delve into TEX’s “whatsits”, and yet we’ll want to use print , etc, to transfer text into the file. Previous versions of the VMS implementation tried to create the file using the first free file in the array write file. But this approach failed, if TEX has got all sixteen available files in use (although this is a rare case). To prevent this interference with TeX’s own use of its output streams, the present solution uses a dedicated file edcmd file for creating the editor command file. It is access by setting selector to the additional mode edcmd write. ⟨ Create command file 1656* ⟩ ≡

begin name of file ← ´ ´ ; default name ← ´ ´ ;

if a open out (edcmd file) then begin cmd file ← make name string ; equivalence ← ´ ´ ; equv len ← 6; { If it’s defined } if ¬translate(equivalence, equv len) then equv len ← 6; copy err ← ignore it ; selector ← edcmd write; print ( ␣ ); print ln; print ( ␣ ); print int (line); print char ( ); with stack item do print int (loc field − start field ); print ( ); print ln; print ( ␣ ␣ ); print ln; print ( ␣ ␣ ); for kkk ← 1 to equv len do print char (xord [equivalence[kkk ]]); a close(edcmd file); copy err ← save it ; selector ← log only ; print ( ); print (cmd file); print char ( ␣ ); end

end

This code is used in section 1655*.

1657* . Here are the other variables used in the above module: ⟨ Variables for edit file 1657* ⟩ ≡ kkk : integer ; cmd file: str number ;

See also sections 1660* and 1663*. This code is used in section 1651*.

1658* . Neither does the editor accept such a qualifier, so again we create a suitable command file. ⟨ Create command file 1658* ⟩ ≡

begin name of file ← ´ ´ ; default name ← ´ ´ ; if a open out (edcmd file) then

begin cmd file ← make name string ; equivalence ← ´ $ ´ ; equv len ← 8; { If it’s defined } copy err ← ignore it ; selector ← edcmd write; if translate(equivalence, equv len) then

begin if equivalence[1] = ´ $´ then begin print ( ); for kkk ← 2 to equv len do print char (xord [equivalence[kkk ]]); end

else for kkk ← 1 to equv len do print char (xord [equivalence[kkk ]]); print char (˝ 1B); print ln; end;

print ( ); print int (line); print ( ); with stack item do print int (loc field − start field ); print ( ´ ´ ); print char (˝ 1B); print char (˝ 1B); print ln; a close(edcmd file); copy err ← save it ; selector ← log only ; print ( ); print (cmd file); print char ( ␣ ); ⟨ Create logical $ 1659* ⟩ end

end

This code is used in section 1655*.

1659* . Unfortunately, the present version (V40.36) of does not appear to make use of the third parameter (which is supposed to be the name of an initialization file). Therefore, we create (or redefine) the logical name $ , which the callable version of TECO will then use. Afterwards, of course, we have to put things back as they were, since otherwise a further invocation of the editor would introduce a circularity.

The requirement for $ is that its first character shall be a dollar sign (‘$’) to indicate that the rest of the logical name gives the name of a file to be used for initialization.

define VAX create logical ≡ \underline{\overline{␣$}} ⟨ Create logical $ 1659* ⟩ ≡

begin TECO cmd ← ´ $´ ; kkk ← str start [cmd file]; while kkk < str start [cmd file + 1] do

begin TECO cmd ← TECO cmd + xchr [so(str pool [kkk ])]; incr (kkk ) end;

with item list [0] do begin buffer length ← VAX length(TECO cmd ); item code ← VAX lnm string ; buffer addr ← VAX address of (VAX body (TECO cmd )); ret len addr ← 0; end;

item list [1].next item ← 0; VAX create logical (, ´ $ ´ , ´ $ ´ , , item list ); end

This code is used in section 1658*.

1660* . Here are some additional variables used in the above module. ⟨ Variables for edit file 1657* ⟩ +≡ TECO cmd : [VAX volatile] varying [file name size] of char ; item list : [VAX volatile] array [0 . . 1] of VMS item list ;

1661* . After  or  has completed its editing, we are at liberty to delete the command file that was

used to direct the cursor to the appropriate place. We’ve got the full file specification saved up from when the file was created, so we can go ahead and use the VAX-Pascal delete file command to remove the file.

define VAX delete logical ≡ \underline{\overline{␣$}}

define VAX delete file ≡ \underline{\overline{␣}} ⟨ Delete an editor command file 1661* ⟩ ≡

begin if edit found = TECO editor then

begin if equv len > 0 then begin with item list [0] do

begin buffer length ← equv len; item code ← VAX lnm string ; buffer addr ← VAX address of (equivalence); ret len addr ← 0; end;

item list [1].next item ← 0; VAX create logical (, ´ $ ´ , ´ $ ´ , , item list ); end

else VAX delete logical (´ $ ´ , ´ $ ´ ); end;

VAX delete file(last name)

end

This code is used in section 1655*.

1662* . Once a source file has been edited, any further calls of an editor should access the latest version of the source file, rather than that first opened by TEX. Therefore, as a crude approximation to this desired outcome, we truncate the file specification held in the pool by substituting spaces for the ‘ ’ and any characters that follow it in there. (This is a good approximation, since generally any revised file will have been written out to the next higher version number, and the method adopted is easier than trying to shuffle all of the pool down to fill the vacant space.) ⟨ Remove version number from file specification 1662* ⟩ ≡

begin had semicolon ← false;

for next ch ← str start [stack item.name field ] to str start [stack item.name field + 1] − 1 do begin if str pool [next ch] = si ( ) then had semicolon ← true; if had semicolon then str pool [next ch] ← si ( ␣ ) end;

end

This code is used in section 1651*.

1663* . Here’s the necessary global variables for the previous module: ⟨ Variables for edit file 1657* ⟩ +≡ next ch: pool pointer ; had semicolon: boolean; 1664* . If we were unable to recognize the equivalence string for the logical name, it’s assumed to be a DCL command (most probably preceded by an ‘ ’ to invoke a command procedure). The command will be run in a sub-process, and provided with three parameters: the name of the file to be edited, and the row and column numbers (starting from 1) of the file at which the error was detected.

The following code constructs the requisite DCL command ready to be passed to the spawned sub-process by procedure Edit . As for the callable editors above, this command is constructed in the Pascal internal file temp file, using various print commands. ⟨ Invoke editor in a sub-process 1664* ⟩ ≡

begin rewrite(temp file); copy err ← save it ; print ln;

for kkk ← 1 to equv len do print (xord [equivalence[kkk ]]);

print ( ␣ ); print (stack item.name field ); print ( ␣ ); print int (line); print ( ␣ );

with stack item do print int (loc field − start field + 1);

edit status ← Edit (0, 0, empty editor );

end

This code is used in section 1652*.

1665* . Here’s a dummy editor structure to be passed to Edit for non-callable editors: ⟨ Global variables 13 ⟩ +≡ empty editor : editor ident ;

1666* . and its initialization: ⟨ Set initial values of key variables 21 ⟩ +≡

with empty editor do

256  PART 55: INDEX  ε-TEX 3.14159 [PD VMS 3.6] changes §1667

begin logical ← ´ ´ ; image ← 0; entry ← 0; quitting ← 0; exiting ← 0; cmd text ← 0; cmd offset ← 0; start qual ← false; EDT like ← false; end; 1667* . Index. Here is where you can find all uses of each identifier in the program, with underlined entries pointing to where the identifier was defined. If the identifier is only one letter long, however, you get to see only the underlined entries. All references are to section numbers instead of page numbers.

This index also lists error messages and other aspects of the program that you might want to look up some day. For example, the entry for “system dependencies” lists all sections that should receive special attention from people who are installing TEX in a new operating environment. A list of various things that can’t happen appears under “this can’t happen”. Approximately 40 sections are listed under “inner loop”; these account for about 60% of TEX’s running time, exclusive of input and output.

The following sections were changed by the change file: 1, 2, 4, 7, 8, 9, 10, 11, 12, 15, 23, 25, 26, 27, 28, 30, 31, 33, 34, 37, 47, 49, 50, 51, 52, 53, 54, 56, 57, 58, 61, 71, 73, 82, 84, 86, 96, 97, 109, 110, 112, 113, 141, 142, 147, 175, 184, 186, 192, 196, 208, 209, 210, 212, 213, 215, 216, 230, 231, 232, 233, 236, 237, 241, 264, 265, 266, 268, 273, 274, 275, 277, 278, 279, 281, 282, 284, 289, 294, 296, 298, 299, 303, 307, 311, 313, 314, 317, 318, 319, 326, 328, 329, 331, 362, 366, 367, 377, 378, 382, 385, 386, 389, 409, 411, 412, 413, 415, 416, 417, 419, 420, 423, 424, 427, 461, 464, 465, 469, 470, 471, 472, 478, 482, 483, 487, 488, 494, 496, 498, 501, 505, 510, 513, 514, 516, 517, 520, 521, 522, 525, 529, 530, 532, 534, 535, 536, 537, 563, 564, 575, 581, 595, 597, 598, 599, 616, 619, 620, 622, 623, 625, 626, 628, 629, 632, 633, 634, 637, 638, 642, 649, 651, 687, 696, 727, 760, 762, 785, 791, 807, 808, 814, 815, 816, 819, 827, 829, 845, 846, 851, 852, 855, 863, 864, 866, 876, 877, 879, 880, 881, 890, 891, 896, 897, 898, 934, 937, 952, 958, 960, 966, 968, 977, 979, 982, 991, 996, 999, 1012, 1014, 1021, 1023, 1026, 1070, 1071, 1075, 1077, 1079, 1080, 1082, 1096, 1101, 1105, 1108, 1110, 1130, 1138, 1145, 1146, 1147, 1185, 1189, 1191, 1192, 1194, 1199, 1202, 1203, 1204, 1205, 1206, 1208, 1209, 1211, 1213, 1218, 1224, 1225, 1226, 1227, 1236, 1237, 1238, 1239, 1240, 1241, 1246, 1247, 1248, 1252, 1275, 1292, 1293, 1295, 1296, 1305, 1306, 1307, 1308, 1311, 1312, 1324, 1325, 1329, 1331, 1332, 1333, 1335, 1336, 1337, 1348, 1363, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667.

: 37* , 534* . : 174, 176, 178, 313* , 360, 856, 1006, 1355. : 294* . : 84* . : 84* . : 49* , 1332* . : 1601* . : 520* . : 363. : 59. : 83. : 856. : 846* . $  : 1600* . $  : 241* . $  : 96* . $  : 1629* , 1630* . $  : 1629* . a: \underline{47*} , \underline{102}, \underline{218}, \underline{281*} , \underline{518}, \underline{519}, \underline{523}, \underline{560}, \underline{691}, \underline{722}, \underline{738}, \underline{752}, \underline{1075*} , \underline{1123}, \underline{1194*} , \underline{1211*} , \underline{1236*} , \underline{1257}, \underline{1413*} , \underline{1515*} , \underline{1526*} , \underline{1530*} , \underline{1532*} , \underline{1558*} . : 1084.

a close: \underline{28*} , 51* , 329* , 485, 486, 1275* , 1332* , 1333* ,

1374, 1378, 1656* , 1658* . a leaders : \underline{149}, 189, 625* , 627, 634* , 636, 656, 671,

1071* , 1072, 1073, 1078, 1148, 1415* , 1433* , 1459* . a make name string : \underline{525*} , 534* , 537* , 1615* .

a open in: \underline{27*} , 51* , 537* .
a open out : \underline{27*} , 534* , 1374, 1615* , 1656* , 1658* .
A token: \underline{445}.

abort : \underline{560}, 563* , 564* , 565, 568, 569, 570, 571,

573, 575* . above: \underline{208*} , 1046, 1178, 1179, 1180.

primitive: \underline{1178}.
above code: \underline{1178}, 1179, 1182, 1183.
above display short skip: \underline{224}, 814* .
primitive: \underline{226}.

above display short skip code: \underline{224}, 225, 226, 1203* .

above display skip: \underline{224}, 814* .
primitive: \underline{226}.

above display skip code: \underline{224}, 225, 226, 1203* , 1206* .

primitive: \underline{1178}.

§1667 ε-TEX 3.14159 [PD VMS 3.6] changes PART 55: INDEX 257

abs : 66, 186* , 211, 218, 219, 418, 422, 448, 501* , 610, 663, 675, 718, 737, 757, 758, 759, 831, 836, 849, 859, 944, 948, 1029, 1030, 1056, 1076, 1078, 1080* , 1083, 1093, 1110* , 1120, 1127, 1149, 1243, 1244, 1377, 1415* , 1523* .

absorbing : \underline{305}, 306, 339, 473, 1417* . acc kern: \underline{155}, 191, 1125. accent : \underline{208*} , 265* , 266* , 1090, 1122, 1164, 1165. primitive: \underline{265*} . accent chr : \underline{687*} , 696* , 738, 1165. accent noad : \underline{687*} , 690, 696* , 698, 733, 761,

1165, 1186. accent noad size: \underline{687*} , 698, 761, 1165. act width: \underline{866*} , 867, 868, 869, 871. action procedure: \underline{1029}. active: \underline{162}, 819* , 829* , 843, 854, 860, 861, 863* ,

864* , 865, 873, 874, 875. active base: 220, \underline{222}, 252, 253, 255, 262, 263, 353,

442, 506, 1152, 1257, 1289, 1315, 1317. active char : \underline{207}, 344, 506. active glue: \underline{1575*} , 1578* , 1579* , 1584* , 1585* , 1586* . active height : \underline{970}, 975, 976. active node size: 845* , 860, 864* , 865, \underline{1575*} , 1576* . active node size extended : \underline{1575*} , 1576* . active node size normal : \underline{819*} , 1576* . active short : \underline{1575*} , 1578* , 1579* , 1584* , 1585* , 1586* . active width: \underline{823}, 824, 829* , 843, 861, 864* ,

866* , 868, 970. actual looseness : \underline{872}, 873, 875. add delims to: \underline{347}. add glue: 625* , 634* , \underline{1433*} , 1459* . add glue ref : \underline{203}, 206, 430, 802, 881* , 996* , 1100,

1229, 1466* , 1515* , 1553* . add or sub: 1525* , \underline{1526*} . add sa ptr : \underline{1552*} . add sa ref : 1224* , \underline{1554*} , 1570* , 1572* , 1573* . add stretch shrink : \underline{1433*} . add token ref : \underline{203}, 206, 323, 979* , 1012* , 1016,

1221, 1227* , 1357, 1560* , 1561* , 1562* , 1563* . additional : \underline{644}, 645, 657, 672. adj demerits : \underline{236*} , 836, 859. primitive: \underline{238}. adj demerits code: \underline{236*} , 237* , 238. adjust : \underline{576}. adjust head : \underline{162}, 888, 889, 1076, 1085, 1199* , 1205* . adjust node: \underline{142*} , 148, 175* , 183, 202, 206, 647,

651* , 655, 730, 761, 866* , 899, 1100, 1433* . adjust ptr : \underline{142*} , 197, 202, 206, 655, 1100. adjust space factor : \underline{1034}, 1038. adjust tail : \underline{647}, 648, 649* , 651* , 655, 796, 888,

889, 1076, 1085, 1199* . adjusted hbox group: \underline{269}, 1062, 1083, 1085,

1395* , 1413* . adv past : \underline{1362}. advance: \underline{209*} , 265* , 266* , 1210, 1235, 1236* , 1238* . primitive: \underline{265*} . advance major tail : \underline{914}, 917. after : \underline{147*} , 192* , 1196, 1461* , 1472* . after assignment : \underline{208*} , 265* , 266* , 1268. primitive: \underline{265*} . after group: \underline{208*} , 265* , 266* , 1271. primitive: \underline{265*} . after math: 1193, \underline{1194*} . after token: \underline{1266}, 1267, 1268, 1269. aire: \underline{560}, 561, 563* , 576. align error : 1126, \underline{1127}. align group: \underline{269}, 768, 774, 791* , 800, 1131, 1132,

1395* , 1413* . align head : \underline{162}, 770, 777. align peek : 773, 774, \underline{785*} , 799, 1048, 1133. align ptr : \underline{770}, 771, 772. align stack node size: \underline{770}, 772. align state: 88, \underline{309}, 324, 325, 326* , 331* , 339, 342,

347, 357, 394, 395, 396, 403, 442, 475, 482* , 483* , 486, 770, 771, 772, 774, 777, 783, 784, 785* , 788, 789, 791* , 1069, 1094, 1126, 1127.

aligning : \underline{305}, 306, 339, 777, 789. alignment of rules with characters: 589. alloc: 1632* . alpha: \underline{560}, 571, 572. alpha file: \underline{25*} , 27* , 28* , 31* , 32, 50* , 54* , 304, 480,

525* , 537* , 1342, 1616* . alpha token: \underline{438}, 440. alter aux : 1242, \underline{1243}. alter box dimen: 1242, \underline{1247*} . alter integer : 1242, \underline{1246*} . alter page so far : 1242, \underline{1245}. alter prev graf : 1242, \underline{1244}. : 1183. Amble, Ole: 925. : 1331* . any mode: \underline{1045}, 1048, 1057, 1063, 1067, 1073,

1097, 1102, 1104, 1126, 1134, 1210, 1268, 1271, 1274, 1276, 1285, 1290, 1347.

any state plus : \underline{344}, 345, 347. app display : 1203* , 1204* , 1205* , \underline{1477*} . app lc hex : \underline{48}. app space: 1030, \underline{1043}. append char : \underline{42}, 48, 52* , 58* , 180, 195, 260, 514* ,

516* , 525* , 537* , 692, 695, 939. append charnode to t : \underline{908}, 911. append choices : 1171, \underline{1172}. append discretionary : 1116, \underline{1117}. append glue: 1057, \underline{1060}, 1078. append italic correction: 1112, \underline{1113}. append kern: 1057, \underline{1061}. append normal space: \underline{1030}. append penalty : 1102, \underline{1103}. append to name: \underline{519}, 523. append to vlist : \underline{679}, 799, 888, 1076, 1477* . area delimiter : \underline{513*} , 515, 516* , 517* . arg list : 1631* . : 395. arith error : \underline{104}, 105, 106, 107, 448, 453, 460,

1236* , 1515* , 1516* , 1523* , 1579* . : 1236* , 1515* . array: 30* . artificial demerits : \underline{830}, 851* , 854, 855* , 856. ASCII code: 17, 503. ASCII code: \underline{18}, 19, 20, 29, 30* , 31* , 38, 42, 54* , 56* ,

58* , 60, 82* , 292, 341, 389* , 516* , 519, 523, 692, 892, 912, 921, 943, 950, 953, 959, 960* , 1376.

assign dimen: \underline{209*} , 248, 249, 413* , 1210, 1224* ,

1228. assign font dimen: \underline{209*} , 265* , 266* , 413* , 1210, 1253. assign font int : \underline{209*} , 413* , 1210, 1253, 1254, 1255. assign glue: \underline{209*} , 226, 227, 413* , 782, 1210,

1224* , 1228. assign int : \underline{209*} , 238, 239, 413* , 1210, 1222, 1224* ,

1228, 1237* , 1391* , 1435* . assign mu glue: \underline{209*} , 226, 227, 413* , 1210, 1222,

1224* , 1228, 1237* . assign toks : \underline{209*} , 230* , 231* , 233* , 323, 413* , 415* ,

1210, 1224* , 1226* , 1227* , 1391* . assign trace: \underline{277*} , 278* , 279* . : 1258. primitive: \underline{1178}. atop code: \underline{1178}, 1179, 1182. primitive: \underline{1178}. attach fraction: \underline{448}, 453, 454, 456. attach sign: \underline{448}, 449, 455. attributes : \underline{1629*} . auto breaking : \underline{862}, 863* , 866* , 868. aux : 212* , \underline{213*} , 216* , 800, 812. aux buf : \underline{30*} , 31* . aux field : \underline{212*} , 213* , 218, 775. aux save: \underline{800}, 812, 1206* . avail : \underline{118}, 120, 121, 122, 123, 164, 168, 1311* , 1312* . : 168. awful bad : \underline{833}, 834, 835, 836, 854, 874, 970, 974,

975, 987, 1005, 1006, 1007. axis height : \underline{700}, 706, 736, 746, 747, 749, 762* . b: \underline{464*} , \underline{465*} , \underline{470*} , \underline{498*} , \underline{523}, \underline{560}, \underline{595*} , \underline{679}, \underline{705},

\underline{706}, \underline{709}, \underline{711}, \underline{715}, \underline{830}, \underline{970}, \underline{994}, \underline{1198}, \underline{1247*} , \underline{1288}, \underline{1390*} , \underline{1477*} , \underline{1515*} . b close: \underline{28*} , 560, 642* . b make name string : \underline{525*} , 532* . b open in: \underline{27*} , 563* . b open out : \underline{27*} , 532* . back error : \underline{327}, 373, 396, 403, 415* , 442, 446, 476,

479, 503, 577, 783, 1078, 1084, 1161, 1197, 1207, 1212, 1498* , 1517* .

back input : 281* , \underline{325}, 326* , 327, 368, 369, 372, 375, 379, 395, 405, 407, 415* , 443, 444, 448, 452, 455, 461* , 526, 788, 1031, 1047, 1054, 1064, 1090, 1095, 1124, 1127, 1132, 1138* , 1150, 1152, 1153, 1215, 1221, 1226* , 1269, 1375, 1517* , 1518* .

back list : \underline{323}, 325, 337, 407, 1288. backed up: \underline{307*} , 311* , 312, 314* , 323, 324, 325, 1026* . background : \underline{823}, 824, 827* , 837, 863* , 864* , 1576* . backup backup: \underline{366*} . backup head : \underline{162}, 366* , 407. : 293, 294* . bad : \underline{13}, 14, 111, 290, 597* , 1249, 1332* . : 961. : 1244. : 434. : 437. : 170. : 1430* . : 182. : 436. : 435. : 433, 1544* . : 1243. bad fmt : \underline{1303}, 1306* , 1308* , 1312* , 1317, 1327. bad pool : \underline{51*} , 52* , 53* . bad symbol : \underline{1640*} , 1641* , 1643* , 1645* . bad tfm: \underline{560}. badness : \underline{108}, 660, 667, 674, 678, 828, 852* , 853,

975, 1007, 1580* , 1581* . primitive: \underline{416*} . badness code: \underline{416*} , 424* . banner : \underline{2*} , 1299, 1617* . base line: \underline{619*} , 623* , 624, 628* . base ptr : 84* , 85, \underline{310}, 311* , 312, 313* , 1507* ,

1508* , 1509* . baseline skip: \underline{224}, 247, 679. primitive: \underline{226}. baseline skip code: 149, \underline{224}, 225, 226, 679. batch mode: 34* , \underline{73*} , 75, 86* , 90, 92, 93, 535* , 1262,

1263, 1327, 1328, 1430* , 1617* . primitive: \underline{1262}. batch qual : \underline{1616*} , 1617* , 1621* . bc: 540, 541, 543, 545, \underline{560}, 565, 566, 570, 576. bch label : \underline{560}, 573, 576. bchar : \underline{560}, 573, 576, \underline{901}, 903, 905, \underline{906}, 908, 911,

913, 916, 917, \underline{1032}, 1034, 1037, 1038, 1040. bchar label : \underline{549}, 552, 576, 909, 916, 1034, 1040,

1322, 1323. before: \underline{147*} , 192* , 1196, 1446* , 1448* , 1451* , 1461* ,

1472* . begin: 7* , 8* . begin box : 1073, \underline{1079*} , 1084. begin diagnostic: 76, \underline{245}, 284* , 299* , 323, 400,

401, 502, 509, 581* , 638* , 641, 663, 675, 863* , 987, 992, 1006, 1011, 1121, 1293* , 1296* , 1396* , 1411* , 1425* , 1556* .

begin file reading : 78, 87, \underline{328*} , 483* , 537* , 1488* . begin group: \underline{208*} , 265* , 266* , 1063. primitive: \underline{265*} . begin insert or adjust : 1097, \underline{1099}. begin L code: \underline{147*} , 1435* , 1436* , 1467* . begin LR type: \underline{147*} , 1441* . begin M code: \underline{147*} , 1445* , 1479* . begin name: 512, \underline{515}, 517* , 526, 527, 531. begin pseudoprint : \underline{316}, 318* , 319* . begin R code: \underline{147*} , 1435* , 1436* . begin reflect : 1434* . begin token list : \underline{323}, 359, 362* , 386* , 390, 774,

788, 789, 799, 1025, 1030, 1083, 1091, 1139, 1145* , 1167, 1371.

primitive: \underline{1435*} . : 1328. primitive: \underline{1435*} . below display short skip: \underline{224}. primitive: \underline{226}. below display short skip code: \underline{224}, 225, 226, 1203* . below display skip: \underline{224}. primitive: \underline{226}. below display skip code: \underline{224}, 225, 226, 1203* , 1206* . best bet : \underline{872}, 874, 875, 877* , 878, 1586* . best height plus depth: \underline{971}, 974, 1010, 1011. best ins ptr : \underline{981}, 1005, 1009, 1018, 1020, 1021* . best line: \underline{872}, 874, 875, 877* , 890* . best page break : \underline{980}, 1005, 1013, 1014* . best pl glue: \underline{1575*} , 1583* , 1584* . best pl line: \underline{833}, 845* , 855* . best pl short : \underline{1575*} , 1583* , 1584* . best place: \underline{833}, 845* , 855* , \underline{970}, 974, 980. best size: \underline{980}, 1005, 1017. beta: \underline{560}, 571, 572. big op spacing1 : \underline{701}, 751. big op spacing2 : \underline{701}, 751. big op spacing3 : \underline{701}, 751. big op spacing4 : \underline{701}, 751. big op spacing5 : \underline{701}, 751.

big switch: 209* , 236* , 994, 1029, \underline{1030}, 1031,

1036, 1041. BigEndian order: \underline{540}.

bin noad : \underline{682}, 690, 696* , 698, 728, 729, 761,

1156, 1157. bin op penalty : \underline{236*} , 761. primitive: \underline{238}. bin op penalty code: \underline{236*} , 237* , 238. blank line: \underline{245}. body : 30* . boolean: 27* , 31* , 37* , 45, 46, 47* , 76, 79, 96* , 104,

106, 107, 165, 167, 245, 256, 281* , 311* , 361, 407, 413* , 440, 448, 461* , 473, 498* , 516* , 524, 527, 529* , 537* , 549, 560, 578, 592, 595* , 619* , 629* , 645, 706, 719, 726, 791* , 815* , 825, 828, 829* , 830, 862, 877* , 900, 907, 950, 960* , 968* , 989, 1012* , 1032, 1051, 1054, 1091, 1160, 1194* , 1211* , 1236* , 1281, 1303, 1331* , 1342, 1390* , 1394* , 1395* , 1396* , 1489* , 1507* , 1509* , 1515* , 1526* , 1530* , 1532* , 1552* , 1558* , 1575* , 1616* , 1623* , 1629* , 1630* , 1636* , 1650* , 1651* , 1663* .

bop: 583, 585, \underline{586}, 588, 590, 592, 638* , 640.

Bosshard, Hans Rudolf: 458.

bot : \underline{546}.

bot mark : \underline{382*} , 383, 1012* , 1016, 1542* , 1561* .

primitive: \underline{384}.

bot mark code: \underline{382*} , 384, 385* , 1542* .

primitive: \underline{1542*} .

bottom level : \underline{269}, 272, 281* , 1064, 1068, 1395* ,

1413* . bottom line: \underline{311*} . bowels: 592. box : \underline{230*} , 232* , 992, 993, 1009, 1015, 1017, 1018, 1021* , 1023* , 1028, 1553* , 1554* , 1572* .

primitive: \underline{1071*} .

box base: \underline{230*} , 232* , 233* , 255, 1077* .
box code: \underline{1071*} , 1072, 1079* , 1107, 1110* , 1594* .

box context : \underline{1075*} , 1076, 1077* , 1078, \underline{1079*} , 1083,

\underline{1084}.

box end : \underline{1075*} , 1079* , 1084, 1086.
box error : \underline{992}, 993, 1015, 1028.
box flag : \underline{1071*} , 1075* , 1077* , 1083, 1241* , 1415* .
box max depth: \underline{247}, 1086.
primitive: \underline{248}.
box max depth code: \underline{247}, 248.
box node size: \underline{135}, 136, 202, 206, 649* , 668,

715, 727* , 751, 756, 977* , 1021* , 1100, 1110* , 1201, 1466* , 1478* . box ref : \underline{210*} , 232* , 275* , 1077* . box there: \underline{980}, 987, 1000, 1001. box val : 1224* , \underline{1548*} , 1553* , 1554* , 1556* , 1572* . box val limit : \underline{1548*} , 1571* . : 1015.

: 458. brain: 1029. breadth max : \underline{181}, 182, 198, 233* , 236* , 1339, 1556* . break node: \underline{819*} , 845* , 855* , 856, 864* , 877* , 878. break penalty : \underline{208*} , 265* , 266* , 1102. break type: \underline{829*} , 837, 845* , 846* , 859. break width: \underline{823}, 824, 837, 838, 840, 841, 842,

843, 844, 879* . breakpoint : \underline{1338}. broken ins : \underline{981}, 986, 1010, 1021* . broken penalty : \underline{236*} , 890* . primitive: \underline{238}. broken penalty code: \underline{236*} , 237* , 238. broken ptr : \underline{981}, 1010, 1021* . buf size: \underline{11*} , 30* , 31* , 35, 71* , 111, 264* , 315, 328* ,

331* , 341, 363, 366* , 374, 524, 530* , 534* , 1334, 1489* , 1501* , 1621* .

buffer : \underline{30*} , 31* , 36, 37* , 45, 71* , 83, 87, 88, 259, 260, 261, 264* , 302, 303* , 315, 318* , 331* , 341, 343, 352, 354, 355, 356, 360, 362* , 363, 366* , 374, 483* , 484, 523, 524, 530* , 531, 534* , 538, 1337* , 1339, 1379* , 1489* , 1494* , 1501* , 1617* , 1621* .

: 35. buffer addr : 1629* , \underline{1630*} , 1659* , 1661* . buffer address : 1630* . buffer length: 1629* , \underline{1630*} , 1659* , 1661* . build choices : 1173, \underline{1174}. build discretionary : 1118, \underline{1119}. build page: 800, 812, 988, \underline{994}, 1026* , 1054, 1060,

1076, 1091, 1094, 1100, 1103, 1145* , 1200. bypass eoln: \underline{31*} . byte block : \underline{25*} , 595* . byte file: \underline{25*} , 27* , 28* , 525* , 532* , 539, 1622* . b0 : 110* , \underline{113*} , 114, 133, 221, 268* , 545, 546, 550,

554, 556, 564* , 602, 683, 685, 921, 958* , 1309, 1310, 1487* , 1489* .

b1 : 110* , \underline{113*} , 114, 133, 221, 268* , 545, 546, 554, 556, 564* , 602, 683, 685, 921, 958* , 1309, 1310, 1487* , 1489* .

b2 : 110* , \underline{113*} , 114, 545, 546, 554, 556, 564* , 602,

683, 685, 1309, 1310, 1487* , 1489* . b3 : 110* , \underline{113*} , 114, 545, 546, 556, 564* , 602, 683,

685, 1309, 1310, 1487* , 1489* . c: \underline{47*} , \underline{63}, \underline{82*} , \underline{144}, \underline{264*} , \underline{274*} , \underline{292}, \underline{341}, \underline{465*} , \underline{470*} ,

\underline{516*} , \underline{519}, \underline{523}, \underline{560}, \underline{581*} , \underline{582}, \underline{592}, \underline{645}, \underline{692}, \underline{694}, \underline{706}, \underline{709}, \underline{711}, \underline{712}, \underline{738}, \underline{749}, \underline{893}, \underline{912}, \underline{953}, \underline{959}, \underline{960*} , \underline{994}, \underline{1012*} , \underline{1086}, \underline{1101*} , \underline{1110*} , \underline{1117}, \underline{1136}, \underline{1151}, \underline{1155}, \underline{1181}, \underline{1243}, \underline{1245}, \underline{1246*} , \underline{1247*} , \underline{1275*} , \underline{1279}, \underline{1288}, \underline{1335*} , \underline{1413*} , \underline{1510*} .

c leaders : \underline{149}, 190, 627, 636, 1071* , 1072. primitive: \underline{1071*} . c loc: \underline{912}, 916. call : \underline{210*} , 223, 275* , 296* , 366* , 380, 387, 395,

396, 478* , 507, 1218* , 1221, 1225* , 1226* , 1227* , 1295* , 1505* .

call editor : \underline{1631*} , 1642* , 1646* . call G descriptor : \underline{1631*} . Callable editors: 1631* , 1640* . : 1636* . cancel boundary : 1030, \underline{1032}, 1033, 1034. cancel glue: \underline{1479*} . cancel glue cont : \underline{1479*} . cancel glue cont cont : \underline{1479*} . cancel glue end : \underline{1479*} . cancel glue end end : \underline{1479*} . : 484. car ret : \underline{207}, 232* , 342, 347, 777, 780, 781, 783,

784, 785* , 788, 1126. carriage return: \underline{22}, 23* , 49* , 207, 232* , 240, 363. case shift : \underline{208*} , 1285, 1286, 1287. cat : \underline{341}, 354, 355, 356. cat code: \underline{230*} , 232* , 236* , 262, 341, 343, 354,

355, 356, 1337* . primitive: \underline{1230}. cat code base: \underline{230*} , 232* , 233* , 235, 1230, 1231, 1233. cc: \underline{341}, 352, 355. : 458. : 34* . ch: \underline{56*} . ch ctr : \underline{1633*} . ch ptr : \underline{1633*} , \underline{1640*} , 1646* , 1648* . change box : 977* , 1079* , 1110* , \underline{1554*} . change if limit : \underline{497}, 498* , 509. char : 19, 26* , 30* , 37* , 56* , 513* , 517* , 520* , 529* , 534* ,

1616* , 1618* , 1620* , 1621* , 1626* , 1628* , 1629* , 1636* , 1651* , 1660* .

primitive: \underline{265*} . char base: \underline{550}, 552, 554, 566, 570, 576, 1322, 1323. char box : \underline{709}, 710, 711, 738. char ct : \underline{1640*} , 1646* , 1647* , 1648* . primitive: \underline{1222}. char def code: \underline{1222}, 1223, 1224* . char depth: \underline{554}, 654, 708, 709, 712, 1405* . char depth end : \underline{554}. char exists : \underline{554}, 573, 576, 582, 708, 722, 738,

740, 749, 755, 1036, 1502* . char given: \underline{208*} , 413* , 935, 1030, 1038, 1090, 1124,

1151, 1154, 1222, 1223, 1224* . char height : \underline{554}, 654, 708, 709, 712, 1125, 1405* . char height end : \underline{554}. char info: 543, 550, \underline{554}, 555, 557, 570, 573, 576,

582, 620* , 654, 708, 709, 712, 714, 715, 722, 724, 738, 740, 749, 841, 842, 866* , 867, 870, 871, 909, 1036, 1037, 1039, 1040, 1113, 1123, 1125, 1147* , 1405* , 1457* , 1502* .

char info end : \underline{554}. char info word : 541, \underline{543}, 544. char italic: \underline{554}, 709, 714, 749, 755, 1113, 1405* . char italic end : \underline{554}. char kern: \underline{557}, 741, 753, 909, 1040. char kern end : \underline{557}. char node: \underline{134}, 143, 145, 162, 176, 548, 592, 620* ,

649* , 752, 881* , 907, 1029, 1113, 1138* , 1444* . char num: \underline{208*} , 265* , 266* , 935, 1030, 1038, 1090,

1124, 1151, 1154. char tag : \underline{554}, 570, 708, 710, 740, 741, 749,

752, 909, 1039. char warning : \underline{581*} , 582, 722, 1036. char width: \underline{554}, 620* , 654, 709, 714, 715, 740,

841, 842, 866* , 867, 870, 871, 1123, 1125, 1147* , 1405* , 1457* .

char width end : \underline{554}. character : \underline{134}, 143, 144, 174, 176, 206, 582, 620* ,

654, 681, 682, 683, 687* , 691, 709, 715, 722, 724, 749, 752, 753, 841, 842, 866* , 867, 870, 871, 896* , 897* , 898* , 903, 907, 908, 910, 911, 1032, 1034, 1035, 1036, 1037, 1038, 1040, 1113, 1123, 1125, 1147* , 1151, 1155, 1165, 1457* , 1466* .

character set dependencies: 23* , 49* . check sum: 53* , 542, 588. check byte range: \underline{570}, 573. check cli : \underline{1620*} . check dimensions : \underline{726}, 727* , 733, 754. check existence: \underline{573}, 574. check full save stack : \underline{273*} , 274* , 276, 280, 1570* . check interrupt : \underline{96*} , 324, 343, 753, 911, 1031, 1040. check mem: 165, \underline{167}, 1031, 1339. check outer validity : \underline{336}, 351, 353, 354, 357,

362* , 375. check shrinkage: \underline{825}, 827* , 868. Chinese characters: 134, 585. choice node: 688, \underline{689}, 690, 698, 730. choose mlist : \underline{731}. chr : 19, 20, 23* , 24, 34* , 1222, 1627* . chr cmd : \underline{298*} , 781. chr code: 227, 231* , 239, 249, 266* , \underline{298*} , 377* , 385* ,

411* , 413* , 417* , 469* , 488* , 492, 781, 984, 1053, 1059, 1071* , 1072, 1089, 1108* , 1115, 1143, 1157, 1170, 1179, 1189* , 1209* , 1220, 1223, 1231, 1251, 1255, 1261, 1263, 1273, 1278, 1287, 1289, 1292* , 1295* , 1346, 1421* , 1427* , 1432* , 1436* , 1481* , 1504* , 1565* , 1566* , 1594* , 1595* .

chrptr : \underline{1626*} , 1627* , 1633* , 1640* , 1646* , 1648* . clang : 212* , \underline{213*} , 812, 1034, 1091, 1200, 1376, 1377. cld table: \underline{1618*} . clean box : \underline{720}, 734, 735, 737, 738, 742, 744, 749,

750, 757, 758, 759. clear default name: \underline{529*} , 532* , 534* , 1615* . clear for error prompt : 78, 83, \underline{330}, 346. clear terminal : \underline{34*} , 330, 530* . $ : 1618* , 1620* . $ : 37* , 1618* . $ : 1618* . : 293. clobbered : \underline{167}, 168, 169. close: 27* , 28* . close files and terminate: 78, 81, 1332* , \underline{1333*} . primitive: \underline{1272}. close noad : \underline{682}, 690, 696* , 698, 728, 761, 762* ,

1156, 1157. close node: \underline{1341}, 1344, 1346, 1348* , 1356, 1357,

1358, 1373, 1374, 1375. primitive: \underline{1344}. closed : \underline{480}, 481, 483* , 485, 486, 501* , 1275* . clr : \underline{737}, \underline{743}, 745, 746, \underline{756}, 757, 758, 759. primitive: \underline{1597*} . club penalties loc: \underline{230*} , 1597* , 1598* . club penalties ptr : 890* , \underline{1597*} . club penalty : \underline{236*} , 890* . primitive: \underline{238}. club penalty code: \underline{236*} , 237* , 238. : 458. cmd : \underline{298*} , 1222, 1289, 1295* , 1565* , \underline{1640*} . cmd file: \underline{1640*} , 1655* , 1656* , \underline{1657*} , 1658* , 1659* . cmd line present : 37* , \underline{1616*} , 1617* , 1621* . cmd offset : \underline{1636*} , 1638* , 1646* , 1666* . cmd text : \underline{1636*} , 1638* , 1655* , 1666* . cmdlin: \underline{1618*} . cmdline: \underline{1618*} . co backup: \underline{366*} . col : \underline{1649*} . combine two deltas : \underline{860}. command line: \underline{37*} , \underline{1620*} . comment : \underline{207}, 232* , 347. common ending : \underline{15*} , 498* , 500, 509, 649* , 660, 666,

667, 668, 674, 677, 678, 895, 903, 1257, 1260, 1293* , 1294, 1297, 1448* .

: 638* . compress trie: \underline{949}, 952* . cond code: 1632* . cond math glue: \underline{149}, 189, 732, 1171. cond ptr : 299* , 328* , 362* , \underline{489}, 490, 495, 496* ,

497, 498* , 500, 509, 1335* , 1402* , 1425* , 1506* , 1509* , 1510* .

conditional : 366* , 367* , \underline{498*} . confusion: \underline{95}, 202, 206, 281* , 497, 630, 669, 728,

736, 754, 761, 766, 791* , 798, 800, 841, 842, 866* , 870, 871, 877* , 968* , 973, 1000, 1068, 1185* , 1200, 1211* , 1348* , 1357, 1358, 1373, 1448* , 1458* , 1463* , 1478* .

continental point token: \underline{438}, 448. continue: \underline{15*} , 82* , 83, 84* , 88, 89, 389* , 392, 393, 394,

397, 706, 708, 774, 784, 815* , 829* , 832, 851* , 896* , 906, 909, 910, 911, 994, 1001, 1433* , 1515* , 1516* .

continue qual : 84* , \underline{1616*} , 1621* . contrib head : \underline{162}, 215* , 218, 988, 994, 995, 998,

999* , 1001, 1017, 1023* , 1026* . contrib tail : \underline{995}, 1017, 1023* , 1026* . contribute: \underline{994}, 997, 1000, 1002, 1008, 1364. conv toks : 366* , 367* , \underline{470*} . conventions for representing stacks: 300. convert : \underline{210*} , 366* , 367* , 468, 469* , 470* , 1380* . convert to break width: \underline{843}. primitive: \underline{1071*} . copy code: \underline{1071*} , 1072, 1079* , 1107, 1108* , 1110* ,

1592* , 1594* . copy err : 73* , 1602* , \underline{1603*} , 1604* , 1607* , 1608* , 1610* ,

1611* , 1612* , 1613* , 1614* , 1617* , 1652* , 1655* , 1656* , 1658* , 1664* .

copy node list : 161, 203, \underline{204}, 206, 1079* , 1110* ,

1478* . copy to cur active: \underline{829*} , 861. count : \underline{236*} , 427* , 638* , 640, 986, 1008, 1009, 1010. primitive: \underline{411*} . count base: \underline{236*} , 239, 242, 1224* , 1237* . primitive: \underline{1222}. count def code: \underline{1222}, 1223, 1224* . primitive: \underline{780}. cr code: \underline{780}, 781, 789, 791* , 792. primitive: \underline{780}. cr cr code: \underline{780}, 785* , 789. cramped : \underline{688}, 702. cramped style: \underline{702}, 734, 737, 738. crlf : \underline{34*} , 37* , 51* , 56* . cs count : \underline{256}, 258, 260, 1318, 1319, 1334. cs error : 1134, \underline{1135}. cs name: \underline{210*} , 265* , 266* , 366* , 367* . primitive: \underline{265*} . cs token flag : \underline{289*} , 290, 293, 334, 336, 337, 339,

357, 358, 365, 369, 372, 375, 379, 380, 381, 442, 466, 506, 780, 1065, 1132, 1215, 1289, 1314, 1371.

ctrlc rout : 96* , \underline{1625*} . cur active width: \underline{823}, 824, 829* , 832, 837, 843,

844, 851* , 852* , 853, 860, 1579* , 1580* , 1581* , 1582* . cur align: \underline{770}, 771, 772, 777, 778, 779, 783, 786,

788, 789, 791* , 792, 795, 796, 798. cur area: \underline{512}, 517* , 529* , 530* , 537* , 1257, 1260,

1351, 1374.

cur boundary : 270, \underline{271}, 272, 274* , 282* , 328* , 362* ,

1413* , 1506* , 1507* , 1510* . cur box : \underline{1074}, 1075* , 1076, 1077* , 1078, 1079* , 1080* ,

1081, 1082* , 1084, 1086, 1087, 1572* . cur break : \underline{821}, 845* , 879* , 880* , 881* , 1441* .

cur c: 722, 723, \underline{724}, 738, 749, 752, 753, 755.

cur chr : 88, 296* , \underline{297}, 299* , 332, 337, 341, 343, 348, 349, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 364, 365, 367* , 378* , 380, 381, 386* , 387, 389* , 403, 407, 413* , 424* , 428, 442, 465* , 470* , 472* , 474, 476, 478* , 479, 483* , 494* , 495, 498* , 500, 506, 507, 508, 509, 510* , 526, 577, 782, 785* , 789, 935, 937* , 962, 1030, 1034, 1036, 1038, 1049, 1058, 1060, 1061, 1066, 1073, 1079* , 1083, 1090, 1093, 1101* , 1105* , 1106, 1110* , 1117, 1124, 1128, 1140, 1142, 1151, 1152, 1154, 1155, 1158, 1159, 1160, 1171, 1181, 1191* , 1211* , 1212, 1213* , 1217, 1218* , 1221, 1224* , 1225* , 1226* , 1227* , 1228, 1232, 1233, 1234, 1237* , 1243, 1245, 1246* , 1247* , 1248* , 1252* , 1253, 1265, 1275* , 1279, 1288, 1293* , 1335* , 1348* , 1350, 1375, 1408* , 1422* , 1430* , 1437* , 1482* , 1494* , 1498* , 1505* , 1596* . cur cmd : 88, 211, 296* , \underline{297}, 299* , 332, 337, 341,

342, 343, 344, 348, 349, 351, 353, 354, 357, 358, 360, 364, 365, 366* , 367* , 368, 372, 380, 381, 386* , 387, 403, 404, 406, 407, 413* , 415* , 428, 440, 442, 443, 444, 448, 452, 455, 461* , 463, 474, 476, 477, 478* , 479, 483* , 494* , 506, 507, 526, 577, 777, 782, 783, 784, 785* , 788, 789, 791* , 935, 961, 1029, 1030, 1038, 1049, 1066, 1078, 1079* , 1084, 1095, 1099, 1124, 1128, 1138* , 1151, 1152, 1160, 1165, 1176, 1177, 1197, 1206* , 1211* , 1212, 1213* , 1221, 1226* , 1227* , 1228, 1236* , 1237* , 1252* , 1270, 1375, 1417* , 1437* , 1498* , 1499* , 1500* , 1505* , 1517* . cur cs : \underline{297}, 332, 333, 336, 337, 338, 341, 351, 353, 354, 356, 357, 358, 365, 372, 374, 379, 380, 381, 389* , 391, 407, 472* , 473, 507, 774, 1152, 1215, 1218* , 1221, 1224* , 1225* , 1226* , 1257, 1294, 1352, 1371, 1417* , 1500* , 1501* .

cur dir : 616* , 619* , 623* , 626* , 628* , 632* , 633* , 637* , \underline{1439*} , 1440* , 1450* , 1453* , 1455* , 1461* , 1463* , 1467* , 1468* , 1469* , 1470* , 1471* , 1472* .

cur ext : \underline{512}, 517* , 529* , 530* , 537* , 1275* , 1351, 1374.

cur f : 722, \underline{724}, 738, 741, 749, 752, 753, 755.
cur fam: \underline{236*} , 1151, 1155, 1165.
cur fam code: \underline{236*} , 237* , 238, 1139, 1145* .
cur file: \underline{304}, 329* , 362* , 537* , 538, 1488* .

cur font : \underline{230*} , 232* , 558, 559, 577, 1032, 1034, 1042, 1044, 1117, 1123, 1124, 1467* . cur font loc: \underline{230*} , 232* , 233* , 234, 1217.

cur group: 270, \underline{271}, 272, 274* , 281* , 282* , 800,

1062, 1063, 1064, 1065, 1067, 1068, 1069, 1130* , 1131, 1140, 1142, 1191* , 1192* , 1193, 1194* , 1200, 1395* , 1399* , 1413* , 1510* .

cur h: \underline{616*} , 617, 618, 619* , 620* , 622* , 623* , 626* , 627, 628* , 629* , 632* , 633* , 637* , 1452* , 1453* , 1454* , 1455* , 1457* , 1458* , 1462* .

cur head : \underline{770}, 771, 772, 786, 799. cur height : \underline{970}, 972, 973, 974, 975, 976. cur i : 722, 723, \underline{724}, 738, 741, 749, 752, 753, 755. cur if : 299* , 336, \underline{489}, 490, 495, 496* , 1335* , 1402* ,

1425* , 1509* , 1510* . cur indent : \underline{877*} , 889. cur input : 35, 36, 87, \underline{301}, 302, 311* , 321, 322,

534* , 1507* , 1509* . cur l : \underline{907}, 908, 909, 910, 911, 1032, 1034, 1035,

1036, 1037, 1039, 1040. cur lang : 891* , \underline{892}, 923, 924, 930, 934* , 939, 944,

963, 1091, 1200, 1362, 1363* , 1588* , 1591* . cur length: \underline{41}, 180, 182, 260, 516* , 525* , 537* ,

617, 692, 1368. cur level : 270, \underline{271}, 272, 274* , 277* , 278* , 280, 281* ,

1304, 1335* , 1395* , 1399* , 1413* , 1510* , 1570* , 1572* . cur line: \underline{877*} , 889, 890* . cur list : \underline{213*} , 216* , 217, 218, 422, 1244, 1413* . cur loop: \underline{770}, 771, 772, 777, 783, 792, 793, 794. cur mark : 296* , \underline{382*} , 386* , 1335* , 1542* . cur mlist : \underline{719}, 720, 726, 754, 1194* , 1196, 1199* . cur mu: 703, \underline{719}, 730, 732, 766. cur name: \underline{512}, 517* , 529* , 530* , 537* , 1257, 1258,

1260, 1351, 1374. cur order : 366* , 439, \underline{447}, 448, 454, 462. cur p: 823, \underline{828}, 829* , 830, 833, 837, 839, 840, 845* ,

851* , 852* , 853, 855* , 856, 857, 858, 859, 860, 862, 863* , 865, 866* , 867, 868, 869, 872, 877* , 878, 879* , 880* , 881* , 894, 903, 1362, 1441* , 1582* , 1585* .

cur ptr : 386* , 415* , 427* , 1224* , 1226* , 1227* , 1237* , 1548* , \underline{1549*} , 1552* , 1553* , 1554* , 1557* , 1558* , 1560* , 1563* , 1564* , 1572* .

cur q : \underline{907}, 908, 910, 911, 1034, 1035, 1036,

1037, 1040. cur r : \underline{907}, 908, 909, 910, 911, 1032, 1034, 1037,

1038, 1039, 1040. cur rh: \underline{906}, 908, 909, 910. cur s : 593, \underline{616*} , 619* , 629* , 640, 642* . cur size: 700, 701, 703, \underline{719}, 722, 723, 732, 736,

737, 744, 746, 747, 748, 749, 757, 758, 759, 762* . cur span: \underline{770}, 771, 772, 787, 796, 798. cur style: 703, \underline{719}, 720, 726, 727* , 730, 731, 734,

735, 737, 738, 742, 744, 745, 746, 748, 749, 750, 754, 756, 757, 758, 759, 760* , 762* , 763, 766, 1194* , 1196, 1199* .

cur tail : \underline{770}, 771, 772, 786, 796, 799. cur tok : 88, 281* , \underline{297}, 325, 326* , 327, 336, 364, 365, 366* , 368, 369, 372, 375, 379, 380, 381, 392, 393, 394, 395, 397, 399, 403, 405, 407, 440, 441, 442, 444, 445, 448, 452, 474, 476, 477, 479, 483* , 494* , 503, 506, 783, 784, 1038, 1047, 1095, 1127, 1128, 1132, 1215, 1221, 1268, 1269, 1271, 1371, 1372, 1417* , 1494* , 1500* , 1505* , 1517* , 1518* . cur v : \underline{616*} , 618, 619* , 623* , 624, 628* , 629* , 631, 632* ,

633* , 635, 636, 637* , 640. cur val : 264* , 265* , 334, 366* , 386* , \underline{410}, 413* , 414, 415* , 418, 419* , 420* , 421, 423* , 424* , 425, 426, 427* , 429, 430, 431, 433, 434, 435, 436, 437, 438, 439, 440, 442, 444, 445, 447, 448, 450, 451, 453, 455, 457, 458, 460, 461* , 462, 463, 465* , 466, 472* , 482* , 491, 501* , 503, 504, 509, 553, 577, 578, 579, 580, 645, 780, 782, 935, 977* , 1030, 1038, 1060, 1061, 1073, 1077* , 1082* , 1099, 1101* , 1103, 1123, 1124, 1151, 1154, 1160, 1161, 1165, 1182, 1188, 1224* , 1225* , 1226* , 1227* , 1228, 1229, 1232, 1234, 1236* , 1237* , 1238* , 1239* , 1240* , 1241* , 1243, 1244, 1245, 1246* , 1247* , 1248* , 1253, 1258, 1259, 1275* , 1296* , 1344, 1350, 1377, 1382* , 1399* , 1402* , 1405* , 1408* , 1417* , 1422* , 1428* , 1430* , 1502* , 1513* , 1515* , 1518* , 1536* , 1537* , 1544* , 1552* , 1553* , 1554* , 1557* , 1572* , 1599* . cur val level : 366* , \underline{410}, 413* , 415* , 418, 419* , 420* , 421, 423* , 424* , 427* , 429, 430, 439, 449, 451, 455, 461* , 465* , 466, 1408* , 1513* , 1515* .

cur width: \underline{877*} , 889. current page: 980. current character being worked on: \underline{570}. primitive: \underline{1397*} . current group level code: \underline{1397*} , 1398* , 1399* . primitive: \underline{1397*} . current group type code: \underline{1397*} , 1398* , 1399* . primitive: \underline{1400*} . current if branch code: \underline{1400*} , 1401* , 1402* . primitive: \underline{1400*} . current if level code: \underline{1400*} , 1401* , 1402* . primitive: \underline{1400*} . current if type code: \underline{1400*} , 1401* , 1402* . cv backup: \underline{366*} . cvl backup: \underline{366*} . d: \underline{107}, \underline{176}, \underline{177}, \underline{259}, \underline{341}, \underline{440}, \underline{560}, \underline{649*} , \underline{668}, \underline{679}, \underline{706}, \underline{815*} , \underline{830}, \underline{877*} , \underline{944}, \underline{970}, \underline{1068}, \underline{1086}, \underline{1138*} , \underline{1198}, \underline{1417*} , \underline{1477*} , \underline{1530*} , \underline{1532*} .

d buffer : \underline{595*} , 598* , 599* .

d fixed : \underline{608}, 609.

danger : \underline{1194*} , 1195, 1199* .

data: \underline{210*} , 232* , 1217, 1232, 1234.

data structure assumptions: \underline{161}, 164, 204, \underline{616*} ,

816* , 968* , 981, 1289, 1466* . day : \underline{236*} , 241* , 536* , 617, 1328. primitive: \underline{238}. day code: \underline{236*} , 237* , 238. dble: 109* . : 458. deactivate: \underline{829*} , 851* , 854. dead cycles : 419* , \underline{592}, 593, 638* , 1012* , 1024, 1025,

1054, 1242, 1246* . primitive: \underline{416*} . debug: \underline{7*} , \underline{78}, \underline{84*} , \underline{93}, \underline{114}, \underline{165}, \underline{166}, \underline{167}, \underline{172},

\underline{1031}, \underline{1338}. # : 1338. debug help: 78, 84* , 93, \underline{1338}. debugging: 7* , 84* , 114, 165, 182, 1031, 1338. decent fit : \underline{817}, 834, 852* , 853, 864* , 1580* , 1581* . decr : \underline{16}, 31* , 42, 44, 64, 71* , 86* , 88, 89, 90, 92, 102,

120, 121, 123, 175* , 177, 200, 201, 205, 217, 245, 260, 281* , 282* , 311* , 322, 324, 325, 326* , 329* , 331* , 347, 356, 357, 360, 362* , 394, 399, 422, 429, 442, 477, 483* , 494* , 509, 534* , 538, 568, 576, 601, 619* , 629* , 638* , 642* , 643, 716, 717, 803, 808* , 840, 858, 869, 883, 915, 916, 930, 931, 940, 944, 948, 965, 1060, 1100, 1120, 1127, 1174, 1186, 1194* , 1244, 1293* , 1311* , 1335* , 1337* , 1413* , 1417* , 1425* , 1461* , 1466* , 1472* , 1487* , 1489* , 1507* , 1508* , 1509* , 1510* , 1513* , 1552* , 1554* , 1602* , 1633* , 1651* .

def : \underline{209*} , 1208* , 1209* , 1210, 1213* , 1218* . primitive: \underline{1208*} . def code: \underline{209*} , 413* , 1210, 1230, 1231, 1232. def family : \underline{209*} , 413* , 577, 1210, 1230, 1231, 1234. def font : \underline{209*} , 265* , 266* , 413* , 577, 1210, 1256. def ref : \underline{305}, 306, 473, 482* , 960* , 1101* , 1218* , 1226* ,

1279, 1288, 1352, 1354, 1370, 1417* . default code: \underline{683}, 697, 743, 1182. default hyphen char : \underline{236*} , 576. primitive: \underline{238}. default hyphen char code: \underline{236*} , 237* , 238. default name: \underline{26*} , 27* , 529* , 1656* , 1658* . default rule: \underline{463}. default rule thickness : 683, \underline{701}, 734, 735, 737,

743, 745, 759. default skew char : \underline{236*} , 576. primitive: \underline{238}. default skew char code: \underline{236*} , 237* , 238. defecation: 597* . define: 1077* , \underline{1214}, 1217, 1218* , 1221, 1224* , 1225* ,

1228, 1232, 1234, 1248* , 1257, 1572* . defining : \underline{305}, 306, 339, 473, 482* . deflt length: \underline{26*} , 529* . del code: \underline{236*} , 240, 1160. primitive: \underline{1230}. del code base: \underline{236*} , 240, 242, 1230, 1232, 1233. delete: 1332* . delete file: 1661* . delete glue ref : \underline{201}, 202, 275* , 451, 465* , 578, 732,

802, 816* , 826, 881* , 976, 996* , 1004, 1017, 1022, 1100, 1229, 1239* , 1459* , 1513* , 1515* , 1523* , 1524* , 1527* , 1536* , 1537* , 1554* , 1571* , 1586* .

delete last : 1104, \underline{1105*} . delete q : \underline{726}, 760* , 763. delete sa ptr : \underline{1552*} , 1554* , 1558* . delete sa ref : \underline{1554*} , 1567* , 1572* , 1573* , 1574* . delete token ref : \underline{200}, 202, 275* , 324, 977* , 979* ,

1012* , 1016, 1335* , 1358, 1559* , 1560* , 1561* , 1563* , 1564* , 1571* .

deletions allowed : \underline{76}, 77, 84* , 85, 98, 336, 346. delim num: \underline{207}, 265* , 266* , 1046, 1151, 1154, 1160. delim ptr : 212* , \underline{213*} , 1185* , 1191* . delimited code: \underline{1178}, 1179, 1182, 1183. delimiter : \underline{687*} , 762* , 1191* . primitive: \underline{265*} . delimiter factor : \underline{236*} , 762* . primitive: \underline{238}. delimiter factor code: \underline{236*} , 237* , 238. delimiter shortfall : \underline{247}, 762* . primitive: \underline{248}. delimiter shortfall code: \underline{247}, 248. delim1 : \underline{700}, 748. delim2 : \underline{700}, 748. delta: \underline{103}, \underline{726}, 728, 733, \underline{735}, \underline{736}, \underline{737}, \underline{738}, 742,

\underline{743}, 745, 746, 747, 748, \underline{749}, 750, 754, 755, \underline{756},

759, \underline{762*} , \underline{994}, 1008, 1010, \underline{1123}, 1125.

delta node: \underline{822}, 830, 832, 843, 844, 860, 861,

865, 874, 875. delta node size: \underline{822}, 843, 844, 860, 861, 865. delta1 : \underline{743}, 746, \underline{762*} . delta2 : \underline{743}, 746, \underline{762*} . den: 585, \underline{587}, 590. denom: \underline{450}, 458. denom style: \underline{702}, 744. denominator : \underline{683}, 690, 697, 698, 744, 1181, 1185* . denom1 : \underline{700}, 744. denom2 : \underline{700}, 744. deplorable: \underline{974}, 1005. : 463. depth: \underline{135}, 136, 138, 139, 140, 184* , 187, 188, 463,

554, 622* , 624, 626* , 631, 632* , 635, 641, 649* , 653, 656, 668, 670, 679, 688, 704, 706, 709, 713, 727* , 730, 731, 735, 736, 737, 745, 746, 747, 749, 750, 751, 756, 758, 759, 768, 769, 801, 806, 810, 973, 1002, 1009, 1010, 1021* , 1087, 1100, 1452* , 1478* .

depth base: \underline{550}, 552, 554, 566, 571, 1322, 1323. depth index : \underline{543}, 554. depth offset : \underline{135}, 416* , 769, 1247* . depth threshold : \underline{181}, 182, 198, 233* , 236* , 692,

1339, 1556* . desc class : 1633* , \underline{1634*} , 1648* . desc type: 1633* , \underline{1634*} , 1648* . descr ptr : 1601* , 1631* , 1632* , 1633* , \underline{1634*} , 1635* ,

1640* . descr type: \underline{1634*} . descrp: 1632* . destroy marks : 1335* , \underline{1558*} , 1564* . primitive: \underline{1420*} . df len: 529* . df name: 529* . diag char : \underline{56*} , 1602* . diag file: 56* , 1333* , 1603* , 1615* , \underline{1616*} . diag name: 1333* , 1615* , \underline{1616*} , 1617* . diag print : \underline{56*} , 1609* . diag qual : 56* , 1333* , 1615* , \underline{1616*} , 1621* . diagf len: 1615* , \underline{1616*} , 1621* . diagf name: 1615* , \underline{1616*} , 1621* . : 1333* . dig : \underline{54*} , 64, 65, 67, 102, 452. digit sensed : \underline{960*} , 961, 962. primitive: \underline{1511*} . dimen: \underline{247}, 427* , 1008, 1010. primitive: \underline{411*} . dimen base: 220, \underline{236*} , 247, 248, 249, 250, 251,

252, 1070* , 1145* . primitive: \underline{1222}. dimen def code: \underline{1222}, 1223, 1224* . dimen par : \underline{247}. dimen pars : \underline{247}. dimen val : \underline{410}, 411* , 413* , 415* , 416* , 417* , 418, 420* ,

421, 424* , 425, 427* , 428, 429, 449, 455, 465* , 1237* , 1408* , 1511* , 1512* , 1518* , 1523* , 1525* , 1528* , 1531* , 1548* , 1553* , 1556* , 1565* .

dimen val limit : \underline{1548*} , 1554* , 1555* , 1570* , 1574* . : 460. dirty Pascal: \underline{3}, 114, 172, 182, 186* , 285, 1331* . dirty Pascal: 812, 1035. disc break : \underline{877*} , 880* , 881* , 882, 890* . disc group: \underline{269}, 1117, 1118, 1119, 1395* , 1413* . disc node: \underline{145}, 148, 175* , 183, 202, 206, 730,

761, 817, 819* , 829* , 856, 858, 866* , 881* , 914, 1081, 1105* .

disc ptr : 1335* , \underline{1592*} , 1596* . disc width: \underline{839}, 840, 869, 870. discretionary : \underline{208*} , 1090, 1114, 1115, 1116. : 1120. primitive: \underline{1114}. $$ : 1197. display indent : \underline{247}, 800, 1138* , 1145* , 1199* , 1477* . primitive: \underline{248}. display indent code: \underline{247}, 248, 1145* . primitive: \underline{1156}. display mlist : \underline{689}, 695, 698, 731, 1174. display style: \underline{688}, 694, 731, 1169, 1199* . primitive: \underline{1169}. primitive: \underline{1597*} . display widow penalties loc: \underline{230*} , 1597* , 1598* . display widow penalties ptr : 890* , \underline{1597*} . display widow penalty : \underline{236*} , 814* , 890* . primitive: \underline{238}. display widow penalty code: \underline{236*} , 237* , 238. display width: \underline{247}, 1138* , 1145* , 1199* , 1477* . primitive: \underline{248}. display width code: \underline{247}, 248, 1145* . dispose: 1635* . disposition: 28* , 1332* . div: \underline{100}, \underline{627}, \underline{636}. divide: \underline{209*} , 265* , 266* , 1210, 1235, 1236* . primitive: \underline{265*} . dlist : \underline{616*} , 619* , 807* , 1194* , 1202* , 1438* , 1478* . do all six : \underline{823}, 829* , 832, 837, 843, 844, 860,

861, 864* , 970, 987. do assignments : 800, 1123, 1206* , \underline{1270}. do endv : 1130* , \underline{1131}. do extension: 1347, \underline{1348*} , 1375. do glue: \underline{1433*} . do last line fit : 845* , 846* , 851* , 852* , 855* , 863* , 864* ,

\underline{1575*} , 1576* , 1586* . do marks : 977* , 1012* , 1335* , \underline{1558*} . do nothing : \underline{16}, 57* , 58* , 84* , 175* , 202, 275* , 344, 357, 538, 569, 609, 611, 612, 622* , 631, 651* , 669, 692, 728, 733, 761, 837, 866* , 899, 1045, 1236* , 1359, 1360, 1373, 1384* , 1433* , 1602* .

do register command : 1235, \underline{1236*} .

doing leaders : \underline{592}, 593, 628* , 637* , 1374.

done: \underline{15*} , 47* , 53* , 202, 281* , 282* , 311* , 380, 389* , 397, 440, 445, 448, 453, 458, 473, 474, 476, 482* , 483* , 494* , 526, 530* , 531, 537* , 560, 567, 576, 615, 638* , 640, 641, 698, 726, 738, 740, 760* , 761, 774, 777, 815* , 829* , 837, 863* , 873, 877* , 881* , 895, 906, 909, 911, 931, 960* , 961, 970, 974, 977* , 979* , 994, 997, 998, 1005, 1079* , 1081, 1110* , 1119, 1121, 1138* , 1146* , 1211* , 1227* , 1252* , 1358, 1413* , 1433* , 1445* , 1456* , 1462* , 1469* , 1470* , 1471* , 1494* , 1532* , 1596* , 1627* . done with noad : \underline{726}, 727* , 728, 733, 754.

done with node: \underline{726}, 727* , 730, 731, 754.

done1 : \underline{15*} , 167, 168, 389* , 399, 448, 452, 473, 474, 738, 741, 774, 783, 815* , 829* , 852* , 877* , 879* , 894, 896* , 899, 960* , 965, 994, 997, 1000, 1302, 1315. done2 : \underline{15*} , 167, 169, 448, 458, 459, 473, 478* , 774,

784, 815* , 896* , 1302, 1316. done3 : \underline{15*} , 815* , 897* , 898* . done4 : \underline{15*} , 815* , 899. done5 : \underline{15*} , 815* , 866* , 869. done6 : \underline{15*} . dont expand : \underline{210*} , 258, 357, 369. double: 109* . : 1177. : 1177. double hyphen demerits : \underline{236*} , 859. primitive: \underline{238}. double hyphen demerits code: \underline{236*} , 237* , 238. : 169. down ptr : \underline{605}, 606, 607, 615. downdate width: \underline{860}. down1 : 585, \underline{586}, 607, 609, 610, 613, 614, 616* . down2 : \underline{585}, 594, 610. down3 : \underline{585}, 610. down4 : \underline{585}, 610. primitive: \underline{416*} . dry rot: 95. : 1335* . primitive: \underline{1052}. dump four ASCII : \underline{1309}. dump hh: \underline{1305*} , 1318, 1324* . dump int : \underline{1305*} , 1307* , 1309, 1311* , 1313, 1315,

1316, 1318, 1320, 1322, 1324* , 1326, 1329* , 1388* . dump qqqq : \underline{1305*} , 1309, 1322. dump wd : \underline{1305*} , 1311* , 1315, 1316, 1320. : 963. dvi buf : 594, \underline{595*} , 597* , 598* , 599* , 607, 613, 614. dvi buf size: \underline{11*} , 14, 594, 595* , 596, 597* , 598* , 599* ,

607, 613, 614, 642* . dvi f : \underline{616*} , 617, 620* , 621. dvi file: \underline{532*} , 592, 595* , 597* , 598* , 599* , 642* . files: 583. dvi font def : \underline{602}, 621, 643. dvi four : \underline{600}, 602, 610, 617, 624, 633* , 640,

642* , 1368. dvi gone: 594, \underline{595*} , 596, 598* , 612. dvi h: \underline{616*} , 617, 619* , 620* , 623* , 624, 628* , 629* ,

632* , 637* . dvi index : \underline{594}, 595* . dvi limit : 594, \underline{595*} , 596, 598* , 599* . dvi offset : 594, \underline{595*} , 596, 598* , 601, 605, 607, 613,

614, 619* , 629* , 640, 642* . dvi out : \underline{598*} , 600, 601, 602, 603, 609, 610, 617,

619* , 620* , 621, 624, 629* , 633* , 640, 642* , 1368. dvi pop: \underline{601}, 619* , 629* . dvi ptr : 594, \underline{595*} , 596, 598* , 599* , 601, 607, 619* ,

629* , 640, 642* . dvi qual : 532* , 598* , 599* , 642* , \underline{1616*} , 1621* . dvi swap: \underline{598*} . dvi v : \underline{616*} , 617, 619* , 623* , 628* , 629* , 632* , 637* . dvif len: 532* , \underline{1616*} , 1621* . dvif name: 532* , \underline{1616*} , 1621* . dyn used : \underline{117}, 120, 121, 122, 123, 164, 639,

1311* , 1312* . dynam str : \underline{1633*} . D0 : 109* . e: \underline{277*} , \underline{279*} , \underline{518}, \underline{519}, \underline{530*} , \underline{1198}, \underline{1211*} , \underline{1236*} , \underline{1395*} ,

\underline{1396*} , \underline{1477*} , \underline{1515*} , \underline{1572*} , \underline{1573*} . easy line: 819* , 835, \underline{847}, 848, 850. ec: 540, 541, 543, 545, \underline{560}, 565, 566, 570, 576. edcmd file: \underline{54*} , 57* , 58* , 1656* , 1658* . edcmd write: \underline{54*} , 57* , 58* , 1656* , 1658* . primitive: \underline{1208*} . edge: \underline{619*} , 623* , 626* , \underline{629*} , 635. edge dist : \underline{1452*} , 1453* , 1455* , 1462* . edge node: 616* , \underline{1452*} , 1453* , 1458* , 1469* . edge node size: \underline{1452*} . Edit : \underline{1640*} , 1643* , 1644* , 1645* , 1655* , 1664* , 1665* . : 1631* , 1640* . : 1631* , 1640* . : 1631* , 1640* . edit cmd : \underline{1640*} , 1642* , 1643* . edit command line: \underline{1640*} , 1643* , 1646* , 1648* . edit ctr : \underline{1651*} , 1653* , 1654* . edit file: 84* , \underline{1640*} , 1642* , 1643* , \underline{1650*} , \underline{1651*} . edit found : \underline{1651*} , 1652* , 1654* , 1655* , 1661* . edit len: \underline{1616*} , 1621* , 1651* . edit locate: \underline{1649*} , 1655* . edit name: \underline{1616*} , 1621* , 1651* . edit qual : \underline{1616*} , 1621* , 1651* . edit result : \underline{1639*} , 1640* , 1651* . edit status : \underline{1651*} , 1655* , 1664* . edited : 1639* , 1644* , 1651* . editor : \underline{1637*} , 1638* , \underline{1640*} , 1641* , 1642* , 1645* , 1646* ,

1654* , 1655* , 1665* . editor entry : \underline{1640*} , 1642* , 1646* . editor ident : \underline{1636*} , 1637* , 1640* , 1665* . editor status : \underline{1640*} , 1642* , 1644* , 1646* . EDT: 84* , 1631* , 1640* . EDT editor : \underline{1637*} , 1638* , 1655* . EDT like: \underline{1636*} , 1638* , 1640* , 1642* , 1655* , 1666* . eight bits : \underline{25*} , 64, 297, 549, 560, 581* , 582, 595* , 607,

649* , 706, 709, 712, 992, 993, 1288, 1618* , 1634* . eight qual : 49* , 1332* , \underline{1616*} . : 50* . eject penalty : \underline{157}, 829* , 831, 851* , 859, 873, 970,

972, 974, 1005, 1010, 1011. else: 10* . primitive: \underline{491}. else code: \underline{489}, 491, 498* , 1402* . : 455.

: 93. emergency stretch: \underline{247}, 828, 863* . primitive: \underline{248}. emergency stretch code: \underline{247}, 248. empty : \underline{16}, 421, 681, 685, 687* , 692, 722, 723, 738,

749, 751, 752, 754, 755, 756, 980, 986, 987, 991* , 1001, 1008, 1176, 1177, 1186.

empty line at end of file: 486, 538. empty editor : 1664* , \underline{1665*} , 1666* . empty field : \underline{684}, 685, 686, 742, 1163, 1165, 1181. empty flag : \underline{124}, 126, 130, 150, 164, 1312* . enable control C : \underline{96*} , 97* , 1625* . end: 7* , 8* , 10* . : 37* , 71* . : 1335* . primitive: \underline{1052}. end cs name: \underline{208*} , 265* , 266* , 372, 1134, 1500* . primitive: \underline{265*} . end diagnostic: \underline{245}, 284* , 299* , 323, 400, 401, 502,

509, 581* , 638* , 641, 663, 675, 863* , 987, 992, 1006, 1011, 1121, 1298, 1396* , 1556* .

end file reading : \underline{329*} , 330, 360, 362* , 483* , 537* ,

1335* . end graf : 1026* , 1085, 1094, \underline{1096*} , 1100, 1131,

1133, 1168. end group: \underline{208*} , 265* , 266* , 1063. primitive: \underline{265*} . primitive: \underline{376}. end L code: \underline{147*} , 1435* , 1436* , 1439* , 1467* . end line char : 87, \underline{236*} , 240, 303* , 318* , 332, 360,

362* , 483* , 534* , 538, 1337* . primitive: \underline{238}. end line char code: \underline{236*} , 237* , 238. end line char inactive: \underline{360}, 362* , 483* , 538, 1337* . end LR: \underline{147*} , 192* , 866* , 1442* , 1447* , 1450* , 1461* ,

1470* , 1472* . end LR type: \underline{147*} , 1439* , 1442* , 1447* , 1450* , 1461* ,

1470* , 1472* . end M code: \underline{147*} , 424* , 1080* , 1105* , 1439* , 1479* . end match: \underline{207}, 289* , 291, 294* , 391, 392, 394. end match token: \underline{289*} , 389* , 391, 392, 393, 394,

474, 476, 482* . end name: 512, \underline{517*} , 526, 531. end of TEX : \underline{6}, 81, 1332* . end R code: \underline{147*} , 1435* , 1439* . end reflect : 1434* . end span: \underline{162}, 768, 779, 793, 797, 801, 803. end template: \underline{210*} , 366* , 375, 380, 780, 1295* , 1505* . end template token: \underline{780}, 784, 790. end token list : \underline{324}, 325, 357, 390, 1026* , 1335* ,

1371. end write: \underline{222}, 1369, 1371.

: 1369.

end write token: \underline{1371}, 1372.

endcases: \underline{10*} .

primitive: \underline{1435*} . primitive: \underline{1435*} . endv : \underline{207}, 298* , 375, 380, 768, 780, 782, 791* ,

1046, 1130* . ensure dvi open: \underline{532*} , 617. ensure vbox : \underline{993}, 1009, 1018. entity : \underline{1618*} . entry : \underline{1636*} , 1638* , 1641* , 1666* . entry point : \underline{1640*} , 1641* , 1643* . eof : 26* , 27* , 31* , 52* , 564* , 1327, 1606* , 1647* , 1648* . eof seen: 328* , 362* , \underline{1394*} . eoln: 31* , 52* . eop: 583, 585, \underline{586}, 588, 640, 642* . eq define: \underline{277*} , 278* , 279* , 372, 782, 1070* , 1214. eq destroy : \underline{275*} , 277* , 279* , 283. eq level : \underline{221}, 222, 228, 232* , 236* , 253, 264* , 277* , 279* , 283, 780, 977* , 1315, 1369, 1553* , 1554* .

eq level field : \underline{221}.

eq no: \underline{208*} , 1140, 1141, 1143, 1144, 1413* .
primitive: \underline{1141}.
eq save: \underline{276}, 277* , 278* .

eq type: 210* , \underline{221}, 222, 223, 228, 232* , 253, 258, 264* , 265* , 267, 277* , 279* , 351, 353, 354, 357, 358, 372, 389* , 391, 780, 1152, 1315, 1369, 1500* .

eq type field : \underline{221}, 275* .

eq word define: \underline{278*} , 279* , 1070* , 1139, 1145* , 1214. eqtb: 2* , 115, 163, 220, 221, 222, 223, 224, 228,

230* , 232* , 236* , 240, 242, 247, 250, 251, 252, \underline{253}, 255, 262, 264* , 265* , 266* , 267, 268* , 270, 272, 274* , 275* , 276, 277* , 278* , 279* , 281* , 282* , 283, 284* , 285, 286, 289* , 291, 297, 298* , 305, 307* , 332, 333, 354, 389* , 413* , 414, 473, 491, 548, 553, 780, 814* , 1188, 1208* , 1222, 1237* , 1253, 1257, 1315, 1316, 1317, 1339, 1345, 1380* , 1556* , 1568* . eqtb size: 220, \underline{247}, 250, 252, 253, 254, 1307* ,

1308* , 1316, 1317. equiv : \underline{221}, 222, 223, 224, 228, 229, 230* , 232* , 233* , 234, 235, 253, 255, 264* , 265* , 267, 275* , 277* , 279* , 351, 353, 354, 357, 358, 413* , 414, 415* , 508, 577, 780, 1152, 1227* , 1237* , 1257, 1289, 1315, 1369, 1392* , 1597* , 1599* .

equiv field : \underline{221}, 275* , 285, 1567* .

equivalence: \underline{1651*} , 1653* , 1654* , 1656* , 1658* , 1661* ,

1664* . equv len: \underline{1651*} , 1653* , 1656* , 1658* , 1661* , 1664* .

err help: 79, \underline{230*} , 1283, 1284.
primitive: \underline{230*} .
err help loc: \underline{230*} .
primitive: \underline{1277}.

error : 28* , 72, 75, 76, 78, 79, \underline{82*} , 88, 91, 93, 98, 327, 338, 346, 370, 398, 408, 418, 428, 445, 454, 456, 459, 460, 475, 476, 486, 500, 510* , 523, 530* , 535* , 561, 567, 579, 641, 723, 776, 784, 792, 826, 936, 937* , 960* , 961, 962, 963, 976, 978, 992, 1004, 1009, 1024, 1027, 1050, 1064, 1066, 1068, 1069, 1080* , 1082* , 1095, 1099, 1106, 1110* , 1120, 1121, 1128, 1129, 1135, 1159, 1166, 1177, 1183, 1192* , 1195, 1213* , 1225* , 1232, 1236* , 1237* , 1241* , 1252* , 1259, 1283, 1284, 1293* , 1372, 1390* , 1515* .

error context lines : \underline{236*} , 311* . primitive: \underline{238}. error context lines code: \underline{236*} , 237* , 238. error count : \underline{76}, 77, 82* , 86* , 1096* , 1293* . error line: \underline{11*} , 14, 54* , 58* , 306, 311* , 315, 316, 317* . error message issued : \underline{76}, 82* , 95, 1600* . error stop mode: 72, \underline{73*} , 74, 82* , 93, 98, 1262,

1283, 1293* , 1294, 1297, 1327, 1335* , 1430* . primitive: \underline{1262}. escape: \underline{207}, 232* , 344, 1337* . escape char : \underline{236*} , 240, 243. primitive: \underline{238}. escape char code: \underline{236*} , 237* , 238. : 182. : 292. ETEX : 2* . : 53* . : 53* . : 52* . : 52* . eTeX aux : 212* , \underline{213*} , 215* , 216* . eTeX aux field : \underline{212*} , 213* , 1413* . eTeX banner : \underline{2*} , 61* , 536* . eTeX CLD table: 1332* , \underline{1619*} . eTeX dim: \underline{416*} , 424* , 1403* , 1406* , 1534* . eTeX enabled : \underline{1390*} , 1437* . eTeX ex : 184* , 274* , 277* , 278* , 282* , 326* , 536* , 581* ,

619* , 622* , 638* , 1145* , 1211* , 1311* , 1312* , 1335* , 1337* , \underline{1386*} , 1389* , 1433* , 1467* .

eTeX expr : \underline{416*} , 1511* , 1512* , 1513* . eTeX glue: \underline{416*} , 424* , 1538* . eTeX int : \underline{416*} , 1380* , 1397* , 1400* , 1534* . eTeX mode: 1379* , \underline{1386*} , 1387* , 1388* , 1389* . eTeX mu: \underline{416*} , 1513* , 1538* . eTeX revision: \underline{2*} , 1385* . primitive: \underline{1380*} . eTeX revision code: \underline{1380*} , 1383* , 1384* , 1385* . eTeX state: \underline{1380*} , 1388* , 1434* . eTeX state base: \underline{1380*} , 1435* . eTeX state code: \underline{236*} , 1380* , 1434* . eTeX states : \underline{2*} , 236* , 1388* . eTeX version: \underline{2*} , 1382* . primitive: \underline{1380*} . eTeX version code: 416* , \underline{1380*} , 1381* , 1382* . eTeX version string : \underline{2*} . every cr : \underline{230*} , 774, 799. primitive: \underline{230*} . every cr loc: \underline{230*} , 231* . every cr text : \underline{307*} , 314* , 774, 799. every display : \underline{230*} , 1145* . primitive: \underline{230*} . every display loc: \underline{230*} , 231* . every display text : \underline{307*} , 314* , 1145* . every eof : 362* , \underline{1392*} . primitive: \underline{1391*} . every eof loc: \underline{230*} , 1391* , 1392* . every eof text : \underline{307*} , 314* , 362* . every hbox : \underline{230*} , 1083. primitive: \underline{230*} . every hbox loc: \underline{230*} , 231* . every hbox text : \underline{307*} , 314* , 1083. every job: \underline{230*} , 1030. primitive: \underline{230*} . every job loc: \underline{230*} , 231* . every job text : \underline{307*} , 314* , 1030. every math: \underline{230*} , 1139. primitive: \underline{230*} . every math loc: \underline{230*} , 231* . every math text : \underline{307*} , 314* , 1139. every par : \underline{230*} , 1091. primitive: \underline{230*} . every par loc: \underline{230*} , 231* , 307* , 1226* . every par text : \underline{307*} , 314* , 1091. every vbox : \underline{230*} , 1083, 1167. primitive: \underline{230*} . every vbox loc: \underline{230*} , 231* . every vbox text : \underline{307*} , 314* , 1083, 1167. : 455. ex hyphen penalty : 145, \underline{236*} , 869. primitive: \underline{238}. ex hyphen penalty code: \underline{236*} , 237* , 238. ex space: \underline{208*} , 265* , 266* , 1030, 1090. exactly : \underline{644}, 645, 715, 889, 977* , 1017, 1062,

1201, 1414* . exit : \underline{15*} , 16, 37* , 47* , 58* , 59, 69, 82* , 125, 182, 277* ,

278* , 292, 341, 389* , 407, 413* , 461* , 465* , 497, 498* , 517* , 524, 582, 607, 615, 649* , 668, 752, 791* , 829* , 895, 934* , 944, 948, 977* , 994, 1012* , 1030, 1054, 1079* , 1105* , 1110* , 1113, 1119, 1151, 1159, 1174, 1211* , 1236* , 1270, 1303, 1335* , 1338, 1395* , 1505* , 1552* , 1554* , 1620* .

exit status : \underline{1640*} , 1644* , 1645* . exiting : \underline{1636*} , 1638* , 1641* , 1645* , 1666* . expand : 358, \underline{366*} , 368, 371, 380, 381, 439, 467,

478* , 498* , 510* , 782, 1416* , 1505* . expand after : \underline{210*} , 265* , 266* , 366* , 367* , 1495* . primitive: \underline{265*} . explicit : \underline{155}, 717, 837, 866* , 868, 879* , 1058,

1113, 1447* . Expo: 186* , \underline{1623*} . expr a: \underline{1525*} , 1527* . expr add : \underline{1516*} , 1517* . expr add sub: \underline{1525*} . expr d : \underline{1529*} . expr div : \underline{1516*} , 1517* , 1528* , 1529* . expr e field : \underline{1521*} , 1522* . expr m: \underline{1528*} . expr mult : \underline{1516*} , 1517* , 1528* . expr n field : \underline{1521*} , 1522* . expr node size: \underline{1521*} , 1522* . expr none: \underline{1516*} , 1517* , 1524* , 1525* . expr s : \underline{1531*} . expr scale: \underline{1516*} , 1528* , 1531* . expr sub: \underline{1516*} , 1517* , 1523* , 1525* . expr t field : \underline{1521*} , 1522* . ext bot : \underline{546}, 713, 714. ext delimiter : \underline{513*} , 515, 516* , 517* . ext mid : \underline{546}, 713, 714. ext rep: \underline{546}, 713, 714. ext tag : \underline{544}, 569, 708, 710. ext top: \underline{546}, 713, 714. exten: \underline{544}. exten base: \underline{550}, 552, 566, 573, 574, 576, 713,

1322, 1323. extensible recipe: 541, \underline{546}. extension: \underline{208*} , 1344, 1346, 1347, 1375. extensions to TEX: 2* , 146, 1340. extern: \underline{9*} , 1618* , 1627* , 1631* , 1632* , 1640* . external : 1601* . : 510* . : 1135. : 510* . : 1192* . : 500, 510* . : 1192* . : 1069. : 792. : 1066. extra info: \underline{769}, 788, 789, 791* , 792. extra right brace: 1068, \underline{1069}. extra space: 547, \underline{558}, 1044. extra space code: \underline{547}, 558. eyes and mouth: 332. F: \underline{1627*} . f: \underline{27*} , \underline{28*} , \underline{31*} , \underline{144}, \underline{448}, \underline{525*} , \underline{537*} , \underline{560}, \underline{577}, \underline{578},

\underline{581*} , \underline{582}, \underline{592}, \underline{602}, \underline{649*} , \underline{706}, \underline{709}, \underline{711}, \underline{712},
\underline{715}, \underline{716}, \underline{717}, \underline{738}, \underline{830}, \underline{862}, \underline{1068}, \underline{1113}, \underline{1123},
\underline{1138*} , \underline{1211*} , \underline{1257}, \underline{1515*} , \underline{1532*} .

FAB : 33* , \underline{1627*} .

FAB ptr : \underline{1626*} , 1627* , 1628* . failed : 1639* , 1640* , 1644* , 1651* . false: 27* , 31* , 34* , 37* , 45, 46, 47* , 51* , 71* , 76, 80, 88, 89, 98, 106, 107, 166, 167, 168, 169, 264* , 274* , 281* , 284* , 299* , 311* , 323, 327, 328* , 331* , 336, 346, 361, 362* , 365, 374, 400, 401, 407, 415* , 425, 427* , 440, 441, 445, 447, 448, 449, 455, 460, 461* , 462, 465* , 485, 501* , 502, 505* , 507, 509, 512, 516* , 524, 526, 528, 537* , 538, 551, 563* , 581* , 593, 595* , 706, 720, 722, 754, 774, 791* , 826, 828, 837, 851* , 854, 863* , 881* , 903, 906, 910, 911, 951, 954, 960* , 961, 962, 963, 966* , 968* , 987, 990, 1006, 1011, 1020, 1021* , 1026* , 1031, 1033, 1034, 1035, 1040, 1051, 1054, 1061, 1096* , 1101* , 1167, 1182, 1183, 1191* , 1192* , 1194* , 1199* , 1226* , 1227* , 1236* , 1258, 1270, 1279, 1282, 1283, 1288, 1303, 1325* , 1336* , 1342, 1343, 1352, 1354, 1371, 1374, 1379* , 1390* , 1396* , 1416* , 1489* , 1502* , 1507* , 1509* , 1515* , 1526* , 1530* , 1532* , 1553* , 1554* , 1556* , 1557* , 1576* , 1579* , 1586* , 1588* , 1589* , 1629* , 1630* , 1638* , 1650* , 1651* , 1662* , 1666* .

false bchar : \underline{1032}, 1034, 1038.

fam: \underline{681}, 682, 683, 687* , 691, 722, 723, 752, 753,

1151, 1155, 1165. primitive: \underline{238}. fam fnt : \underline{230*} , 700, 701, 707, 722, 1195. fam in range: \underline{1151}, 1155, 1165. fao argument : 1632* . fast delete glue ref : \underline{201}, 202, 1433* . fast get avail : \underline{122}, 371, 1034, 1038. fast store new token: \underline{371}, 399, 464* , 466. : 1303. fatal error : 71* , \underline{93}, 324, 360, 484, 530* , 535* ,

782, 789, 791* . fatal error stop: \underline{76}, 77, 82* , 93, 1332* , 1600* . fbyte: \underline{564*} , 568, 571, 575* . Ferguson, Michael John: 2* . fetch: \underline{722}, 724, 738, 741, 749, 752, 755. fetch box : 420* , 505* , 977* , 1079* , 1110* , 1247* ,

1296* , \underline{1553*} . fewest demerits : \underline{872}, 874, 875. fget : \underline{564*} , 565, 568, 571, 575* . primitive: \underline{491}. fi code: \underline{489}, 491, 492, 494* , 498* , 500, 509, 510* ,

1402* , 1425* , 1510* . fi or else: \underline{210*} , 299* , 366* , 367* , 489, 491, 492,

494* , 510* , 1293* .

: 454. fil : 135, \underline{150}, 164, 177, 454, 650, 659, 665, 1201. fil code: \underline{1058}, 1059, 1060. fil glue: \underline{162}, 164, 1060. fil neg code: \underline{1058}, 1060. fil neg glue: \underline{162}, 164, 1060. : 338. : 486. file name size: \underline{11*} , 26* , 513* , 517* , 519, 520* , 523, 525* ,

529* , 1616* , 1623* , 1628* , 1629* , 1636* , 1651* , 1660* . file offset : \underline{54*} , 55, 57* , 58* , 62, 537* , 638* , 1280, 1488* . file opened : \underline{560}, 561, 563* . file size: 26* , 513* , 520* , 529* , 1616* , \underline{1623*} . file warning : 362* , \underline{1510*} . filenm: \underline{1640*} . fill : 135, \underline{150}, 164, 650, 659, 665, 1201. fill code: \underline{1058}, 1059, 1060. fill glue: \underline{162}, 164, 1054, 1060. fill width: \underline{1575*} , 1576* , 1579* . filll : 135, \underline{150}, 177, 454, 650, 659, 665, 1201. fin align: 773, 785* , \underline{800}, 1131. fin col : 773, \underline{791*} , 1131. fin mlist : 1174, \underline{1184}, 1186, 1191* , 1194* . fin row : 773, \underline{799}, 1131. fin rule: \underline{619*} , 622* , 626* , 629* , 631, 635. final cleanup: 1332* , \underline{1335*} , 1558* . final end : \underline{6}, 35, 331* , 1332* , 1337* , 1621* . final hyphen demerits : \underline{236*} , 859. primitive: \underline{238}. final hyphen demerits code: \underline{236*} , 237* , 238. final pass : \underline{828}, 854, 863* , 873. find font dimen: 425, \underline{578}, 1042, 1253. find sa element : 415* , 427* , 1224* , 1226* , 1227* , 1237* ,

1549* , \underline{1552*} , 1553* , 1554* , 1557* , 1560* , 1563* , 1572* . fingers: 511. finite shrink : 825, \underline{826}. fire up: 1005, \underline{1012*} , 1542* , 1558* , 1561* . fire up done: 1012* , \underline{1558*} , 1562* . fire up init : 1012* , \underline{1558*} , 1561* . firm up the line: 340, 362* , \underline{363}, 538. first : \underline{30*} , 31* , 35, 36, 37* , 71* , 83, 87, 88, 264* , 328* ,

329* , 331* , 355, 360, 362* , 363, 374, 483* , 531, 538, 1336* , 1489* , 1501* .

first child : \underline{960*} , 963, 964, 1588* , 1589* . first count : \underline{54*} , 315, 316, 317* . first fit : \underline{953}, 957, 966* , 1590* . first indent : \underline{847}, 849, 889. first mark : \underline{382*} , 383, 1012* , 1016, 1542* , 1561* . primitive: \underline{384}. first mark code: \underline{382*} , 384, 385* , 1542* . primitive: \underline{1542*} . first text char : \underline{19}, 24.

first width: \underline{847}, 849, 850, 889.
fit class : \underline{830}, 836, 845* , 846* , 852* , 853, 855* , 859,

1580* , 1581* , 1583* , 1584* . fitness : \underline{819*} , 845* , 859, 864* .

fix date and time: \underline{241*} , 1332* , 1337* .
fix language: 1034, \underline{1376}.
fix word : \underline{541}, 542, 547, 548, 571.
flag : \underline{1618*} .
flags : \underline{1640*} .
float : \underline{109*} , 114, 186* , 809, 1433* .
float constant : \underline{109*} , 186* , 625* , 1123, 1125.
float cost : \underline{140}, 188, 1008, 1100.
floating penalty : 140, \underline{236*} , 1068, 1100.
primitive: \underline{238}.
floating penalty code: \underline{236*} , 237* , 238.
flush char : \underline{42}, 180, 195, 692, 695.

flush list : \underline{123}, 200, 324, 372, 396, 407, 801, 903, 960* , 1096* , 1279, 1297, 1370, 1422* , 1486* , 1500* .

flush math: \underline{718}, 776, 1195.

flush node list : 199, \underline{202}, 275* , 639, 698, 718, 731, 732, 742, 800, 816* , 879* , 883, 903, 918, 968* , 977* , 992, 999* , 1023* , 1026* , 1078, 1105* , 1120, 1121, 1206* , 1335* , 1375, 1460* , 1468* , 1471* , 1476* , 1571* .

flush string : \underline{44}, 264* , 517* , 537* , 1260, 1279,

1328, 1486* . flushable string : \underline{1257}, 1260. fmem ptr : 425, \underline{549}, 552, 566, 569, 570, 576, 578,

579, 580, 1320, 1321, 1323, 1334. fmt count : 27* , 1305* , 1306* , 1329* , \underline{1622*} .

fmt file: 524, \underline{1305*} , 1306* , 1327, 1328, 1329* ,

1337* , 1621* . fmt get : \underline{1306*} .

fmt put : \underline{1305*} .
fmt word : \underline{1305*} , 1306* , 1308* .
fnt def1 : 585, \underline{586}, 602.
fnt def2 : \underline{585}.
fnt def3 : \underline{585}.
fnt def4 : \underline{585}.
fnt num 0 : 585, \underline{586}, 621.
fnt1 : 585, \underline{586}, 621.
fnt2 : \underline{585}.
fnt3 : \underline{585}.
fnt4 : \underline{585}.

font : \underline{134}, 143, 144, 174, 176, 193, 206, 267, 548, 582, 620* , 654, 681, 709, 715, 724, 841, 842, 866* , 867, 870, 871, 896* , 897* , 898* , 903, 908, 911, 1034, 1038, 1113, 1147* , 1457* , 1466* .

font metric files: 539. font parameters: 700, 701. : 579. : 561. primitive: \underline{265*} . font area: \underline{549}, 552, 576, 602, 603, 1260, 1322,

1323. font base: 11* , \underline{12*} , 111, 134, 174, 176, 222, 232* ,

548, 551, 602, 621, 643, 1260, 1320, 1321, 1334. font bc: \underline{549}, 552, 576, 582, 708, 722, 1036, 1322,

1323, 1405* , 1502* . font bchar : \underline{549}, 552, 576, 897* , 898* , 915, 1032,

1034, 1322, 1323. primitive: \underline{1403*} . font char dp code: \underline{1403*} , 1404* , 1405* . primitive: \underline{1403*} . font char ht code: \underline{1403*} , 1404* , 1405* . primitive: \underline{1403*} . font char ic code: \underline{1403*} , 1404* , 1405* . primitive: \underline{1403*} . font char wd code: \underline{1403*} , 1404* , 1405* . font check : \underline{549}, 568, 602, 1322, 1323. primitive: \underline{265*} . font dsize: 472* , \underline{549}, 552, 568, 602, 1260, 1261,

1322, 1323. font ec: \underline{549}, 552, 576, 582, 708, 722, 1036, 1322,

1323, 1405* , 1502* . font false bchar : \underline{549}, 552, 576, 1032, 1034,

1322, 1323. font glue: \underline{549}, 552, 576, 578, 1042, 1322, 1323. font id base: \underline{222}, 234, 256, 415* , 548, 1257. font id text : 234, \underline{256}, 267, 579, 1257, 1322. font in short display : \underline{173}, 174, 193, 663, 864* ,

1339. font index : \underline{548}, 549, 560, 906, 1032, 1211* . font info: 11* , 425, 548, \underline{549}, 550, 552, 554, 557,

558, 560, 566, 569, 571, 573, 574, 575* , 578, 580, 700, 701, 713, 741, 752, 909, 1032, 1039, 1042, 1211* , 1253, 1320, 1321, 1339.

font max : \underline{11*} , 111, 174, 176, 548, 551, 566,

1321, 1334. font mem size: \underline{11*} , 548, 566, 580, 1321, 1334. font name: 472* , \underline{549}, 552, 576, 581* , 602, 603,

1260, 1261, 1322, 1323. primitive: \underline{468}. font name code: \underline{468}, 469* , 471* , 472* . font params : \underline{549}, 552, 576, 578, 579, 580, 1195,

1322, 1323. font ptr : \underline{549}, 552, 566, 576, 578, 643, 1260,

1320, 1321, 1334. font size: 472* , \underline{549}, 552, 568, 602, 1260, 1261,

1322, 1323. font used : \underline{549}, 551, 621, 643. fonts len: \underline{513*} , 514* . fonts name: \underline{513*} , 514* . : 1257. foobar : \underline{1627*} . : 191. : 338. force eof : 331* , \underline{361}, 362* , 378* . form feed : \underline{23*} , 232* . format area length: \underline{520*} , 521* , 524. format default length: \underline{520*} , 521* , 523, 524. format ext length: \underline{520*} , 523, 524. format extension: \underline{520*} , 529* , 1328. format ident : 35, 61* , 536* , \underline{1299}, 1300, 1301, 1326,

1327, 1328, 1337* , 1379* , 1621* . format name length: \underline{520*} , 521* . format qual : \underline{1616*} , 1621* . forward : 9* , 78, 218, 281* , 340, 366* , 409* , 618, 692, 693, 720, 774, 800, 1416* , 1429* , 1485* , 1514* , 1519* , 1543* , 1650* .

found : \underline{15*} , 31* , 125, 128, 129, 259, 341, 354, 356, 389* , 392, 394, 448, 455, 473, 475, 477, 524, 607, 609, 612, 613, 614, 645, 706, 708, 720, 829* , 851* , 895, 923, 931, 934* , 941, 953, 955, 1138* , 1146* , 1147* , 1148, 1236* , 1237* , 1413* , 1417* , 1466* , 1471* , 1472* , 1515* , 1516* , 1522* , 1532* , 1580* , 1581* . found1 : \underline{15*} , 895, 902, 1302, 1315, 1413* , 1532* , 1533* .

found2 : \underline{15*} , 895, 903, 1302, 1316, 1413* .
four choices : \underline{113*} .

four quarters : \underline{113*} , 413* , 548, 549, 554, 555, 560, 649* , 683, 684, 706, 709, 712, 724, 738, 749, 906, 1032, 1123, 1302, 1303, 1486* , 1489* .

Frac: \underline{1623*} .

fract : 1531* , \underline{1532*} , 1579* .
fraction noad : \underline{683}, 687* , 690, 698, 733, 761,

1178, 1181. fraction noad size: \underline{683}, 698, 761, 1181.

fraction rule: \underline{704}, 705, 735, 747.
Frac1 : \underline{1623*} .
free: \underline{165}, 167, 168, 169, 170, 171.

free avail : \underline{121}, 202, 204, 217, 400, 452, 772, 915,

1036, 1226* , 1288, 1417* , 1439* , 1490* . free node: \underline{130}, 201, 202, 275* , 496* , 615, 655, 698, 715, 721, 727* , 751, 753, 756, 760* , 772, 803, 860, 861, 865, 903, 910, 977* , 1019, 1021* , 1022, 1037, 1100, 1110* , 1186, 1187, 1201, 1335* , 1358, 1445* , 1455* , 1458* , 1459* , 1460* , 1462* , 1471* , 1478* , 1489* , 1490* , 1522* , 1554* , 1558* , 1574* .

freeze page specs : \underline{987}, 1001, 1008.

frozen control sequence: \underline{222}, 258, 1215, 1314,

1318, 1319. frozen cr : \underline{222}, 339, 780, 1132.

frozen dont expand : \underline{222}, 258, 369.
frozen end group: \underline{222}, 265* , 1065.
frozen end template: \underline{222}, 375, 780.
frozen endv : \underline{222}, 375, 380, 780.

frozen fi : \underline{222}, 336, 491. frozen null font : \underline{222}, 553. frozen protection: \underline{222}, 1215, 1216. frozen relax : \underline{222}, 265* , 379. frozen right : \underline{222}, 1065, 1188. frustration: 514* . Fuchs, David Raymond: 2* , 583, 591. primitive: \underline{1219}. g: \underline{47*} , \underline{182}, \underline{560}, \underline{592}, \underline{649*} , \underline{668}, \underline{706}, \underline{716}, \underline{1577*} . g order : \underline{1433*} . g sign: \underline{619*} , 625* , \underline{629*} , 634* , \underline{1433*} , \underline{1456*} , 1459* . garbage: \underline{162}, 467, 470* , 960* , 1183, 1192* , 1279. primitive: \underline{1208*} . geq define: \underline{279*} , 782, 1214. geq word define: \underline{279*} , 288, 1013, 1214. get : 26* , 29, 31* , 485, 538, 564* , 1306* , 1606* ,

1647* , 1648* . get avail : \underline{120}, 122, 204, 205, 216* , 325, 326* , 337,

339, 369, 371, 372, 452, 473, 482* , 582, 709, 772, 783, 784, 794, 908, 911, 938, 1035, 1064, 1065, 1218* , 1226* , 1371, 1417* , 1422* , 1439* , 1460* , 1466* , 1487* , 1500* .

get command line: 1617* , \underline{1621*} . get next : 76, 297, 332, 336, 340, \underline{341}, 357, 360,

364, 365, 366* , 369, 380, 381, 387, 389* , 478* , 494* , 507, 644, 1038, 1126, 1499* .

get node: \underline{125}, 131, 136, 139, 144, 145, 147* , 151, 152, 153, 156, 158, 206, 495, 607, 649* , 668, 686, 688, 689, 716, 772, 798, 843, 844, 845* , 864* , 914, 1009, 1100, 1101* , 1163, 1165, 1181, 1248* , 1249, 1349, 1357, 1452* , 1466* , 1487* , 1521* , 1548* , 1553* , 1570* .

get preamble token: \underline{782}, 783, 784. get r token: \underline{1215}, 1218* , 1221, 1224* , 1225* , 1257. get sa ptr : \underline{1552*} , 1558* , 1564* . get strings started : \underline{47*} , 51* , 1332* . get token: 76, 78, 88, 364, \underline{365}, 368, 369, 392, 399,

442, 452, 471* , 473, 474, 476, 477, 479, 483* , 782, 1027, 1138* , 1215, 1221, 1252* , 1268, 1271, 1294, 1371, 1372, 1417* , 1498* , 1505* .

get x or protected : 785* , 791* , \underline{1505*} . get x token: 364, 366* , 372, \underline{380}, 381, 402, 404,

406, 407, 443, 444, 445, 452, 465* , 479, 506, 526, 780, 935, 961, 1029, 1030, 1138* , 1197, 1237* , 1375, 1500* , 1505* .

get x token or active char : \underline{506}. give err help: 78, 89, 90, \underline{1284}. global : \underline{1214}, 1218* , 1241* , 1572* . global definitions: 221, 279* , 283, 1573* . primitive: \underline{1208*} . global box flag : \underline{1071*} , 1077* , 1241* , 1415* . global defs : \underline{236*} , 782, 1214, 1218* .

primitive: \underline{238}.
global defs code: \underline{236*} , 237* , 238.
glue base: 220, \underline{222}, 224, 226, 227, 228, 229,

252, 782. glue error : \underline{1523*} .

primitive: \underline{1511*} .

glue node: \underline{149}, 152, 153, 175* , 183, 202, 206, 424* , 622* , 631, 651* , 669, 730, 732, 761, 816* , 817, 837, 856, 862, 866* , 879* , 881* , 899, 903, 968* , 972, 973, 988, 996* , 997, 1000, 1106, 1107, 1108* , 1147* , 1202* , 1433* , 1459* , 1466* , 1479* .

glue offset : \underline{135}, 159.

glue ord : \underline{150}, 447, 646, 649* , 668, 791* , 1433* .

glue order : \underline{135}, 136, 159, 185, 186* , 657, 658, 664, 672, 673, 676, 769, 796, 801, 807* , 809, 810, 811, 1148, 1433* , 1473* .

glue par : \underline{224}, 766.

glue pars : \underline{224}.

glue ptr : \underline{149}, 152, 153, 175* , 189, 190, 202, 206, 424* , 625* , 634* , 656, 671, 679, 732, 786, 793, 795, 802, 803, 809, 816* , 838, 868, 881* , 969, 976, 996* , 1001, 1004, 1148, 1433* , 1459* , 1466* , 1479* , 1576* , 1586* .

glue ratio: \underline{109*} , 110* , 113* , 135, 186* .

glue ref : \underline{210*} , 228, 275* , 782, 1228, 1236* .

glue ref count : \underline{150}, 151, 152, 153, 154, 164, 201,

203, 228, 766, 1043, 1060. glue set : \underline{135}, 136, 159, 186* , 657, 658, 664, 672,

673, 676, 807* , 809, 810, 811, 1148, 1433* , 1473* . glue shrink : \underline{159}, 185, 796, 799, 801, 810, 811.

primitive: \underline{1534*} .
glue shrink code: \underline{1534*} , 1535* , 1537* .
primitive: \underline{1534*} .
glue shrink order code: \underline{1534*} , 1535* , 1536* .

glue sign: \underline{135}, 136, 159, 185, 186* , 619* , 629* , 657, 658, 664, 672, 673, 676, 769, 796, 801, 807* , 809, 810, 811, 1148, 1433* , 1456* , 1473* . glue spec size: \underline{150}, 151, 162, 164, 201, 716. glue stretch: \underline{159}, 185, 796, 799, 801, 810, 811.

primitive: \underline{1534*} .
glue stretch code: \underline{1534*} , 1535* , 1537* .
primitive: \underline{1534*} .
glue stretch order code: \underline{1534*} , 1535* , 1536* .
glue temp: 625* , \underline{1433*} .
primitive: \underline{1538*} .
glue to mu code: \underline{1538*} , 1539* , 1541* .

glue val : \underline{410}, 411* , 413* , 416* , 417* , 424* , 427* , 429, 430, 451, 461* , 465* , 782, 1060, 1228, 1236* , 1237* , 1238* , 1240* , 1511* , 1512* , 1513* , 1515* , 1518* , 1520* , 1524* , 1529* , 1548* , 1556* , 1565* .

: 986, 987.

good symbol : \underline{1640*} , 1641* , 1643* , 1645* . goto: \underline{35}, \underline{81}. gr : 110* , \underline{113*} , 114, 135. group code: \underline{269}, 271, 274* , 645, 1136, 1413* . group trace: 274* , 282* , \underline{1396*} . group warning : 282* , \underline{1507*} . grp stack : 282* , 328* , 331* , 362* , \underline{1506*} , 1507* , 1510* . gsa def : 1572* , \underline{1573*} . gsa w def : 1572* , \underline{1573*} . gubed: \underline{7*} . Guibas, Leonidas Ioannis: 2* . g1 : \underline{1198}, 1203* . g2 : \underline{1198}, 1203* , 1205* . h: \underline{204}, \underline{259}, \underline{649*} , \underline{668}, \underline{738}, \underline{929}, \underline{934*} , \underline{944}, \underline{948}, \underline{953},

\underline{966*} , \underline{970}, \underline{977*} , \underline{994}, \underline{1086}, \underline{1091}, \underline{1123}, \underline{1466*} , \underline{1532*} . h offset : \underline{247}, 617, 641. primitive: \underline{248}. h offset code: \underline{247}, 248. ha: \underline{892}, 896* , 900, 903, 912. had semicolon: 1662* , \underline{1663*} . half : \underline{100}, 706, 736, 737, 738, 745, 746, 749,

750, 1202* . half buf : 594, \underline{595*} , 596, 598* , 599* . half error line: \underline{11*} , 14, 311* , 315, 316, 317* . halfword : 108, 110* , \underline{113*} , 115, 130, 264* , 277* , 279* ,

280, 281* , 297, 298* , 300, 333, 341, 366* , 389* , 413* , 464* , 473, 482* , 549, 560, 577, 681, 791* , 800, 821, 829* , 830, 833, 847, 872, 877* , 892, 901, 906, 907, 977* , 1032, 1079* , 1101* , 1211* , 1243, 1266, 1288, 1390* , 1417* , 1456* , 1471* , 1547* , 1552* , 1555* , 1572* , 1573* .

halign: \underline{208*} , 265* , 266* , 1094, 1130* . primitive: \underline{265*} . handle right brace: 1067, \underline{1068}. hang after : \underline{236*} , 240, 847, 849, 1070* , 1149. primitive: \underline{238}. hang after code: \underline{236*} , 237* , 238, 1070* . hang indent : \underline{247}, 847, 848, 849, 1070* , 1149. primitive: \underline{248}. hang indent code: \underline{247}, 248, 1070* . hanging indentation: 847. hash: 234, \underline{256}, 257, 259, 260, 1318, 1319. hash base: 220, \underline{222}, 256, 257, 259, 262, 263,

1257, 1314, 1318, 1319. hash brace: \underline{473}, 476. hash is full : \underline{256}, 260. hash prime: \underline{12*} , 14, 259, 261, 1307* , 1308* . hash size: \underline{12*} , 14, 222, 260, 261, 1334. hash used : \underline{256}, 258, 260, 1318, 1319. hb: \underline{892}, 897* , 898* , 900, 903. hbadness : \underline{236*} , 660, 666, 667. primitive: \underline{238}. hbadness code: \underline{236*} , 237* , 238.

primitive: \underline{1071*} .
hbox group: \underline{269}, 274* , 1083, 1085, 1395* , 1413* .
hc: \underline{892}, 893, 896* , 897* , 898* , 900, 901, 919, 920,

923, 930, 931, 934* , 937* , 939, 960* , 962, 963, 965, 1591* .

hchar : 905, \underline{906}, 908, 909.

hd : \underline{649*} , 654, \underline{706}, 708, \underline{709}, \underline{712}.

head : 212* , \underline{213*} , 215* , 216* , 217, 424* , 718, 776, 796, 799, 805, 812, 814* , 816* , 1026* , 1054, 1080* , 1081, 1086, 1091, 1096* , 1100, 1105* , 1113, 1119, 1121, 1145* , 1159, 1168, 1176, 1181, 1184, 1185* , 1187, 1191* , 1444* , 1445* .

head field : \underline{212*} , 213* , 218. head for vmode: 1094, \underline{1095}. header : 542. Hedrick, Charles Locke: 3. height : \underline{135}, 136, 138, 139, 140, 184* , 187, 188, 463, 554, 622* , 624, 626* , 629* , 631, 632* , 635, 637* , 640, 641, 649* , 653, 656, 670, 672, 679, 704, 706, 709, 711, 713, 727* , 730, 735, 736, 737, 738, 739, 742, 745, 746, 747, 749, 750, 751, 756, 757, 759, 768, 769, 796, 801, 804, 806, 807* , 809, 810, 811, 969, 973, \underline{981}, 986, 1001, 1002, 1008, 1009, 1010, 1021* , 1087, 1100, 1478* .

: 463.

height base: \underline{550}, 552, 554, 566, 571, 1322, 1323. height depth: \underline{554}, 654, 708, 709, 712, 1125, 1405* . height index : \underline{543}, 554. height offset : \underline{135}, 416* , 417* , 769, 1247* . height plus depth: \underline{712}, 714. : 986. help line: \underline{79}, 89, 90, 336, 1106. help ptr : \underline{79}, 80, 89, 90. help0 : \underline{79}, 1252* , 1293* . help1 : \underline{79}, 93, 95, 288, 408, 428, 454, 476, 486,

500, 503, 510* , 960* , 961, 962, 963, 1066, 1080* , 1099, 1121, 1132, 1135, 1159, 1177, 1192* , 1212, 1213* , 1232, 1237* , 1243, 1244, 1258, 1283, 1304, 1390* , 1498* , 1517* .

help2 : 72, \underline{79}, 88, 89, 94, 95, 288, 346, 373, 433, 434, 435, 436, 437, 442, 445, 460, 475, 476, 577, 579, 641, 936, 937* , 978, 1015, 1027, 1047, 1068, 1080* , 1082* , 1095, 1106, 1120, 1129, 1166, 1197, 1207, 1225* , 1236* , 1241* , 1259, 1372, 1430* , 1515* , 1544* .

help3 : 72, \underline{79}, 98, 336, 396, 415* , 446, 479, 776, 783, 784, 792, 993, 1009, 1024, 1028, 1078, 1084, 1110* , 1127, 1183, 1195, 1293* . help4 : \underline{79}, 89, 338, 398, 403, 418, 456, 567, 723,

976, 1004, 1050, 1283. help5 : \underline{79}, 370, 561, 826, 1064, 1069, 1128,

1215, 1293* . help6 : \underline{79}, 395, 459, 1128, 1161. : 1334. hex dig1 : \underline{1552*} . hex dig2 : \underline{1552*} . hex dig3 : \underline{1552*} . hex dig4 : \underline{1552*} , 1554* , 1555* . hex to cur chr : \underline{352}, 355. hex token: \underline{438}, 444. hf : \underline{892}, 896* , 897* , 898* , 903, 908, 909, 910,

911, 915, 916. primitive: \underline{1058}. primitive: \underline{1058}. primitive: \underline{1058}. hfuzz : \underline{247}, 666. primitive: \underline{248}. hfuzz code: \underline{247}, 248. hh: 110* , \underline{113*} , 114, 118, 133, 182, 213* , 219, 221,

268* , 686, 742, 1163, 1165, 1181, 1186, 1305* , 1306* , 1550* .

hi : \underline{112*} , 232* , 1232, 1487* . hi mem min: \underline{116}, 118, 120, 125, 126, 134, 164,

165, 167, 168, 171, 172, 176, 293, 639, 1311* , 1312* , 1334.

hi mem stat min: \underline{162}, 164, 1312* . hi mem stat usage: \underline{162}, 164. history : \underline{76}, 77, 82* , 93, 95, 245, 1332* , 1335* , 1507* ,

1509* , 1510* , 1600* . hlist node: \underline{135}, 136, 137, 138, 148, 159, 175* , 183,

184* , 202, 206, 505* , 616* , 618, 619* , 622* , 631, 644, 649* , 651* , 669, 681, 807* , 810, 814* , 841, 842, 866* , 870, 871, 968* , 973, 993, 1000, 1074, 1080* , 1087, 1110* , 1147* , 1203* , 1438* , 1458* , 1466* .

hlist out : 592, 615, 616* , 618, \underline{619*} , 620* , 623* , 628* ,

629* , 632* , 637* , 638* , 640, 693, 1373. hlp1 : \underline{79}. hlp2 : \underline{79}. hlp3 : \underline{79}. hlp4 : \underline{79}. hlp5 : \underline{79}. hlp6 : \underline{79}. hmode: \underline{211}, 218, 416* , 501* , 786, 787, 796, 799,

1030, 1045, 1046, 1048, 1056, 1057, 1071* , 1073, 1076, 1079* , 1083, 1086, 1091, 1092, 1093, 1094, 1096* , 1097, 1109, 1110* , 1112, 1116, 1117, 1119, 1122, 1130* , 1137, 1200, 1243, 1377, 1413* .

hmove: \underline{208*} , 1048, 1071* , 1072, 1073, 1415* . hn: \underline{892}, 897* , 898* , 899, 902, 912, 913, 915, 916,

917, 919, 923, 930, 931. ho: \underline{112*} , 235, 414, 1151, 1154, 1489* , 1490* . hold head : \underline{162}, 306, 779, 783, 784, 794, 808* , 905,

906, 913, 914, 915, 916, 917, 1014* , 1017. holding inserts : \underline{236*} , 1014* . primitive: \underline{238}. holding inserts code: \underline{236*} , 237* , 238. hpack : 162, 236* , 644, 645, 646, 647, \underline{649*} , 661, 709,

715, 720, 727* , 737, 748, 754, 756, 796, 799, 804, 806, 889, 1062, 1086, 1125, 1194* , 1199* , 1201, 1204* , 1439* , 1469* , 1479* .

hrule: \underline{208*} , 265* , 266* , 463, 1046, 1056, 1084,

1094, 1095. primitive: \underline{265*} . hsize: \underline{247}, 847, 848, 849, 1054, 1149. primitive: \underline{248}. hsize code: \underline{247}, 248. hskip: \underline{208*} , 1057, 1058, 1059, 1078, 1090. primitive: \underline{1058}. primitive: \underline{1058}. primitive: \underline{416*} . hu: \underline{892}, 893, 897* , 898* , 901, 903, 905, 907, 908,

910, 911, 912, 915, 916. : 641. hyf : \underline{900}, 902, 905, 908, 909, 913, 914, 919, 920,

923, 924, 932, 960* , 961, 962, 963, 965. hyf bchar : \underline{892}, 897* , 898* , 903. hyf char : \underline{892}, 896* , 913, 915. hyf distance: 920, \underline{921}, 922, 924, 943, 944, 945,

1324* , 1325* . hyf next : 920, \underline{921}, 924, 943, 944, 945, 1324* , 1325* . hyf node: \underline{912}, 915. hyf num: 920, \underline{921}, 924, 943, 944, 945, 1324* , 1325* . hyph codes : 1587* , 1591* . hyph count : \underline{926}, 928, 940, 1324* , 1325* , 1334. hyph data: \underline{209*} , 1210, 1250, 1251, 1252* . hyph index : 934* , 1589* , \underline{1591*} . hyph list : \underline{926}, 928, 929, 932, 933, 934* , 940,

941, 1324* , 1325* . hyph pointer : \underline{925}, 926, 927, 929, 934* . hyph root : 952* , 958* , 966* , \underline{1587*} , 1590* . hyph size: \underline{12*} , 925, 928, 930, 933, 939, 940, 1307* ,

1308* , 1324* , 1325* , 1334. hyph start : 1324* , 1325* , 1587* , 1590* , \underline{1591*} . hyph word : \underline{926}, 928, 929, 931, 934* , 940, 941,

1324* , 1325* . hyphen char : 426, \underline{549}, 552, 576, 891* , 896* , 1035,

1117, 1253, 1322, 1323. primitive: \underline{1254}. hyphen passed : \underline{905}, 906, 909, 913, 914. hyphen penalty : 145, \underline{236*} , 869. primitive: \underline{238}. hyphen penalty code: \underline{236*} , 237* , 238. hyphenate: 894, \underline{895}. hyphenated : \underline{819*} , 820, 829* , 846* , 859, 869, 873. : 1324* . primitive: \underline{1250}. i: \underline{19}, \underline{37*} , \underline{315}, \underline{413*} , \underline{513*} , \underline{517*} , \underline{587}, \underline{649*} , \underline{738}, \underline{749},

\underline{901}, \underline{1123}, \underline{1413*} , \underline{1507*} , \underline{1509*} , \underline{1510*} , \underline{1548*} , \underline{1552*} , \underline{1554*} , \underline{1558*} , \underline{1570*} , \underline{1621*} , \underline{1627*} .

: 530* . : 524. : 95. : 51* . : 530* . iaddress : 1629* . ichr : \underline{1627*} . id byte: \underline{587}, 617, 642* . id lookup: \underline{259}, 264* , 356, 374, 1501* . ident val : \underline{410}, 415* , 465* , 466. primitive: \underline{487*} . if case code: \underline{487*} , 488* , 501* , 1498* . if cat code: \underline{487*} , 488* , 501* . primitive: \underline{487*} . primitive: \underline{487*} . if char code: \underline{487*} , 501* , 506. if code: \underline{489}, 495, 510* . if cs code: \underline{1495*} , 1497* , 1500* . primitive: \underline{1495*} . if cur ptr is null then return or goto: \underline{1552*} . if def code: \underline{1495*} , 1497* , 1499* . primitive: \underline{1495*} . primitive: \underline{487*} . if dim code: \underline{487*} , 488* , 501* . primitive: \underline{487*} . if eof code: \underline{487*} , 488* , 501* . primitive: \underline{487*} . if false code: \underline{487*} , 488* , 501* . primitive: \underline{1495*} . if font char code: \underline{1495*} , 1497* , 1502* . primitive: \underline{487*} . if hbox code: \underline{487*} , 488* , 501* , 505* . primitive: \underline{487*} . if hmode code: \underline{487*} , 488* , 501* . primitive: \underline{487*} . if inner code: \underline{487*} , 488* , 501* . primitive: \underline{487*} . if int code: \underline{487*} , 488* , 501* , 503. if limit : \underline{489}, 490, 495, 496* , 497, 498* , 510* , 1402* ,

1425* , 1510* . if line: 299* , \underline{489}, 490, 495, 496* , 1335* , 1425* ,

1509* , 1510* . if line field : \underline{489}, 495, 496* , 1335* , 1425* , 1510* . primitive: \underline{487*} . if mmode code: \underline{487*} , 488* , 501* . if node size: \underline{489}, 495, 496* , 1335* . primitive: \underline{487*} . if odd code: \underline{487*} , 488* , 501* . if stack : 328* , 331* , 362* , 496* , \underline{1506*} , 1509* , 1510* .

if test : \underline{210*} , 299* , 336, 366* , 367* , 487* , 488* , 494* , 498* ,

503, 1335* , 1425* , 1495* , 1498* , 1509* , 1510* . primitive: \underline{487*} .

if true code: \underline{487*} , 488* , 501* .
primitive: \underline{487*} .
if vbox code: \underline{487*} , 488* , 501* .
primitive: \underline{487*} .
if vmode code: \underline{487*} , 488* , 501* .
primitive: \underline{487*} .
if void code: \underline{487*} , 488* , 501* , 505* .
if warning : 496* , \underline{1509*} .
primitive: \underline{487*} .
ifx code: \underline{487*} , 488* , 501* .
ignore: \underline{207}, 232* , 332, 345.

ignore depth: \underline{212*} , 215* , 219, 679, 787, 1025, 1056,

1083, 1099, 1167. ignore it : 1602* , 1603* , 1604* , 1608* , 1611* , 1612* , 1614* , 1617* , 1652* , 1655* , 1656* , 1658* .

ignore spaces : \underline{208*} , 265* , 266* , 1045. primitive: \underline{265*} . : 288, 1258. : 1120. : 479. : 454, 456, 459. image: \underline{1636*} , 1638* , 1640* , 1641* , 1666* . image name: \underline{1640*} . image symbol : \underline{1640*} , 1641* , 1643* , 1645* . primitive: \underline{1344}. immediate code: \underline{1344}, 1346, 1348* . : 262. : 1437* . : 1437* . : 1437* . : 1437* . : 776. : 936. : 418. : 1241* . : 418. : 1259. : 442. : 1121. : 458. in FAB : 33* , \underline{1628*} . in open: 282* , \underline{304}, 313* , 328* , 329* , 331* , 362* , 496* ,

1507* , 1509* , 1510* . in RAB : 33* , 34* , 71* , \underline{1628*} . in state record : \underline{300}, 301, 1650* , 1651* . in stream: \underline{208*} , 1272, 1273, 1274. : 408. : 1110* . : 288. incompleat noad : 212* , \underline{213*} , 718, 776, 1136, 1178,

1181, 1182, 1184, 1185* . : 336. incr : \underline{16}, 37* , 42, 43, 45, 46, 53* , 56* , 58* , 59, 60, 65,

67, 70, 71* , 82* , 90, 98, 120, 122, 152, 153, 170, 182, 203, 216* , 260, 274* , 276, 280, 294* , 299* , 311* , 312, 321, 325, 326* , 328* , 343, 347, 352, 354, 355, 356, 357, 360, 362* , 374, 392, 395, 397, 399, 400, 403, 407, 442, 452, 454, 464* , 475, 476, 477, 494* , 517* , 519, 524, 531, 537* , 564* , 580, 598* , 619* , 629* , 640, 642* , 645, 714, 798, 845* , 877* , 897* , 898* , 910, 911, 914, 915, 923, 930, 931, 937* , 939, 940, 941, 944, 954, 956, 962, 963, 964, 986, 1022, 1025, 1035, 1039, 1069, 1099, 1117, 1119, 1121, 1127, 1142, 1153, 1172, 1174, 1305* , 1306* , 1315, 1316, 1318, 1337* , 1379* , 1402* , 1413* , 1417* , 1425* , 1447* , 1450* , 1461* , 1472* , 1487* , 1488* , 1494* , 1501* , 1530* , 1533* , 1552* , 1554* , 1570* , 1621* , 1633* , 1647* , 1654* , 1659* .

primitive: \underline{1088}. indent in hmode: 1092, \underline{1093}. indented : \underline{1091}. index : 300, \underline{302}, 303* , 304, 307* , 313* , 328* , 329* ,

331* , 362* , 1654* . index field : \underline{300}, 302, 1508* . index node size: \underline{1548*} , 1554* , 1558* . inf : 447, \underline{448}, 453. inf bad : \underline{108}, 157, 851* , 852* , 853, 856, 863* , 974,

1005, 1017, 1580* . inf penalty : \underline{157}, 761, 767, 816* , 829* , 831, 974,

1005, 1013, 1203* , 1205* . : 826, 976, 1004,

1009. infinity : \underline{445}, 1523* , 1525* , 1531* . info: \underline{118}, 124, 126, 140, 141* , 164, 172, 200, 233* ,

275* , 291, 293, 325, 326* , 337, 339, 357, 358, 369, 371, 374, 389* , 391, 392, 393, 394, 397, 400, 423* , 452, 466, 478* , 508, 605, 608, 609, 610, 611, 612, 613, 614, 615, 681, 689, 692, 693, 698, 720, 734, 735, 736, 737, 738, 742, 749, 754, 768, 769, 772, 779, 783, 784, 790, 793, 794, 797, 798, 801, 803, 821, 847, 848, 925, 932, 938, 981, 1065, 1076, 1093, 1149, 1151, 1168, 1181, 1185* , 1186, 1191* , 1218* , 1226* , 1248* , 1249, 1289, 1295* , 1312* , 1339, 1341, 1371, 1408* , 1439* , 1441* , 1442* , 1443* , 1447* , 1448* , 1450* , 1451* , 1456* , 1461* , 1464* , 1470* , 1472* , 1483* , 1487* , 1489* , 1490* , 1501* , 1505* , 1548* , 1552* , 1553* , 1557* , 1558* .

Init: \underline{8*} , \underline{1252*} , \underline{1332*} , \underline{1335*} . init: \underline{8*} , \underline{47*} , \underline{50*} , \underline{131}, \underline{264*} , \underline{891*} , \underline{934*} , \underline{942}, \underline{943}, \underline{947},

\underline{950}, \underline{1302}, \underline{1325*} , \underline{1331*} , \underline{1332*} , \underline{1336*} , \underline{1379*} , \underline{1564*} . init align: 773, \underline{774}, 1130* . init cli : 1332* , \underline{1620*} . init col : 773, 785* , \underline{788}, 791* . init cur lang : 816* , 891* , \underline{892}. init flag : 8* , \underline{1331*} , 1332* . init l hyf : 816* , 891* , \underline{892}. init lft : \underline{900}, 903, 905, 908. init lig : \underline{900}, 903, 905, 908. init list : \underline{900}, 903, 905, 908. init math: 1137, \underline{1138*} , 1439* . init pool ptr : \underline{39}, 42, 1310, 1332* , 1334. init prim: 1332* , \underline{1336*} . init r hyf : 816* , 891* , \underline{892}. init row : 773, 785* , \underline{786}. init span: 773, 786, \underline{787}, 791* . init str ptr : \underline{39}, 43, 517* , 1310, 1332* , 1334. init terminal : \underline{37*} , 331* , 1621* . init trie: 891* , \underline{966*} , 1324* . : 8* , 11* , 12* , 47* , 116, 1299, 1331* , 1558* , 1564* . initialize: \underline{4*} , 1332* , 1337* , 1621* . inner loop: 31* , 112* , 120, 121, 122, 123, 125, 127,

128, 130, 202, 324, 325, 341, 342, 343, 357, 365, 380, 399, 407, 554, 597* , 611, 620* , 651* , 654, 832, 835, 851* , 852* , 867.

inner noad : \underline{682}, 683, 690, 696* , 698, 733, 761,

764, 1156, 1157, 1191* . inp len: \underline{513*} , 514* . inp name: \underline{513*} , 514* . input : \underline{210*} , 366* , 367* , 376, 377* , 1480* . primitive: \underline{376}. input file: \underline{304}. primitive: \underline{416*} . input line no code: \underline{416*} , 417* , 424* . input ln: 30* , \underline{31*} , 37* , 58* , 71* , 362* , 485, 486, 538. input ptr : \underline{301}, 311* , 312, 321, 322, 330, 331* , 360,

534* , 1335* , 1507* , 1509* . input stack : 84* , \underline{301}, 311* , 321, 322, 534* , 1507* ,

1508* , 1509* . ins disc: \underline{1032}, 1033, 1035. ins error : \underline{327}, 336, 395, 1047, 1127, 1132, 1215. ins list : \underline{323}, 339, 467, 470* , 1064, 1371. ins node: \underline{140}, 148, 175* , 183, 202, 206, 647, 651* ,

730, 761, 866* , 899, 968* , 973, 981, 986, 1000, 1014* , 1100, 1433* .

ins node size: \underline{140}, 202, 206, 1022, 1100. ins ptr : \underline{140}, 188, 202, 206, 1010, 1020, 1021* , 1100. ins the toks : 366* , 367* , \underline{467}. insert : \underline{208*} , 265* , 266* , 1097. : 87. primitive: \underline{265*} . insert dollar sign: 1045, \underline{1047}. insert end M : 424* , 1080* , 1105* , \underline{1445*} . insert group: \underline{269}, 1068, 1099, 1100, 1395* , 1413* . insert penalties : 419* , \underline{982*} , 990, 1005, 1008, 1010,

1014* , 1022, 1026* , 1242, 1246* . primitive: \underline{416*} . insert relax : 378* , \underline{379}, 510* . insert token: \underline{268*} , 280, 282* . inserted : \underline{307*} , 314* , 323, 324, 327, 379, 1095. inserting : \underline{981}, 1009. : 993. inserts only : \underline{980}, 987, 1008. int : 110* , \underline{113*} , 114, 140, 142* , 157, 213* , 219, 236* ,

240, 242, 274* , 278* , 279* , 413* , 414, 489, 605, 725, 769, 772, 819* , 1237* , 1248* , 1305* , 1306* , 1308* , 1316, 1380* , 1521* , 1553* .

int avl : 1548* . int base: 220, \underline{230*} , 232* , 236* , 238, 239, 240, 242,

252, 253, 254, 268* , 283, 288, 1013, 1070* , 1139, 1145* , 1315, 1380* , 1391* .

int error : \underline{91}, 288, 433, 434, 435, 436, 437, 1243,

1244, 1258, 1430* , 1544* . int par : \underline{236*} . int pars : \underline{236*} . int val : \underline{410}, 411* , 413* , 414, 416* , 417* , 418, 419* ,

422, 423* , 424* , 426, 427* , 428, 429, 439, 440, 449, 461* , 465* , 1224* , 1236* , 1237* , 1238* , 1240* , 1311* , 1312* , 1511* , 1512* , 1513* , 1516* , 1518* , 1523* , 1525* , 1528* , 1531* , 1549* , 1551* , 1556* , 1565* .

integer : 3, 13, 19, 31* , 37* , 45, 47* , 54* , 56* , 59, 60, 63, 65, 66, 67, 69, 82* , 91, 94, 96* , 100, 101, 102, 105, 106, 107, 108, 109* , 110* , 113* , 117, 125, 158, 163, 172, 173, 174, 176, 177, 178, 181, 182, 211, 212* , 218, 225, 237* , 247, 256, 259, 262, 278* , 279* , 286, 292, 298* , 299* , 304, 308, 309, 311* , 315, 366* , 410, 440, 448, 450, 482* , 489, 493, 494* , 498* , 513* , 518, 519, 520* , 523, 529* , 537* , 549, 550, 560, 578, 581* , 592, 595* , 600, 601, 607, 615, 616* , 619* , 629* , 638* , 645, 646, 661, 691, 694, 699, 706, 716, 717, 726, 738, 752, 764, 828, 829* , 830, 833, 872, 877* , 892, 912, 922, 966* , 970, 980, 982* , 994, 1012* , 1030, 1032, 1068, 1075* , 1079* , 1084, 1091, 1117, 1119, 1138* , 1151, 1155, 1194* , 1211* , 1236* , 1293* , 1302, 1303, 1333* , 1338, 1348* , 1370, 1413* , 1439* , 1477* , 1486* , 1489* , 1510* , 1515* , 1526* , 1530* , 1532* , 1572* , 1573* , 1601* , 1618* , 1620* , 1621* , 1624* , 1627* , 1628* , 1629* , 1630* , 1631* , 1632* , 1633* , 1634* , 1635* , 1636* , 1640* , 1646* , 1648* , 1649* , 1650* , 1651* , 1657* .

primitive: \underline{1597*} . inter line penalties loc: \underline{230*} , 1070* , 1597* , 1598* . inter line penalties ptr : 890* , 1070* , \underline{1597*} . inter line penalty : \underline{236*} , 890* . primitive: \underline{238}. inter line penalty code: \underline{236*} , 237* , 238. interaction: 71* , 72, \underline{73*} , 74, 75, 82* , 84* , 86* , 90, 92, 93, 98, 360, 363, 484, 530* , 1265, 1283, 1293* , 1294, 1297, 1326, 1327, 1328, 1335* , 1428* , 1617* .

primitive: \underline{1426*} . internal font number : \underline{548}, 549, 550, 560, 577,

578, 581* , 582, 602, 616* , 649* , 706, 709, 711, 712, 715, 724, 738, 830, 862, 892, 1032, 1113, 1123, 1138* , 1211* , 1257.

interrupt : \underline{96*} , 97* , 98, 1031, 1625* . : 98. : 324,

782, 789, 791* . : 1232. invalid char : \underline{207}, 232* , 344. invalid code: \underline{22}, 24, 232* . is char node: \underline{134}, 174, 183, 202, 205, 424* , 620* ,

630, 651* , 669, 715, 720, 721, 756, 805, 816* , 837, 841, 842, 866* , 867, 868, 870, 871, 879* , 896* , 897* , 899, 903, 1036, 1040, 1080* , 1081, 1105* , 1113, 1121, 1147* , 1202* , 1433* , 1441* , 1444* , 1445* , 1457* , 1466* , 1471* .

is empty : \underline{124}, 127, 169, 170. is hex : \underline{352}, 355. is running : \underline{138}, 176, 624, 633* , 806. is unless : \underline{498*} . issue message: 1276, \underline{1279}. : 1652* . ital corr : \underline{208*} , 265* , 266* , 1111, 1112. italic correction: \underline{543}. italic base: \underline{550}, 552, 554, 566, 571, 1322, 1323. italic index : \underline{543}. item code: 1629* , \underline{1630*} , 1659* , 1661* . item list : \underline{1629*} , 1630* , 1659* , \underline{1660*} , 1661* . its all over : 1045, \underline{1054}, 1335* . j: \underline{45}, \underline{46}, \underline{56*} , \underline{59}, \underline{60}, \underline{69}, \underline{70}, \underline{259}, \underline{264*} , \underline{315}, \underline{366*} ,

\underline{482*} , \underline{519}, \underline{523}, \underline{524}, \underline{595*} , \underline{638*} , \underline{893}, \underline{901}, \underline{906}, \underline{934*} , \underline{966*} , \underline{1138*} , \underline{1211*} , \underline{1302}, \underline{1303}, \underline{1370}, \underline{1373}, \underline{1390*} , \underline{1413*} , \underline{1474*} , \underline{1477*} , \underline{1621*} .

Japanese characters: 134, 585. Jensen, Kathleen: 10* . : 360. : 530* . job name: 92, 471* , 472* , \underline{527}, 528, 529* , 532* , 534* ,

537* , 1257, 1328, 1335* , 1601* . primitive: \underline{468}. job name code: \underline{468}, 471* , 472* . job qual : 1601* , \underline{1616*} , 1621* . jump out : \underline{81}, 82* , 84* , 93. jumpout : 1332* . just box : \underline{814*} , 888, 889, 1148, 1467* , 1473* . just copy : \underline{1466*} , 1467* , 1471* . just open: \underline{480}, 483* , 1275* . just reverse: 1470* , \underline{1471*} . k: \underline{31*} , \underline{45}, \underline{46}, \underline{47*} , \underline{64}, \underline{65}, \underline{67}, \underline{69}, \underline{71*} , \underline{102}, \underline{163}, \underline{259},

\underline{264*} , \underline{341}, \underline{363}, \underline{407}, \underline{450}, \underline{464*} , \underline{519}, \underline{523}, \underline{525*} , \underline{529*} , \underline{530*} , \underline{534*} , \underline{537*} , \underline{560}, \underline{587}, \underline{602}, \underline{607}, \underline{638*} , \underline{705}, \underline{906}, \underline{929}, \underline{934*} , \underline{960*} , \underline{966*} , \underline{1079*} , \underline{1211*} , \underline{1302}, \underline{1303}, \underline{1333*} , \underline{1338}, \underline{1348*} , \underline{1368}, \underline{1390*} , \underline{1548*} .

kern: \underline{208*} , 545, 1057, 1058, 1059. primitive: \underline{1058}. kern base: \underline{550}, 552, 557, 566, 573, 576, 1322, 1323. kern base offset : \underline{557}, 566, 573. kern break : \underline{866*} . kern flag : \underline{545}, 741, 753, 909, 1040. kern node: \underline{155}, 156, 183, 202, 206, 424* , 622* , 631,

651* , 669, 721, 730, 732, 761, 837, 841, 842, 856, 866* , 868, 870, 871, 879* , 881* , 896* , 897* , 899, 968* , 972, 973, 976, 996* , 997, 1000, 1004, 1106, 1107, 1108* , 1121, 1147* , 1433* , 1447* , 1450* , 1458* , 1461* , 1466* , 1472* .

kk : \underline{450}, 452. kkk : 1656* , \underline{1657*} , 1658* , 1659* , 1664* . Knuth, Donald Ervin: 2* , 86* , 693, 813, 891* , 925,

997, 1154, 1371, 1413* , 1434* . l: \underline{47*} , \underline{259}, \underline{264*} , \underline{276}, \underline{281*} , \underline{292}, \underline{299*} , \underline{315}, \underline{494*} , \underline{497},

\underline{534*} , \underline{595*} , \underline{601}, \underline{615}, \underline{668}, \underline{830}, \underline{901}, \underline{944}, \underline{953}, \underline{960*} , \underline{1138*} , \underline{1194*} , \underline{1236*} , \underline{1293*} , \underline{1302}, \underline{1338}, \underline{1376}, \underline{1413*} , \underline{1456*} , \underline{1471*} , \underline{1486*} , \underline{1510*} , \underline{1515*} , \underline{1558*} .

L code: \underline{147*} , 175* , 192* , 866* , 1450* , 1451* , 1469* , 1470* . l hyf : 891* , \underline{892}, 894, 899, 902, 923, 1362, 1363* . l jobname: 1601* , \underline{1616*} , 1621* . l len name: \underline{1616*} , 1621* . label max : \underline{1602*} , 1603* , 1607* , 1610* . label size: 1602* , \underline{1603*} , 1607* , 1610* , 1613* . language: \underline{236*} , 934* , 1034, 1376. Language-sensitive editor: 56* , 73* , 84* , 1602* , 1615* ,

1616* , 1631* , 1640* . primitive: \underline{238}. language code: \underline{236*} , 237* , 238. language node: \underline{1341}, 1356, 1357, 1358, 1362,

1363* , 1373, 1376, 1377. large attempt : \underline{706}. large char : \underline{683}, 691, 697, 706, 1160. large fam: \underline{683}, 691, 697, 706, 1160. last : \underline{30*} , 31* , 35, 36, 37* , 71* , 83, 87, 88, 331* , 360,

363, 483* , 524, 531, 1489* . last active: \underline{819*} , 820, 832, 835, 844, 854, 860, 861,

863* , 864* , 865, 873, 874, 875. last badness : 424* , \underline{646}, 648, 649* , 660, 664, 667,

668, 674, 676, 678. last basenam len: 537* , 1627* , \underline{1628*} . last basename: 537* , 1627* , \underline{1628*} . last bop: \underline{592}, 593, 640, 642* . primitive: \underline{1071*} . last box code: \underline{1071*} , 1072, 1079* , 1335* , 1592* ,

1594* , 1595* . last glue: 424* , \underline{982*} , 991* , 996* , 1017, 1106. last ins ptr : \underline{981}, 1005, 1008, 1018, 1020. last item: \underline{208*} , 413* , 416* , 417* , 1048, 1380* , 1397* ,

1400* , 1403* , 1406* , 1511* , 1534* , 1538* . last kern: 424* , \underline{982*} , 991* , 996* . primitive: \underline{416*} . last length: 525* , 1627* , \underline{1628*} . last line fill : 816* , \underline{1575*} , 1576* , 1586* . last line fit : \underline{236*} , 1575* , 1576* , 1579* . primitive: \underline{1391*} . last line fit code: \underline{236*} , 1391* , 1393* . last name: 525* , 1627* , \underline{1628*} , 1661* . last node type: 424* , \underline{982*} , 991* , 996* . primitive: \underline{1380*} . last node type code: \underline{416*} , 424* , 1380* , 1381* . last penalty : 424* , \underline{982*} , 991* , 996* . primitive: \underline{416*} . primitive: \underline{416*} . last special line: \underline{847}, 848, 849, 850, 889. last text char : \underline{19}, 24. lc code: \underline{230*} , 232* , 891* , 962, 1587* , 1589* , 1590* , 1591* . primitive: \underline{1230}. lc code base: \underline{230*} , 235, 1230, 1231, 1286, 1287,

1288. leader box : \underline{619*} , 626* , 628* , \underline{629*} , 635, 637* . leader flag : \underline{1071*} , 1073, 1078, 1084, 1415* . leader ht : \underline{629*} , 635, 636, 637* . leader ptr : \underline{149}, 152, 153, 190, 202, 206, 626* , 635,

656, 671, 816* , 1078, 1459* , 1466* . leader ship: \underline{208*} , 1071* , 1072, 1073, 1415* . leader wd : \underline{619*} , 626* , 627, 628* . leaders: 1374. : 1078. primitive: \underline{1071*} . least cost : \underline{970}, 974, 980. least page cost : \underline{980}, 987, 1005, 1006. primitive: \underline{1188}. left brace: \underline{207}, 289* , 294* , 298* , 347, 357, 403, 473,

476, 777, 1063, 1150, 1226* . left brace limit : \underline{289*} , 325, 326* , 392, 394, 399. left brace token: \underline{289*} , 403, 1127, 1226* , 1371. left delimiter : \underline{683}, 696* , 697, 737, 748, 1163,

1181, 1182. left edge: \underline{619*} , 627, \underline{629*} , 632* , 633* , 637* , 1452* ,

1453* , 1455* . left hyphen min: \underline{236*} , 1091, 1200, 1376, 1377. primitive: \underline{238}. left hyphen min code: \underline{236*} , 237* , 238. left noad : 212* , \underline{687*} , 690, 696* , 698, 725, 727* , 728,

733, 760* , 761, 762* , 1185* , 1188, 1189* , 1191* , 1413* . left right : \underline{208*} , 1046, 1188, 1189* , 1190, 1431* . left skip: \underline{224}, 827* , 880* , 887, 1473* , 1576* . primitive: \underline{226}. left skip code: \underline{224}, 225, 226, 887, 1473* , 1479* . left to right : \underline{616*} , 619* , 1440* , 1463* , 1468* . len: \underline{31*} , \underline{37*} , \underline{517*} , \underline{1618*} , \underline{1620*} , \underline{1621*} , \underline{1629*} , 1633* ,

\underline{1634*} , 1648* . length: 30* , \underline{40}, 46, 259, 517* , 537* , 602, 931,

941, 1280. length of lines: 847. primitive: \underline{1141}. let : \underline{209*} , 1210, 1219, 1220, 1221. primitive: \underline{1219}. letter : \underline{207}, 232* , 262, 289* , 291, 294* , 298* , 347,

354, 356, 935, 961, 1029, 1030, 1038, 1090, 1124, 1151, 1154, 1160.

letter token: \underline{289*} , 445. level : 410, \underline{413*} , 415* , 418, 428, \underline{461*} , 1513* . level boundary : \underline{268*} , 270, 274* , 282* . level one: \underline{221}, 228, 232* , 254, 264* , 272, 277* , 278* ,

279* , 280, 281* , 283, 780, 1304, 1335* , 1369, 1399* , 1553* , 1573* , 1574* .

level zero: \underline{221}, 222, 272, 276, 280, 1569* . lf : 540, \underline{560}, 565, 566, 575* , 576. lft hit : 906, \underline{907}, 908, 910, 911, 1033, 1035, 1040. lh: 110* , \underline{113*} , 114, 118, 213* , 219, 256, 540, 541,

\underline{560}, 565, 566, 568, 685, 950, 1550* . Liang, Franklin Mark: 2* , 919. $ : 1641* . $ : 1618* , 1620* . $ : 1632* . $ : 1640* . lib signal : \underline{1632*} , 1633* , 1635* , 1648* . lig char : \underline{143}, 144, 193, 206, 652, 841, 842, 866* ,

870, 871, 898* , 903, 1113, 1460* , 1466* . lig kern: 544, 545, 549. lig kern base: \underline{550}, 552, 557, 566, 571, 573, 576,

1322, 1323. lig kern command : 541, \underline{545}. lig kern restart : \underline{557}, 741, 752, 909, 1039. lig kern restart end : \underline{557}. lig kern start : \underline{557}, 741, 752, 909, 1039. lig ptr : \underline{143}, 144, 175* , 193, 202, 206, 896* , 898* , 903,

907, 910, 911, 1037, 1040, 1460* . lig stack : \underline{907}, 908, 910, 911, 1032, 1034, 1035,

1036, 1037, 1038, 1040. lig tag : \underline{544}, 569, 741, 752, 909, 1039. lig trick : \underline{162}, 620* , 652. ligature node: \underline{143}, 144, 148, 175* , 183, 202, 206,

622* , 651* , 752, 841, 842, 866* , 870, 871, 896* , 897* , 899, 903, 1113, 1121, 1147* , 1460* , 1466* .

ligature present : 906, \underline{907}, 908, 910, 911, 1033,

1035, 1037, 1040. limit : 300, \underline{302}, 303* , 307* , 318* , 328* , 330, 331* , 343, 348, 350, 351, 352, 354, 355, 356, 360, 362* , 363, 483* , 537* , 538, 1337* , 1488* , 1494* . : 1159. limit field : 35, 87, \underline{300}, 302, 534* . limit switch: \underline{208*} , 1046, 1156, 1157, 1158. limits : \underline{682}, 696* , 733, 749, 1156, 1157. primitive: \underline{1156}. line: 84* , 216* , 274* , 299* , \underline{304}, 313* , 328* , 329* , 331* , 362* , 424* , 494* , 495, 538, 663, 675, 1025, 1488* , 1609* , \underline{1649*} , 1650* , 1651* , 1655* , 1656* , 1658* , 1664* . line break : 162, 814* , \underline{815*} , 828, 839, 848, 862, 863* , 866* , 876* , 894, 934* , 967, 970, 982* , 1096* , 1145* .

line diff : \underline{872}, 875.

line feed : 23* .

line number : \underline{819*} , 820, 833, 835, 845* , 846* , 850,

864* , 872, 874, 875. line penalty : \underline{236*} , 859. primitive: \underline{238}. line penalty code: \underline{236*} , 237* , 238. line skip: \underline{224}, 247. primitive: \underline{226}. line skip code: 149, 152, \underline{224}, 225, 226, 679. line skip limit : \underline{247}, 679. primitive: \underline{248}. line skip limit code: \underline{247}, 248. line stack : \underline{304}, 313* , 328* , 329* . line width: \underline{830}, 850, 851* . linelimit : 27* , 33* . link : \underline{118}, 120, 121, 122, 123, 124, 125, 126, 130,

133, 134, 135, 140, 141* , 143, 150, 164, 168, 172, 174, 175* , 176, 182, 202, 204, 212* , 214, 218, 223, 233* , 292, 295, 299* , 306, 319* , 323, 326* , 339, 357, 358, 366* , 369, 371, 374, 389* , 390, 391, 394, 396, 397, 400, 407, 452, 464* , 466, 467, 470* , 478* , 489, 495, 496* , 497, 508, 605, 607, 609, 611, 615, 620* , 622* , 630, 649* , 651* , 652, 654, 655, 666, 669, 679, 681, 689, 705, 711, 715, 718, 719, 720, 721, 727* , 731, 732, 735, 737, 738, 739, 747, 748, 751, 752, 753, 754, 755, 756, 759, 760* , 761, 766, 767, 770, 772, 778, 779, 783, 784, 786, 790, 791* , 793, 794, 795, 796, 797, 798, 799, 801, 802, 803, 804, 805, 806, 807* , 808* , 809, 812, 814* , 816* , 819* , 821, 822, 829* , 830, 837, 840, 843, 844, 845* , 854, 857, 858, 860, 861, 862, 863* , 864* , 865, 866* , 867, 869, 873, 874, 875, 877* , 879* , 880* , 881* , 882, 883, 884, 885, 886, 887, 888, 890* , 894, 896* , 897* , 898* , 899, 903, 905, 906, 907, 908, 910, 911, 913, 914, 915, 916, 917, 918, 932, 938, 960* , 968* , 969, 970, 973, 979* , 980, 981, 986, 988, 991* , 994, 998, 999* , 1000, 1001, 1005, 1008, 1009, 1014* , 1017, 1018, 1019, 1020, 1021* , 1022, 1023* , 1026* , 1035, 1037, 1040, 1041, 1043, 1064, 1065, 1076, 1081, 1086, 1091, 1100, 1101* , 1105* , 1110* , 1119, 1120, 1121, 1123, 1125, 1146* , 1155, 1168, 1181, 1184, 1185* , 1186, 1187, 1191* , 1194* , 1196, 1199* , 1204* , 1205* , 1206* , 1218* , 1226* , 1279, 1288, 1295* , 1297, 1311* , 1312* , 1335* , 1339, 1341, 1349, 1368, 1371, 1375, 1402* , 1417* , 1422* , 1425* , 1433* , 1439* , 1441* , 1443* , 1444* , 1445* , 1448* , 1454* , 1455* , 1457* , 1458* , 1460* , 1462* , 1466* , 1467* , 1468* , 1471* , 1473* , 1478* , 1479* , 1486* , 1487* , 1489* , 1490* , 1501* , 1505* , 1509* , 1510* , 1521* , 1522* , 1548* , 1552* , 1553* , 1554* , 1555* , 1556* , 1557* , 1558* , 1561* , 1570* , 1574* , 1596* .

list offset : \underline{135}, 619* , 649* , 769, 1018. list ptr : \underline{135}, 136, 184* , 202, 206, 619* , 623* , 629* ,

632* , 658, 663, 664, 668, 673, 676, 709, 711, 715, 721, 739, 747, 751, 807* , 977* , 979* , 1021* , 1087, 1100, 1110* , 1199* , 1466* , 1467* , 1473* , 1478* , 1479* .

list state record : \underline{212*} , 213* . list tag : \underline{544}, 569, 570, 708, 740, 749. ll : \underline{953}, 956. llink : \underline{124}, 126, 127, 129, 130, 131, 145, 149, 164,

169, 772, 819* , 821, 1312* . lo mem max : \underline{116}, 120, 125, 126, 164, 165, 167,

169, 170, 171, 172, 178, 639, 1311* , 1312* , 1323, 1334.

lo mem stat max : \underline{162}, 164, 427* , 1237* , 1312* ,

1565* , 1567* . load fmt file: \underline{1303}, 1337* , 1621* . loc: \underline{36}, 37* , 87, 300, 302, 303* , 307* , 312, 314* , 318* ,

319* , 323, 325, 326* , 328* , 330, 331* , 343, 348, 350, 351, 352, 354, 356, 357, 358, 360, 362* , 369, 390, 483* , 524, 537* , 538, 1026* , 1027, 1337* , 1379* , 1488* , 1494* , 1612* , 1621* .

loc field : 35, 36, \underline{300}, 302, 1655* , 1656* , 1658* , 1664* . local base: 220, \underline{224}, 228, 230* , 252. location: \underline{605}, 607, 612, 613, 614, 615. log file: \underline{54*} , 56* , 75, 534* , 1332* . log name: \underline{532*} , 534* , 1332* . log only : \underline{54*} , 57* , 58* , 62, 75, 98, 360, 534* , 1328,

1370, 1651* , 1656* , 1658* . log opened : 92, 93, \underline{527}, 528, 534* , 535* , 1265,

1332* , 1334. log qual : 56* , 534* , 1332* , \underline{1616*} , 1621* . logf len: 534* , \underline{1616*} , 1621* . logf name: 534* , \underline{1616*} , 1621* . logical : \underline{1636*} , 1638* , 1654* , 1666* . primitive: \underline{1208*} . long call : \underline{210*} , 275* , 366* , 387, 389* , 392, 399, 1295* . long help seen: \underline{1281}, 1282, 1283. long outer call : \underline{210*} , 275* , 366* , 387, 389* , 1295* . long state: 339, \underline{387}, 391, 392, 395, 396, 399. loop: 15* , \underline{16}. : 660. : 674. loose fit : \underline{817}, 834, 852* , 1580* . looseness : \underline{236*} , 848, 873, 875, 1070* . primitive: \underline{238}. looseness code: \underline{236*} , 237* , 238, 1070* . primitive: \underline{1071*} . primitive: \underline{1286}. lq : \underline{592}, 627, 636. lr : \underline{592}, 627, 636. LR box : 212* , \underline{213*} , 1145* , 1206* , 1475* . LR dir : \underline{1450*} , 1461* , 1470* , 1472* . LR problems : \underline{1439*} , 1440* , 1447* , 1448* , 1449* , 1450* ,

1451* , 1456* , 1461* , 1463* , 1468* , 1472* . LR ptr : \underline{877*} , \underline{1439*} , 1440* , 1441* , 1442* , 1443* , 1447* ,

1448* , 1450* , 1451* , 1456* , 1461* , 1463* , 1468* , 1470* , 1472* .

LR save: 212* , \underline{213*} , 877* , 1096* , 1464* . LR temp: 424* , 1080* , 1105* , \underline{1439*} , 1440* , 1444* , 1445* . LSE: 56* , 84* , 1602* , 1615* , 1616* , 1631* , 1640* . LSE editor : \underline{1637*} , 1638* . lx : \underline{619*} , 626* , 627, 628* , \underline{629*} , 635, 636, 637* . l1 : 529* , 1618* , 1620* , 1629* . l2 : 1618* , 1620* . m: \underline{47*} , \underline{65}, \underline{158}, \underline{211}, \underline{218}, \underline{292}, \underline{315}, \underline{389*} , \underline{413*} , \underline{440},

\underline{482*} , \underline{498*} , \underline{577}, \underline{649*} , \underline{668}, \underline{706}, \underline{716}, \underline{717}, \underline{1079*} , \underline{1105*} , \underline{1194*} , \underline{1293*} , \underline{1338}, \underline{1413*} , \underline{1456*} , \underline{1471*} , \underline{1486*} .

M code: \underline{147*} . mac param: \underline{207}, 291, 294* , 298* , 347, 474, 477,

479, 783, 784, 1045. MacKay, Pierre: 1434* . macro: \underline{307*} , 314* , 319* , 323, 324, 390. macro call : 291, 366* , 380, 382* , 387, 388, \underline{389*} , 391. macro def : \underline{473}, 477. mag : \underline{236*} , 240, 288, 457, 585, \underline{587}, 588, 590,

617, 642* . primitive: \underline{238}. mag code: \underline{236*} , 237* , 238, 288. mag set : \underline{286}, 287, 288. magic offset : \underline{764}, 765, 766. $ : 1636* . main control : 1029, \underline{1030}, 1032, 1040, 1041, 1052,

1054, 1055, 1056, 1057, 1126, 1134, 1208* , 1290, 1332* , 1337* , 1344, 1347.

main f : \underline{1032}, 1034, 1035, 1036, 1037, 1038,

1039, 1040. main i : \underline{1032}, 1036, 1037, 1039, 1040. main j : \underline{1032}, 1039, 1040. main k : \underline{1032}, 1034, 1039, 1040, 1042. main lig loop: \underline{1030}, 1034, 1037, 1038, 1039, 1040. main loop: \underline{1030}. main loop lookahead : \underline{1030}, 1034, 1036, 1037,

1038. main loop move: \underline{1030}, 1034, 1036, 1040. main loop move lig : \underline{1030}, 1034, 1036, 1037. main loop wrapup: \underline{1030}, 1034, 1039, 1040. main p: \underline{1032}, 1035, 1037, 1040, 1041, 1042,

1043, 1044. main s : \underline{1032}, 1034. major tail : \underline{912}, 914, 917, 918. make accent : 1122, \underline{1123}. make box : \underline{208*} , 1071* , 1072, 1073, 1079* , 1084. make fraction: 733, 734, \underline{743}, 1532* . make left right : 761, \underline{762*} . make mark : 1097, \underline{1101*} . make math accent : 733, \underline{738}. make name string : \underline{525*} , 1656* , 1658* . make op: 733, \underline{749}. make ord : 733, \underline{752}. make over : 733, \underline{734}. make radical : 733, 734, \underline{737}. make scripts : 754, \underline{756}. make string : \underline{43}, 48, 52* , 260, 514* , 517* , 525* , 537* ,

939, 1257, 1279, 1328, 1333* , 1486* . make under : 733, \underline{735}. make vcenter : 733, \underline{736}. mark : \underline{208*} , 265* , 266* , 1097, 1542* . primitive: \underline{265*} . mark class : \underline{141*} , 196* , 979* , 1014* , 1101* , 1560* , 1563* . mark class node size: \underline{1553*} , 1558* . mark node: \underline{141*} , 148, 175* , 183, 202, 206, 647,

651* , 730, 761, 866* , 899, 968* , 973, 979* , 1000, 1014* , 1101* , 1433* .

mark ptr : \underline{141*} , 196* , 202, 206, 979* , 1016, 1101* ,

1560* , 1563* . mark text : \underline{307*} , 314* , 323, 386* . mark val : \underline{1548*} , 1549* , 1553* , 1557* , 1560* , 1563* . primitive: \underline{1542*} . marks code: 296* , \underline{382*} , 385* , 386* , 1542* . mastication: 341. match: \underline{207}, 289* , 291, 292, 294* , 391, 392. match chr : \underline{292}, 294* , \underline{389*} , 391, 400. match token: \underline{289*} , 391, 392, 393, 394, 476. matching : \underline{305}, 306, 339, 391. : 1195. math ac: 1164, \underline{1165}. math accent : \underline{208*} , 265* , 266* , 1046, 1164. primitive: \underline{265*} . primitive: \underline{1156}. math char : \underline{681}, 692, 720, 722, 724, 738, 741, 749,

752, 753, 754, 1151, 1155, 1165. primitive: \underline{265*} .

primitive: \underline{1222}.
math char def code: \underline{1222}, 1223, 1224* .
math char num: \underline{208*} , 265* , 266* , 1046, 1151, 1154.
math choice: \underline{208*} , 265* , 266* , 1046, 1171.
primitive: \underline{265*} .
math choice group: \underline{269}, 1172, 1173, 1174, 1395* ,

1413* . primitive: \underline{1156}.

math code: \underline{230*} , 232* , 236* , 414, 1151, 1154.
primitive: \underline{1230}.
math code base: \underline{230*} , 235, 414, 1230, 1231,

1232, 1233. math comp: \underline{208*} , 1046, 1156, 1157, 1158.

math font base: \underline{230*} , 232* , 234, 1230, 1231.
math fraction: 1180, \underline{1181}.

math given: \underline{208*} , 413* , 1046, 1151, 1154, 1222,

1223, 1224* . math glue: \underline{716}, 732, 766. math group: \underline{269}, 1136, 1150, 1153, 1186, 1395* ,

1413* . primitive: \underline{1156}.

math kern: \underline{717}, 730.

math left group: 212* , \underline{269}, 1065, 1068, 1069, 1150,

1191* , 1395* , 1413* . math left right : 1190, \underline{1191*} .

math limit switch: 1158, \underline{1159}.

math node: \underline{147*} , 148, 175* , 183, 202, 206, 424* , 622* , 651* , 817, 837, 866* , 879* , 881* , 1080* , 1105* , 1434* , 1441* , 1445* , 1461* , 1466* , 1469* , 1471* .

primitive: \underline{1156}.

primitive: \underline{1156}.
primitive: \underline{1156}.
primitive: \underline{1156}.
math quad : \underline{700}, 703, 1199* .
math radical : 1162, \underline{1163}.
primitive: \underline{1156}.

math shift : \underline{207}, 289* , 294* , 298* , 347, 1090, 1137,

1138* , 1193, 1197, 1206* . math shift group: \underline{269}, 1065, 1068, 1069, 1130* , 1139, 1140, 1142, 1145* , 1192* , 1193, 1194* , 1200, 1395* , 1413* .

math shift token: \underline{289*} , 1047, 1065.

math spacing : \underline{764}, 765.
math style: \underline{208*} , 1046, 1169, 1170, 1171.
math surround : \underline{247}, 1196.
primitive: \underline{248}.
math surround code: \underline{247}, 248.
math text char : \underline{681}, 752, 753, 754, 755.

math type: \underline{681}, 683, 687* , 692, 698, 720, 722, 723, 734, 735, 737, 738, 741, 742, 749, 751, 752, 753, 754, 755, 756, 1076, 1093, 1151, 1155, 1165, 1168, 1176, 1181, 1185* , 1186, 1191* . math x height : \underline{700}, 737, 757, 758, 759. mathex : \underline{701}. mathsy : \underline{700}. mathsy end : \underline{700}. max answer : \underline{105}, \underline{1526*} , \underline{1532*} . max buf stack : \underline{30*} , 31* , 331* , 374, 1334, 1489* , 1501* . max char code: \underline{207}, 303* , 344, 1233. max command : \underline{209*} , 210* , 211, 219, 358, 366* , 368,

380, 381, 478* , 782, 1505* . max d : \underline{726}, 727* , 730, 760* , 761, \underline{762*} . max dead cycles : \underline{236*} , 240, 1012* . primitive: \underline{238}. max dead cycles code: \underline{236*} , 237* , 238. max depth: \underline{247}, 980, 987. primitive: \underline{248}. max depth code: \underline{247}, 248. max dimen: \underline{421}, 460, 641, 668, 1010, 1017,

1145* , 1146* , 1148, 1468* , 1469* , 1470* , 1523* , 1525* , 1531* , 1579* .

max editor : \underline{1637*} , 1654* . max group code: \underline{269}. max h: \underline{592}, 593, 641, 642* , \underline{726}, 727* , 730, 760* ,

761, \underline{762*} . max halfword : 11* , 14, \underline{110*} , 111, 113* , 124, 125,

126, 131, 132, 289* , 290, 424* , 820, 848, 850, 982* , 991* , 996* , 1017, 1106, 1249, 1323, 1325* .

max in open: \underline{11*} , 14, 304, 328* , 1394* , 1506* ,

1507* , 1509* . max in stack : \underline{301}, 321, 331* , 1334. max internal : \underline{209*} , 413* , 440, 448, 455, 461* . max nest stack : \underline{213*} , 215* , 216* , 1334. max non prefixed command : \underline{208*} , 1211* , 1270. max param stack : \underline{308}, 331* , 390, 1334. max print line: \underline{11*} , 14, 54* , 58* , 61* , 72, 176, 537* ,

638* , 1280, 1488* . max push: \underline{592}, 593, 619* , 629* , 642* . max quarterword : 11* , \underline{110*} , 111, 113* , 274* , 797,

798, 944, 1120, 1325* . max reg help line: 1544* , 1545* , 1546* , \underline{1547*} . max reg num: 1544* , 1545* , 1546* , \underline{1547*} . max save stack : \underline{271}, 272, 273* , 1334. max selector : \underline{54*} , 246, 311* , 465* , 470* , 534* , 638* ,

1257, 1279, 1368, 1370, 1486* . max size: 30* . max strings : \underline{11*} , 38, 43, 111, 517* , 525* , 537* ,

1310, 1334. max v : \underline{592}, 593, 641, 642* . maxint : 27* , 33* . primitive: \underline{468}. meaning code: \underline{468}, 469* , 471* , 472* . mechan args : \underline{1618*} . med mu skip: \underline{224}.

primitive: \underline{226}.
med mu skip code: \underline{224}, 225, 226, 766.
mem: 11* , 12* , 109* , 115, \underline{116}, 118, 124, 126, 131,

133, 134, 135, 140, 142* , 150, 151, 157, 159, 162, 163, 164, 165, 167, 172, 182, 203, 205, 206, 221, 224, 275* , 291, 387, 420* , 489, 605, 652, 680, 681, 683, 686, 687* , 720, 725, 742, 753, 769, 770, 772, 797, 816* , 818, 819* , 822, 823, 832, 843, 844, 847, 848, 850, 860, 861, 889, 925, 1149, 1151, 1160, 1163, 1165, 1181, 1186, 1247* , 1248* , 1311* , 1312* , 1339, 1408* , 1460* , 1466* , 1487* , 1489* , 1521* , 1548* , 1553* , 1575* .

mem bot : 11* , \underline{12*} , 14, 111, 116, 125, 126, 162, 164, 265* , 411* , 415* , 427* , 1226* , 1227* , 1237* , 1307* , 1308* , 1311* , 1312* , 1565* , 1566* , 1567* .

mem end : 116, \underline{118}, 120, 164, 165, 167, 168, 171, 172, 174, 176, 182, 293, 1311* , 1312* , 1334. mem max : \underline{11*} , 12* , 14, 110* , 111, 116, 120, 124,

125, 165, 166. mem min: \underline{11*} , 12* , 111, 116, 120, 125, 165, 166, 167, 169, 170, 171, 172, 174, 178, 182, 1249, 1312* , 1334.

mem top: 11* , \underline{12*} , 14, 111, 116, 162, 164, 1249,

1307* , 1308* , 1312* . : 639. memory word : 110* , \underline{113*} , 114, 116, 182, 212* ,

218, 221, 253, 268* , 271, 275* , 548, 549, 800, 1305* , 1549* .

message: \underline{208*} , 1276, 1277, 1278.

primitive: \underline{1277}.

: 589. mid : \underline{546}. mid line: 87, \underline{303*} , 328* , 344, 347, 352, 353, 354. middle: 1431* . primitive: \underline{1431*} . middle noad : 212* , \underline{687*} , 1191* , 1192* , 1431* , 1432* . min halfword : 11* , \underline{110*} , 111, 113* , 115, 230* , 1027, 1323, 1325* , 1456* , 1461* , 1471* , 1472* . min internal : \underline{208*} , 413* , 440, 448, 455, 461* . min quarterword : 12* , \underline{110*} , 111, 112* , 113* , 134, 136, 140, 185, 221, 274* , 549, 550, 554, 556, 557, 566, 576, 616* , 619* , 649* , 668, 685, 697, 707, 713, 714, 796, 801, 803, 808* , 920, 923, 924, 943, 944, 945, 946, 958* , 963, 964, 965, 994, 1012* , 1323, 1324* , 1325* .

minimal demerits : \underline{833}, 834, 836, 845* , 855* , 1575* . minimum demerits : \underline{833}, 834, 835, 836, 854, 855* . minor tail : \underline{912}, 915, 916. : 462. : 1128. : 1128.

: 1129. : 1128. : 1517* . : 503. # : 783. $ : 1047, 1065. : 1132. : 373. : 1065. : 1065. : 403, 475, 1127. : 1065, 1127. : 1082* . : 1225* . $$ : 1207. : 581* . : 1215. : 1161. : 577. : 415* , 446. mkern: \underline{208*} , 1046, 1057, 1058, 1059. primitive: \underline{1058}. ml field : \underline{212*} , 213* , 218. mlist : \underline{726}, 760* . mlist penalties : \underline{719}, 720, 726, 754, 1194* , 1196,

1199* . mlist to hlist : 693, 719, 720, 725, \underline{726}, 734, 754,

760* , 1194* , 1196, 1199* . : 458. mmode: \underline{211}, 212* , 213* , 218, 501* , 718, 775, 776,

800, 807* , 812, 1030, 1045, 1046, 1048, 1056, 1057, 1073, 1078, 1080* , 1092, 1097, 1109, 1110* , 1112, 1116, 1120, 1130* , 1136, 1140, 1145* , 1150, 1154, 1158, 1162, 1164, 1167, 1171, 1175, 1180, 1190, 1193, 1194* , 1413* , 1475* .

mode: 211, 212* , \underline{213*} , 215* , 216* , 299* , 418, 422, 424* , 501* , 718, 775, 776, 785* , 786, 787, 796, 799, 804, 807* , 808* , 809, 812, 1025, 1029, 1030, 1034, 1035, 1049, 1051, 1056, 1076, 1078, 1080* , 1083, 1086, 1091, 1093, 1094, 1095, 1096* , 1099, 1103, 1105* , 1110* , 1117, 1119, 1120, 1136, 1138* , 1145* , 1167, 1194* , 1196, 1200, 1243, 1370, 1371, 1377, 1475* .

mode field : \underline{212*} , 213* , 218, 422, 800, 807* , 1244,

1413* , 1415* . mode line: 212* , \underline{213*} , 215* , 216* , 304, 804, 815* , 1025. month: \underline{236*} , 241* , 536* , 617, 1328. primitive: \underline{238}. month code: \underline{236*} , 237* , 238. months : \underline{534*} , 536* . more name: 512, \underline{516*} , 517* , 526, 531. primitive: \underline{1071*} . move past : \underline{619*} , 622* , 625* , 629* , 631, 634* . primitive: \underline{1071*} . movement : \underline{607}, 609, 616* . movement node size: \underline{605}, 607, 615. mskip: \underline{208*} , 1046, 1057, 1058, 1059, 1078. primitive: \underline{1058}. mskip code: \underline{1058}, 1060. mstate: \underline{607}, 611, 612. mtype: \underline{4*} . mu: 447, \underline{448}, 449, 453, 455, \underline{461*} , 462. : 456. mu error : \underline{408}, 429, 449, 455, 461* , 1513* . primitive: \underline{1511*} . mu glue: \underline{149}, 155, 191, 424* , 717, 732, 1058,

1060, 1061. mu mult : \underline{716}, 717. mu skip: \underline{224}, 427* . primitive: \underline{411*} . mu skip base: \underline{224}, 227, 229, 1224* , 1237* . primitive: \underline{1222}. mu skip def code: \underline{1222}, 1223, 1224* . primitive: \underline{1538*} . mu to glue code: \underline{1538*} , 1539* , 1540* . mu val : \underline{410}, 411* , 413* , 424* , 427* , 429, 430, 449,

451, 455, 461* , 465* , 1060, 1224* , 1228, 1236* , 1237* , 1511* , 1512* , 1513* , 1520* , 1548* , 1553* , 1556* .

mu val limit : \underline{1548*} , 1554* , 1571* . mult and add : \underline{105}. mult integers : \underline{105}, 1240* , 1528* . multiply : \underline{209*} , 265* , 266* , 1210, 1235, 1236* , 1240* . primitive: \underline{265*} . : 1303. n: \underline{47*} , \underline{65}, \underline{66}, \underline{67}, \underline{69}, \underline{91}, \underline{94}, \underline{105}, \underline{106}, \underline{107}, \underline{152},

\underline{154}, \underline{174}, \underline{182}, \underline{225}, \underline{237*} , \underline{247}, \underline{252}, \underline{292}, \underline{298*} , \underline{299*} , \underline{315}, \underline{389*} , \underline{482*} , \underline{498*} , \underline{518}, \underline{519}, \underline{523}, \underline{578}, \underline{706}, \underline{716}, \underline{717}, \underline{791*} , \underline{800}, \underline{906}, \underline{934*} , \underline{944}, \underline{977*} , \underline{992}, \underline{993}, \underline{994}, \underline{1012*} , \underline{1079*} , \underline{1119}, \underline{1138*} , \underline{1211*} , \underline{1275*} , \underline{1293*} , \underline{1338}, \underline{1456*} , \underline{1471*} , \underline{1515*} , \underline{1530*} , \underline{1532*} , \underline{1552*} , \underline{1555*} .

NAM : \underline{1627*} . NAM ptr : \underline{1626*} , 1627* . name: 300, \underline{302}, 303* , 304, 307* , 311* , 313* , 314* ,

318* , 323, 328* , 329* , 331* , 337, 360, 362* , 390, 483* , 537* , 1488* , 1609* .

name field : 84* , \underline{300}, 302, 1507* , 1508* , 1655* ,

1662* , 1664* . name in progress : 378* , 526, \underline{527}, 528, 1258. name length: \underline{26*} , 51* , 519, 523, 529* . name of file: \underline{26*} , 27* , 51* , 519, 523, 525* , 529* , 530* ,

537* , 1656* , 1658* . natural : \underline{644}, 705, 715, 720, 727* , 735, 737, 738,

748, 754, 756, 759, 796, 799, 806, 977* , 1021* , 1100, 1125, 1194* , 1199* , 1204* , 1479* . nd : 540, 541, \underline{560}, 565, 566, 569. ne: 540, 541, \underline{560}, 565, 566, 569. negate: \underline{16}, 65, 103, 105, 106, 107, 430, 431, 440,

448, 461* , 775, 1513* , 1526* , 1530* , 1532* . negative: \underline{106}, \underline{413*} , 430, \underline{440}, 441, \underline{448}, \underline{461*} , 1513* ,

\underline{1526*} , \underline{1530*} , \underline{1532*} . nest : 212* , \underline{213*} , 216* , 217, 218, 219, 413* , 422, 775,

800, 807* , 995, 1244, 1413* , 1415* . nest ptr : \underline{213*} , 215* , 216* , 217, 218, 422, 775,

800, 807* , 995, 1017, 1023* , 1091, 1100, 1145* , 1200, 1244, 1413* .

nest size: \underline{11*} , 213* , 216* , 218, 413* , 1244, 1334, 1413* . new : 27* , 1633* , 1648* . new character : \underline{582}, 755, 915, 1117, 1123, 1124. new choice: \underline{689}, 1172. new delta from break width: \underline{844}. new delta to break width: \underline{843}. new disc: \underline{145}, 1035, 1117. new edge: \underline{1452*} , 1455* , 1471* . new font : 1256, \underline{1257}. new glue: \underline{153}, 154, 715, 766, 786, 793, 795, 809,

1041, 1043, 1054, 1060, 1171. new graf : 1090, \underline{1091}. new hlist : \underline{725}, 727* , 743, 748, 749, 750, 754,

756, 762* , 767. new hyph exceptions : \underline{934*} , 1252* . new index : \underline{1548*} , 1549* , 1552* . new interaction: 1264, \underline{1265}, 1429* , 1430* . new kern: \underline{156}, 705, 715, 735, 738, 739, 747, 751,

753, 755, 759, 910, 1040, 1061, 1112, 1113, 1125, 1204* , 1454* , 1473* , 1479* .

new lig item: \underline{144}, 911, 1040. new ligature: \underline{144}, 910, 1035. new line: \underline{303*} , 331* , 343, 344, 345, 347, 483* , 537* . new line char : 59, \underline{236*} , 244, 1487* . primitive: \underline{238}. new line char code: \underline{236*} , 237* , 238. new math: \underline{147*} , 1196, 1437* , 1441* , 1443* , 1448* ,

1456* , 1467* , 1479* . new noad : \underline{686}, 720, 742, 753, 1076, 1093, 1150,

1155, 1158, 1168, 1177, 1191* . new null box : \underline{136}, 706, 709, 713, 720, 747, 750,

779, 793, 809, 1018, 1054, 1091, 1093, 1473* . new param glue: \underline{152}, 154, 679, 778, 816* , 886, 887,

1041, 1043, 1091, 1203* , 1205* , 1206* , 1473* . new patterns : \underline{960*} , 1252* . new penalty : \underline{158}, 767, 816* , 890* , 1054, 1103,

1203* , 1205* , 1206* . new rule: \underline{139}, 463, 666, 704. new save level : \underline{274*} , 645, 774, 785* , 791* , 1025,

1063, 1099, 1117, 1119, 1136. new skip param: \underline{154}, 679, 969, 1001, 1479* . new spec: \underline{151}, 154, 430, 462, 826, 976, 1004, 1042,

1043, 1239* , 1240* , 1513* , 1523* , 1524* , 1586* . new string : \underline{54*} , 57* , 58* , 465* , 470* , 617, 1257, 1279,

1328, 1368, 1422* , 1486* , 1648* . new style: \underline{688}, 1171. new trie op: 943, \underline{944}, 945, 965. new whatsit : \underline{1349}, 1350, 1354, 1376, 1377. new write whatsit : \underline{1350}, 1351, 1352, 1353. next : \underline{256}, 257, 259, 260. next break : \underline{877*} , 878. next ch: 1662* , \underline{1663*} . next char : \underline{545}, 741, 753, 909, 1039. next item: 1629* , \underline{1630*} , 1659* , 1661* . next p: \underline{619*} , 622* , 626* , 629* , 630, 631, 633* , 635,

1433* , 1456* , 1458* . nh: 540, 541, \underline{560}, 565, 566, 569. ni : 540, 541, \underline{560}, 565, 566, 569. nil: 16. nk : 540, 541, \underline{560}, 565, 566, 573. nl : \underline{59}, 540, 541, 545, \underline{560}, 565, 566, 569, 573,

576, \underline{1486*} , 1487* . nn: \underline{311*} , 312. : 642* . no align: \underline{208*} , 265* , 266* , 785* , 1126. primitive: \underline{265*} . no align error : 1126, \underline{1129}. no align group: \underline{269}, 768, 785* , 1133, 1395* , 1413* . no boundary : \underline{208*} , 265* , 266* , 1030, 1038, 1045,

1090. primitive: \underline{265*} . no break yet : \underline{829*} , 836, 837. no expand : \underline{210*} , 265* , 266* , 366* , 367* . primitive: \underline{265*} . no expand flag : \underline{358}, 478* , 506. primitive: \underline{1088}. no limits : \underline{682}, 1156, 1157. primitive: \underline{1156}. no new control sequence: \underline{256}, 257, 259, 264* , 365,

374, 1336* , 1379* , 1501* . no print : \underline{54*} , 57* , 58* , 75, 98. no shrink error yet : \underline{825}, 826, 827* . no tag : \underline{544}, 569. noad size: \underline{681}, 686, 698, 753, 761, 1186, 1187. node list display : \underline{180}, 184* , 188, 190, 195, 197. node r stays active: \underline{830}, 851* , 854. node size: \underline{124}, 126, 127, 128, 130, 164, 169,

1311* , 1312* . nom: \underline{560}, 561, 563* , 576. non address : \underline{549}, 552, 576, 909, 916, 1034. non char : \underline{549}, 552, 576, 897* , 898* , 901, 908, 909,

910, 911, 915, 916, 917, 1032, 1034, 1035, 1038, 1040, 1323. non discardable: \underline{148}, 879* . non math: \underline{1046}, 1063, 1144. non script : \underline{208*} , 265* , 266* , 1046, 1171. primitive: \underline{265*} , \underline{732}. none seen: \underline{611}, 612. : 262. : 962. nonnegative integer : 69, \underline{101}, 107. nonstop mode: \underline{73*} , 86* , 360, 363, 484, 1262, 1263. primitive: \underline{1262}. nop: 583, 585, \underline{586}, 588, 590. norm min: \underline{1091}, 1200, 1376, 1377. normal : \underline{135}, 136, 149, 150, 153, 155, 156, 164,

177, 186* , 189, 191, 305, 331* , 336, 369, 448, 471* , 473, 480, 482* , 485, 489, 490, 507, 619* , 625* , 629* , 634* , 650, 657, 658, 659, 660, 664, 665, 666, 667, 672, 673, 674, 676, 677, 678, 682, 686, 696* , 716, 732, 749, 777, 801, 810, 811, 825, 826, 896* , 897* , 899, 976, 988, 1004, 1009, 1156, 1163, 1165, 1181, 1201, 1219, 1220, 1221, 1239* , 1293* , 1417* , 1433* , 1456* , 1459* , 1499* , 1524* , 1527* , 1576* .

normal paragraph: 774, 785* , 787, 1025, \underline{1070*} ,

1083, 1094, 1096* , 1099, 1167. normalize glue: \underline{1524*} , 1527* . normalize selector : 78, \underline{92}, 93, 94, 95, 863* . : 937* . not found : \underline{15*} , 45, 46, 448, 455, 560, 570, 607, 611,

612, 829* , 895, 930, 931, 934* , 941, 953, 955, 970, 972, 973, 1138* , 1146* , 1365, 1466* , 1552* , 1579* .

not found1 : \underline{15*} , 934* , 1552* . not found2 : \underline{15*} , 1552* . not found3 : \underline{15*} , 1552* . not found4 : \underline{15*} , 1552* . : 258. np: 540, 541, \underline{560}, 565, 566, 575* , 576. nucleus : \underline{681}, 682, 683, 686, 687* , 690, 696* , 698,

720, 725, 734, 735, 736, 737, 738, 741, 742, 749, 750, 752, 753, 754, 755, 1076, 1093, 1150, 1151, 1155, 1158, 1163, 1165, 1168, 1186, 1191* .

null : 23* , \underline{115}, 116, 118, 120, 122, 123, 125, 126, 135, 136, 144, 145, 149, 150, 151, 152, 153, 154, 164, 168, 169, 175* , 176, 182, 196* , 200, 201, 202, 204, 210* , 212* , 215* , 216* , 218, 219, 222, 223, 232* , 233* , 275* , 292, 295, 299* , 306, 307* , 312, 314* , 325, 331* , 357, 358, 362* , 371, 374, 382* , 383, 386* , 390, 391, 392, 397, 400, 407, 410, 415* , 420* , 423* , 424* , 427* , 452, 464* , 466, 473, 478* , 482* , 489, 490, 497, 505* , 508, 549, 552, 576, 578, 582, 606, 611, 615, 619* , 623* , 629* , 632* , 648, 649* , 651* , 655, 658, 664, 666, 668, 673, 676, 681, 685, 689, 692, 715, 718, 719, 720, 721, 726, 731, 732, 752, 754, 755, 756, 760* , 761, 766, 767, 771, 774, 776, 777, 783, 784, 790, 791* , 792, 794, 796, 797, 799, 801, 804, 805, 806, 807* , 812, 821, 829* , 837, 840, 846* , 847, 848, 850, 852* , 856, 857, 858, 859, 863* , 864* , 865, 867, 869, 872, 877* , 878, 879* , 881* , 882, 883, 884, 885, 887, 888, 889, 890* , 894, 896* , 898* , 903, 906, 907, 908, 910, 911, 913, 914, 915, 916, 917, 918, 928, 932, 935, 968* , 969, 970, 972, 973, 977* , 978, 979* , 981, 991* , 992, 993, 994, 998, 999* , 1000, 1009, 1010, 1011, 1012* , 1014* , 1015, 1016, 1017, 1018, 1020, 1021* , 1022, 1023* , 1026* , 1027, 1028, 1030, 1032, 1035, 1036, 1037, 1038, 1040, 1042, 1043, 1070* , 1074, 1075* , 1076, 1079* , 1080* , 1081, 1083, 1087, 1091, 1096* , 1105* , 1110* , 1121, 1123, 1124, 1136, 1139, 1145* , 1146* , 1149, 1167, 1174, 1176, 1181, 1184, 1185* , 1186, 1194* , 1196, 1199* , 1202* , 1205* , 1206* , 1226* , 1227* , 1247* , 1248* , 1283, 1288, 1296* , 1311* , 1312* , 1335* , 1339, 1353, 1354, 1368, 1369, 1375, 1402* , 1408* , 1417* , 1425* , 1433* , 1440* , 1441* , 1442* , 1443* , 1444* , 1445* , 1448* , 1454* , 1456* , 1458* , 1463* , 1464* , 1466* , 1467* , 1468* , 1471* , 1478* , 1479* , 1484* , 1489* , 1490* , 1491* , 1501* , 1515* , 1516* , 1517* , 1542* , 1548* , 1549* , 1550* , 1551* , 1552* , 1553* , 1554* , 1556* , 1557* , 1558* , 1559* , 1560* , 1561* , 1562* , 1563* , 1564* , 1565* , 1569* , 1570* , 1571* , 1574* , 1582* , 1585* , 1593* , 1596* , 1599* .

null delimiter: 240, 1065.

null character : \underline{555}, 556, 722, 723.

null code: \underline{22}, 232* .

null cs : \underline{222}, 262, 263, 354, 374, 1257, 1501* .

null delimiter : \underline{684}, 685, 1181. null delimiter space: \underline{247}, 706. primitive: \underline{248}. null delimiter space code: \underline{247}, 248. null flag : \underline{138}, 139, 463, 653, 779, 793, 801. null font : \underline{232*} , 552, 553, 560, 577, 617, 663, 706, 707, 722, 864* , 1257, 1320, 1321, 1339.

primitive: \underline{553}. null list : 14, \underline{162}, 380, 780. num: \underline{450}, 458, 585, \underline{587}, 590. num error : \underline{1523*} , 1526* , 1530* , 1532* . primitive: \underline{1511*} . num of args : 1632* . num style: \underline{702}, 744. : 445. primitive: \underline{468}. number code: \underline{468}, 469* , 471* , 472* . numerator : \underline{683}, 690, 697, 698, 744, 1181, 1185* . num1 : \underline{700}, 744. num2 : \underline{700}, 744. num3 : \underline{700}, 744. nw : 540, 541, \underline{560}, 565, 566, 569. nx plus y : \underline{105}, 455, 716, 1240* , 1528* . o: \underline{264*} , \underline{607}, \underline{649*} , \underline{668}, \underline{791*} , \underline{800}, \underline{1515*} . octal token: \underline{438}, 444. odd : 34* , 62, 100, 147* , 193, 504, 758, 898* , 902,

908, 909, 913, 914, 1211* , 1218* , 1248* , 1295* , 1332* , 1422* , 1533* , 1552* , 1557* , 1620* , 1621* , 1627* , 1633* , 1635* , 1645* , 1648* .

off save: 1063, \underline{1064}, 1094, 1095, 1130* , 1131,

1140, 1192* , 1193. : 1298. OK so far : \underline{440}, 445. OK to interrupt : 88, \underline{96*} , 97* , 98, 327, 1031. old l : \underline{829*} , 835, 850. old mode: \underline{1370}, 1371. old rover : \underline{131}. old setting : 245, \underline{246}, \underline{311*} , 312, \underline{465*} , \underline{470*} , \underline{534*} ,

\underline{581*} , 617, \underline{638*} , \underline{1257}, \underline{1279}, \underline{1368}, \underline{1370}, 1422* , \underline{1486*} , \underline{1651*} , 1652* , 1655* .

omit : \underline{208*} , 265* , 266* , 788, 789, 1126. primitive: \underline{265*} . omit error : 1126, \underline{1129}. omit template: \underline{162}, 789, 790. # : 784. op byte: \underline{545}, 557, 741, 753, 909, 911, 1040. op noad : \underline{682}, 690, 696* , 698, 726, 728, 733, 749,

761, 1156, 1157, 1159. op start : 920, \underline{921}, 924, 945, 1325* . open: 27* , 28* , 33* , 525* , 529* , 537* , 1627* . open area: \underline{1341}, 1351, 1356, 1374. open diag file: 534* , \underline{1615*} . open ext : \underline{1341}, 1351, 1356, 1374. open fmt file: \underline{524}, 1337* , 1621* . primitive: \underline{1272}. open log file: 78, 92, 360, 471* , 532* , \underline{534*} , 535* ,

537* , 1257, 1335* . open name: \underline{1341}, 1351, 1356, 1374. open noad : \underline{682}, 690, 696* , 698, 728, 733, 760* ,

761, 762* , 1156, 1157. open node: \underline{1341}, 1344, 1346, 1348* , 1356, 1357,

1358, 1373. open node size: \underline{1341}, 1351, 1357, 1358. open or close in: 537* , 1274, \underline{1275*} . primitive: \underline{1344}. open parens : \underline{304}, 331* , 362* , 537* , 1335* , 1488* . primitive: \underline{491}. or code: \underline{489}, 491, 492, 500, 509, 1293* , 1402* . ord : 20, 1627* . ord noad : 681, \underline{682}, 686, 687* , 690, 696* , 698, 728,

729, 733, 752, 753, 761, 764, 765, 1075* , 1155, 1156, 1157, 1186.

order : \underline{177}. oriental characters: 134, 585. other A token: \underline{445}. other char : \underline{207}, 232* , 289* , 291, 294* , 298* , 347,

445, 464* , 526, 935, 961, 1030, 1038, 1090, 1124, 1151, 1154, 1160.

other token: \underline{289*} , 405, 438, 441, 445, 464* , 503,

1065, 1221, 1494* , 1517* , 1518* . othercases: \underline{10*} . others : 10* . otherwise: 10* . : 1332* . out FAB : 33* , 1628* . out param: \underline{207}, 289* , 291, 294* , 357. out param token: \underline{289*} , 479. out RAB : 33* , 34* , 1628* . out what : 1366, 1367, \underline{1373}, 1375. primitive: \underline{1208*} . outer call : \underline{210*} , 275* , 339, 351, 353, 354, 357, 366* ,

387, 391, 396, 780, 1152, 1295* , 1369. outer doing leaders : \underline{619*} , 628* , \underline{629*} , 637* . output : \underline{4*} . : 1024. : 1028. : 642* . primitive: \underline{230*} . output active: 421, 663, 675, 986, \underline{989}, 990, 994,

1005, 1025, 1026* . output file name: \underline{532*} , 533, 642* . output group: \underline{269}, 1025, 1100, 1395* , 1413* . output penalty : \underline{236*} . primitive: \underline{238}. output penalty code: \underline{236*} , 237* , 238, 1013. output routine: \underline{230*} , 1012* , 1025. output routine loc: \underline{230*} , 231* , 232* , 307* , 323, 1226* . output text : \underline{307*} , 314* , 323, 1025, 1026* . primitive: \underline{1178}. over code: \underline{1178}, 1179, 1182. over noad : \underline{687*} , 690, 696* , 698, 733, 761, 1156. primitive: \underline{1178}. overbar : \underline{705}, 734, 737. overflow : 35, 42, 43, \underline{94}, 120, 125, 216* , 260, 264* ,

273* , 274* , 321, 328* , 374, 390, 517* , 580, 940, 944, 954, 964, 1333* , 1501* .

Overflow in arithmetic: 9* , 104. : 666. : 677. overfull boxes: 854. overfull rule: \underline{247}, 666, 800, 804. primitive: \underline{248}. overfull rule code: \underline{247}, 248. primitive: \underline{1156}. p: \underline{120}, \underline{123}, \underline{125}, \underline{130}, \underline{131}, \underline{136}, \underline{139}, \underline{144}, \underline{145}, \underline{147*} ,

\underline{151}, \underline{152}, \underline{153}, \underline{154}, \underline{156}, \underline{158}, \underline{167}, \underline{172}, \underline{174}, \underline{176}, \underline{178}, \underline{182}, \underline{198}, \underline{200}, \underline{201}, \underline{202}, \underline{204}, \underline{218}, \underline{259}, \underline{262}, \underline{263}, \underline{276}, \underline{277*} , \underline{278*} , \underline{279*} , \underline{281*} , \underline{284*} , \underline{292}, \underline{295}, \underline{299*} , \underline{306}, \underline{315}, \underline{323}, \underline{325}, \underline{336}, \underline{366*} , \underline{389*} , \underline{407}, \underline{413*} , \underline{450}, \underline{464*} , \underline{465*} , \underline{473}, \underline{482*} , \underline{497}, \underline{498*} , \underline{582}, \underline{607}, \underline{615}, \underline{619*} , \underline{629*} , \underline{638*} , \underline{649*} , \underline{668}, \underline{679}, \underline{686}, \underline{688}, \underline{689}, \underline{691}, \underline{692}, \underline{704}, \underline{705}, \underline{709}, \underline{711}, \underline{715}, \underline{716}, \underline{717}, \underline{720}, \underline{726}, \underline{735}, \underline{738}, \underline{743}, \underline{749}, \underline{752}, \underline{756}, \underline{772}, \underline{774}, \underline{787}, \underline{791*} , \underline{799}, \underline{800}, \underline{826}, \underline{906}, \underline{934*} , \underline{948}, \underline{949}, \underline{953}, \underline{957}, \underline{959}, \underline{960*} , \underline{966*} , \underline{968*} , \underline{970}, \underline{993}, \underline{994}, \underline{1012*} , \underline{1064}, \underline{1068}, \underline{1075*} , \underline{1079*} , \underline{1086}, \underline{1093}, \underline{1101*} , \underline{1105*} , \underline{1110*} , \underline{1113}, \underline{1119}, \underline{1123}, \underline{1138*} , \underline{1151}, \underline{1155}, \underline{1160}, \underline{1174}, \underline{1176}, \underline{1184}, \underline{1191*} , \underline{1194*} , \underline{1211*} , \underline{1236*} , \underline{1244}, \underline{1288}, \underline{1293*} , \underline{1302}, \underline{1303}, \underline{1348*} , \underline{1349}, \underline{1355}, \underline{1368}, \underline{1370}, \underline{1373}, \underline{1413*} , \underline{1417*} , \underline{1433*} , \underline{1444*} , \underline{1445*} , \underline{1452*} , \underline{1456*} , \underline{1466*} , \underline{1471*} , \underline{1477*} , \underline{1486*} , \underline{1489*} , \underline{1490*} , \underline{1510*} , \underline{1515*} , \underline{1554*} , \underline{1556*} , \underline{1570*} , \underline{1571*} , \underline{1572*} , \underline{1573*} , \underline{1574*} , \underline{1627*} .

p 1 : 1587* . pack begin line: \underline{661}, 662, 663, 675, 804, 815* . pack buffered name: \underline{523}, 524. pack cur name: \underline{529*} , 530* , 537* , 1275* , 1374. pack default name: \underline{529*} , 532* , 534* , 1615* , 1616* . pack file name: \underline{519}, 529* , 537* , 563* . pack job name: \underline{529*} , 532* , 534* , 1328, 1615* . pack lig : \underline{1035}. package: 1085, \underline{1086}. packed ASCII code: \underline{38}, 39, 947. page: \underline{304}. page contents : 421, \underline{980}, 986, 987, 991* , 1000,

1001, 1008. page depth: \underline{982*} , 987, 991* , 1002, 1003, 1004,

1008, 1010. primitive: \underline{983}. page disc: 999* , 1023* , 1026* , \underline{1592*} , 1593* . primitive: \underline{1594*} . primitive: \underline{983}. primitive: \underline{983}. primitive: \underline{983}. page goal : 980, \underline{982*} , 986, 987, 1005, 1006, 1007,

1008, 1009, 1010. primitive: \underline{983}. page head : \underline{162}, 215* , 980, 986, 988, 991* , 1014* ,

1017, 1023* , 1026* , 1054. page ins head : \underline{162}, 981, 986, 1005, 1008, 1018,

1019, 1020. page ins node size: \underline{981}, 1009, 1019. page loc: \underline{638*} , 640. page max depth: \underline{980}, 982* , 987, 991* , 1003, 1017. page shrink : \underline{982*} , 985, 1004, 1007, 1008, 1009. primitive: \underline{983}. page so far : 421, \underline{982*} , 985, 987, 1004, 1007,

1009, 1245. page stack : \underline{304}. primitive: \underline{983}. page tail : 215* , \underline{980}, 986, 991* , 998, 1000, 1017,

1023* , 1026* , 1054. page total : \underline{982*} , 985, 1002, 1003, 1004, 1007,

1008, 1010. primitive: \underline{983}. panicking : \underline{165}, 166, 1031, 1339. primitive: \underline{334}. par end : \underline{207}, 334, 335, 1046, 1094. par fill skip: \underline{224}, 816* , 1575* , 1576* , 1579* , 1586* . primitive: \underline{226}. par fill skip code: \underline{224}, 225, 226, 816* . par indent : \underline{247}, 1091, 1093. primitive: \underline{248}. par indent code: \underline{247}, 248. par loc: \underline{333}, 334, 351, 1313, 1314. primitive: \underline{265*} . primitive: \underline{1406*} . par shape dimen code: \underline{1406*} , 1407* , 1408* . primitive: \underline{1406*} . par shape indent code: \underline{1406*} , 1407* , 1408* . primitive: \underline{1406*} . par shape length code: \underline{1406*} , 1407* , 1408* . par shape loc: \underline{230*} , 232* , 233* , 265* , 266* , 423* ,

1070* , 1248* . par shape ptr : \underline{230*} , 232* , 233* , 423* , 814* , 847, 848,

850, 889, 1070* , 1149, 1249, 1408* . par skip: \underline{224}, 1091. primitive: \underline{226}. par skip code: \underline{224}, 225, 226, 1091. par token: \underline{333}, 334, 339, 392, 395, 399, 1095, 1314. : 396. param: 542, 547, \underline{558}. param base: \underline{550}, 552, 558, 566, 574, 575* , 576,

578, 580, 700, 701, 1042, 1322, 1323. param end : \underline{558}. param ptr : \underline{308}, 323, 324, 331* , 390. param size: \underline{11*} , 308, 390, 1334. param stack : 307* , \underline{308}, 324, 359, 388, 389* , 390. param start : \underline{307*} , 323, 324, 359. param 1 : \underline{1631*} . param 3 : \underline{1631*} . parameter : \underline{307*} , 314* , 359. parameters for symbols: 700, 701. : 476. Pascal-H: \underline{3}. Pascal: 1* , 10* , 693, 764. pass number : \underline{821}, 845* , 864* . pass text : 366* , \underline{494*} , 500, 509, 510* . passive: \underline{821}, 845* , 846* , 864* , 865. passive node size: \underline{821}, 845* , 865. : 1252* . primitive: \underline{1250}. pause for instructions : 96* , \underline{98}. pausing : \underline{236*} , 363. primitive: \underline{238}. pausing code: \underline{236*} , 237* , 238. : 458. pen: \underline{726}, 761, 767, \underline{877*} , 890* . penalties: 1102. penalties : \underline{726}, 767. penalty : \underline{157}, 158, 194, 233* , 424* , 816* , 866* , 890* ,

973, 996* , 1000, 1010, 1011, 1013, 1599* . primitive: \underline{265*} . penalty node: \underline{157}, 158, 183, 202, 206, 424* , 730,

761, 767, 816* , 817, 837, 856, 866* , 879* , 899, 968* , 973, 996* , 1000, 1010, 1011, 1013, 1107, 1433* .

pg field : \underline{212*} , 213* , 218, 219, 422, 1244. pi : \underline{829*} , 831, 851* , 856, 859, \underline{970}, 972, 973, 974,

\underline{994}, 1000, 1005, 1006. pid : \underline{1640*} . : 521* , 524, 1331* . Plass, Michael Frederick: 2* , 813. : 360, 530* . : 1166. : 561. : 462. point token: \underline{438}, 440, 448, 452. pointer : \underline{115}, 116, 118, 120, 123, 124, 125, 130,

131, 136, 139, 144, 145, 147* , 151, 152, 153, 154, 156, 158, 165, 167, 172, 198, 200, 201, 202, 204, 212* , 218, 252, 256, 259, 263, 275* , 276, 277* , 278* , 279* , 281* , 284* , 295, 297, 299* , 305, 306, 308, 323, 325, 333, 336, 366* , 382* , 388, 389* , 407, 450, 461* , 463, 464* , 465* , 473, 482* , 489, 497, 498* , 549, 560, 582, 592, 605, 607, 615, 619* , 629* , 638* , 647, 649* , 668, 679, 686, 688, 689, 691, 692, 704, 705, 706, 709, 711, 715, 716, 717, 719, 720, 722, 726, 734, 735, 736, 737, 738, 743, 749, 752, 756, 762* , 770, 772, 774, 787, 791* , 799, 800, 814* , 821, 826, 828, 829* , 830, 833, 862, 872, 877* , 892, 900, 901, 906, 907, 912, 926, 934* , 968* , 970, 977* , 980, 982* , 993, 994, 1012* , 1032, 1043, 1064, 1068, 1074, 1075* , 1079* , 1086, 1093, 1101* , 1105* , 1110* , 1113, 1119, 1123, 1138* , 1151, 1155, 1160, 1174, 1176, 1184, 1191* , 1194* , 1198, 1211* , 1236* , 1247* , 1257, 1288, 1293* , 1302, 1303, 1345, 1348* , 1349, 1355, 1368, 1370, 1373, 1417* , 1433* , 1439* , 1444* , 1445* , 1452* , 1456* , 1466* , 1471* , 1474* , 1477* , 1483* , 1486* , 1489* , 1490* , 1506* , 1510* , 1515* , 1548* , 1549* , 1552* , 1554* , 1555* , 1556* , 1558* , 1568* , 1570* , 1571* , 1572* , 1573* , 1574* , 1575* , 1592* .

pointer node size: \underline{1553*} , 1554* , 1570* , 1574* . Poirot, Hercule: 1283. pool f name: \underline{11*} , 520* , 521* . pool file: 47* , \underline{50*} , 51* , 52* , 53* . pool name: 11* , 51* , \underline{520*} , 521* . pool name length: \underline{520*} , 521* . pool pointer : \underline{38}, 39, 45, 46, 56* , 59, 60, 69, 70,

264* , 407, 464* , 465* , 470* , 513* , 517* , 519, 602, 638* , 929, 934* , 1368, 1486* , 1663* .

pool ptr : 38, \underline{39}, 41, 42, 43, 44, 47* , 52* , 58* , 70, 198, 260, 464* , 465* , 470* , 516* , 517* , 525* , 537* , 617, 1309, 1310, 1332* , 1334, 1339, 1368, 1422* , 1487* .

pool size: \underline{11*} , 38, 42, 52* , 58* , 198, 525* , 537* , 1310,

1334, 1339, 1368. pool string : \underline{1633*} . pop: 584, 585, \underline{586}, 590, 601, 608, 642* . pop alignment : \underline{772}, 800. pop input : \underline{322}, 324, 329* . pop lig stack : \underline{910}, 911. pop LR: \underline{1439*} , 1442* , 1447* , 1448* , 1450* , 1451* ,

1461* , 1468* , 1470* , 1472* . pop nest : \underline{217}, 796, 799, 812, 816* , 1026* , 1086,

1096* , 1100, 1119, 1168, 1184, 1206* , 1465* . positive: \underline{107}. post : 583, 585, \underline{586}, 590, 591, 642* . post break : \underline{145}, 175* , 195, 202, 206, 840, 858,

882, 884, 916, 1119. post disc break : \underline{877*} , 881* , 884. post display penalty : \underline{236*} , 1205* , 1206* . primitive: \underline{238}. post display penalty code: \underline{236*} , 237* , 238. post line break : 876* , \underline{877*} , 1439* . post post : 585, \underline{586}, 590, 591, 642* . prcnm: \underline{1640*} . pre: 583, 585, \underline{586}, 617. pre break : \underline{145}, 175* , 195, 202, 206, 858, 869, 882,

885, 915, 1117, 1119. pre display direction: \underline{236*} , 1138* , 1199* , 1477* . primitive: \underline{1391*} . pre display direction code: \underline{236*} , 1145* , 1391* , 1393* . pre display penalty : \underline{236*} , 1203* , 1206* . primitive: \underline{238}. pre display penalty code: \underline{236*} , 237* , 238. pre display size: \underline{247}, 1138* , 1145* , 1148, 1203* , 1466* . primitive: \underline{248}. pre display size code: \underline{247}, 248, 1145* . preamble: 768, 774. preamble: \underline{770}, 771, 772, 777, 786, 801, 804. preamble of file: 617. precedes break : \underline{148}, 868, 973, 1000. prefix : \underline{209*} , 1208* , 1209* , 1210, 1211* , 1503* . prefixed command : 1210, \underline{1211*} , 1270. prepare mag : \underline{288}, 457, 617, 642* , 1333* . pretolerance: \underline{236*} , 828, 863* . primitive: \underline{238}. pretolerance code: \underline{236*} , 237* , 238. prev break : \underline{821}, 845* , 846* , 877* , 878. prev depth: 212* , \underline{213*} , 215* , 418, 679, 775, 786, 787,

1025, 1056, 1083, 1099, 1167, 1206* , 1242, 1243. primitive: \underline{416*} . prev dp: \underline{970}, 972, 973, 974, 976. prev graf : 212* , \underline{213*} , 215* , 216* , 422, 814* , 816* , 864* ,

877* , 890* , 1091, 1149, 1200, 1242. primitive: \underline{265*} . prev p: \underline{619*} , 620* , 622* , \underline{862}, 863* , 866* , 867, 868,

869, \underline{968*} , 969, \underline{970}, 973, \underline{1012*} , 1014* , 1017, 1022, 1454* , 1455* .

prev prev r : \underline{830}, 832, 843, 844, 860. prev r : \underline{829*} , 830, 832, 843, 844, 845* , 851* , 854, 860. prev s : \underline{862}, 894, 896* . primitive: 226, 230* , 238, 248, \underline{264*} , 265* , 266* , 298* ,

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, 1331* , 1332* , 1344, 1380* , 1391* , 1397* , 1400* , 1403* , 1406* , 1409* , 1418* , 1420* , 1423* , 1426* , 1431* , 1435* , 1480* , 1492* , 1495* , 1503* , 1511* , 1534* , 1538* , 1542* , 1594* , 1597* .

print : 54* , \underline{59}, 60, 62, 63, 68, 70, 71* , 73* , 84* , 85, 86* , 89, 91, 94, 95, 175* , 177, 178, 182, 183, 184* , 185, 186* , 187, 188, 190, 191, 192* , 193, 195, 211, 218, 219, 225, 233* , 234, 237* , 247, 251, 262, 263, 284* , 288, 294* , 298* , 299* , 306, 317* , 318* , 323, 336, 338, 339, 363, 373, 395, 396, 398, 400, 428, 454, 456, 459, 465* , 472* , 502, 509, 530* , 534* , 536* , 561, 567, 579, 581* , 617, 638* , 639, 642* , 660, 663, 666, 674, 675, 677, 692, 694, 697, 723, 776, 846* , 856, 936, 978, 985, 986, 987, 1006, 1011, 1015, 1024, 1049, 1064, 1095, 1132, 1166, 1213* , 1232, 1237* , 1257, 1259, 1261, 1295* , 1296* , 1298, 1309, 1311* , 1318, 1320, 1322, 1324* , 1328, 1334, 1335* , 1338, 1339, 1346, 1356, 1385* , 1395* , 1396* , 1413* , 1414* , 1415* , 1425* , 1438* , 1449* , 1488* , 1498* , 1507* , 1509* , 1510* , 1556* , 1585* , 1649* , 1655* , 1656* , 1658* , 1664* .

print ASCII : \underline{68}, 174, 176, 298* , 581* , 691, 723. print char : \underline{58*} , 59, 60, 64, 65, 66, 67, 69, 70, 82* ,

91, 94, 95, 103, 114, 171, 172, 174, 175* , 176, 177, 178, 184* , 186* , 187, 188, 189, 190, 191, 192* , 193, 196* , 218, 219, 223, 229, 233* , 234, 235, 242, 251, 252, 255, 262, 266* , 284* , 285, 294* , 296* , 299* , 306, 313* , 317* , 362* , 385* , 472* , 509, 536* , 537* , 561, 581* , 617, 638* , 639, 642* , 691, 723, 846* , 856, 933, 1006, 1011, 1065, 1069, 1212, 1213* , 1280, 1294, 1295* , 1296* , 1311* , 1320, 1322, 1324* , 1328, 1332* , 1333* , 1335* , 1340, 1355, 1356, 1395* , 1396* , 1413* , 1414* , 1415* , 1463* , 1488* ,

1498* , 1556* , 1611* , 1649* , 1656* , 1658* . print cmd chr : 223, 233* , 266* , 296* , \underline{298*} , 299* , 323,

336, 418, 428, 503, 510* , 1049, 1066, 1128, 1212, 1213* , 1237* , 1335* , 1339, 1390* , 1413* , 1415* , 1425* , 1498* , 1509* , 1510* , 1556* .

print cs : \underline{262}, 293, 314* , 401. print current string : \underline{70}, 182, 692. print delimiter : \underline{691}, 696* , 697. print err : 72, \underline{73*} , 93, 94, 95, 98, 288, 336, 338,

346, 370, 373, 395, 396, 398, 403, 408, 415* , 418, 428, 433, 434, 435, 436, 437, 442, 445, 446, 454, 456, 459, 460, 475, 476, 479, 486, 500, 503, 510* , 530* , 561, 577, 579, 641, 723, 776, 783, 784, 792, 826, 936, 937* , 960* , 961, 962, 963, 976, 978, 993, 1004, 1009, 1015, 1024, 1027, 1028, 1047, 1049, 1064, 1066, 1068, 1069, 1078, 1082* , 1084, 1095, 1099, 1110* , 1120, 1121, 1127, 1128, 1129, 1132, 1135, 1159, 1161, 1166, 1177, 1183, 1192* , 1195, 1197, 1207, 1212, 1213* , 1215, 1225* , 1232, 1236* , 1237* , 1241* , 1243, 1244, 1252* , 1258, 1259, 1283, 1298, 1304, 1372, 1390* , 1430* , 1498* , 1515* , 1517* , 1544* .

print esc: \underline{63}, 86* , 176, 184* , 187, 188, 189, 190, 191, 192* , 194, 195, 196* , 197, 225, 227, 229, 231* , 233* , 234, 235, 237* , 239, 242, 247, 249, 251, 262, 263, 266* , 267, 292, 293, 294* , 323, 335, 373, 377* , 385* , 417* , 428, 469* , 486, 488* , 492, 500, 579, 691, 694, 695, 696* , 697, 699, 776, 781, 792, 856, 936, 960* , 961, 978, 984, 986, 1009, 1015, 1028, 1053, 1059, 1065, 1069, 1072, 1089, 1095, 1099, 1108* , 1115, 1120, 1129, 1132, 1135, 1143, 1157, 1166, 1179, 1189* , 1192* , 1209* , 1213* , 1220, 1223, 1231, 1241* , 1244, 1251, 1255, 1263, 1273, 1278, 1287, 1292* , 1295* , 1322, 1335* , 1346, 1355, 1356, 1381* , 1383* , 1392* , 1393* , 1398* , 1401* , 1404* , 1407* , 1410* , 1413* , 1415* , 1419* , 1421* , 1424* , 1425* , 1427* , 1432* , 1434* , 1436* , 1481* , 1493* , 1496* , 1497* , 1498* , 1504* , 1510* , 1512* , 1535* , 1539* , 1556* , 1565* , 1566* , 1595* , 1598* .

print fam and char : \underline{691}, 692, 696* . print file name: \underline{518}, 530* , 561, 1322, 1356. print font and char : \underline{176}, 183, 193. print glue: \underline{177}, 178, 185, 186* . print group: \underline{1395*} , 1396* , 1413* , 1507* , 1510* . print hex : \underline{67}, 691, 1223. print if line: 299* , \underline{1425*} , 1509* , 1510* . print int : \underline{65}, 84* , 91, 94, 103, 114, 168, 169, 170,

171, 172, 185, 188, 194, 195, 196* , 218, 219, 227, 229, 231* , 233* , 234, 235, 239, 242, 249, 251, 255, 285, 288, 299* , 313* , 336, 400, 465* , 472* , 509, 536* , 561, 579, 617, 638* , 639, 642* , 660, 663, 667, 674, 675, 678, 691, 723, 846* , 856, 933, 986, 1006, 1009, 1011, 1024, 1028, 1099, 1232, 1296* , 1309, 1311* , 1318, 1320, 1324* , 1328, 1335* , 1339, 1355, 1356, 1395* , 1413* , 1415* , 1425* , 1449* , 1555* , 1556* , 1649* , 1656* , 1658* , 1664* .

print it : 1602* , 1603* , 1607* , 1610* , 1611* , 1612* , 1613* . print length param: \underline{247}, 249, 251. print ln: \underline{57*} , 58* , 59, 61* , 62, 71* , 86* , 89, 90, 114,

182, 198, 218, 236* , 245, 296* , 306, 314* , 330, 360, 363, 401, 484, 534* , 537* , 638* , 639, 660, 663, 666, 667, 674, 675, 677, 678, 692, 986, 1265, 1280, 1309, 1311* , 1318, 1320, 1324* , 1340, 1370, 1413* , 1425* , 1449* , 1463* , 1488* , 1507* , 1509* , 1510* , 1611* , 1656* , 1658* , 1664* .

print locs : \underline{167}. print mark : \underline{176}, 196* , 1356. print meaning : \underline{296*} , 472* , 1294. print mode: \underline{211}, 218, 299* , 1049. print nl : \underline{62}, 73* , 82* , 84* , 85, 90, 168, 169, 170, 171,

172, 218, 219, 245, 255, 285, 288, 299* , 306, 311* , 313* , 314* , 323, 360, 400, 530* , 534* , 581* , 638* , 639, 641, 642* , 660, 666, 667, 674, 677, 678, 846* , 856, 857, 863* , 933, 986, 987, 992, 1006, 1011, 1121, 1294, 1296* , 1297, 1322, 1324* , 1328, 1332* , 1333* , 1335* , 1338, 1370, 1413* , 1425* , 1449* , 1507* , 1509* , 1510* , 1652* , 1655* .

print param: \underline{237*} , 239, 242. print plus : \underline{985}. print plus end : \underline{985}. print roman int : \underline{69}, 472* . print rule dimen: \underline{176}, 187. print sa num: \underline{1555*} , 1556* , 1565* , 1566* . print scaled : \underline{103}, 114, 176, 177, 178, 184* , 188,

191, 192* , 219, 251, 465* , 472* , 561, 666, 677, 697, 985, 986, 987, 1006, 1011, 1259, 1261, 1322, 1414* , 1415* , 1556* , 1585* .

print size: \underline{699}, 723, 1231. print skip param: 189, \underline{225}, 227, 229. print spec: \underline{178}, 188, 189, 190, 229, 465* , 1556* . print style: 690, \underline{694}, 1170. print subsidiary data: \underline{692}, 696* , 697. print the digs : \underline{64}, 65, 67. print totals : 218, \underline{985}, 986, 1006. print two: \underline{66}, 536* , 617. print word : \underline{114}, 1339. print write whatsit : \underline{1355}, 1356. printed node: \underline{821}, 856, 857, 858, 864* . privileged : \underline{1051}, 1054, 1130* , 1140. proc: \underline{1631*} . prompt : \underline{1618*} . prompt file name: \underline{530*} , 532* , 535* , 537* , 1328,

1374, 1615* . prompt input : \underline{71*} , 83, 87, 360, 363, 484, 530* . protected : 1503* . primitive: \underline{1503*} . protected token: \underline{289*} , 389* , 478* , 1213* , 1295* , 1505* . prune movements : \underline{615}, 619* , 629* . prune page top: \underline{968*} , 977* , 1021* . pseudo: \underline{54*} , 57* , 58* , 59, 316. pseudo close: 329* , \underline{1490*} , 1491* . pseudo files : \underline{1483*} , 1484* , 1487* , 1489* , 1490* , 1491* . pseudo input : 362* , \underline{1489*} . pseudo start : 1482* , 1485* , \underline{1486*} . pstack : \underline{388}, 390, 396, 400. : 453. : 34* , 71* . punct noad : \underline{682}, 690, 696* , 698, 728, 752, 761,

1156, 1157. push: 584, 585, \underline{586}, 590, 592, 601, 608, 616* ,

619* , 629* . push alignment : \underline{772}, 774.

push input : \underline{321}, 323, 325, 328* .

push LR: \underline{1439*} , 1442* , 1447* , 1450* , 1461* , 1470* , 1472* . push math: \underline{1136}, 1139, 1145* , 1153, 1172, 1174,

1191* . push nest : \underline{216*} , 774, 786, 787, 1025, 1083, 1091, 1099, 1117, 1119, 1136, 1167, 1200.

put : 26* , 29, 1305* . put LR: \underline{1439*} , 1446* . put rule: 585, \underline{586}, 633* . put sa ptr : \underline{1552*} , 1564* . put1 : \underline{585}. put2 : \underline{585}. put3 : \underline{585}. put4 : \underline{585}. q: \underline{123}, \underline{125}, \underline{130}, \underline{131}, \underline{144}, \underline{151}, \underline{152}, \underline{153}, \underline{167}, \underline{172}, \underline{202}, \underline{204}, \underline{218}, \underline{275*} , \underline{292}, \underline{315}, \underline{336}, \underline{366*} , \underline{389*} , \underline{407}, \underline{413*} , \underline{450}, \underline{461*} , \underline{463}, \underline{464*} , \underline{465*} , \underline{473}, \underline{482*} , \underline{497}, \underline{498*} , \underline{607}, \underline{649*} , \underline{705}, \underline{706}, \underline{709}, \underline{712}, \underline{720}, \underline{726}, \underline{734}, \underline{735}, \underline{736}, \underline{737}, \underline{738}, \underline{743}, \underline{749}, \underline{752}, \underline{756}, \underline{762*} , \underline{791*} , \underline{800}, \underline{826}, \underline{830}, \underline{862}, \underline{877*} , \underline{901}, \underline{906}, \underline{934*} , \underline{948}, \underline{953}, \underline{957}, \underline{959}, \underline{960*} , \underline{968*} , \underline{970}, \underline{994}, \underline{1012*} , \underline{1043}, \underline{1068}, \underline{1079*} , \underline{1093}, \underline{1105*} , \underline{1119}, \underline{1123}, \underline{1138*} , \underline{1184}, \underline{1191*} , \underline{1198}, \underline{1211*} , \underline{1236*} , \underline{1302}, \underline{1303}, \underline{1370}, \underline{1417*} , \underline{1433*} , \underline{1456*} , \underline{1471*} , \underline{1477*} , \underline{1486*} , \underline{1490*} , \underline{1515*} , \underline{1548*} , \underline{1552*} , \underline{1554*} , \underline{1555*} , \underline{1558*} , \underline{1570*} . qi : \underline{112*} , 545, 549, 564* , 570, 573, 576, 582, 620* , 753, 907, 908, 911, 913, 923, 958* , 959, 981, 1008, 1009, 1034, 1035, 1038, 1039, 1040, 1100, 1151, 1155, 1160, 1165, 1309, 1325* , 1405* , 1487* , 1502* , 1589* , 1591* .

qo: \underline{112*} , 159, 174, 176, 185, 188, 554, 570, 576, 602, 620* , 691, 708, 722, 723, 741, 752, 755, 896* , 897* , 898* , 903, 909, 923, 945, 981, 986, 1008, 1018, 1021* , 1039, 1310, 1324* , 1325* , 1395* , 1591* . qqqq : 110* , \underline{113*} , 114, 550, 554, 569, 573, 574,

683, 713, 741, 752, 909, 1039, 1181, 1305* , 1306* , 1487* , 1489* .

quad : 547, \underline{558}, 1467* . quad code: \underline{547}, 558. qual : 529* . qual argument : \underline{1621*} . qual name: \underline{1620*} . quarterword : 110* , \underline{113*} , 144, 253, 264* , 271, 276,

277* , 279* , 281* , 298* , 300, 323, 592, 681, 706, 709, 711, 712, 724, 738, 749, 877* , 921, 943, 944, 947, 960* , 1061, 1079* , 1105* , 1390* , 1413* , 1510* , 1548* , 1568* , 1570* .

quit : 1639* , 1644* . quit status : \underline{1640*} , 1644* , 1645* . quitting : \underline{1636*} , 1638* , 1641* , 1645* , 1666* . quotient : 1529* , \underline{1530*} . qw : \underline{560}, 564* , 570, 573, 576. r: \underline{108}, \underline{123}, \underline{125}, \underline{131}, \underline{204}, \underline{218}, \underline{366*} , \underline{389*} , \underline{465*} , \underline{482*} ,

\underline{498*} , \underline{595*} , \underline{649*} , \underline{668}, \underline{706}, \underline{720}, \underline{726}, \underline{752}, \underline{791*} , \underline{800}, \underline{829*} , \underline{862}, \underline{877*} , \underline{901}, \underline{953}, \underline{966*} , \underline{968*} , \underline{970}, \underline{994}, \underline{1012*} , \underline{1123}, \underline{1160}, \underline{1198}, \underline{1236*} , \underline{1370}, \underline{1466*} , \underline{1477*} , \underline{1486*} , \underline{1489*} , \underline{1515*} , \underline{1532*} .

R code: \underline{147*} , 192* , 1450* , 1464* . r count : \underline{912}, 914, 918. r hyf : 891* , \underline{892}, 894, 899, 902, 923, 1362, 1363* . r type: \underline{726}, 727* , 728, 729, 760* , 766, 767. RAB : 33* , 34* , \underline{1627*} . RAB ptr : \underline{1626*} , 1627* , 1628* . radical : \underline{208*} , 265* , 266* , 1046, 1162. primitive: \underline{265*} . radical noad : \underline{683}, 690, 696* , 698, 733, 761, 1163. radical noad size: \underline{683}, 698, 761, 1163. radix : 366* , \underline{438}, 439, 440, 444, 445, 448. radix backup: \underline{366*} . primitive: \underline{1071*} . Ramshaw, Lyle Harold: 539. rbrace ptr : \underline{389*} , 399, 400. read : 27* , 31* , 52* , 53* , 1338, 1339. primitive: \underline{265*} . read file: \underline{480}, 485, 486, 1275* . read font info: \underline{560}, 564* , 1040, 1257. primitive: \underline{1492*} . read ln: 31* , 52* . read open: \underline{480}, 481, 483* , 485, 486, 501* , 1275* . read sixteen: \underline{564*} , 565, 568. read to cs : \underline{209*} , 265* , 266* , 1210, 1225* , 1492* . read toks : 303* , \underline{482*} , 1225* . ready already : 1331* , 1332* . real : 3, \underline{109*} , 110* , 182, 186* , 1123, 1125, 1433* . real addition: 1125. real division: 658, 664, 673, 676, 810, 811,

1123, 1125. real multiplication: 114, 186* , 809, 1125, 1433* . rebox : \underline{715}, 744, 750. reconstitute: 905, \underline{906}, 913, 915, 916, 917, 1032. Record Access Block: 34* . Record Management Services: 11* , 27* , 34* . recursion: 76, 78, 173, 180, 198, 202, 203, 366* ,

402, 407, 498* , 527, 592, 618, 692, 719, 720, 725, 754, 949, 957, 959, 1333* , 1375, 1416* .

ref count : \underline{389*} , 390, 401.

reference counts: 150, 200, 201, 203, 275* , 291,

307* , 1553* , 1554* . reflected : \underline{616*} , 1455* , 1471* . register : \underline{209*} , 411* , 412* , 413* , 1210, 1224* , 1235,

1236* , 1237* , 1556* , 1565* , 1567* . rel noad : \underline{682}, 690, 696* , 698, 728, 761, 767,

1156, 1157. rel penalty : \underline{236*} , 682, 761.

primitive: \underline{238}.
rel penalty code: \underline{236*} , 237* , 238.

relax : \underline{207}, 265* , 266* , 358, 372, 404, 478* , 506,

1045, 1224* , 1517* . primitive: \underline{265*} .

release: \underline{1635*} , 1643* .
rem byte: \underline{545}, 554, 557, 570, 708, 713, 740,

749, 753, 911, 1040. remainder : \underline{104}, 106, 107, 457, 458, \underline{543}, 544,

545, 716, 717. remove end M : 424* , 1080* , 1105* , \underline{1444*} .

remove item: \underline{208*} , 1104, 1107, 1108* .
rep: \underline{546}.

replace count : \underline{145}, 175* , 195, 840, 858, 869, 882,

883, 918, 1081, 1105* , 1120. report illegal case: 1045, \underline{1050}, 1051, 1243, 1377. res : \underline{1624*} . reset : 26* , 27* , 33* , 537* , 1602* , 1604* , 1614* , 1647* , 1648* . restart : \underline{15*} , 125, 126, 341, 346, 357, 359, 360,

362* , 380, 517* , 752, 753, 782, 785* , 789, 1151, 1215, 1515* , 1516* , 1521* . restore old value: \underline{268*} , 276, 282* .

restore sa: \underline{268*} , 282* , 1570* .
restore trace: 277* , 283, \underline{284*} , 1556* .
restore zero: \underline{268*} , 276, 278* .
result : \underline{45}, \underline{46}.
resume after display : 800, 1199* , \underline{1200}, 1206* .

reswitch: \underline{15*} , 341, 343, 352, 366* , 463, 619* , 620* , 649* , 651* , 652, 726, 728, 934* , 935, 1029, 1030, 1036, 1045, 1138* , 1147* , 1151, 1455* , 1456* , 1457* , 1460* , 1498* .

ret len addr : 1629* , \underline{1630*} , 1659* , 1661* .

retlen: \underline{1618*} .

return: 15* , \underline{16}. return length: \underline{1629*} . returns : \underline{1618*} . reverse: 1454* , 1455* , \underline{1456*} . reversed : \underline{616*} , 619* , 1454* . rewrite: 26* , 27* , 33* , 73* , 1614* , 1655* , 1664* . rh: 110* , \underline{113*} , 114, 118, 213* , 219, 221, 234, 256,

268* , 685, 921, 958* , 1550* . primitive: \underline{1188}. right brace: \underline{207}, 289* , 294* , 298* , 347, 357, 389* , 442,

474, 477, 785* , 935, 961, 1067, 1252* , 1417* . right brace limit : \underline{289*} , 325, 326* , 392, 399, 400,

474, 477, 1417* . right brace token: \underline{289*} , 339, 1065, 1127, 1226* ,

1371. right delimiter : \underline{683}, 697, 748, 1181, 1182. right hyphen min: \underline{236*} , 1091, 1200, 1376, 1377. primitive: \underline{238}. right hyphen min code: \underline{236*} , 237* , 238. right noad : \underline{687*} , 690, 696* , 698, 725, 727* , 728, 760* ,

761, 762* , 1184, 1188, 1191* . right ptr : \underline{605}, 606, 607, 615. right skip: \underline{224}, 827* , 880* , 881* , 1473* , 1576* . primitive: \underline{226}. right skip code: \underline{224}, 225, 226, 881* , 886, 1473* ,

1479* . right to left : \underline{616*} , 619* , 623* , 626* , 628* , 632* , 633* ,

637* , 1467* . right1 : 585, \underline{586}, 607, 610, 616* . right2 : 585, 610. right3 : 585, 610. right4 : 585, 610. rlink : \underline{124}, 125, 126, 127, 129, 130, 131, 132, 145,

149, 164, 169, 772, 819* , 821, 1311* , 1312* . RMS: 34* . : 11* , 27* . primitive: \underline{468}. roman numeral code: \underline{468}, 469* , 471* , 472* . round : 114, 186* , 809, 1125, 1433* . round decimals : \underline{102}, 103, 452. rover : \underline{124}, 125, 126, 127, 128, 129, 130, 131,

132, 164, 169, 1311* , 1312* . rt hit : 906, \underline{907}, 910, 911, 1033, 1035, 1040. rule dp: \underline{592}, 622* , 624, 626* , 631, 633* , 635. rule ht : \underline{592}, 622* , 624, 626* , 631, 633* , 634* , 635, 636. rule node: \underline{138}, 139, 148, 175* , 183, 202, 206, 622* ,

626* , 631, 635, 651* , 653, 669, 670, 730, 761, 805, 841, 842, 866* , 870, 871, 968* , 973, 1000, 1074, 1087, 1121, 1147* , 1458* , 1459* , 1466* .

rule node size: \underline{138}, 139, 202, 206, 1466* . rule save: \underline{800}, 804. rule wd : \underline{592}, 622* , 624, 625* , 626* , 627, 631, 633* ,

635, 1455* , 1458* , 1459* , 1461* , 1462* . rules aligning with characters: 589. runaway : 120, \underline{306}, 338, 396, 486. : 306. s: \underline{45}, \underline{46}, \underline{56*} , \underline{58*} , \underline{59}, \underline{60}, \underline{62}, \underline{63}, \underline{93}, \underline{94}, \underline{95}, \underline{103},

\underline{108}, \underline{125}, \underline{130}, \underline{147*} , \underline{177}, \underline{178}, \underline{264*} , \underline{284*} , \underline{389*} , \underline{407}, \underline{473}, \underline{482*} , \underline{529*} , \underline{530*} , \underline{560}, \underline{638*} , \underline{645}, \underline{649*} , \underline{668}, \underline{688}, \underline{699}, \underline{706}, \underline{720}, \underline{726}, \underline{738}, \underline{791*} , \underline{800}, \underline{830}, \underline{862}, \underline{877*} , \underline{901}, \underline{934*} , \underline{966*} , \underline{968*} , \underline{987}, \underline{1012*} , \underline{1060}, \underline{1061}, \underline{1123}, \underline{1138*} , \underline{1198}, \underline{1236*} , \underline{1257}, \underline{1279}, \underline{1349}, \underline{1355}, \underline{1413*} , \underline{1417*} , \underline{1433*} , \underline{1452*} , \underline{1477*} , \underline{1486*} , \underline{1515*} , \underline{1554*} , \underline{1556*} , \underline{1629*} .

sa bot mark : \underline{1558*} , 1561* , 1563* . sa chain: 268* , 282* , \underline{1568*} , 1569* , 1570* , 1574* . sa def : \underline{1572*} , 1573* . sa def box : 1077* , \underline{1572*} . sa define: 1226* , 1227* , 1236* , \underline{1572*} . sa destroy : \underline{1571*} , 1572* , 1573* , 1574* . sa dim: \underline{1553*} , 1556* . sa first mark : \underline{1558*} , 1561* , 1562* , 1563* . sa index : \underline{1548*} , 1553* , 1554* , 1555* , 1570* , 1571* , 1574* . sa int : 427* , 1237* , \underline{1553*} , 1554* , 1556* , 1570* , 1572* ,

1573* , 1574* . sa lev : \underline{1553*} , 1570* , 1572* , 1573* , 1574* . sa level : 268* , 282* , \underline{1568*} , 1569* , 1570* . sa loc: \underline{1570*} , 1574* . sa mark : 977* , 1012* , 1335* , \underline{1549*} , 1550* . sa null : 1548* , \underline{1549*} , 1550* , 1553* . sa num: \underline{1553*} , 1555* . sa ptr : 415* , 427* , 1227* , 1237* , \underline{1553*} , 1554* , 1556* ,

1570* , 1571* , 1572* , 1573* , 1574* . sa ref : \underline{1553*} , 1554* , 1570* . sa restore: 282* , \underline{1574*} . sa root : 1311* , 1312* , \underline{1549*} , 1551* , 1552* , 1554* . sa save: \underline{1570*} , 1572* . sa split bot mark : \underline{1558*} , 1559* , 1560* . sa split first mark : \underline{1558*} , 1559* , 1560* . sa top mark : \underline{1558*} , 1561* , 1562* . sa type: 427* , 1237* , \underline{1553*} , 1556* , 1565* . sa used : \underline{1548*} , 1552* , 1553* , 1554* , 1558* . sa w def : \underline{1572*} , 1573* . sa word define: 1236* , \underline{1572*} . save cond ptr : \underline{498*} , 500, 509. save cs ptr : \underline{774}, 777. save cur val : \underline{450}, 455. save for after : \underline{280}, 1271. save h: \underline{619*} , 623* , 627, 628* , \underline{629*} , 632* , 637* , 1454* ,

1455* . save index : \underline{268*} , 274* , 276, 280, 282* , 1413* , 1507* ,

1510* , 1570* . save it : 73* , 1602* , 1603* , 1655* , 1656* , 1658* , 1664* . save level : \underline{268*} , 269, 274* , 276, 280, 282* , 1413* ,

1510* , 1570* . save link : \underline{830}, 857. save loc: \underline{619*} , \underline{629*} . save pointer : \underline{1412*} , 1413* , 1506* . save ptr : 268* , \underline{271}, 272, 273* , 274* , 276, 280, 282* ,

283, 285, 645, 804, 1086, 1099, 1100, 1117, 1120, 1142, 1153, 1168, 1172, 1174, 1186, 1194* , 1304, 1413* , 1507* , 1510* , 1570* .

save scanner status : \underline{366*} , 369, \underline{389*} , \underline{470*} , 471* ,

\underline{494*} , \underline{498*} , 507, 1499* . save size: \underline{11*} , 111, 271, 273* , 1334, 1412* . save split top skip: \underline{1012*} , 1014* . save stack : 203, 268* , 270, \underline{271}, 273* , 274* , 275* , 276,

277* , 281* , 282* , 283, 285, 300, 372, 489, 645, 768, 1062, 1071* , 1131, 1140, 1150, 1153, 1339, 1412* .

save style: \underline{720}, \underline{726}, 754. save type: \underline{268*} , 274* , 276, 280, 282* , 1570* . save v : \underline{619*} , 623* , 628* , \underline{629*} , 632* , 636, 637* . save vbadness : \underline{1012*} , 1017. save vfuzz : \underline{1012*} , 1017. save warning index : \underline{389*} . saved : \underline{274*} , 645, 804, 1083, 1086, 1099, 1100, 1117,

1119, 1142, 1153, 1168, 1172, 1174, 1186, 1194* , 1395* , 1396* , 1413* , 1414* , 1415* .

saving hyph codes : \underline{236*} , 960* . primitive: \underline{1391*} . saving hyph codes code: \underline{236*} , 1391* , 1393* . saving vdiscards : \underline{236*} , 977* , 999* , 1592* . primitive: \underline{1391*} . saving vdiscards code: \underline{236*} , 1391* , 1393* . sc: 110* , \underline{113*} , 114, 135, 150, 159, 164, 213* , 219,

247, 250, 251, 413* , 420* , 425, 550, 552, 554, 557, 558, 571, 573, 575* , 580, 700, 701, 775, 822, 823, 832, 843, 844, 848, 850, 860, 861, 889, 1042, 1149, 1206* , 1247* , 1248* , 1253, 1408* , 1553* , 1575* .

scaled : \underline{101}, 102, 103, 104, 105, 106, 107, 108, 110* , 113* , 147* , 150, 156, 176, 177, 447, 448, 450, 453, 548, 549, 560, 584, 592, 607, 616* , 619* , 629* , 646, 649* , 668, 679, 704, 705, 706, 712, 715, 716, 717, 719, 726, 735, 736, 737, 738, 743, 749, 756, 762* , 791* , 800, 823, 830, 839, 847, 877* , 906, 970, 971, 977* , 980, 982* , 994, 1012* , 1068, 1086, 1123, 1138* , 1198, 1257, 1433* , 1452* , 1477* , 1575* , 1577* .

: 1258. scaled base: \underline{247}, 249, 251, 1224* , 1237* . scan box : 1073, \underline{1084}, 1241* . scan char num: 414, \underline{434}, 935, 1030, 1038, 1123,

1124, 1151, 1154, 1224* , 1232, 1405* , 1502* . scan delimiter : \underline{1160}, 1163, 1182, 1183, 1191* , 1192* . scan dimen: 410, 440, 447, \underline{448}, 461* , 462, 1061. scan eight bit int : \underline{433}, 1099. scan expr : 1513* , 1514* , \underline{1515*} . scan fifteen bit int : \underline{436}, 1151, 1154, 1165, 1224* . scan file name: 265* , 334, \underline{526}, 527, 537* , 1257,

1275* , 1351. scan font ident : 415* , 426, 471* , \underline{577}, 578, 1234,

1253, 1405* , 1502* . scan four bit int : \underline{435}, 501* , 577, 1234, 1275* , 1350. scan general text : 1416* , \underline{1417*} , 1422* , 1486* . scan glue: 410, \underline{461*} , 782, 1060, 1228, 1238* , 1520* . scan int : 409* , 410, 432, 433, 434, 435, 436, 437,

438, \underline{440}, 447, 448, 461* , 471* , 503, 504, 509, 578, 1103, 1225* , 1228, 1232, 1238* , 1240* , 1243, 1244, 1246* , 1248* , 1253, 1258, 1350, 1377, 1408* , 1518* , 1544* , 1599* .

scan keyword : 162, \underline{407}, 453, 454, 455, 456, 458,

462, 463, 645, 1082* , 1225* , 1236* , 1258. scan left brace: \underline{403}, 473, 645, 785* , 934* , 960* , 1025,

1099, 1117, 1119, 1153, 1172, 1174, 1417* . scan math: 1150, \underline{1151}, 1158, 1163, 1165, 1176. scan mu glue: 1518* , 1519* , \underline{1520*} , 1540* . scan normal dimen: \underline{448}, 463, 503, 645, 1073,

1082* , 1182, 1183, 1228, 1238* , 1243, 1245, 1247* , 1248* , 1253, 1259, 1518* .

scan normal glue: 1518* , 1519* , \underline{1520*} , 1536* , 1537* ,

1541* . scan optional equals : \underline{405}, 782, 1224* , 1226* , 1228,

1232, 1234, 1236* , 1241* , 1243, 1244, 1245, 1246* , 1247* , 1248* , 1253, 1257, 1275* , 1351.

scan register num: 386* , 415* , 420* , 427* , 505* , 1079* , 1082* , 1101* , 1110* , 1224* , 1226* , 1227* , 1237* , 1241* , 1247* , 1296* , 1543* , \underline{1544*} .

scan rule spec: \underline{463}, 1056, 1084. scan something internal : 409* , 410, \underline{413*} , 432, 440,

449, 451, 455, 461* , 465* , 1513* . scan spec: \underline{645}, 768, 774, 1071* , 1083, 1167. scan tokens : 1480* . primitive: \underline{1480*} . scan toks : 291, 464* , \underline{473}, 960* , 1101* , 1218* , 1226* ,

1279, 1288, 1352, 1354, 1371, 1416* . scan twenty seven bit int : \underline{437}, 1151, 1154, 1160. scanned result : \underline{413*} , 414, 415* , 418, 422, 425,

426, 428. scanned result end : \underline{413*} . scanner status : \underline{305}, 306, 331* , 336, 339, 366* , 369,

389* , 391, 470* , 471* , 473, 482* , 494* , 498* , 507, 777, 789, 1417* , 1499* .

primitive: \underline{1230}. script mlist : \underline{689}, 695, 698, 731, 1174. primitive: \underline{1230}. script script mlist : \underline{689}, 695, 698, 731, 1174. script script size: \underline{699}, 756, 1195, 1230. script script style: \underline{688}, 694, 731, 1169. primitive: \underline{1169}. script size: \underline{699}, 756, 1195, 1230. script space: \underline{247}, 757, 758, 759. primitive: \underline{248}. script space code: \underline{247}, 248. script style: \underline{688}, 694, 702, 703, 731, 756, 766,

1169. primitive: \underline{1169}. scripts allowed : \underline{687*} , 1176. scroll mode: 71* , \underline{73*} , 84* , 86* , 93, 530* , 1262,

1263, 1281. primitive: \underline{1262}. search mem: 165, \underline{172}, 255, 1339. second indent : \underline{847}, 848, 849, 889. second pass : \underline{828}, 863* , 866* . second width: \underline{847}, 848, 849, 850, 889. Sedgewick, Robert: 2* . : 1335* . selector : 34* , \underline{54*} , 55, 57* , 58* , 59, 62, 71* , 75, 86* ,

90, 92, 98, 245, 311* , 312, 316, 360, 465* , 470* , 534* , 535* , 617, 638* , 1257, 1265, 1279, 1298, 1328, 1332* , 1335* , 1368, 1370, 1422* , 1486* , 1648* , 1651* , 1652* , 1655* , 1656* , 1658* .

semi simple group: \underline{269}, 1063, 1065, 1068, 1069,

1395* , 1413* . serial : \underline{821}, 845* , 846* , 856. set aux : \underline{209*} , 413* , 416* , 417* , 418, 1210, 1242. set box : \underline{209*} , 265* , 266* , 1210, 1241* . primitive: \underline{265*} . set box allowed : \underline{76}, 77, 1241* , 1270. set box dimen: \underline{209*} , 413* , 416* , 417* , 1210, 1242. set break width to background : \underline{837}. set char 0 : 585, \underline{586}, 620* . set conversion: \underline{458}. set conversion end : \underline{458}. set cur lang : \underline{934*} , 960* , 1091, 1200. set cur r : \underline{908}, 910, 911. set font : \underline{209*} , 413* , 553, 577, 1210, 1217, 1257,

1261. set glue ratio one: \underline{109*} , 664, 676, 810, 811. set glue ratio zero: \underline{109*} , 136, 657, 658, 664, 672,

673, 676, 810, 811. set height zero: \underline{970}. set hyph index : 891* , 934* , 1363* , \underline{1591*} . set interaction: \underline{209*} , 1210, 1262, 1263, 1264. primitive: \underline{1344}. set language code: \underline{1344}, 1346, 1348* . set lc code: 896* , 897* , 898* , 937* , \underline{1591*} . set math char : 1154, \underline{1155}. set page dimen: \underline{209*} , 413* , 982* , 983, 984, 1210,

1242. set page int : \underline{209*} , 413* , 416* , 417* , 1210, 1242, 1426* .

set page so far zero: \underline{987}.
set prev graf : \underline{209*} , 265* , 266* , 413* , 1210, 1242.
set rule: 583, 585, \underline{586}, 624.
set sa box : \underline{1554*} .
set shape: \underline{209*} , 233* , 265* , 266* , 413* , 1210, 1248* ,

1597* . set trick count : \underline{316}, 317* , 318* , 320.

set1 : 585, \underline{586}, 620* .
set2 : \underline{585}.
set3 : \underline{585}.
set4 : \underline{585}.
sf code: \underline{230*} , 232* , 1034.
primitive: \underline{1230}.
sf code base: \underline{230*} , 235, 1230, 1231, 1233.
shape ref : \underline{210*} , 232* , 275* , 1070* , 1248* .

shift amount : \underline{135}, 136, 159, 184* , 623* , 628* , 632* , 637* , 649* , 653, 668, 670, 681, 706, 720, 737, 738, 749, 750, 756, 757, 759, 799, 806, 807* , 808* , 889, 1076, 1081, 1125, 1467* , 1473* , 1477* , 1478* , 1479* .

shift case: 1285, \underline{1288}.

shift down: \underline{743}, 744, 745, 746, 747, \underline{749}, 751,

\underline{756}, 757, 759.

shift up: \underline{743}, 744, 745, 746, 747, \underline{749}, 751,

\underline{756}, 758, 759. ship out : 211, 592, \underline{638*} , 644, 807* , 808* , 1023* , 1075* ,

1379* , 1433* , 1434* , 1439* . primitive: \underline{1071*} . ship out flag : \underline{1071*} , 1075* , 1415* . short display : 173, \underline{174}, 175* , 193, 663, 857, 1339. short real : 109* , 110* . shortcut : 447, \underline{448}. shortfall : \underline{830}, 851* , 852* , 853, 1575* , 1580* , 1582* ,

1583* . shorthand def : \underline{209*} , 1210, 1222, 1223, 1224* .

primitive: \underline{1291}.
show activities : \underline{218}, 1293* .

show box : 180, 182, \underline{198}, 218, 219, 236* , 638* , 641, 663, 675, 986, 992, 1121, 1296* , 1339.

primitive: \underline{1291}.

show box breadth: \underline{236*} , 1339.
primitive: \underline{238}.
show box breadth code: \underline{236*} , 237* , 238.
show box code: \underline{1291}, 1292* , 1293* .
show box depth: \underline{236*} , 1339.
primitive: \underline{238}.
show box depth code: \underline{236*} , 237* , 238.
show code: \underline{1291}, 1293* .

show context : 54* , 78, 82* , 84* , 88, 310, \underline{311*} , 318* , 530* , 535* , 537* , 1507* , 1509* , 1510* , 1610* . show cur cmd chr : \underline{299*} , 367* , 494* , 498* , 510* ,

1031, 1211* . show eqtb: \underline{252}, 284* , 1556* . show groups : \underline{1409*} , 1410* , 1411* . primitive: \underline{1409*} . show ifs : \underline{1423*} , 1424* , 1425* . primitive: \underline{1423*} . show info: 692, \underline{693}. show lists : \underline{1291}, 1292* , 1293* . primitive: \underline{1291}. show node list : 173, 176, 180, 181, \underline{182}, 195, 198,

233* , 690, 692, 693, 695, 1339, 1556* . show sa: \underline{1556*} , 1572* , 1573* , 1574* . show save groups : 1335* , 1411* , \underline{1413*} . primitive: \underline{1291}. show the code: \underline{1291}, 1292* . show token list : 176, 223, 233* , \underline{292}, 295, 306, 319* ,

320, 400, 1339, 1368, 1556* . show tokens : \underline{1418*} , 1419* , 1420* . primitive: \underline{1418*} . show whatever : 1290, \underline{1293*} . shown mode: \underline{213*} , 215* , 299* . shrink : \underline{150}, 151, 164, 178, 431, 462, 656, 671, 716,

809, 825, 827* , 838, 868, 976, 1004, 1009, 1042, 1044, 1148, 1229, 1239* , 1240* , 1433* , 1479* , 1523* , 1524* , 1527* , 1528* , 1529* , 1531* , 1537* .

shrink order : \underline{150}, 164, 178, 462, 656, 671, 716, 809, 825, 826, 976, 1004, 1009, 1148, 1239* , 1433* , 1479* , 1524* , 1527* , 1536* .

shrinking : \underline{135}, 186* , 619* , 629* , 664, 676, 809, 810,

811, 1148, 1433* , 1456* . si : \underline{38}, 42, 69, 517* , 537* , 951, 964, 1310, 1487* ,

1589* , 1662* . Sign: 186* , \underline{1623*} . signal args : \underline{1618*} . signed halfword : 241* , 517* , \underline{1623*} , 1624* , 1629* , 1651* . simple group: \underline{269}, 1063, 1068, 1395* , 1413* . single: 109* . Single-character primitives: \underline{267}.

: \underline{1114}.

: \underline{265*} .

␣ : \underline{265*} . single base: \underline{222}, 262, 263, 264* , 354, 374, 442,

1257, 1289, 1501* . sixteen bits : 37* , 1618* , 1620* , 1621* , \underline{1623*} , 1630* ,

1632* , 1633* , 1634* , 1640* . size input line: \underline{11*} , 30* . skew char : 426, \underline{549}, 552, 576, 741, 1253, 1322,

1323. primitive: \underline{1254}. skip: \underline{224}, 427* , 1009. primitive: \underline{411*} . skip base: \underline{224}, 227, 229, 1224* , 1237* . skip blanks : \underline{303*} , 344, 345, 347, 349, 354. skip byte: \underline{545}, 557, 741, 752, 753, 909, 1039.

skip code: \underline{1058}, 1059, 1060.
primitive: \underline{1222}.
skip def code: \underline{1222}, 1223, 1224* .
skip line: 336, \underline{493}, 494* .
skipping : \underline{305}, 306, 336, 494* .
slant : 547, \underline{558}, 575* , 1123, 1125.
slant code: \underline{547}, 558.
slow print : \underline{60}, 61* , 63, 84* , 518, 536* , 537* , 581* , 642* ,

1261, 1280, 1283, 1328, 1332* , 1333* , 1339. small char : \underline{683}, 691, 697, 706, 1160.

small fam: \underline{683}, 691, 697, 706, 1160.

small node size: \underline{141*} , 144, 145, 147* , 152, 153, 156, 158, 202, 206, 655, 721, 903, 910, 914, 1037, 1100, 1101* , 1357, 1358, 1376, 1377, 1445* , 1455* , 1458* , 1459* , 1460* , 1462* , 1466* , 1471* . small number : \underline{101}, 102, 147* , 152, 154, 264* , 366* , 389* , 413* , 438, 440, 450, 461* , 465* , 470* , 482* , 489, 494* , 497, 498* , 523, 607, 649* , 668, 688, 706, 719, 720, 726, 756, 762* , 829* , 892, 893, 905, 906, 921, 934* , 944, 960* , 970, 987, 1060, 1075* , 1086, 1091, 1176, 1181, 1191* , 1198, 1211* , 1236* , 1246* , 1247* , 1257, 1293* , 1325* , 1335* , 1349, 1350, 1370, 1373, 1439* , 1452* , 1515* , 1548* , 1552* , 1554* , 1556* , 1558* , 1575* .

sngl : 109* .

so: \underline{38}, 45, 56* , 59, 60, 69, 70, 264* , 407, 464* , 517* , 519, 603, 617, 766, 931, 953, 955, 956, 959, 963, 1309, 1368, 1487* , 1588* , 1633* , 1659* .

: 524.

sort avail : \underline{131}, 1311* .

sp: 104, 587. : 458. space: 547, \underline{558}, 752, 755, 1042. space code: \underline{547}, 558, 578, 1042. space factor : 212* , \underline{213*} , 418, 786, 787, 799, 1030,

1034, 1043, 1044, 1056, 1076, 1083, 1091, 1093, 1117, 1119, 1123, 1196, 1200, 1242, 1243.

primitive: \underline{416*} .

space shrink : 547, \underline{558}, 1042.
space shrink code: \underline{547}, 558, 578.
space skip: \underline{224}, 1041, 1043.
primitive: \underline{226}.
space skip code: \underline{224}, 225, 226, 1041.
space stretch: 547, \underline{558}, 1042.
space stretch code: \underline{547}, 558.
space token: \underline{289*} , 393, 464* , 1215, 1494* .

spacer : \underline{207}, 208* , 232* , 289* , 291, 294* , 298* , 303* , 337, 345, 347, 348, 349, 354, 404, 406, 407, 443, 444, 452, 464* , 783, 785* , 791* , 935, 961, 1030, 1045, 1221. primitive: \underline{780}.

span code: \underline{780}, 781, 782, 789, 791* .

span count : 136, \underline{159}, 185, 796, 801, 808* . span node size: \underline{797}, 798, 803. spec code: \underline{645}. primitive: \underline{1344}. special node: \underline{1341}, 1344, 1346, 1348* , 1354, 1356,

1357, 1358, 1373. special out : \underline{1368}, 1373. : 1011. split bot mark : \underline{382*} , 383, 977* , 979* , 1542* , 1559* ,

1560* . primitive: \underline{384}. split bot mark code: \underline{382*} , 384, 385* , 1335* , 1542* ,

1564* . primitive: \underline{1542*} . split disc: 968* , 977* , \underline{1592*} , 1593* . primitive: \underline{1594*} . split first mark : \underline{382*} , 383, 977* , 979* , 1542* , 1560* . primitive: \underline{384}. split first mark code: \underline{382*} , 384, 385* , 1542* . primitive: \underline{1542*} . split fist mark : 1559* . split max depth: 140, \underline{247}, 977* , 1068, 1100. primitive: \underline{248}. split max depth code: \underline{247}, 248. split top ptr : \underline{140}, 188, 202, 206, 1021* , 1022, 1100. split top skip: 140, \underline{224}, 968* , 977* , 1012* , 1014* ,

1021* , 1100. primitive: \underline{226}. split top skip code: \underline{224}, 225, 226, 969. split up: \underline{981}, 986, 1008, 1010, 1020, 1021* . spotless : \underline{76}, 77, 245, 1332* , 1335* , 1507* , 1509* ,

1510* , 1600* . : 645. sprint cs : 223, \underline{263}, 338, 395, 396, 398, 472* ,

479, 484, 561, 1294. square roots: 737. ss code: \underline{1058}, 1059, 1060. ss glue: \underline{162}, 164, 715, 1060. stack conventions: 300. stack into box : \underline{711}, 713. stack item: \underline{1650*} , \underline{1651*} , 1655* , 1656* , 1658* , 1662* ,

1664* . stack size: \underline{11*} , 301, 310, 321, 1334. start : 300, \underline{302}, 303* , 307* , 318* , 319* , 323, 324,

325, 326* , 328* , 329* , 331* , 360, 362* , 363, 369, 483* , 538, 1488* , 1612* .

start cs : \underline{341}, 354, 355. start eq no: 1140, \underline{1142}. start field : \underline{300}, 302, 1655* , 1656* , 1658* , 1664* . start font error message: \underline{561}, 567. start here: 5, \underline{1332*} . start input : 366* , 376, 378* , \underline{537*} , 1337* .

start of TEX : \underline{6}, 1332* .
start par : \underline{208*} , 1088, 1089, 1090, 1092.
start qual : \underline{1636*} , 1638* , 1655* , 1666* .
stat: \underline{7*} , \underline{117}, \underline{120}, \underline{121}, \underline{122}, \underline{123}, \underline{125}, \underline{130}, \underline{252},

\underline{260}, \underline{274*} , \underline{277*} , \underline{282*} , \underline{283}, \underline{284*} , \underline{639}, \underline{829*} , \underline{845*} , \underline{855*} , \underline{863*} , \underline{987}, \underline{1005}, \underline{1010}, \underline{1333*} , \underline{1396*} , \underline{1556*} , \underline{1572*} , \underline{1573*} , \underline{1574*} .

state: 87, 300, \underline{302}, 303* , 307* , 311* , 312, 323, 325,

328* , 330, 331* , 337, 341, 343, 344, 346, 347, 349, 352, 353, 354, 390, 483* , 537* , 1335* .

state field : \underline{300}, 302, 1508* . status : 27* , 31* , 537* , 575* , \underline{1640*} . stomach: 402. stop: \underline{207}, 1045, 1046, 1052, 1053, 1054, 1094. stop flag : \underline{545}, 557, 741, 752, 753, 909, 1039. store background : \underline{864*} . store break width: \underline{843}. store fmt file: \underline{1302}, 1335* . store four quarters : \underline{564*} , 568, 569, 573, 574. store new token: \underline{371}, 372, 393, 397, 399, 407,

464* , 466, 473, 474, 476, 477, 482* , 483* , 1417* , 1494* , 1500* .

store scaled : \underline{571}, 573, 575* .

str allocate: \underline{1632*} , 1633* , 1648* .
str eq buf : \underline{45}, 259.
str eq str : \underline{46}, 1260.

str number : \underline{38}, 39, 43, 45, 46, 47* , 62, 63, 79, 93, 94, 95, 177, 178, 264* , 284* , 407, 512, 513* , 519, 525* , 527, 529* , 530* , 532* , 549, 560, 926, 929, 934* , 1257, 1279, 1299, 1355, 1413* , 1486* , 1547* , 1556* , 1616* , 1633* , 1636* , 1640* , 1657* . str pool : 38, \underline{39}, 42, 43, 45, 46, 47* , 56* , 59, 60, 69, 70, 256, 260, 264* , 303* , 407, 464* , 517* , 519, 537* , 602, 603, 617, 638* , 764, 766, 929, 931, 934* , 941, 1309, 1310, 1334, 1368, 1486* , 1487* , 1633* , 1659* , 1662* .

str ptr : 38, \underline{39}, 41, 43, 44, 47* , 59, 60, 70, 260, 262, 517* , 525* , 537* , 617, 1260, 1309, 1310, 1323, 1325* , 1327, 1332* , 1334, 1368.

str release: \underline{1632*} , 1633* , 1635* .

str room: \underline{42}, 180, 260, 464* , 514* , 516* , 525* , 939, 1257, 1279, 1328, 1333* , 1368, 1486* .

str size: \underline{1633*} .

str start : 38, \underline{39}, 40, 41, 43, 44, 45, 46, 47* , 56* , 59, 60, 69, 70, 256, 260, 264* , 407, 517* , 519, 537* , 603, 617, 765, 929, 931, 934* , 941, 1309, 1310, 1368, 1487* , 1633* , 1659* , 1662* . str stat : \underline{1633*} , \underline{1635*} , \underline{1640*} , 1648* .

str to descr : 1601* , \underline{1633*} , 1640* , 1641* , 1648* .
str toks : \underline{464*} , 465* , 470* , 1422* .

stretch: \underline{150}, 151, 164, 178, 431, 462, 656, 671, 716, 809, 827* , 838, 868, 976, 1004, 1009, 1042, 1044, 1148, 1229, 1239* , 1240* , 1433* , 1479* , 1523* , 1524* , 1527* , 1528* , 1529* , 1531* , 1537* , 1576* , 1586* .

stretch order : \underline{150}, 164, 178, 462, 656, 671, 716, 809, 827* , 838, 868, 976, 1004, 1009, 1148, 1239* , 1433* , 1479* , 1524* , 1527* , 1536* , 1576* .

stretching : \underline{135}, 658, 673, 809, 810, 811, 1148,

1433* . string : 1633* , \underline{1634*} , \underline{1635*} , 1646* , 1648* . string pool: 47* , 1308* . primitive: \underline{468}. string code: \underline{468}, 469* , 471* , 472* . string vacancies : \underline{11*} , 52* . sts : \underline{1620*} , \underline{1627*} . style: \underline{726}, 727* , 760* , 761, \underline{762*} . style node: 160, \underline{688}, 690, 698, 730, 731, 761,

1169, 1452* . style node size: \underline{688}, 689, 698, 763, 1452* . sub box : \underline{681}, 687* , 692, 698, 720, 734, 735, 737,

738, 749, 754, 1076, 1093, 1168. sub drop: \underline{700}, 756. sub mark : \underline{207}, 294* , 298* , 347, 1046, 1175. sub mlist : \underline{681}, 683, 692, 720, 742, 754, 1181,

1185* , 1186, 1191* . sub style: \underline{702}, 750, 757, 759. sub sup: 1175, \underline{1176}. subscr : \underline{681}, 683, 686, 687* , 690, 696* , 698, 738, 742,

749, 750, 751, 752, 753, 754, 755, 756, 757, 759, 1151, 1163, 1165, 1175, 1176, 1177, 1186.

subscripts: 754, 1175. substr : 1629* . subtype: \underline{133}, 134, 135, 136, 139, 140, 143, 144,

145, 146, 147* , 149, 150, 152, 153, 154, 155, 156, 158, 159, 175* , 188, 189, 190, 191, 192* , 193, 424* , 489, 495, 496* , 619* , 625* , 627, 634* , 636, 649* , 656, 668, 671, 681, 682, 686, 687* , 688, 689, 690, 696* , 717, 730, 731, 732, 733, 749, 763, 766, 768, 786, 795, 807* , 808* , 809, 819* , 820, 822, 837, 843, 844, 866* , 868, 879* , 881* , 896* , 897* , 898* , 899, 903, 910, 981, 986, 988, 1008, 1009, 1018, 1020, 1021* , 1035, 1060, 1061, 1078, 1080* , 1100, 1101* , 1105* , 1113, 1125, 1148, 1159, 1163, 1165, 1171, 1181, 1191* , 1194* , 1202* , 1335* , 1341, 1349, 1356, 1357, 1358, 1362, 1363* , 1373, 1374, 1425* , 1433* , 1438* , 1445* , 1447* , 1450* , 1452* , 1453* , 1454* , 1459* , 1461* , 1469* , 1470* , 1472* , 1478* , 1510* , 1521* , 1522* , 1548* .

sub1 : \underline{700}, 757. sub2 : \underline{700}, 759. succumb: \underline{93}, 94, 95, 1304. sup drop: \underline{700}, 756. sup mark : \underline{207}, 294* , 298* , 344, 355, 1046, 1175,

1176, 1177. sup style: \underline{702}, 750, 758. superscripts: 754, 1175. supscr : \underline{681}, 683, 686, 687* , 690, 696* , 698, 738,

742, 750, 751, 752, 753, 754, 756, 758, 1151, 1163, 1165, 1175, 1176, 1177, 1186.

sup1 : \underline{700}, 758. sup2 : \underline{700}, 758. sup3 : \underline{700}, 758. sw : \underline{560}, 571, 575* . switch: \underline{341}, 343, 344, 346, 350. symbol : 1601* , \underline{1640*} . symbol jobname: 1600* , \underline{1601*} . symbol value: \underline{1640*} . synch h: \underline{616*} , 620* , 624, 628* , 633* , 637* , 1368. synch v : \underline{616*} , 620* , 624, 628* , 632* , 633* , 637* , 1368. $ : 96* . $ : 33* . $ : 33* . sys input : \underline{1640*} . sys output : \underline{1640*} . system dependencies: 2* , \underline{3}, 4* , 9* , 10* , 11* , 12* , 19,

21, 23* , 26* , 27* , 28* , 32, 33* , 34* , 35, 37* , 49* , 56* , 59, 72, 81, 84* , 96* , 109* , 110* , 112* , 113* , 161, 186* , 241* , 304, 313* , 328* , 485, 511, 512, 513* , 514* , 515, 516* , 517* , 518, 519, 520* , 521* , 523, 525* , 538, 557, 564* , 591, 597* , 798, 1331* , 1333* , 1338, 1340, 1564* , 1666* .

sz : \underline{1486*} , 1487* , \underline{1489*} . s1 : \underline{82*} , 88. s2 : \underline{82*} , 88. s3 : \underline{82*} , 88. s4 : \underline{82*} , 88. t: \underline{46}, \underline{107}, \underline{108}, \underline{125}, \underline{218}, \underline{241*} , \underline{277*} , \underline{279*} , \underline{280}, \underline{281*} ,

\underline{323}, \underline{341}, \underline{366*} , \underline{389*} , \underline{464*} , \underline{473}, \underline{517*} , \underline{704}, \underline{705}, \underline{726}, \underline{756}, \underline{800}, \underline{830}, \underline{877*} , \underline{906}, \underline{934*} , \underline{966*} , \underline{970}, \underline{1030}, \underline{1123}, \underline{1176}, \underline{1191*} , \underline{1198}, \underline{1257}, \underline{1288}, \underline{1293*} , \underline{1456*} , \underline{1466*} , \underline{1471*} , \underline{1477*} , \underline{1515*} , \underline{1532*} , \underline{1552*} , \underline{1556*} , \underline{1629*} .

t open in: \underline{33*} , 37* . t open out : \underline{33*} , 1332* . tab: \underline{23*} . tab mark : \underline{207}, 289* , 294* , 342, 347, 780, 781, 782,

783, 784, 788, 1126. tab skip: \underline{224}. primitive: \underline{226}. tab skip code: \underline{224}, 225, 226, 778, 782, 786,

795, 809. tab token: \underline{289*} , 1128. table: \underline{1620*} . tag : \underline{543}, 544, 554. tail : 212* , \underline{213*} , 214, 215* , 216* , 424* , 679, 718, 776,

786, 795, 796, 799, 812, 816* , 888, 890* , 995, 1017, 1023* , 1026* , 1034, 1035, 1036, 1037, 1040, 1041, 1043, 1054, 1060, 1061, 1076, 1078, 1080* , 1081, 1091, 1096* , 1100, 1101* , 1105* , 1110* , 1113, 1117, 1119, 1120, 1123, 1125, 1145* , 1150, 1155, 1158, 1159, 1163, 1165, 1168, 1171, 1174, 1176, 1177, 1181, 1184, 1186, 1187, 1191* , 1196, 1205* , 1206* , 1349, 1350, 1351, 1352, 1353, 1354, 1375, 1376, 1377, 1444* , 1445* , 1596* .

tail append : \underline{214}, 786, 795, 816* , 1035, 1036, 1037, 1040, 1054, 1056, 1060, 1061, 1091, 1093, 1100, 1103, 1112, 1113, 1117, 1150, 1158, 1163, 1165, 1168, 1171, 1172, 1177, 1191* , 1196, 1203* , 1205* , 1206* , 1437* .

tail field : \underline{212*} , 213* , 995. tail page disc: 999* , \underline{1592*} . take fraction: 1532* . tally : \underline{54*} , 55, 57* , 58* , 292, 312, 315, 316, 317* . tats: \underline{7*} . tbl ind : 1601* . $ : 1659* . TECO: 84* , 1631* , 1640* . TECO cmd : 1659* , \underline{1660*} . TECO editor : \underline{1637*} , 1638* , 1655* , 1661* . temp char : \underline{56*} , 1602* . temp file: 56* , 73* , 530* , 1602* , 1603* , 1604* , 1606* ,

1613* , 1614* , \underline{1616*} , 1647* , 1648* , 1649* , 1650* , 1655* , 1664* .

temp head : \underline{162}, 306, 391, 396, 400, 464* , 466, 467, 470* , 478* , 719, 720, 754, 760* , 816* , 862, 863* , 864* , 877* , 879* , 880* , 881* , 887, 968* , 1064, 1065, 1194* , 1196, 1199* , 1297, 1417* , 1422* , 1441* , 1443* , 1467* , 1468* , 1470* , 1471* , 1486* .

temp ptr : \underline{115}, 154, 618, 619* , 623* , 628* , 629* , 632* , 637* , 640, 679, 692, 693, 969, 1001, 1021* , 1037, 1041, 1335* , 1439* , 1441* , 1443* , 1448* , 1454* , 1455* , 1456* , 1459* , 1460* , 1479* .

term and log : \underline{54*} , 57* , 58* , 71* , 75, 92, 245, 534* ,

1298, 1328, 1335* , 1370. term in: \underline{32}, 33* , 36, 37* , 71* , 1338, 1339. term input : \underline{71*} , 78. term offset : \underline{54*} , 55, 57* , 58* , 61* , 62, 71* , 537* ,

638* , 1280, 1488* . term only : \underline{54*} , 55, 57* , 58* , 71* , 75, 92, 535* , 1298,

1332* , 1335* . term out : \underline{32}, 33* , 34* , 35, 36, 37* , 51* , 56* . terminal input : \underline{304}, 313* , 328* , 330, 360. test char : \underline{906}, 909. TEX : \underline{2*} , \underline{4*} . : 94.

buffer size: 35, 264* , 328* , 374, 1501* . exception dictionary: 940. font memory: 580. grouping levels: 274* . hash size: 260. input stack size: 321. main memory size: 120, 125. number of strings: 43, 517* . parameter stack size: 390. pattern memory: 954, 964. pool size: 42. save size: 273* . semantic nest size: 216* . text input levels: 328* .

TEX area: \underline{513*} , 514* , 537* . : 84* , 1636* , 1647* , 1652* , 1653* , 1664* . TEX f name default : \underline{520*} , 521* . TEX font area: \underline{513*} , 514* , 563* . TEX format default : \underline{520*} , 521* , 522* , 523. The TEXbook: 1* , 23* , 49* , 108, 207, 415* , 446, 456,

459, 683, 688, 764, 1215, 1331* . : 11* . : 35, 534* , 1257. text : 25* , \underline{256}, 257, 258, 259, 260, 262, 263, 264* ,

265* , 491, 553, 780, 1188, 1216, 1257, 1318, 1369. : 346. text char : \underline{19}, 20, 47* . primitive: \underline{1230}. text mlist : \underline{689}, 695, 698, 731, 1174. text size: \underline{699}, 703, 732, 1195, 1199* . text style: \underline{688}, 694, 703, 731, 737, 744, 745, 746,

748, 749, 758, 1169, 1194* , 1196. primitive: \underline{1169}. TeXXeT : 1434* . TeXXeT code: \underline{2*} , 1434* , 1435* . TeXXeT en: 649* , 651* , 879* , 880* , 881* , \underline{1434*} , 1437* ,

1467* , 1468* , 1469* . TeXXeT state: \underline{1434*} . primitive: \underline{1435*} . TEX82: \underline{1*} , 99. files: 539. tfm count : 563* , 564* , \underline{1622*} . tfm file: \underline{539}, 560, 563* , 564* , 575* . : 561. : 82* . the: \underline{210*} , 265* , 266* , 366* , 367* , 478* , 1420* . : 641, 992, 1121. primitive: \underline{265*} . the toks : \underline{465*} , 466, 467, 478* , 1297, 1422* . thick mu skip: \underline{224}. primitive: \underline{226}. thick mu skip code: \underline{224}, 225, 226, 766. thickness : \underline{683}, 697, 725, 743, 744, 746, 747, 1182. thin mu skip: \underline{224}. primitive: \underline{226}. thin mu skip code: \underline{224}, 225, 226, 229, 766. : 95. align: 800. copying: 206. curlevel: 281* . disc1: 841. disc2: 842. disc3: 870. disc4: 871. display: 1200. endv: 791* . ext1: 1348* . ext2: 1357. ext3: 1358. ext4: 1373. flushing: 202. if: 497. line breaking: 877* . LR1: 1448* . LR2: 1458* . LR3: 1463* . mlist1: 728. mlist2: 754. mlist3: 761. mlist4: 766. page: 1000. paragraph: 866* . prefix: 1211* . pruning: 968* . right: 1185* . rightbrace: 1068. vcenter: 736. vertbreak: 973. vlistout: 630. vpack: 669. 256 spans: 798.

this box : \underline{619*} , 624, \underline{629*} , 633* , \underline{1433*} , 1454* , 1455* ,

\underline{1456*} . this if : \underline{498*} , 501* , 503, 505* , 506. three codes : \underline{645}. threshold : \underline{828}, 851* , 854, 863* . : 667. : 678. tight fit : \underline{817}, 819* , 830, 833, 834, 836, 853,

1575* , 1581* . time: \underline{236*} , 241* , 536* , 617. primitive: \underline{238}. time code: \underline{236*} , 237* , 238. tini: \underline{8*} . Tini: \underline{8*} . tmp descr : \underline{1601*} . : 645, 1082* . tok val : \underline{410}, 415* , 418, 428, 465* , 1224* , 1226* , 1227* ,

1311* , 1312* , 1548* , 1551* , 1556* . tok val limit : \underline{1548*} , 1570* . token: 289* . token base: \underline{230*} , 232* , 233* . token list : \underline{307*} , 311* , 312, 323, 325, 330, 337, 341,

346, 390, 1335* , 1508* . token ref count : \underline{200}, 203, 291, 473, 482* , 979* , 1417* . token show : \underline{295}, 296* , 323, 401, 1279, 1284, 1297,

1370, 1422* , 1486* . token type: \underline{307*} , 311* , 312, 314* , 319* , 323, 324,

325, 327, 379, 1026* , 1095. toks : \underline{230*} . primitive: \underline{265*} . toks base: \underline{230*} , 231* , 232* , 233* , 415* , 1224* , 1226* ,

1227* . primitive: \underline{1222}. toks def code: \underline{1222}, 1224* . toks register : \underline{209*} , 265* , 266* , 413* , 415* , 1210, 1224* ,

1226* , 1227* , 1556* , 1566* , 1567* . tolerance: \underline{236*} , 240, 828, 863* . primitive: \underline{238}. tolerance code: \underline{236*} , 237* , 238. : 1068. too big : \underline{1532*} . too small : \underline{1303}, 1306* . top: \underline{546}. top bot mark : \underline{210*} , 296* , 366* , 367* , 384, 385* ,

386* , 1542* . top edge: \underline{629*} , 636. top mark : \underline{382*} , 383, 1012* , 1542* , 1561* . primitive: \underline{384}. top mark code: \underline{382*} , 384, 386* , 1335* , 1542* , 1564* . primitive: \underline{1542*} . top skip: \underline{224}. primitive: \underline{226}. top skip code: \underline{224}, 225, 226, 1001. total demerits : \underline{819*} , 845* , 846* , 855* , 864* , 874, 875. : 986. total mathex params : \underline{701}, 1195. total mathsy params : \underline{700}, 1195. total pages : \underline{592}, 593, 617, 640, 642* . total shrink : \underline{646}, 650, 656, 664, 665, 666, 667,

671, 676, 677, 678, 796, 1201. total stretch: \underline{646}, 650, 656, 658, 659, 660, 671,

673, 674, 796. TPU: 84* , 1631* , 1640* . TPU editor : \underline{1637*} , 1638* . tracing assigns : \underline{236*} , 277* , 1572* , 1573* . primitive: \underline{1391*} . tracing assigns code: \underline{236*} , 1391* , 1393* . tracing commands : \underline{236*} , 367* , 498* , 509, 510* ,

1031, 1211* . primitive: \underline{238}. tracing commands code: \underline{236*} , 237* , 238. tracing groups : \underline{236*} , 274* , 282* . primitive: \underline{1391*} . tracing groups code: \underline{236*} , 1391* , 1393* . tracing ifs : \underline{236*} , 299* , 494* , 498* , 510* . primitive: \underline{1391*} . tracing ifs code: \underline{236*} , 1391* , 1393* . tracing lost chars : \underline{236*} , 581* . primitive: \underline{238}. tracing lost chars code: \underline{236*} , 237* , 238. tracing macros : \underline{236*} , 323, 389* , 400. primitive: \underline{238}. tracing macros code: \underline{236*} , 237* , 238. tracing nesting : \underline{236*} , 362* , 1507* , 1508* , 1509* , 1510* . primitive: \underline{1391*} . tracing nesting code: \underline{236*} , 1391* , 1393* . tracing online: \underline{236*} , 245, 581* , 1293* , 1298. primitive: \underline{238}. tracing online code: \underline{236*} , 237* , 238. tracing output : \underline{236*} , 638* , 641. primitive: \underline{238}. tracing output code: \underline{236*} , 237* , 238. tracing pages : \underline{236*} , 987, 1005, 1010. primitive: \underline{238}. tracing pages code: \underline{236*} , 237* , 238. tracing paragraphs : \underline{236*} , 845* , 855* , 863* . primitive: \underline{238}. tracing paragraphs code: \underline{236*} , 237* , 238. tracing restores : \underline{236*} , 283, 1574* . primitive: \underline{238}. tracing restores code: \underline{236*} , 237* , 238. tracing scan tokens : \underline{236*} , 1488* . primitive: \underline{1391*} . tracing scan tokens code: \underline{236*} , 1391* , 1393* . tracing stats : 117, \underline{236*} , 639, 1326, 1333* . primitive: \underline{238}. tracing stats code: \underline{236*} , 237* , 238. : 1332* . translate: 517* , \underline{1629*} , 1651* , 1656* , 1658* . trap zero glue: 1228, \underline{1229}, 1236* . trick buf : \underline{54*} , 58* , 315, 317* . trick count : \underline{54*} , 58* , 315, 316, 317* . Trickey, Howard Wellington: 2* . trie: 920, \underline{921}, 922, 950, 952* , 953, 954, 958* , 959,

966* , 1324* , 1325* . trie back : \underline{950}, 954, 956. trie c: \underline{947}, 948, 951, 953, 955, 956, 959, 963,

964, 1588* , 1589* . trie char : 920, \underline{921}, 923, 958* , 959, 1591* . trie fix : 958* , \underline{959}. trie hash: \underline{947}, 948, 949, 950, 952* . trie l : \underline{947}, 948, 949, 957, 959, 960* , 963, 964, 1589* .

trie link : 920, \underline{921}, 923, 950, 952* , 953, 954, 955,

956, 958* , 959, 1591* . trie max : \underline{950}, 952* , 954, 958* , 1324* , 1325* .

trie min: \underline{950}, 952* , 953, 956, 1590* .
trie node: \underline{948}, 949.
trie not ready : 891* , 934* , \underline{950}, 951, 960* , 966* ,

1324* , 1325* . trie o: \underline{947}, 948, 959, 963, 964, 1589* .

trie op: 920, \underline{921}, 923, 924, 943, 958* , 959,

1587* , 1591* . trie op hash: \underline{943}, 944, 945, 946, 948, 952* .

trie op lang : \underline{943}, 944, 945, 952* .
trie op ptr : \underline{943}, 944, 945, 946, 1324* , 1325* .

trie op size: \underline{11*} , 921, 943, 944, 946, 1324* , 1325* .

trie op val : \underline{943}, 944, 945, 952* .
trie pack : \underline{957}, 966* , 1590* .

trie pointer : \underline{920}, 921, 922, 947, 948, 949, 950,

953, 957, 959, 960* , 966* , 1591* . trie ptr : \underline{947}, 951, 952* , 964. trie r : \underline{947}, 948, 949, 955, 956, 957, 959, 963,

964, 1587* , 1588* , 1589* . trie ref : \underline{950}, 952* , 953, 956, 957, 959, 1590* . trie root : \underline{947}, 949, 951, 952* , 958* , 966* , 1587* , 1590* . trie size: \underline{11*} , 920, 948, 950, 952* , 954, 964, 1325* . trie taken: \underline{950}, 952* , 953, 954, 956. trie used : \underline{943}, 944, 945, 946, 1324* , 1325* . trnlnm return: \underline{1629*} . true: 4* , 16, 27* , 31* , 34* , 37* , 45, 46, 49* , 51* , 53* , 71* ,

77, 88, 97* , 98, 104, 105, 106, 107, 168, 169, 186* , 256, 257, 259, 282* , 311* , 327, 328* , 336, 346, 361, 362* , 365, 374, 378* , 407, 413* , 430, 440, 444, 447, 453, 461* , 462, 486, 501* , 508, 512, 516* , 524, 526, 534* , 563* , 578, 592, 595* , 621, 628* , 637* , 638* , 641, 663, 675, 706, 719, 791* , 827* , 828, 829* , 851* , 854, 863* , 880* , 882, 884, 903, 905, 910, 911, 951, 956, 962, 963, 992, 1020, 1021* , 1025, 1030, 1035, 1037, 1040, 1051, 1054, 1083, 1090, 1101* , 1121, 1145* , 1163, 1194* , 1195, 1218* , 1224* , 1226* , 1236* , 1237* , 1253, 1258, 1270, 1279, 1283, 1298, 1303, 1336* , 1342, 1354, 1371, 1374, 1379* , 1390* , 1396* , 1413* , 1489* , 1501* , 1507* , 1508* , 1510* , 1523* , 1526* , 1530* , 1532* , 1552* , 1558* , 1560* , 1563* , 1572* , 1576* , 1589* , 1627* , 1629* , 1630* , 1638* , 1650* , 1651* , 1662* .

: 453.

try break : 828, \underline{829*} , 839, 851* , 858, 862, 866* ,

868, 869, 873, 879* . tt chan: 96* , 97* , \underline{1624*} .

two: \underline{101}, 102.
two choices : \underline{113*} .

two halves : \underline{113*} , 118, 124, 172, 221, 256, 684,

921, 966* . type: \underline{4*} , \underline{133}, 134, 135, 136, 137, 138, 139, 140, 141* , 142* , 143, 144, 145, 146, 147* , 148, 149, 150, 152, 153, 155, 156, 157, 158, 159, 160, 175* , 183, 184* , 202, 206, 424* , 489, 495, 496* , 497, 505* , 622* , 623* , 626* , 628* , 631, 632* , 635, 637* , 640, 649* , 651* , 653, 655, 668, 669, 670, 680, 681, 682, 683, 686, 687* , 688, 689, 696* , 698, 713, 715, 720, 721, 726, 727* , 728, 729, 731, 732, 736, 747, 750, 752, 760* , 761, 762* , 767, 768, 796, 799, 801, 805, 807* , 809, 810, 811, 816* , 819* , 820, 822, 830, 832, 837, 841, 842, 843, 844, 845* , 856, 858, 859, 860, 861, 862, 864* , 865, 866* , 868, 870, 871, 874, 875, 879* , 881* , 896* , 897* , 899, 903, 914, 968* , 970, 972, 973, 976, 978, 979* , 981, 986, 988, 993, 996* , 997, 1000, 1004, 1008, 1009, 1010, 1011, 1013, 1014* , 1021* , 1074, 1080* , 1081, 1087, 1100, 1101* , 1105* , 1110* , 1113, 1121, 1147* , 1155, 1158, 1159, 1163, 1165, 1168, 1181, 1185* , 1186, 1191* , 1202* , 1203* , 1341, 1349, 1413* , 1425* , 1433* , 1438* , 1441* , 1445* , 1447* , 1450* , 1452* , 1458* , 1459* , 1461* , 1466* , 1471* , 1472* , 1479* , 1510* , 1521* , 1522* , 1548* .

: 85. u: \underline{69}, \underline{107}, \underline{389*} , \underline{560}, \underline{706}, \underline{791*} , \underline{800}, \underline{929}, \underline{934*} ,

\underline{944}, \underline{1257}, \underline{1477*} . u part : 768, \underline{769}, 779, 788, 794, 801. u template: \underline{307*} , 314* , 324, 788. uc code: \underline{230*} , 232* , 407. primitive: \underline{1230}. uc code base: \underline{230*} , 235, 1230, 1231, 1286, 1288. uc hyph: \underline{236*} , 891* , 896* . primitive: \underline{238}. uc hyph code: \underline{236*} , 237* , 238. un hbox : \underline{208*} , 1090, 1107, 1108* , 1109. primitive: \underline{1107}. primitive: \underline{1107}. primitive: \underline{1107}. primitive: \underline{1107}. primitive: \underline{1107}. un vbox : \underline{208*} , 1046, 1094, 1107, 1108* , 1109, 1594* . primitive: \underline{1107}. primitive: \underline{1107}. unbalance: \underline{389*} , 391, 396, 399, \underline{473}, 477, \underline{1417*} . : 1027. : 1372. undefined : 186* . : 370. undefined control sequence: \underline{222}, 232* , 256, 257,

259, 262, 268* , 282* , 290, 1318, 1319. undefined cs : \underline{210*} , 222, 366* , 372, 1226* , 1227* ,

1295* , 1499* , 1500* . under noad : \underline{687*} , 690, 696* , 698, 733, 761, 1156,

1157.

: 674. primitive: \underline{1156}. undump: \underline{1306*} , 1310, 1312* , 1314, 1319, 1323,

1325* , 1327, 1389* . undump end : \underline{1306*} . undump end end : \underline{1306*} . undump four ASCII : \underline{1310}. undump hh: \underline{1306*} , 1319, 1325* . undump int : \underline{1306*} , 1308* , 1312* , 1317, 1319,

1323, 1327. undump qqqq : \underline{1306*} , 1310, 1323. undump size: \underline{1306*} , 1310, 1321, 1325* . undump size end : \underline{1306*} . undump size end end : \underline{1306*} . undump wd : \underline{1306*} , 1312* , 1317, 1321. primitive: \underline{1420*} . unfloat : \underline{109*} , 658, 664, 673, 676, 810, 811. unhyphenated : \underline{819*} , 829* , 837, 864* , 866* , 868. unique def qual : \underline{1620*} . unity : \underline{101}, 103, 114, 164, 186* , 453, 568, 1259. primitive: \underline{1495*} . unless code: \underline{487*} , 488* , 498* , 1402* , 1498* . unpackage: 1109, \underline{1110*} . unsafe file: \underline{1626*} , 1627* . unsave: \underline{281*} , 283, 791* , 800, 1026* , 1063, 1068,

1086, 1100, 1119, 1133, 1168, 1174, 1186, 1191* , 1194* , 1196, 1200.

unset node: 136, \underline{159}, 175* , 183, 184* , 202, 206, 424* ,

651* , 669, 682, 688, 689, 768, 796, 799, 801, 805. unsigned : 1629* . update active: \underline{861}. update heights : \underline{970}, 972, 973, 994, 997, 1000. update terminal : \underline{34*} , 37* , 61* , 71* , 86* , 362* , 524, 537* ,

638* , 1280, 1338, 1488* . update width: \underline{832}, 860. primitive: \underline{1286}. : 398. use err help: \underline{79}, 80, 89, 90, 1283. user action: 27* , 525* , 1627* . user proc: 1631* . user reset : 27* , 537* , \underline{1627*} . user rewrite: 27* , \underline{1627*} . u1 : 529* , 1618* , 1620* , 1629* . u2 : 1618* , 1620* . v: \underline{69}, \underline{107}, \underline{389*} , \underline{450}, \underline{706}, \underline{715}, \underline{736}, \underline{743}, \underline{749}, \underline{800},

\underline{830}, \underline{922}, \underline{934*} , \underline{944}, \underline{960*} , \underline{977*} , \underline{1138*} , \underline{1413*} . v offset : \underline{247}, 640, 641. primitive: \underline{248}. v offset code: \underline{247}, 248. v part : 768, \underline{769}, 779, 789, 794, 801. v template: \underline{307*} , 314* , 789. vacuous : \underline{440}, 444, 445. vadjust : \underline{208*} , 265* , 266* , 1097, 1098, 1099, 1100. primitive: \underline{265*} . valign: \underline{208*} , 265* , 266* , 1046, 1090, 1130* , 1434* , 1435* . primitive: \underline{265*} . value string : 1601* . var code: \underline{232*} , 1151, 1155, 1165. var delimiter : \underline{706}, 737, 748, 762* . var used : \underline{117}, 125, 130, 164, 639, 1311* , 1312* . varying: \underline{30*} . VAX address of : 1620* , \underline{1629*} , 1631* , 1659* , 1661* . VAX aligned : \underline{96*} , 595* . VAX assign: \underline{96*} , 97* . VAX asynchronous : \underline{1618*} , 1625* , 1632* . VAX block length: \underline{11*} , 25* , 113* , 564* , 597* , 1305* ,

1306* , 1622* . VAX body : \underline{30*} , 1659* . VAX byte: 1618* , \underline{1623*} . VAX carriage control : \underline{33*} . VAX char string : \underline{1632*} , 1633* , 1648* . VAX class D : \underline{1632*} , 1633* , 1648* . VAX class S : \underline{1632*} . VAX cli dcl parse: \underline{1618*} , 1620* . VAX cli get value: \underline{37*} , 514* , 521* , \underline{1618*} , 1620* , 1621* . VAX cli present : \underline{37*} , 1332* , \underline{1618*} , 1620* , 1621* . VAX create logical : \underline{1659*} , 1661* . VAX default : \underline{27*} . VAX delete file: \underline{1661*} . VAX delete logical : \underline{1661*} . VAX disposition delete: \underline{27*} . VAX disposition save: \underline{28*} . VAX establish: \underline{1618*} , 1620* . VAX exit : \underline{1600*} . VAX external : \underline{1618*} , 1619* , 1631* , 1632* , 1640* . VAX F float : 186* , \underline{1623*} . VAX FAB L NAM : \underline{1627*} . VAX FAB type: \underline{1626*} , 1627* . VAX FAB V NAM : \underline{1627*} . VAX find image: \underline{1640*} , 1645* . VAX ignore error : \underline{27*} , 28* , 31* , 537* , 564* , 1305* ,

1306* . VAX immed : \underline{96*} , 1601* , 1618* , 1631* , 1632* , 1640* . VAX index : \underline{1654*} . VAX io setmode: \underline{96*} . VAX iom ctrlcast : \underline{96*} . VAX length: \underline{30*} , 31* , 1659* . VAX lib callg : \underline{1631*} . VAX lib get foreign: \underline{1618*} , 1620* . VAX lib sig to ret : \underline{1618*} , 1620* . VAX lib spawn: \underline{1640*} . VAX lnm case blind : \underline{1629*} . VAX lnm string : \underline{1629*} , 1659* , 1661* . VAX longword : \underline{1623*} , 1630* , 1631* , 1634* , 1640* .

VAX NAM B NAME : \underline{1627*} . VAX NAM B RSL: \underline{1627*} . VAX NAM L NAME : \underline{1627*} . VAX NAM L RSA: \underline{1627*} . VAX NAM type: \underline{1626*} . VAX new : \underline{27*} . VAX none: \underline{33*} . VAX numtim: \underline{241*} . VAX PAS FAB : \underline{33*} , \underline{1627*} . VAX PAS RAB : \underline{33*} , \underline{1627*} . VAX qiow : \underline{96*} . VAX RAB cancel ctrlO : \underline{34*} . VAX RAB purge typeahead : \underline{34*} , 71* . VAX RAB type: \underline{1626*} , 1627* . VAX readonly : \underline{27*} , 537* , 1618* , 1619* , 1620* , 1632* . VAX ref : \underline{96*} , 1618* , 1632* , 1640* . VAX rms connect : \underline{1627*} . VAX rms create: \underline{1627*} . VAX rms open: \underline{1627*} . VAX rms parse: \underline{1627*} . VAX rms search: \underline{1627*} . VAX set symbol : \underline{1601*} . VAX ss error : \underline{1600*} . VAX ss fatal : \underline{1600*} . VAX ss ignore: \underline{1600*} , 1644* . VAX ss normal : 97* , \underline{1600*} , 1629* , 1640* , 1645* . VAX ss warning : \underline{1600*} . VAX static: \underline{96*} . VAX stdescr : \underline{96*} , 1601* , 1618* . VAX substr : 1620* , \underline{1629*} . VAX sys input : \underline{33*} . VAX sys output : \underline{33*} . VAX text : \underline{25*} . VAX trnlnm: \underline{1629*} . VAX undefined : \underline{186*} . VAX unsafe: \underline{96*} , 1618* , 1626* . VAX unsigned : 1618* , 1619* , 1620* , \underline{1623*} . VAX user action: \underline{27*} , 537* . VAX volatile: \underline{96*} , 595* , 1618* , 1624* , 1629* , 1631* ,

1633* , 1640* , 1660* . VAX word : \underline{1623*} . vbadness : \underline{236*} , 674, 677, 678, 1012* , 1017. primitive: \underline{238}. vbadness code: \underline{236*} , 237* , 238. primitive: \underline{1071*} . vbox group: \underline{269}, 1083, 1085, 1395* , 1413* . vcenter : \underline{208*} , 265* , 266* , 1046, 1167. primitive: \underline{265*} . vcenter group: \underline{269}, 1167, 1168, 1395* , 1413* . vcenter noad : \underline{687*} , 690, 696* , 698, 733, 761, 1168. verb name: \underline{1620*} . vert break : \underline{970}, 971, 976, 977* , 980, 982* , 1010. very loose fit : \underline{817}, 819* , 830, 833, 834, 836, 852* ,

1575* , 1580* . vet glue: \underline{625*} , 1433* . primitive: \underline{1058}. primitive: \underline{1058}. primitive: \underline{1058}. vfuzz : \underline{247}, 677, 1012* , 1017. primitive: \underline{248}. vfuzz code: \underline{247}, 248. : 1331* . virtual memory: 126. Vitter, Jeffrey Scott: 261. vlist node: \underline{137}, 148, 159, 175* , 183, 184* , 202, 206,

505* , 618, 622* , 623* , 628* , 629* , 631, 632* , 637* , 640, 644, 651* , 668, 669, 681, 713, 715, 720, 736, 747, 750, 807* , 809, 811, 841, 842, 866* , 870, 871, 968* , 973, 978, 1000, 1074, 1080* , 1087, 1110* , 1147* , 1458* , 1466* .

vlist out : 592, 615, 616* , 618, 619* , 623* , 628* , \underline{629*} ,

632* , 637* , 638* , 640, 693, 1373. vmode: \underline{211}, 215* , 416* , 417* , 418, 422, 424* , 501* ,

775, 785* , 786, 804, 807* , 808* , 809, 812, 1025, 1029, 1045, 1046, 1048, 1056, 1057, 1071* , 1072, 1073, 1076, 1078, 1079* , 1080* , 1083, 1090, 1091, 1094, 1098, 1099, 1103, 1105* , 1109, 1110* , 1111, 1130* , 1167, 1243, 1244, 1413* , 1415* .

vmove: \underline{208*} , 1048, 1071* , 1072, 1073, 1415* . VMS item list : 1629* , \underline{1630*} , 1660* . vpack : 236* , 644, 645, 646, \underline{668}, 705, 735, 738, 759,

799, 804, 977* , 1021* , 1100, 1168. vpackage: \underline{668}, 796, 977* , 1017, 1086. vrule: \underline{208*} , 265* , 266* , 463, 1056, 1084, 1090. primitive: \underline{265*} . vsize: \underline{247}, 980, 987. primitive: \underline{248}. vsize code: \underline{247}, 248. vskip: \underline{208*} , 1046, 1057, 1058, 1059, 1078, 1094. primitive: \underline{1058}. vsplit : 967, \underline{977*} , 978, 980, 1082* , 1542* , 1558* , 1559* . : 978. primitive: \underline{1071*} . vsplit code: \underline{1071*} , 1072, 1079* , 1335* , 1592* , 1594* ,

1595* . vsplit init : 977* , \underline{1558*} , 1559* . primitive: \underline{1058}. primitive: \underline{1071*} . vtop code: \underline{1071*} , 1072, 1083, 1085, 1086. vtop group: \underline{269}, 1083, 1085, 1395* , 1413* . w: \underline{114}, \underline{147*} , \underline{156}, \underline{275*} , \underline{278*} , \underline{279*} , \underline{607}, \underline{649*} , \underline{668}, \underline{706},

\underline{715}, \underline{738}, \underline{791*} , \underline{800}, \underline{906}, \underline{994}, \underline{1123}, \underline{1138*} , \underline{1198}, \underline{1236*} , \underline{1302}, \underline{1303}, \underline{1349}, \underline{1350}, \underline{1417*} , \underline{1452*} , \underline{1486*} , \underline{1489*} , \underline{1507*} , \underline{1509*} , \underline{1552*} , \underline{1572*} , \underline{1573*} .

w close: \underline{28*} , 1329* , 1337* , 1621* .
w make name string : \underline{525*} , 1328.
w open in: \underline{27*} , 524.
w open out : \underline{27*} , 1328.
wait : \underline{1012*} , 1020, 1021* , 1022.
wake up terminal : \underline{34*} , 37* , 51* , 71* , 73* , 363, 484,

524, 530* , 1294, 1297, 1303, 1333* , 1338. : 1510* . : 1507* , 1509* . warning index : \underline{305}, 331* , 338, 389* , 390, 395, 396, 398, 401, 473, 479, 482* , 774, 777, 1417* . warning issued : \underline{76}, 245, 1335* , 1507* , 1509* ,

1510* , 1600* . was free: \underline{165}, 167, 171. was hi min: \underline{165}, 166, 167, 171. was lo max : \underline{165}, 166, 167, 171. was mem end : \underline{165}, 166, 167, 171. primitive: \underline{416*} . wdiag : \underline{56*} , 1606* , 1607* , 1608* , 1609* , 1610* , 1612* . wdiag cr : \underline{56*} , 1333* . wdiag ln: \underline{56*} , 1333* , 1605* , 1606* , 1609* , 1612* , 1615* . : 1* , 4* , 38, 40, 50* , 1308* . what lang : \underline{1341}, 1356, 1362, 1363* , 1376, 1377. what lhm: \underline{1341}, 1356, 1362, 1363* , 1376, 1377. what rhm: \underline{1341}, 1356, 1362, 1363* , 1376, 1377. whatsit node: \underline{146}, 148, 175* , 183, 202, 206, 622* ,

631, 651* , 669, 730, 761, 866* , 896* , 899, 968* , 973, 1000, 1147* , 1341, 1349, 1434* , 1466* .

primitive: \underline{1597*} . widow penalties loc: \underline{230*} , 1597* , 1598* . widow penalties ptr : 890* , \underline{1597*} . widow penalty : \underline{236*} , 814* , 890* . primitive: \underline{238}. widow penalty code: \underline{236*} , 237* , 238. : 463. width: \underline{135}, 136, 138, 139, 147* , 150, 151, 155, 156, 178, 184* , 187, 191, 192* , 424* , 429, 431, 451, 462, 463, 554, 605, 607, 611, 619* , 622* , 623* , 625* , 626* , 631, 633* , 634* , 635, 641, 651* , 653, 656, 657, 666, 668, 669, 670, 671, 679, 683, 688, 706, 709, 714, 715, 716, 717, 731, 738, 744, 747, 749, 750, 757, 758, 759, 768, 779, 793, 796, 797, 798, 801, 802, 803, 804, 806, 807* , 808* , 809, 810, 811, 827* , 837, 838, 841, 842, 866* , 868, 870, 871, 881* , 969, 976, 996* , 1001, 1004, 1009, 1042, 1044, 1054, 1091, 1093, 1147* , 1148, 1199* , 1201, 1205* , 1229, 1239* , 1240* , 1433* , 1452* , 1453* , 1454* , 1455* , 1458* , 1459* , 1461* , 1462* , 1467* , 1469* , 1471* , 1473* , 1478* , 1479* , 1513* , 1523* , 1527* , 1528* , 1529* , 1531* , 1586* . width base: \underline{550}, 552, 554, 566, 569, 571, 576,

1322, 1323. width index : \underline{543}, 550. width offset : \underline{135}, 416* , 417* , 1247* . Wirth, Niklaus: 10* . wlog : \underline{56*} , 58* , 536* , 1334. wlog cr : \underline{56*} , 57* , 58* , 536* , 1332* . wlog ln: \underline{56*} , 1334. word block : \underline{113*} . word define: \underline{1214}, 1228, 1232, 1572* . word file: 25* , 27* , 28* , \underline{113*} , 525* , 1305* , 1622* . word node size: \underline{1553*} , 1554* , 1570* , 1574* . words : \underline{204}, 205, 206, 1357, \underline{1466*} . wrap lig : \underline{910}, 911. wrapup: \underline{1035}, 1040. write: 27* , 37* , 56* , 58* , 597* , 598* , 599* . primitive: \underline{1344}. write file: 57* , 58* , \underline{1342}, 1374, 1378, 1656* . write ln: 34* , 35, 37* , 51* , 56* , 57* . write loc: 1313, 1314, 1344, \underline{1345}, 1371. write node: \underline{1341}, 1344, 1346, 1348* , 1356, 1357,

1358, 1373, 1374. write node size: \underline{1341}, 1350, 1352, 1353, 1354,

1357, 1358. write open: \underline{1342}, 1343, 1370, 1374, 1378. write out : \underline{1370}, 1374. write stream: \underline{1341}, 1350, 1354, 1355, 1370, 1374. write text : \underline{307*} , 314* , 323, 1340, 1371. write tokens : \underline{1341}, 1352, 1353, 1354, 1356, 1357,

1358, 1368, 1371. writing : \underline{578}. wtemp: \underline{56*} . wtemp cr : \underline{56*} . wtemp ln: \underline{56*} . wterm: \underline{56*} , 58* , 61* . wterm cr : \underline{56*} , 57* , 58* . wterm ln: \underline{56*} , 61* , 524, 1303, 1332* , 1337* . Wyatt, Douglas Kirk: 2* . w0 : 585, \underline{586}, 604, 609. w1 : 585, \underline{586}, 607. w2 : \underline{585}. w3 : \underline{585}. w4 : \underline{585}. x: \underline{100}, \underline{105}, \underline{106}, \underline{107}, \underline{587}, \underline{600}, \underline{649*} , \underline{668}, \underline{706}, \underline{720},

\underline{726}, \underline{735}, \underline{737}, \underline{738}, \underline{743}, \underline{749}, \underline{756}, \underline{1123}, \underline{1138*} , \underline{1302}, \underline{1303}, \underline{1477*} , \underline{1526*} , \underline{1532*} .

x height : 547, \underline{558}, 559, 738, 1123. x height code: \underline{547}, 558. x leaders : \underline{149}, 190, 627, 1071* , 1072. primitive: \underline{1071*} . x open in: \underline{537*} , 1275* . x over n: \underline{106}, 703, 716, 717, 986, 1008, 1009,

1010, 1240* . x token: 364, \underline{381}, 478* , 1038, 1152. xchr : \underline{20}, 21, 23* , 24, 38, 49* , 56* , 58* , 517* , 519,

1633* , 1653* , 1659* . xclause: 16. primitive: \underline{1208*} . xeq level : \underline{253}, 254, 268* , 278* , 279* , 283, 1304. xn over d : \underline{107}, 455, 457, 458, 568, 716, 1044,

1260. xord : \underline{20}, 24, 31* , 37* , 52* , 53* , 514* , 517* , 523, 525* ,

537* , 1621* , 1653* , 1656* , 1658* , 1664* . xpand : \underline{473}, 477, 479. xray : \underline{208*} , 1290, 1291, 1292* , 1409* , 1418* , 1423* . xspace skip: \underline{224}, 1043. primitive: \underline{226}. xspace skip code: \underline{224}, 225, 226, 1043. xxx1 : 585, \underline{586}, 1368. xxx2 : \underline{585}. xxx3 : \underline{585}. xxx4 : 585, \underline{586}, 1368. x0 : 585, \underline{586}, 604, 609. x1 : 585, \underline{586}, 607. x2 : \underline{585}. x3 : \underline{585}. x4 : \underline{585}. y: \underline{105}, \underline{706}, \underline{726}, \underline{735}, \underline{737}, \underline{738}, \underline{743}, \underline{749}, \underline{756}, \underline{1526*} . y here: \underline{608}, 609, 611, 612, 613. y OK : \underline{608}, 609, 612. y seen: \underline{611}, 612. year : \underline{236*} , 241* , 536* , 617, 1328. primitive: \underline{238}. year code: \underline{236*} , 237* , 238. : 476. : 1099. : 1304. : 1095. : 1213* . : 1498* . : 1212. : 428, 1237* . : 1049. : 52* . : 84* . you cant : \underline{1049}, 1050, 1080* , 1106. yz OK : \underline{608}, 609, 610, 612. y0 : 585, \underline{586}, 594, 604, 609. y1 : 585, \underline{586}, 607, 613. y2 : \underline{585}, 594. y3 : \underline{585}. y4 : \underline{585}. z: \underline{560}, \underline{706}, \underline{726}, \underline{743}, \underline{749}, \underline{756}, \underline{922}, \underline{927}, \underline{953},

\underline{959}, \underline{1198}, \underline{1477*} . z here: \underline{608}, 609, 611, 612, 614. z OK : \underline{608}, 609, 612. z seen: \underline{611}, 612. Zabala Salelles, Ignacio Andres: 2* . zero glue: \underline{162}, 175* , 224, 228, 424* , 427* , 462, 732,

802, 887, 1041, 1042, 1043, 1171, 1229, 1473* , 1515* , 1523* , 1542* , 1553* , 1554* .

zero token: \underline{445}, 452, 473, 476, 479. z0 : 585, \underline{586}, 604, 609. z1 : 585, \underline{586}, 607, 614. z2 : \underline{585}. z3 : \underline{585}. z4 : \underline{585}.

306  NAMES OF THE SECTIONS  ε-TEX 3.14159 [PD VMS 3.6] changes §1667

⟨ Accumulate the constant until cur tok is not a suitable digit 445 ⟩ Used in section 444. ⟨ Add the width of node s to act width 871 ⟩ Used in section 869. ⟨ Add the width of node s to break width 842 ⟩ Used in section 840. ⟨ Add the width of node s to disc width 870 ⟩ Used in section 869. ⟨ Adjust for the magnification ratio 457 ⟩ Used in section 453. ⟨ Adjust for the setting of 1214 ⟩ Used in section 1211*. ⟨ Adjust shift up and shift down for the case of a fraction line 746 ⟩ Used in section 743. ⟨ Adjust shift up and shift down for the case of no fraction line 745 ⟩ Used in section 743. ⟨ Adjust the LR stack for the hlist out routine; if necessary reverse an hlist segment and goto reswitch 1450* ⟩

Used in section 622*.

⟨ Adjust the LR stack for the hpack routine 1447* ⟩ Used in section 651*. ⟨ Adjust the LR stack for the init math routine 1470* ⟩ Used in section 1469*. ⟨ Adjust the LR stack for the just reverse routine 1472* ⟩ Used in section 1471*.

⟨ Adjust the LR stack for the post line break routine 1442* ⟩ Used in sections 879*, 881*, and 1441*.

⟨ Adjust the additional data for last line 1582* ⟩ Used in section 851*. ⟨ Adjust the final line of the paragraph 1586* ⟩ Used in section 863*. ⟨ Advance cur p to the node following the present string of characters 867 ⟩ Used in section 866*. ⟨ Advance past a whatsit node in the line break loop 1362 ⟩ Used in section 866*. ⟨ Advance past a whatsit node in the pre-hyphenation loop 1363* ⟩ Used in section 896*. ⟨ Advance r; goto found if the parameter delimiter has been fully matched, otherwise goto continue 394 ⟩

Used in section 392.

⟨ Allocate entire node p and goto found 129 ⟩ Used in section 127. ⟨ Allocate from the top of node p and goto found 128 ⟩ Used in section 127. ⟨ Apologize for inability to do the operation now, unless follows non-glue 1106 ⟩

Used in section 1105*.

⟨ Apologize for not loading the font, goto done 567 ⟩ Used in section 566. ⟨ Append a ligature and/or kern to the translation; goto continue if the stack of inserted ligatures is

nonempty 910 ⟩ Used in section 906.

⟨ Append a new leader node that uses cur box 1078 ⟩ Used in section 1075*. ⟨ Append a new letter or a hyphen level 962 ⟩ Used in section 961. ⟨ Append a new letter or hyphen 937* ⟩ Used in section 935. ⟨ Append a normal inter-word space to the current list, then goto big switch 1041 ⟩ Used in section 1030. ⟨ Append a penalty node, if a nonzero penalty is appropriate 890* ⟩ Used in section 880*. ⟨ Append an insertion to the current page and goto contribute 1008 ⟩ Used in section 1000. ⟨ Append any new hlist entries for q, and any appropriate penalties 767 ⟩ Used in section 760*. ⟨ Append box cur box to the current list, shifted by box context 1076 ⟩ Used in section 1075*. ⟨ Append character cur chr and the following characters (if any) to the current hlist in the current font;

goto reswitch when a non-character has been fetched 1034 ⟩ Used in section 1030. ⟨ Append characters of hu[j . .] to major tail , advancing j 917 ⟩ Used in section 916. ⟨ Append inter-element spacing based on r type and t 766 ⟩ Used in section 760*. ⟨ Append tabskip glue and an empty box to list u, and update s and t as the prototype nodes are passed 809 ⟩

Used in section 808*.

⟨ Append the accent with appropriate kerns, then set p ← q 1125 ⟩ Used in section 1123. ⟨ Append the current tabskip glue to the preamble list 778 ⟩ Used in section 777. ⟨ Append the display and perhaps also the equation number 1204* ⟩ Used in section 1199*. ⟨ Append the glue or equation number following the display 1205* ⟩ Used in section 1199*. ⟨ Append the glue or equation number preceding the display 1203* ⟩ Used in section 1199*. ⟨ Append the new box to the current vertical list, followed by the list of special nodes taken out of the box

by the packager 888 ⟩ Used in section 880*.

⟨ Append the value n to list p 938 ⟩ Used in section 937*. ⟨ Assign the values depth threshold ← show box depth and breadth max ← show box breadth 236* ⟩

Used in section 198.

§1667 ε-TEX 3.14159 [PD VMS 3.6] changes NAMES OF THE SECTIONS 307

⟨ Assignments 1217, 1218*, 1221, 1224*, 1225*, 1226*, 1228, 1232, 1234, 1235, 1241*, 1242, 1248*, 1252*, 1253, 1256, 1264 ⟩

Used in section 1211*.

⟨ Attach list p to the current list, and record its length; then finish up and return 1120 ⟩ Used in section 1119. ⟨ Attach the limits to y and adjust height (v), depth(v) to account for their presence 751 ⟩ Used in section 750. ⟨ Attempt to invoke desired editor 1652* ⟩ Used in section 1651*. ⟨ Attempt to recognize name of editor 1654* ⟩ Used in section 1652*. ⟨ Back up an outer control sequence so that it can be reread 337 ⟩ Used in section 336.

⟨ Basic printing procedures 56*, 57*, 58*, 59, 60, 62, 63, 64, 65, 262, 263, 518, 699, 1355, 1555*, 1649*, 1650* ⟩

Used in section 4*.

⟨ Break the current page at node p, put it in box 255, and put the remaining nodes on the contribution

list 1017 ⟩ Used in section 1014*.

⟨ Break the paragraph at the chosen breakpoints, justify the resulting lines to the correct widths, and

append them to the current vertical list 876* ⟩ Used in section 815*. ⟨ Calculate the length, l, and the shift amount, s, of the display lines 1149 ⟩ Used in section 1145*. ⟨ Calculate the natural width, w, by which the characters of the final line extend to the right of the reference

point, plus two ems; or set w ← max dimen if the non-blank information on that line is affected by

stretching or shrinking 1146* ⟩ Used in section 1145*.

⟨ Call the packaging subroutine, setting just box to the justified box 889 ⟩ Used in section 880*. ⟨ Call try break if cur p is a legal breakpoint; on the second pass, also try to hyphenate the next word, if

cur p is a glue node; then advance cur p to the next node of the paragraph that could possibly be a

legal breakpoint 866* ⟩ Used in section 863*.

⟨ Carry out a ligature replacement, updating the cursor structure and possibly advancing j; goto continue

if the cursor doesn’t advance, otherwise goto done 911 ⟩ Used in section 909. ⟨ Case statement to copy different types and set words to the number of initial words not yet copied 206 ⟩

Used in section 205.

⟨ Cases for ‘Fetch the dead cycles or the insert penalties ’ 1428* ⟩ Used in section 419*.

⟨ Cases for evaluation of the current term 1524*, 1528*, 1529*, 1531* ⟩ Used in section 1516*. ⟨ Cases for fetching a dimension value 1405*, 1408*, 1537* ⟩ Used in section 424*.

⟨ Cases for fetching a glue value 1540* ⟩ Used in section 1513*. ⟨ Cases for fetching a mu value 1541* ⟩ Used in section 1513*.

⟨ Cases for fetching an integer value 1382*, 1399*, 1402*, 1536* ⟩ Used in section 424*.

⟨ Cases for noads that can follow a bin noad 733 ⟩ Used in section 728. ⟨ Cases for nodes that can appear in an mlist, after which we goto done with node 730 ⟩ Used in section 728.

⟨ Cases for alter integer 1430* ⟩ Used in section 1246*. ⟨ Cases for conditional 1499*, 1500*, 1502* ⟩ Used in section 501*. ⟨ Cases for do marks 1559*, 1561*, 1562*, 1564* ⟩ Used in section 1558*. ⟨ Cases for eq destroy 1567* ⟩ Used in section 275*. ⟨ Cases for input 1482* ⟩ Used in section 378*. ⟨ Cases for print param 1393*, 1434* ⟩ Used in section 237*. ⟨ Cases for show whatever 1411*, 1425* ⟩ Used in section 1293*.

⟨ Cases of ‘Let d be the natural width’ that need special treatment 1469* ⟩ Used in section 1147*. ⟨ Cases of ‘Print the result of command c’ 1385* ⟩ Used in section 472*. ⟨ Cases of ‘Scan the argument for command c’ 1384* ⟩ Used in section 471*.

⟨ Cases of assign toks for print cmd chr 1392* ⟩ Used in section 231*. ⟨ Cases of convert for print cmd chr 1383* ⟩ Used in section 469*. ⟨ Cases of expandafter for print cmd chr 1496* ⟩ Used in section 266*.

⟨ Cases of flush node list that arise in mlists only 698 ⟩ Used in section 202. ⟨ Cases of handle right brace where a right brace triggers a delayed action 1085, 1100, 1118, 1132, 1133, 1168,

1173, 1186 ⟩ Used in section 1068.

⟨ Cases of hlist out that arise in mixed direction text only 1453* ⟩ Used in section 622*.

⟨ Cases of if test for print cmd chr 1497* ⟩ Used in section 488*. ⟨ Cases of input for print cmd chr 1481* ⟩ Used in section 377*.

⟨ Cases of last item for print cmd chr 1381*, 1398*, 1401*, 1404*, 1407*, 1512*, 1535*, 1539* ⟩ Used in section 417*. ⟨ Cases of left right for print cmd chr 1432* ⟩ Used in section 1189*. ⟨ Cases of main control for hmode + valign 1437* ⟩ Used in section 1130*.

⟨ Cases of main control that are for extensions to TEX 1347 ⟩ Used in section 1045. ⟨ Cases of main control that are not part of the inner loop 1045 ⟩ Used in section 1030.

⟨ Cases of main control that build boxes and lists 1056, 1057, 1063, 1067, 1073, 1090, 1092, 1094, 1097, 1102, 1104, 1109, 1112, 1116, 1122, 1126, 1130*, 1134, 1137, 1140, 1150, 1154, 1158, 1162, 1164, 1167, 1171, 1175, 1180, 1190, 1193 ⟩ Used in section 1045.

⟨ Cases of main control that don’t depend on mode 1210, 1268, 1271, 1274, 1276, 1285, 1290 ⟩ Used in section 1045. ⟨ Cases of prefix for print cmd chr 1504* ⟩ Used in section 1209*. ⟨ Cases of print cmd chr for symbolic printing of primitives 227, 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*, 1346 ⟩ Used in section 298*.

⟨ Cases of read for print cmd chr 1493* ⟩ Used in section 266*. ⟨ Cases of register for print cmd chr 1565* ⟩ Used in section 412*. ⟨ Cases of reverse that need special treatment 1459*, 1460*, 1461* ⟩ Used in section 1458*. ⟨ Cases of set page int for print cmd chr 1427* ⟩ Used in section 417*. ⟨ Cases of set shape for print cmd chr 1598* ⟩ Used in section 266*.

⟨ Cases of show node list that arise in mlists only 690 ⟩ Used in section 183.

⟨ Cases of the for print cmd chr 1421* ⟩ Used in section 266*. ⟨ Cases of toks register for print cmd chr 1566* ⟩ Used in section 266*. ⟨ Cases of un vbox for print cmd chr 1595* ⟩ Used in section 1108*. ⟨ Cases of valign for print cmd chr 1436* ⟩ Used in section 266*. ⟨ Cases of xray for print cmd chr 1410*, 1419*, 1424* ⟩ Used in section 1292*.

⟨ Cases where character is ignored 345 ⟩ Used in section 344. ⟨ Change buffered instruction to y or w and goto found 613 ⟩ Used in section 612. ⟨ Change buffered instruction to z or x and goto found 614 ⟩ Used in section 612. ⟨ Change current mode to −vmode for , −hmode for 775 ⟩ Used in section 774. ⟨ Change discretionary to compulsory and set disc break ← true 882 ⟩ Used in section 881*.

⟨ Change font dvi f to f 621 ⟩ Used in section 620*.

⟨ Change state if necessary, and goto switch if the current character should be ignored, or goto reswitch if

the current character changes to another 344 ⟩ Used in section 343. ⟨ Change the case of the token in p, if a change is appropriate 1289 ⟩ Used in section 1288. ⟨ Change the current style and goto delete q 763 ⟩ Used in section 761. ⟨ Change the interaction level and return 86* ⟩ Used in section 84*. ⟨ Change this node to a style node followed by the correct choice, then goto done with node 731 ⟩

Used in section 730.

⟨ Character k cannot be printed 49* ⟩ Used in section 48. ⟨ Character s is the current new-line character 244 ⟩ Used in sections 58* and 59. ⟨ Check flags of unavailable nodes 170 ⟩ Used in section 167. ⟨ Check for LR anomalies at the end of hlist out 1451* ⟩ Used in section 619*. ⟨ Check for LR anomalies at the end of hpack 1448* ⟩ Used in section 649*. ⟨ Check for LR anomalies at the end of ship out 1463* ⟩ Used in section 638*. ⟨ Check for charlist cycle 570 ⟩ Used in section 569. ⟨ Check for improper alignment in displayed math 776 ⟩ Used in section 774. ⟨ Check for special treatment of last line of paragraph 1576* ⟩ Used in section 827*. ⟨ Check if node p is a new champion breakpoint; then goto done if p is a forced break or if the page-so-far

is already too full 974 ⟩ Used in section 972.

⟨ Check if node p is a new champion breakpoint; then if it is time for a page break, prepare for output, and either fire up the user’s output routine and return or ship out the page and goto done 1005 ⟩

Used in section 997.

⟨ Check single-word avail list 168 ⟩ Used in section 167.

⟨ Check that another $ follows 1197 ⟩ Used in sections 1194* and 1206*.

⟨ Check that the necessary fonts for math symbols are present; if not, flush the current math lists and set

danger ← true 1195 ⟩ Used in section 1194*.

⟨ Check that the nodes following hb permit hyphenation and that at least l hyf + r hyf letters have been

found, otherwise goto done1 899 ⟩ Used in section 894.

⟨ Check the “constant” values for consistency 14, 111, 290, 597*, 1249 ⟩ Used in section 1332*. ⟨ Check the pool check sum 53* ⟩ Used in section 52*. ⟨ Check variable-size avail list 169 ⟩ Used in section 167. ⟨ Clean up the memory by removing the break nodes 865 ⟩ Used in sections 815* and 863*.

⟨ Clear dimensions to zero 650 ⟩ Used in sections 649* and 668. ⟨ Clear off top level from save stack 282* ⟩ Used in section 281*. ⟨ Clear out the temp file 1614* ⟩ Used in section 1293*. ⟨ Close the format file 1329* ⟩ Used in section 1302. ⟨ Coerce glue to a dimension 451 ⟩ Used in sections 449 and 455.

⟨ Commence an LSE diagnostic report 1605* ⟩ Used in section 311*. ⟨ Compiler directives 9* ⟩ Used in section 4*. ⟨ Complain about an undefined family and set cur i null 723 ⟩ Used in section 722. ⟨ Complain about an undefined macro 370 ⟩ Used in section 367*.

⟨ Complain about missing 373 ⟩ Used in sections 372 and 1500*.

⟨ Complain about unknown unit and goto done2 459 ⟩ Used in section 458. ⟨ Complain that can’t do this; give zero result 428 ⟩ Used in section 413*. ⟨ Complain that the user should have said 1166 ⟩ Used in section 1165. ⟨ Compleat the incompleat noad 1185* ⟩ Used in section 1184. ⟨ Complete a potentially long command 1298 ⟩ Used in section 1293*.

⟨ Compute f = ⌊xn/d + \frac{1}{2}⌋ 1533* ⟩ Used in section 1532*.

⟨ Compute result of multiply or divide, put it in cur val 1240* ⟩ Used in section 1236*. ⟨ Compute result of register or advance, put it in cur val 1238* ⟩ Used in section 1236*. ⟨ Compute the amount of skew 741 ⟩ Used in section 738. ⟨ Compute the badness, b, of the current page, using awful bad if the box is too full 1007 ⟩

Used in section 1005.

⟨ Compute the badness, b, using awful bad if the box is too full 975 ⟩ Used in section 974. ⟨ Compute the demerits, d, from r to cur p 859 ⟩ Used in section 855*. ⟨ Compute the discretionary break width values 840 ⟩ Used in section 837. ⟨ Compute the hash code h 261 ⟩ Used in section 259. ⟨ Compute the magic offset 765 ⟩ Used in section 1337*. ⟨ Compute the mark pointer for mark type t and class cur val 1557* ⟩ Used in section 386*. ⟨ Compute the minimum suitable height, w, and the corresponding number of extension steps, n; also set

width(b) 714 ⟩ Used in section 713.

⟨ Compute the new line width 850 ⟩ Used in section 835. ⟨ Compute the register location l and its type p; but return if invalid 1237* ⟩ Used in section 1236*. ⟨ Compute the sum of two glue specs 1239* ⟩ Used in section 1238*. ⟨ Compute the sum or difference of two glue specs 1527* ⟩ Used in section 1525*. ⟨ Compute the trie op code, v, and set l ← 0 965 ⟩ Used in section 963. ⟨ Compute the values of break width 837 ⟩ Used in section 836. ⟨ Consider a node with matching width; goto found if it’s a hit 612 ⟩ Used in section 611. ⟨ Consider the demerits for a line from r to cur p; deactivate node r if it should no longer be active; then

goto continue if a line from r to cur p is infeasible, otherwise record a new feasible break 851* ⟩

Used in section 829*.

⟨ Constants in the outer block 11* ⟩ Used in section 4*. ⟨ Construct a box with limits above and below it, skewed by delta 750 ⟩ Used in section 749. ⟨ Construct a sub/superscript combination box x, with the superscript offset by delta 759 ⟩

Used in section 756.

⟨ Construct a subscript box x when there is no superscript 757 ⟩ Used in section 756. ⟨ Construct a superscript box x 758 ⟩ Used in section 756. ⟨ Construct a vlist box for the fraction, according to shift up and shift down 747 ⟩ Used in section 743. ⟨ Construct an extensible character in a new box b, using recipe rem byte(q) and font f 713 ⟩

Used in section 710.

⟨ Contribute an entire group to the current parameter 399 ⟩ Used in section 392. ⟨ Contribute the recently matched tokens to the current parameter, and goto continue if a partial match is

still in effect; but abort if s = null 397 ⟩ Used in section 392.

⟨ Convert a final bin noad to an ord noad 729 ⟩ Used in sections 726 and 728.

⟨ Convert cur val to a lower level 429 ⟩ Used in section 413*. ⟨ Convert math glue to ordinary glue 732 ⟩ Used in section 730. ⟨ Convert nucleus (q) to an hlist and attach the sub/superscripts 754 ⟩ Used in section 728. ⟨ Convert string s into a new pseudo file 1487* ⟩ Used in section 1486*. ⟨ Copy editor command into dynamic string 1648* ⟩ Used in section 1640*. ⟨ Copy remainder of context to diagnostic file 1613* ⟩ Used in sections 318* and 319*. ⟨ Copy the tabskip glue between columns 795 ⟩ Used in section 791*. ⟨ Copy the templates from node cur loop into node p 794 ⟩ Used in section 793.

⟨ Copy the token list 466 ⟩ Used in section 465*. ⟨ Create command file 1656* ⟩ Used in section 1655*. ⟨ Create command file 1658* ⟩ Used in section 1655*.

⟨ Create a character node p for nucleus (q), possibly followed by a kern node for the italic correction, and set

delta to the italic correction if a subscript is present 755 ⟩ Used in section 754. ⟨ Create a character node q for the next character, but set q ← null if problems arise 1124 ⟩

Used in section 1123.

⟨ Create a new array element of type t with index i 1553* ⟩ Used in section 1552*. ⟨ Create a new glue specification whose width is cur val ; scan for its stretch and shrink components 462 ⟩

Used in section 461*.

⟨ Create a page insertion node with subtype(r) = qi (n), and include the glue correction for box n in the

current page state 1009 ⟩ Used in section 1008.

⟨ Create an active breakpoint representing the beginning of the paragraph 864* ⟩ Used in section 863*. ⟨ Create and append a discretionary node as an alternative to the unhyphenated word, and continue to

develop both branches until they become equivalent 914 ⟩ Used in section 913. ⟨ Create equal-width boxes x and z for the numerator and denominator, and compute the default amounts

shift up and shift down by which they are displaced from the baseline 744 ⟩ Used in section 743.

⟨ Create logical $ 1659* ⟩ Used in section 1658*.

⟨ Create names of symbols to be sought 1641* ⟩ Used in section 1640*. ⟨ Create new active nodes for the best feasible breaks just found 836 ⟩ Used in section 835. ⟨ Create the format ident , open the format file, and inform the user that dumping has begun 1328 ⟩

Used in section 1302.

⟨ Current mem equivalent of glue parameter number n 224 ⟩ Used in sections 152 and 154.

⟨ Deactivate node r 860 ⟩ Used in section 851*. ⟨ Declare ε-TEX procedures for expanding 1485*, 1543*, 1548*, 1552* ⟩ Used in section 366*. ⟨ Declare ε-TEX procedures for scanning 1416*, 1444*, 1445*, 1505*, 1514*, 1519* ⟩ Used in section 409*.

⟨ Declare ε-TEX procedures for token lists 1417*, 1486* ⟩ Used in section 464*.

⟨ Declare ε-TEX procedures for tracing and input 284*, 1395*, 1396*, 1489*, 1490*, 1507*, 1509*, 1510*, 1554*,

1556*, 1570*, 1571*, 1572*, 1573*, 1574* ⟩ Used in section 268*. ⟨ Declare ε-TEX procedures for use by main control 1390*, 1413*, 1429* ⟩ Used in section 815*. ⟨ Declare action procedures for use by main control 1043, 1047, 1049, 1050, 1051, 1054, 1060, 1061, 1064, 1069, 1070*,

1075*, 1079*, 1084, 1086, 1091, 1093, 1095, 1096*, 1099, 1101*, 1103, 1105*, 1110*, 1113, 1117, 1119, 1123, 1127, 1129, 1131, 1135, 1136, 1138*, 1142, 1151, 1155, 1159, 1160, 1163, 1165, 1172, 1174, 1176, 1181, 1191*, 1194*, 1200, 1211*, 1270, 1275*, 1279, 1288, 1293*, 1302, 1348*, 1376 ⟩ Used in section 1030.

⟨ Declare math construction procedures 734, 735, 736, 737, 738, 743, 749, 752, 756, 762* ⟩ Used in section 726.

⟨ Declare procedures for preprocessing hyphenation patterns 944, 948, 949, 953, 957, 959, 960*, 966* ⟩

Used in section 942.

⟨ Declare procedures needed for displaying the elements of mlists 691, 692, 694 ⟩ Used in section 179. ⟨ Declare procedures needed for expressions 1515*, 1520* ⟩ Used in section 461*.

⟨ Declare procedures needed in do extension 1349, 1350 ⟩ Used in section 1348*. ⟨ Declare procedures needed in hlist out , vlist out 1368, 1370, 1373, 1433*, 1452*, 1456* ⟩ Used in section 619*.

⟨ Declare procedures that scan font-related stuff 577, 578 ⟩ Used in section 409*. ⟨ Declare procedures that scan restricted classes of integers 433, 434, 435, 436, 437, 1544* ⟩ Used in section 409*. ⟨ Declare subprocedures for after math 1477* ⟩ Used in section 1194*.

⟨ Declare subprocedures for init math 1466*, 1471* ⟩ Used in section 1138*. ⟨ Declare subprocedures for line break 826, 829*, 877*, 895, 942 ⟩ Used in section 815*. ⟨ Declare subprocedures for prefixed command 1215, 1229, 1236*, 1243, 1244, 1245, 1246*, 1247*, 1257, 1265 ⟩

Used in section 1211*. ⟨ Declare subprocedures for scan expr 1526*, 1530*, 1532* ⟩ Used in section 1515*. ⟨ Declare subprocedures for var delimiter 709, 711, 712 ⟩ Used in section 706.

⟨ Declare the function called do marks 1558* ⟩ Used in section 977*. ⟨ Declare the function called fin mlist 1184 ⟩ Used in section 1174. ⟨ Declare the function called open fmt file 524 ⟩ Used in section 1303. ⟨ Declare the function called reconstitute 906 ⟩ Used in section 895. ⟨ Declare the procedure called align peek 785* ⟩ Used in section 800. ⟨ Declare the procedure called fire up 1012* ⟩ Used in section 994. ⟨ Declare the procedure called get preamble token 782 ⟩ Used in section 774. ⟨ Declare the procedure called handle right brace 1068 ⟩ Used in section 1030. ⟨ Declare the procedure called init span 787 ⟩ Used in section 786. ⟨ Declare the procedure called insert relax 379 ⟩ Used in section 366*. ⟨ Declare the procedure called macro call 389* ⟩ Used in section 366*. ⟨ Declare the procedure called print cmd chr 298* ⟩ Used in section 252. ⟨ Declare the procedure called print skip param 225 ⟩ Used in section 179. ⟨ Declare the procedure called runaway 306 ⟩ Used in section 119. ⟨ Declare the procedure called show token list 292 ⟩ Used in section 119.

⟨ Declare the open diag file procedure 1615* ⟩ Used in section 534*.

⟨ Decry the invalid character and goto restart 346 ⟩ Used in section 344.

⟨ Delete c − tokens and goto continue 88 ⟩ Used in section 84*.

⟨ Delete the page-insertion nodes 1019 ⟩ Used in section 1014*. ⟨ Delete an editor command file 1661* ⟩ Used in section 1655*. ⟨ Destroy the t nodes following q, and make r point to the following node 883 ⟩ Used in section 882. ⟨ Determine horizontal glue shrink setting, then return or goto common ending 664 ⟩ Used in section 657. ⟨ Determine horizontal glue stretch setting, then return or goto common ending 658 ⟩ Used in section 657. ⟨ Determine length of the editor command 1647* ⟩ Used in section 1640*. ⟨ Determine the displacement, d, of the left edge of the equation, with respect to the line size z, assuming

that l = false 1202* ⟩ Used in section 1199*. ⟨ Determine the shrink order 665 ⟩ Used in sections 664, 676, and 796. ⟨ Determine the stretch order 659 ⟩ Used in sections 658, 673, and 796.

⟨ Determine the value of height (r) and the appropriate glue setting; then return or goto

common ending 672 ⟩ Used in section 668.

⟨ Determine the value of width(r) and the appropriate glue setting; then return or goto common ending 657 ⟩

Used in section 649*.

⟨ Determine vertical glue shrink setting, then return or goto common ending 676 ⟩ Used in section 672. ⟨ Determine vertical glue stretch setting, then return or goto common ending 673 ⟩ Used in section 672. ⟨ Discard erroneous prefixes and return 1212 ⟩ Used in section 1211*. ⟨ Discard the prefixes and if they are irrelevant 1213* ⟩ Used in section 1211*. ⟨ Dispense with trivial cases of void or bad boxes 978 ⟩ Used in section 977*.

⟨ Display adjustment p 197 ⟩ Used in section 183. ⟨ Display box p 184* ⟩ Used in section 183. ⟨ Display choice node p 695 ⟩ Used in section 690.

⟨ Display discretionary p 195 ⟩ Used in section 183. ⟨ Display fraction noad p 697 ⟩ Used in section 690.

⟨ Display glue p 189 ⟩ Used in section 183.

⟨ Display if this box is never to be reversed 1438* ⟩ Used in section 184*.

⟨ Display insertion p 188 ⟩ Used in section 183. ⟨ Display kern p 191 ⟩ Used in section 183. ⟨ Display leaders p 190 ⟩ Used in section 189. ⟨ Display ligature p 193 ⟩ Used in section 183. ⟨ Display mark p 196* ⟩ Used in section 183. ⟨ Display math node p 192* ⟩ Used in section 183. ⟨ Display node p 183 ⟩ Used in section 182. ⟨ Display normal noad p 696* ⟩ Used in section 690. ⟨ Display penalty p 194 ⟩ Used in section 183. ⟨ Display rule p 187 ⟩ Used in section 183.

⟨ Display special fields of the unset node p 185 ⟩ Used in section 184*. ⟨ Display the current context 312 ⟩ Used in section 311*. ⟨ Display the insertion split cost 1011 ⟩ Used in section 1010. ⟨ Display the page break cost 1006 ⟩ Used in section 1005.

⟨ Display the token (m, c) 294* ⟩ Used in section 293. ⟨ Display the value of b 502 ⟩ Used in section 498*. ⟨ Display the value of glue set (p) 186* ⟩ Used in section 184*.

⟨ Display the whatsit node p 1356 ⟩ Used in section 183. ⟨ Display token p, and return if there are problems 293 ⟩ Used in section 292. ⟨ Dispose of dynamic strings used by Edit 1643* ⟩ Used in section 1640*. ⟨ Do first-pass processing based on type(q); goto done with noad if a noad has been fully processed, goto

check dimensions if it has been translated into new hlist (q), or goto done with node if a node has been

fully processed 728 ⟩ Used in section 727*.

⟨ Do ligature or kern command, returning to main lig loop or main loop wrapup or main loop move 1040 ⟩

Used in section 1039.

⟨ Do magic computation 320 ⟩ Used in section 292. ⟨ Do some work that has been queued up for 1374 ⟩ Used in section 1373. ⟨ Drop current token and complain that it was unmatched 1066 ⟩ Used in section 1064. ⟨ Dump a couple more things and the closing check word 1326 ⟩ Used in section 1302. ⟨ Dump constants for consistency check 1307* ⟩ Used in section 1302.

⟨ Dump regions 1 to 4 of eqtb 1315 ⟩ Used in section 1313. ⟨ Dump regions 5 and 6 of eqtb 1316 ⟩ Used in section 1313. ⟨ Dump the ε-TEX state 1388*, 1491* ⟩ Used in section 1307*.

⟨ Dump the array info for internal font number k 1322 ⟩ Used in section 1320.

⟨ Dump the dynamic memory 1311* ⟩ Used in section 1302.

⟨ Dump the font information 1320 ⟩ Used in section 1302.

⟨ Dump the hash table 1318 ⟩ Used in section 1313.

⟨ Dump the hyphenation tables 1324* ⟩ Used in section 1302.

⟨ Dump the string pool 1309 ⟩ Used in section 1302.

⟨ Dump the table of equivalents 1313 ⟩ Used in section 1302. ⟨ Either append the insertion node p after node q, and remove it from the current page, or delete

node(p) 1022 ⟩ Used in section 1020.

⟨ Either insert the material specified by node p into the appropriate box, or hold it for the next page; also

delete node p from the current page 1020 ⟩ Used in section 1014*. ⟨ Either process or set b to the value of a boolean condition 501* ⟩ Used in section 498*.

⟨ Empty the last bytes out of dvi buf 599* ⟩ Used in section 642*. ⟨ Enable ε-TEX, if requested 1379* ⟩ Used in section 1337*. ⟨ Ensure that box 255 is empty after output 1028 ⟩ Used in section 1026*. ⟨ Ensure that box 255 is empty before output 1015 ⟩ Used in section 1014*.

⟨ Ensure that trie max ≥ h + 256 954 ⟩ Used in section 953. ⟨ Ensure temp file not in use 1604* ⟩ Used in sections 82* and 530*.

⟨ Enter a hyphenation exception 939 ⟩ Used in section 935. ⟨ Enter all of the patterns into a linked trie, until coming to a right brace 961 ⟩ Used in section 960*. ⟨ Enter as many hyphenation exceptions as are listed, until coming to a right brace; then return 935 ⟩

Used in section 934*.

⟨ Enter skip blanks state, emit a space 349 ⟩ Used in section 347.

⟨ Error handling procedures 78, 81, 82*, 93, 94, 95 ⟩ Used in section 4*.

⟨ Evaluate the current expression 1525* ⟩ Used in section 1516*. ⟨ Examine node p in the hlist, taking account of its effect on the dimensions of the new box, or moving it to

the adjustment list; then advance p to the next node 651* ⟩ Used in section 649*. ⟨ Examine node p in the vlist, taking account of its effect on the dimensions of the new box; then advance p

to the next node 669 ⟩ Used in section 668.

⟨ Exit to operating system with final status 1600* ⟩ Used in section 1332*.

⟨ Expand a nonmacro 367* ⟩ Used in section 366*.

⟨ Expand macros in the token list and make link (def ref ) point to the result 1371 ⟩ Used in section 1370. ⟨ Expand the next part of the input 478* ⟩ Used in section 477. ⟨ Expand the token after the next token 368 ⟩ Used in section 367*. ⟨ Explain that too many dead cycles have occurred in a row 1024 ⟩ Used in section 1012*. ⟨ Express astonishment that no number was here 446 ⟩ Used in section 444. ⟨ Express consternation over the fact that no alignment is in progress 1128 ⟩ Used in section 1127. ⟨ Express shock at the missing left brace; goto found 475 ⟩ Used in section 474. ⟨ Extract command-line and qualifiers 1617* ⟩ Used in section 1332*. ⟨ Feed the macro body and its parameters to the scanner 390 ⟩ Used in section 389*.

⟨ Fetch a box dimension 420* ⟩ Used in section 413*.

⟨ Fetch a character code from some table 414 ⟩ Used in section 413*. ⟨ Fetch a font dimension 425 ⟩ Used in section 413*.

⟨ Fetch a font integer 426 ⟩ Used in section 413*.

⟨ Fetch a penalties array element 1599* ⟩ Used in section 423*.

⟨ Fetch a register 427* ⟩ Used in section 413*.

⟨ Fetch a token list or font identifier, provided that level = tok val 415* ⟩ Used in section 413*. ⟨ Fetch an internal dimension and goto attach sign, or fetch an internal integer 449 ⟩ Used in section 448. ⟨ Fetch an item in the current node, if appropriate 424* ⟩ Used in section 413*. ⟨ Fetch something on the page so far 421 ⟩ Used in section 413*.

⟨ Fetch the dead cycles or the insert penalties 419* ⟩ Used in section 413*. ⟨ Fetch the par shape size 423* ⟩ Used in section 413*. ⟨ Fetch the prev graf 422 ⟩ Used in section 413*. ⟨ Fetch the space factor or the prev depth 418 ⟩ Used in section 413*.

⟨ Find an active node with fewest demerits 874 ⟩ Used in section 873. ⟨ Find hyphen locations for the word in hc, or return 923 ⟩ Used in section 895. ⟨ Find optimal breakpoints 863* ⟩ Used in section 815*. ⟨ Find the best active node for the desired looseness 875 ⟩ Used in section 873. ⟨ Find the best way to split the insertion, and change type(r) to split up 1010 ⟩ Used in section 1008. ⟨ Find the glue specification, main p, for text spaces in the current font 1042 ⟩ Used in sections 1041 and 1043. ⟨ Finish an alignment in a display 1206* ⟩ Used in section 812.

⟨ Finish displayed math 1199* ⟩ Used in section 1194*.

⟨ Finish issuing a diagnostic message for an overfull or underfull hbox 663 ⟩ Used in section 649*. ⟨ Finish issuing a diagnostic message for an overfull or underfull vbox 675 ⟩ Used in section 668.

⟨ Finish line, emit a 351 ⟩ Used in section 347.

⟨ Finish line, emit a space 348 ⟩ Used in section 347.

⟨ Finish line, goto switch 350 ⟩ Used in section 347. ⟨ Finish math in text 1196 ⟩ Used in section 1194*. ⟨ Finish the file 642* ⟩ Used in section 1333*. ⟨ Finish the extensions 1378 ⟩ Used in section 1333*.

⟨ Finish the natural width computation 1468* ⟩ Used in section 1146*. ⟨ Finish the reversed hlist segment and goto done 1462* ⟩ Used in section 1461*. ⟨ Fire up the user’s output routine and return 1025 ⟩ Used in section 1012*. ⟨ Fix the reference count, if any, and negate cur val if negative 430 ⟩ Used in section 413*. ⟨ Flush the box from memory, showing statistics if requested 639 ⟩ Used in section 638*.

⟨ Flush the prototype box 1476* ⟩ Used in section 1199*. ⟨ Forbidden cases detected in main control 1048, 1098, 1111, 1144 ⟩ Used in section 1045.

⟨ Generate a down or right command for w and return 610 ⟩ Used in section 607. ⟨ Generate a y0 or z0 command in order to reuse a previous appearance of w 609 ⟩ Used in section 607.

⟨ Generate all ε-TEX primitives 1380*, 1391*, 1397*, 1400*, 1403*, 1406*, 1409*, 1418*, 1420*, 1423*, 1426*, 1431*,

1435*, 1480*, 1492*, 1495*, 1503*, 1511*, 1534*, 1538*, 1542*, 1594*, 1597* ⟩ Used in section 1379*.

⟨ Get ready to compress the trie 952* ⟩ Used in section 966*.

⟨ Get ready to start line breaking 816*, 827*, 834, 848 ⟩ Used in section 815*.

⟨ Get the first line of input and prepare to start 1337* ⟩ Used in section 1332*.

⟨ Get the next non-blank non-call token 406 ⟩ Used in sections 405, 441, 455, 503, 526, 577, 1045, 1517*, and 1518*.

⟨ Get the next non-blank non-relax non-call token 404 ⟩

Used in sections 403, 1078, 1084, 1151, 1160, 1211*, 1226*, and 1270.

⟨ Get the next non-blank non-sign token; set negative appropriately 441 ⟩ Used in sections 440, 448, and 461*. ⟨ Get the next token, suppressing expansion 358 ⟩ Used in section 357. ⟨ Get user’s advice and return 83 ⟩ Used in section 82*. ⟨ Give diagnostic information, if requested 1031 ⟩ Used in section 1030.

⟨ Give improper error 936 ⟩ Used in section 935. ⟨ Global variables 13, 20, 26*, 30*, 32, 39, 50*, 54*, 73*, 76, 79, 96*, 104, 115, 116, 117, 118, 124, 165, 173, 181, 213*, 246,

253, 256, 271, 286, 297, 301, 304, 305, 308, 309, 310, 333, 361, 382*, 387, 388, 410, 438, 447, 480, 489, 493, 512, 513*, 520*, 527, 532*, 539, 549, 550, 555, 592, 595*, 605, 616*, 646, 647, 661, 684, 719, 724, 764, 770, 814*, 821, 823, 825, 828, 833, 839, 847, 872, 892, 900, 905, 907, 921, 926, 943, 947, 950, 971, 980, 982*, 989, 1032, 1074, 1266, 1281, 1299, 1305*, 1331*, 1342, 1345, 1386*, 1394*, 1439*, 1483*, 1506*, 1547*, 1549*, 1568*, 1575*, 1591*, 1592*, 1603*, 1616*, 1619*, 1622*, 1624*, 1628*, 1637*, 1665* ⟩ Used in section 4*.

⟨ Go into display math mode 1145* ⟩ Used in section 1138*. ⟨ Go into ordinary math mode 1139 ⟩ Used in sections 1138* and 1142.

⟨ Go through the preamble list, determining the column widths and changing the alignrecords to dummy

unset boxes 801 ⟩ Used in section 800.

⟨ Grow more variable-size memory and goto restart 126 ⟩ Used in section 125.

⟨ Handle and goto done 1494* ⟩ Used in section 483*. ⟨ Handle or and return 1422* ⟩ Used in section 465*. ⟨ Handle saved items and goto done 1596* ⟩ Used in section 1110*.

⟨ Handle situations involving spaces, braces, changes of state 347 ⟩ Used in section 344. ⟨ If a line number class has ended, create new active nodes for the best feasible breaks in that class; then

return if r = last active, otherwise compute the new line width 835 ⟩ Used in section 829*. ⟨ If all characters of the family fit relative to h, then goto found , otherwise goto not found 955 ⟩

Used in section 953.

⟨ If an alignment entry has just ended, take appropriate action 342 ⟩ Used in section 341. ⟨ If an expanded code is present, reduce it and goto start cs 355 ⟩ Used in sections 354 and 356. ⟨ If dumping is not allowed, abort 1304 ⟩ Used in section 1302. ⟨ If instruction cur i is a kern with cur c, attach the kern after q; or if it is a ligature with cur c, combine

noads q and p appropriately; then return if the cursor has moved past a noad, or goto restart 753 ⟩

Used in section 752.

⟨ If no hyphens were found, return 902 ⟩ Used in section 895. ⟨ If node cur p is a legal breakpoint, call try break ; then update the active widths by including the glue in

glue ptr (cur p) 868 ⟩ Used in section 866*.

⟨ If node p is a legal breakpoint, check if this break is the best known, and goto done if p is null or if the

page-so-far is already too full to accept more stuff 972 ⟩ Used in section 970. ⟨ If node q is a style node, change the style and goto delete q ; otherwise if it is not a noad, put it into the

hlist, advance q, and goto done; otherwise set s to the size of noad q, set t to the associated type (ord noad . . inner noad ), and set pen to the associated penalty 761 ⟩ Used in section 760*.

⟨ If node r is of type delta node, update cur active width, set prev r and prev prev r , then goto continue 832 ⟩

Used in section 829*.

⟨ If the current list ends with a box node, delete it from the list and make cur box point to it; otherwise set

cur box ← null 1080* ⟩ Used in section 1079*.

⟨ If the current page is empty and node p is to be deleted, goto done1 ; otherwise use node p to update the state of the current page; if this node is an insertion, goto contribute; otherwise if this node is not a legal breakpoint, goto contribute or update heights ; otherwise set pi to the penalty associated with

this breakpoint 1000 ⟩ Used in section 997.

⟨ If the cursor is immediately followed by the right boundary, goto reswitch; if it’s followed by an invalid character, goto big switch; otherwise move the cursor one step to the right and goto main lig loop 1036 ⟩

Used in section 1034.

⟨ If the next character is a parameter number, make cur tok a match token; but if it is a left brace, store

‘left brace, end match’, set hash brace, and goto done 476 ⟩ Used in section 474.

⟨ If the preamble list has been traversed, check that the row has ended 792 ⟩ Used in section 791*. ⟨ If the right-hand side is a token parameter or token register, finish the assignment and goto done 1227* ⟩

Used in section 1226*.

⟨ If the string hyph word [h] is less than hc[1 . . hn], goto not found ; but if the two strings are equal, set hyf

to the hyphen positions and goto found 931 ⟩ Used in section 930. ⟨ If the string hyph word [h] is less than or equal to s, interchange (hyph word [h], hyph list [h]) with (s, p) 941 ⟩

Used in section 940.

⟨ If there’s a ligature or kern at the cursor position, update the data structures, possibly advancing j;

continue until the cursor moves 909 ⟩ Used in section 906. ⟨ If there’s a ligature/kern command relevant to cur l and cur r , adjust the text appropriately; exit to

main loop wrapup 1039 ⟩ Used in section 1034.

⟨ If this font has already been loaded, set f to the internal font number and goto common ending 1260 ⟩

Used in section 1257.

⟨ If this sup mark starts an expanded character like  or  , then goto reswitch, otherwise set

state ← mid line 352 ⟩ Used in section 344.

⟨ Ignore the fraction operation and complain about this ambiguous case 1183 ⟩ Used in section 1181.

⟨ Implement 1353 ⟩ Used in section 1348*. ⟨ Implement 1375 ⟩ Used in section 1348*. ⟨ Implement 1351 ⟩ Used in section 1348*. ⟨ Implement 1377 ⟩ Used in section 1348*. ⟨ Implement 1354 ⟩ Used in section 1348*. ⟨ Implement 1352 ⟩ Used in section 1348*.

⟨ Include token report within diagnostics file 1610* ⟩ Used in section 314*. ⟨ Incorporate a whatsit node into a vbox 1359 ⟩ Used in section 669. ⟨ Incorporate a whatsit node into an hbox 1360 ⟩ Used in section 651*. ⟨ Incorporate box dimensions into the dimensions of the hbox that will contain it 653 ⟩ Used in section 651*. ⟨ Incorporate box dimensions into the dimensions of the vbox that will contain it 670 ⟩ Used in section 669. ⟨ Incorporate character dimensions into the dimensions of the hbox that will contain it, then move to the

next node 654 ⟩ Used in section 651*.

⟨ Incorporate glue into the horizontal totals 656 ⟩ Used in section 651*.

⟨ Incorporate glue into the vertical totals 671 ⟩ Used in section 669. ⟨ Increase the number of parameters in the last font 580 ⟩ Used in section 578. ⟨ Indicate offending character 1612* ⟩ Used in section 317*. ⟨ Initialize additional fields of the first active node 1578* ⟩ Used in section 864*. ⟨ Initialize for hyphenating a paragraph 891* ⟩ Used in section 863*.

⟨ Initialize table entries (done by only) 164, 222, 228, 232*, 240, 250, 258, 552, 946, 951, 1216, 1301, 1369,

1387*, 1551*, 1587* ⟩ Used in section 8*. ⟨ Initialize the LR stack 1446* ⟩ Used in sections 619*, 649*, and 1467*.

⟨ Initialize the current page, insert the glue ahead of p, and goto continue 1001 ⟩

Used in section 1000.

⟨ Initialize the input routines 331* ⟩ Used in section 1337*.

⟨ Initialize the output routines 55, 61*, 528, 533 ⟩ Used in section 1332*. ⟨ Initialize the print selector based on interaction 75 ⟩ Used in sections 1265 and 1337*.

⟨ Initialize the special list heads and constant nodes 790, 797, 820, 981, 988 ⟩ Used in section 164. ⟨ Initialize variables as ship out begins 617 ⟩ Used in section 640. ⟨ Initialize variables for ε-TEX compatibility mode 1545* ⟩ Used in sections 1387* and 1389*. ⟨ Initialize variables for ε-TEX extended mode 1546* ⟩ Used in sections 1379* and 1389*. ⟨ Initialize whatever TEX might access 8* ⟩ Used in section 4*. ⟨ Initiate input from new pseudo file 1488* ⟩ Used in section 1486*. ⟨ Initiate or terminate input from a file 378* ⟩ Used in section 367*. ⟨ Initiate the construction of an hbox or vbox, then return 1083 ⟩ Used in section 1079*. ⟨ Input and store tokens from the next line of the file 483* ⟩ Used in section 482*. ⟨ Input for from the terminal 484 ⟩ Used in section 483*. ⟨ Input from external file, goto restart if no input found 343 ⟩ Used in section 341. ⟨ Input from token list, goto restart if end of list or if a parameter needs to be expanded 357 ⟩

Used in section 341.

⟨ Input the first line of read file[m] 485 ⟩ Used in section 483*. ⟨ Input the next line of read file[m] 486 ⟩ Used in section 483*. ⟨ Insert LR nodes at the beginning of the current line and adjust the LR stack based on LR nodes in this

line 1441* ⟩ Used in section 880*.

⟨ Insert LR nodes at the end of the current line 1443* ⟩ Used in section 880*. ⟨ Insert a delta node to prepare for breaks at cur p 843 ⟩ Used in section 836. ⟨ Insert a delta node to prepare for the next active node 844 ⟩ Used in section 836. ⟨ Insert a dummy noad to be sub/superscripted 1177 ⟩ Used in section 1176. ⟨ Insert a new active node from best place[fit class ] to cur p 845* ⟩ Used in section 836. ⟨ Insert a new control sequence after p, then make p point to it 260 ⟩ Used in section 259. ⟨ Insert a new pattern into the linked trie 963 ⟩ Used in section 961. ⟨ Insert a new trie node between q and p, and make p point to it 964 ⟩ Used in sections 963, 1588*, and 1589*. ⟨ Insert a token containing frozen endv 375 ⟩ Used in section 366*. ⟨ Insert a token saved by , if any 1269 ⟩ Used in section 1211*. ⟨ Insert glue for split top skip and set p ← null 969 ⟩ Used in section 968*. ⟨ Insert hyphens as specified in hyph list [h] 932 ⟩ Used in section 931. ⟨ Insert macro parameter and goto restart 359 ⟩ Used in section 357. ⟨ Insert the appropriate mark text into the scanner 386* ⟩ Used in section 367*. ⟨ Insert the current list into its environment 812 ⟩ Used in section 800. ⟨ Insert the pair (s, p) into the exception table 940 ⟩ Used in section 939. ⟨ Insert the ⟨v_{j}⟩ template and goto restart 789 ⟩ Used in section 342. ⟨ Insert token p into TEX’s input 326* ⟩ Used in section 282*. ⟨ Interpret code c and return if done 84* ⟩ Used in section 83. ⟨ Interpret exit status of editor 1644* ⟩ Used in section 1640*. ⟨ Introduce new material from the terminal and return 87 ⟩ Used in section 84*. ⟨ Invoke callable LSEdit or TPU 1646* ⟩ Used in section 1642*.

⟨ Invoke callable editor 1655* ⟩ Used in section 1652*.

⟨ Invoke editor in a sub-process 1664* ⟩ Used in section 1652*. ⟨ Issue an error message if cur val = fmem ptr 579 ⟩ Used in section 578. ⟨ Justify the line ending at breakpoint cur p, and append it to the current vertical list, together with

associated penalties and other insertions 880* ⟩ Used in section 877*. ⟨ Labels in the outer block 6 ⟩ Used in section 4*.

⟨ Last-minute procedures 1333*, 1335*, 1336*, 1338, 1601*, 1620*, 1621*, 1651* ⟩ Used in section 1330.

⟨ Lengthen the preamble periodically 793 ⟩ Used in section 792. ⟨ Let cur h be the position of the first box, and set leader wd + lx to the spacing between corresponding

parts of boxes 627 ⟩ Used in section 626*.

⟨ Let cur v be the position of the first box, and set leader ht + lx to the spacing between corresponding

parts of boxes 636 ⟩ Used in section 635.

⟨ Let d be the natural width of node p; if the node is “visible,” goto found ; if the node is glue that stretches

or shrinks, set v ← max dimen 1147* ⟩ Used in section 1146*.

⟨ Let d be the natural width of this glue; if stretching or shrinking, set v ← max dimen; goto found in the

case of leaders 1148 ⟩ Used in section 1147*.

⟨ Let d be the width of the whatsit p 1361 ⟩ Used in section 1147*. ⟨ Let j be the prototype box for the display 1473* ⟩ Used in section 1467*. ⟨ Let n be the largest legal code value, based on cur chr 1233 ⟩ Used in section 1232. ⟨ Link node p into the current page and goto done 998 ⟩ Used in section 997. ⟨ Load shareable image and call the editor 1642* ⟩ Used in section 1640*. ⟨ Local variables for dimension calculations 450 ⟩ Used in section 448. ⟨ Local variables for finishing a displayed formula 1198, 1474* ⟩ Used in section 1194*. ⟨ Local variables for formatting calculations 315 ⟩ Used in section 311*.

⟨ Local variables for hyphenation 901, 912, 922, 929 ⟩ Used in section 895.

⟨ Local variables for initialization 19, 163, 927 ⟩ Used in section 4*. ⟨ Local variables for line breaking 862, 893 ⟩ Used in section 815*. ⟨ Look ahead for another character, or leave lig stack empty if there’s none there 1038 ⟩ Used in section 1034. ⟨ Look at all the marks in nodes before the break, and set the final link to null at the break 979* ⟩

Used in section 977*.

⟨ Look at the list of characters starting with x in font g; set f and c whenever a better character is found;

goto found as soon as a large enough variant is encountered 708 ⟩ Used in section 707. ⟨ Look at the other stack entries until deciding what sort of command to generate; goto found if node

p is a “hit” 611 ⟩ Used in section 607.

⟨ Look at the variants of (z, x); set f and c whenever a better character is found; goto found as soon as a

large enough variant is encountered 707 ⟩ Used in section 706. ⟨ Look for parameter number or ## 479 ⟩ Used in section 477. ⟨ Look for the word hc[1 . . hn] in the exception table, and goto found (with hyf containing the hyphens) if

an entry is found 930 ⟩ Used in section 923.

⟨ Look up the characters of list n in the hash table, and set cur cs 1501* ⟩ Used in section 1500*. ⟨ Look up the characters of list r in the hash table, and set cur cs 374 ⟩ Used in section 372. ⟨ Make a copy of node p in node r 205 ⟩ Used in section 204. ⟨ Make a ligature node, if ligature present ; insert a null discretionary, if appropriate 1035 ⟩

Used in section 1034.

⟨ Make a partial copy of the whatsit node p and make r point to it; set words to the number of initial words

not yet copied 1357 ⟩ Used in sections 206 and 1466*.

⟨ Make a second pass over the mlist, removing all noads and inserting the proper spacing and penalties 760* ⟩

Used in section 726.

⟨ Make final adjustments and goto done 576 ⟩ Used in section 562.

⟨ Make node p look like a char node and goto reswitch 652 ⟩ Used in sections 622*, 651*, and 1147*.

⟨ Make sure that f is in the proper range 1523* ⟩ Used in section 1516*. ⟨ Make sure that page max depth is not exceeded 1003 ⟩ Used in section 997.

⟨ Make sure that pi is in the proper range 831 ⟩ Used in section 829*. ⟨ Make the contribution list empty by setting its tail to contrib head 995 ⟩ Used in section 994. ⟨ Make the first 256 strings 48 ⟩ Used in section 47*. ⟨ Make the height of box y equal to h 739 ⟩ Used in section 738. ⟨ Make the running dimensions in rule q extend to the boundaries of the alignment 806 ⟩ Used in section 805. ⟨ Make the unset node r into a vlist node of height w, setting the glue as if the height were t 811 ⟩

Used in section 808*.

⟨ Make the unset node r into an hlist node of width w, setting the glue as if the width were t 810 ⟩

Used in section 808*.

⟨ Make variable b point to a box for (f, c) 710 ⟩ Used in section 706. ⟨ Manufacture a control sequence name 372 ⟩ Used in section 367*. ⟨ Math-only cases in non-math modes, or vice versa 1046 ⟩ Used in section 1045. ⟨ Merge the widths in the span nodes of q with those of p, destroying the span nodes of q 803 ⟩

Used in section 801.

⟨ Modify the end of the line to reflect the nature of the break and to include ; also set the proper

value of disc break 881* ⟩ Used in section 880*.

⟨ Modify the glue specification in main p according to the space factor 1044 ⟩ Used in section 1043. ⟨ Move down or output leaders 634* ⟩ Used in section 631. ⟨ Move node p to the current page; if it is time for a page break, put the nodes following the break back onto

the contribution list, and return to the user’s output routine if there is one 997 ⟩ Used in section 994. ⟨ Move node p to the new list and go to the next node; or goto done if the end of the reflected segment has

been reached 1457* ⟩ Used in section 1456*.

⟨ Move pointer s to the end of the current list, and set replace count (r) appropriately 918 ⟩

Used in section 914.

⟨ Move right or output leaders 625* ⟩ Used in section 622*. ⟨ Move the characters of a ligature node to hu and hc; but goto done3 if they are not all letters 898* ⟩

Used in section 897*.

⟨ Move the cursor past a pseudo-ligature, then goto main loop lookahead or main lig loop 1037 ⟩

Used in section 1034. ⟨ Move the data into trie 958* ⟩ Used in section 966*.

⟨ Move the non-char node p to the new list 1458* ⟩ Used in section 1457*. ⟨ Move to next line of file, or goto restart if there is no next line, or return if a line has finished 360 ⟩

Used in section 343.

⟨ Negate a boolean conditional and goto reswitch 1498* ⟩ Used in section 367*. ⟨ Negate all three glue components of cur val 431 ⟩ Used in sections 430 and 1513*. ⟨ Nullify width(q) and the tabskip glue following this column 802 ⟩ Used in section 801.

⟨ Numbered cases for debug help 1339 ⟩ Used in section 1338. ⟨ Open tfm file for input 563* ⟩ Used in section 562. ⟨ Other local variables for try break 830, 1577* ⟩ Used in section 829*. ⟨ Output a box in a vlist 632* ⟩ Used in section 631. ⟨ Output a box in an hlist 623* ⟩ Used in section 622*.

⟨ Output a leader box at cur h, then advance cur h by leader wd + lx 628* ⟩ Used in section 626*. ⟨ Output a leader box at cur v , then advance cur v by leader ht + lx 637* ⟩ Used in section 635. ⟨ Output a rule in a vlist, goto next p 633* ⟩ Used in section 631. ⟨ Output a rule in an hlist 624 ⟩ Used in section 622*. ⟨ Output leaders in a vlist, goto fin rule if a rule or to next p if done 635 ⟩ Used in section 634*. ⟨ Output leaders in an hlist, goto fin rule if a rule or to next p if done 626* ⟩ Used in section 625*. ⟨ Output node p for hlist out and move to the next node, maintaining the condition cur v = base line 620* ⟩

Used in section 619*.

⟨ Output node p for vlist out and move to the next node, maintaining the condition cur h = left edge 630 ⟩

Used in section 629*.

⟨ Output statistics about this job 1334 ⟩ Used in section 1333*.

⟨ Output the font definitions for all fonts that were used 643 ⟩ Used in section 642*. ⟨ Output the font name whose internal number is f 603 ⟩ Used in section 602. ⟨ Output the location to the diagnostics file 1607* ⟩ Used in section 313*. ⟨ Output the non-char node p for hlist out and move to the next node 622* ⟩ Used in section 620*.

⟨ Output the non-char node p for vlist out 631 ⟩ Used in section 630.

⟨ Output the whatsit node p in a vlist 1366 ⟩ Used in section 631. ⟨ Output the whatsit node p in an hlist 1367 ⟩ Used in section 622*.

⟨ Pack all stored hyph codes 1590* ⟩ Used in section 966*.

⟨ Pack the family into trie relative to h 956 ⟩ Used in section 953. ⟨ Package an unset box for the current column and record its width 796 ⟩ Used in section 791*.

⟨ Package the display line 1479* ⟩ Used in section 1477*.

⟨ Package the preamble list, to determine the actual tabskip glue amounts, and let p point to this prototype

box 804 ⟩ Used in section 800.

⟨ Perform computations for last line and goto found 1579* ⟩ Used in section 852*. ⟨ Perform the default output routine 1023* ⟩ Used in section 1012*. ⟨ Pontificate about improper alignment in display 1207 ⟩ Used in section 1206*.

⟨ Pop the condition stack 496* ⟩ Used in sections 498*, 500, 509, and 510*.

⟨ Pop the expression stack and goto found 1522* ⟩ Used in section 1516*. ⟨ Prepare all the boxes involved in insertions to act as queues 1018 ⟩ Used in section 1014*. ⟨ Prepare for display after a non-empty paragraph 1467* ⟩ Used in section 1146*. ⟨ Prepare for display after an empty paragraph 1465* ⟩ Used in section 1145*. ⟨ Prepare to copy tokens to the diagnostic region 1608* ⟩ Used in sections 313* and 314*. ⟨ Prepare to deactivate node r, and goto deactivate unless there is a reason to consider lines of text from r

to cur p 854 ⟩ Used in section 851*.

⟨ Prepare to insert a token that matches cur group, and print what it is 1065 ⟩ Used in section 1064. ⟨ Prepare to move a box or rule node to the current page, then goto contribute 1002 ⟩ Used in section 1000. ⟨ Prepare to move whatsit p to the current page, then goto contribute 1364 ⟩ Used in section 1000. ⟨ Preset anticipated exit statuses of the called editor 1645* ⟩ Used in section 1642*. ⟨ Print a short indication of the contents of node p 175* ⟩ Used in section 174. ⟨ Print a symbolic description of the new break node 846* ⟩ Used in section 845*. ⟨ Print a symbolic description of this feasible break 856 ⟩ Used in section 855*. ⟨ Print additional data in the new active node 1585* ⟩ Used in section 846*.

⟨ Print either ‘  ’ or ‘ ’ or ‘  ’ or ‘  ’, and insert tokens that should lead to

recovery 339 ⟩ Used in section 338.

⟨ Print location of current line 313* ⟩ Used in section 312. ⟨ Print newly busy locations 171 ⟩ Used in section 167. ⟨ Print string s as an error message 1283 ⟩ Used in section 1279. ⟨ Print string s on the terminal 1280 ⟩ Used in section 1279. ⟨ Print the banner line, including the date and time 536* ⟩ Used in section 534*. ⟨ Print the font identifier for font (p) 267 ⟩ Used in sections 174 and 176. ⟨ Print the help information and goto continue 89 ⟩ Used in section 84*. ⟨ Print the list between printed node and cur p, then set printed node ← cur p 857 ⟩ Used in section 856. ⟨ Print the menu of available options 85 ⟩ Used in section 84*. ⟨ Print the result of command c 472* ⟩ Used in section 470*. ⟨ Print two lines using the tricky pseudoprinted information 317* ⟩ Used in section 312. ⟨ Print type of token list 314* ⟩ Used in section 312. ⟨ Process an active-character control sequence and set state ← mid line 353 ⟩ Used in section 344. ⟨ Process an expression and return 1513* ⟩ Used in section 424*. ⟨ Process node-or-noad q as much as possible in preparation for the second pass of mlist to hlist , then move

to the next item in the mlist 727* ⟩ Used in section 726. ⟨ Process whatsit p in vert break loop, goto not found 1365 ⟩ Used in section 973.

⟨ Prune the current list, if necessary, until it contains only char node, kern node, hlist node, vlist node, rule node, and ligature node items; set n to the length of the list, and set q to the list’s tail 1121 ⟩

Used in section 1119.

⟨ Prune unwanted nodes at the beginning of the next line 879* ⟩ Used in section 877*.

⟨ Pseudoprint the line 318* ⟩ Used in section 312.

⟨ Pseudoprint the token list 319* ⟩ Used in section 312. ⟨ Push the condition stack 495 ⟩ Used in section 498*. ⟨ Push the expression stack and goto restart 1521* ⟩ Used in section 1518*.

⟨ Put each of TEX’s primitives into the hash table 226, 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, 1344 ⟩ Used in section 1336*.

⟨ Put help message on the transcript file 90 ⟩ Used in section 82*. ⟨ Put the characters hu[i + 1 . .] into post break (r), appending to this list and to major tail until

synchronization has been achieved 916 ⟩ Used in section 914. ⟨ Put the characters hu[l . . i] and a hyphen into pre break (r) 915 ⟩ Used in section 914. ⟨ Put the fraction into a box with its delimiters, and make new hlist (q) point to it 748 ⟩ Used in section 743. ⟨ Put the glue at the left and detach this line 887 ⟩ Used in section 880*. ⟨ Put the optimal current page into box 255, update first mark and bot mark , append insertions to their

boxes, and put the remaining nodes back on the contribution list 1014* ⟩ Used in section 1012*. ⟨ Put the (positive) ‘at’ size into s 1259 ⟩ Used in section 1258. ⟨ Put the glue after node q 886 ⟩ Used in section 881*. ⟨ Read and check the font data; abort if the file is malformed; if there’s no room for this font, say so

and goto done; otherwise incr (font ptr ) and goto done 562 ⟩ Used in section 560. ⟨ Read box dimensions 571 ⟩ Used in section 562. ⟨ Read character data 569 ⟩ Used in section 562.

⟨ Read extensible character recipes 574 ⟩ Used in section 562.

⟨ Read font parameters 575* ⟩ Used in section 562.

⟨ Read ligature/kern program 573 ⟩ Used in section 562. ⟨ Read next line of file into buffer , or goto restart if the file has ended 362* ⟩ Used in section 360. ⟨ Read one string, but return false if the string memory space is getting too tight for comfort 52* ⟩

Used in section 51*.

⟨ Read the first line of the new file 538 ⟩ Used in section 537*. ⟨ Read the other strings from the file and return true, or give an error message and return

false 51* ⟩ Used in section 47*.

⟨ Read the values of  and  and put them into the string pool 514* ⟩

Used in section 1337*. ⟨ Read the header 568 ⟩ Used in section 562. ⟨ Read the size fields 565 ⟩ Used in section 562.

⟨ Readjust the height and depth of cur box , for 1087 ⟩ Used in section 1086. ⟨ Reconstitute nodes for the hyphenated word, inserting discretionary hyphens 913 ⟩ Used in section 903. ⟨ Record a new feasible break 855* ⟩ Used in section 851*. ⟨ Recover from an unbalanced output routine 1027 ⟩ Used in section 1026*. ⟨ Recover from an unbalanced write command 1372 ⟩ Used in section 1371.

⟨ Recycle node p 999* ⟩ Used in section 997.

⟨ Remove the last box, unless it’s part of a discretionary 1081 ⟩ Used in section 1080*. ⟨ Remove version number from file specification 1662* ⟩ Used in section 1651*. ⟨ Replace nodes ha . . hb by a sequence of nodes that includes the discretionary hyphens 903 ⟩

Used in section 895.

⟨ Replace the tail of the list by p 1187 ⟩ Used in section 1186. ⟨ Replace z by z′ and compute α, β 572 ⟩ Used in section 571.

⟨ Report LR problems 1449* ⟩ Used in sections 1448* and 1463*.

⟨ Report a runaway argument and abort 396 ⟩ Used in sections 392 and 399.

⟨ Report a tight hbox and goto common ending , if this box is sufficiently bad 667 ⟩ Used in section 664. ⟨ Report a tight vbox and goto common ending , if this box is sufficiently bad 678 ⟩ Used in section 676. ⟨ Report an extra right brace and goto continue 395 ⟩ Used in section 392. ⟨ Report an improper use of the macro and abort 398 ⟩ Used in section 397. ⟨ Report an overfull hbox and goto common ending , if this box is sufficiently bad 666 ⟩ Used in section 664. ⟨ Report an overfull vbox and goto common ending , if this box is sufficiently bad 677 ⟩ Used in section 676. ⟨ Report an underfull hbox and goto common ending , if this box is sufficiently bad 660 ⟩ Used in section 658. ⟨ Report an underfull vbox and goto common ending , if this box is sufficiently bad 674 ⟩ Used in section 673. ⟨ Report location within source file to diagnostics 1609* ⟩ Used in section 313*. ⟨ Report overflow of the input buffer, and abort 35 ⟩ Used in sections 31* and 1489*. ⟨ Report that an invalid delimiter code is being changed to null; set cur val ← 0 1161 ⟩ Used in section 1160. ⟨ Report that the font won’t be loaded 561 ⟩ Used in section 560. ⟨ Report that this dimension is out of range 460 ⟩ Used in section 448. ⟨ Resume the page builder after an output routine has come to an end 1026* ⟩ Used in section 1100. ⟨ Retrieve the prototype box 1475* ⟩ Used in section 1194*. ⟨ Reverse an hlist segment and goto reswitch 1455* ⟩ Used in section 1450*. ⟨ Reverse the complete hlist and set the subtype to reversed 1454* ⟩ Used in section 619*. ⟨ Reverse the links of the relevant passive nodes, setting cur p to the first breakpoint 878 ⟩

Used in section 877*.

⟨ Save printed character for diagnostic messages 1602* ⟩ Used in section 58*. ⟨ Scan a control sequence and set state ← skip blanks or mid line 354 ⟩ Used in section 344. ⟨ Scan a factor f of type o or start a subexpression 1518* ⟩ Used in section 1516*. ⟨ Scan a numeric constant 444 ⟩ Used in section 440. ⟨ Scan a parameter until its delimiter string has been found; or, if s = null , simply scan the delimiter

string 392 ⟩ Used in section 391.

⟨ Scan a subformula enclosed in braces and return 1153 ⟩ Used in section 1151. ⟨ Scan ahead in the buffer until finding a nonletter; if an expanded code is encountered, reduce it and

goto start cs ; otherwise if a multiletter control sequence is found, adjust cur cs and loc, and goto

found 356 ⟩ Used in section 354.

⟨ Scan an alphabetic character code into cur val 442 ⟩ Used in section 440.

⟨ Scan an optional space 443 ⟩ Used in sections 442, 448, 455, and 1200.

⟨ Scan and build the body of the token list; goto found when finished 477 ⟩ Used in section 473. ⟨ Scan and build the parameter part of the macro definition 474 ⟩ Used in section 473. ⟨ Scan and evaluate an expression e of type l 1516* ⟩ Used in section 1515*. ⟨ Scan decimal fraction 452 ⟩ Used in section 448. ⟨ Scan file name in the buffer 531 ⟩ Used in section 530*. ⟨ Scan for all other units and adjust cur val and f accordingly; goto done in the case of scaled points 458 ⟩

Used in section 453.

⟨ Scan for units; goto attach fraction if found 454 ⟩ Used in section 453.

⟨ Scan for units and goto attach fraction 456 ⟩ Used in section 453.

⟨ Scan for units that are internal dimensions; goto attach sign with cur val set if found 455 ⟩

Used in section 453.

⟨ Scan preamble text until cur cmd is tab mark or car ret , looking for changes in the tabskip glue; append

an alignrecord to the preamble list 779 ⟩ Used in section 777. ⟨ Scan the argument for command c 471* ⟩ Used in section 470*. ⟨ Scan the font size specification 1258 ⟩ Used in section 1257. ⟨ Scan the next operator and set o 1517* ⟩ Used in section 1516*. ⟨ Scan the parameters and make link (r) point to the macro body; but return if an illegal is

detected 391 ⟩ Used in section 389*.

⟨ Scan the preamble and record it in the preamble list 777 ⟩ Used in section 774. ⟨ Scan the template ⟨u_{j}⟩, putting the resulting token list in hold head 783 ⟩ Used in section 779. ⟨ Scan the template ⟨v_{j}⟩, putting the resulting token list in hold head 784 ⟩ Used in section 779.

⟨ Scan units and set cur val to x · (cur val + f/2^{16}), where there are x sp per unit; goto attach sign if the

units are internal 453 ⟩ Used in section 448.

⟨ Search eqtb for equivalents equal to p 255 ⟩ Used in section 172. ⟨ Search hyph list for pointers to p 933 ⟩ Used in section 172. ⟨ Search save stack for equivalents that point to p 285 ⟩ Used in section 172. ⟨ Select the appropriate case and return or goto common ending 509 ⟩ Used in section 501*.

⟨ Set initial values of key variables 21, 23*, 24, 74, 77, 80, 97*, 166, 215*, 254, 257, 272, 287, 383, 439, 481, 490, 521*, 551, 556, 593, 596, 606, 648, 662, 685, 771, 928, 990, 1033, 1267, 1282, 1300, 1343, 1440*, 1484*, 1550*, 1569*, 1593*, 1638*, 1666* ⟩ Used in section 8*.

⟨ Set line length parameters in preparation for hanging indentation 849 ⟩ Used in section 848. ⟨ Set the glue in all the unset boxes of the current list 805 ⟩ Used in section 800. ⟨ Set the glue in node r and change it from an unset node 808* ⟩ Used in section 807*. ⟨ Set the unset box q and the unset boxes in it 807* ⟩ Used in section 805. ⟨ Set the value of b to the badness for shrinking the line, and compute the corresponding fit class 853 ⟩

Used in section 851*.

⟨ Set the value of b to the badness for stretching the line, and compute the corresponding fit class 852* ⟩

Used in section 851*.

⟨ Set the value of b to the badness of the last line for shrinking, compute the corresponding fit class , ∧goto

found 1581* ⟩ Used in section 1579*.

⟨ Set the value of b to the badness of the last line for stretching, compute the corresponding fit class , ∧goto

found 1580* ⟩ Used in section 1579*. ⟨ Set the value of output penalty 1013 ⟩ Used in section 1012*.

⟨ Set the value of x to the text direction before the display 1464* ⟩ Used in sections 1465* and 1467*. ⟨ Set up data structures with the cursor following position j 908 ⟩ Used in section 906. ⟨ Set up the hlist for the display line 1478* ⟩ Used in section 1477*. ⟨ Set up the values of cur size and cur mu, based on cur style 703 ⟩

Used in sections 720, 726, 727*, 730, 754, 760*, 762*, and 763.

⟨ Set variable c to the current escape character 243 ⟩ Used in section 63. ⟨ Set variable w to indicate if this case should be reported 1508* ⟩ Used in sections 1507* and 1509*.

⟨ Ship box p out 640 ⟩ Used in section 638*.

⟨ Show equivalent n, in region 1 or 2 223 ⟩ Used in section 252. ⟨ Show equivalent n, in region 3 229 ⟩ Used in section 252. ⟨ Show equivalent n, in region 4 233* ⟩ Used in section 252. ⟨ Show equivalent n, in region 5 242 ⟩ Used in section 252. ⟨ Show equivalent n, in region 6 251 ⟩ Used in section 252. ⟨ Show the auxiliary field, a 219 ⟩ Used in section 218.

⟨ Show the box context 1415* ⟩ Used in section 1413*.

⟨ Show the box packaging info 1414* ⟩ Used in section 1413*. ⟨ Show the current contents of a box 1296* ⟩ Used in section 1293*. ⟨ Show the current meaning of a token, then goto common ending 1294 ⟩ Used in section 1293*. ⟨ Show the current value of some parameter or register, then goto common ending 1297 ⟩

Used in section 1293*.

⟨ Show the font identifier in eqtb[n] 234 ⟩ Used in section 233*. ⟨ Show the halfword code in eqtb[n] 235 ⟩ Used in section 233*. ⟨ Show the status of the current page 986 ⟩ Used in section 218. ⟨ Show the text of the macro being expanded 401 ⟩ Used in section 389*. ⟨ Simplify a trivial box 721 ⟩ Used in section 720.

⟨ Skip to or , then goto common ending 500 ⟩ Used in section 498*.

⟨ Skip to node ha, or goto done1 if no hyphenation should be attempted 896* ⟩ Used in section 894. ⟨ Skip to node hb, putting letters into hu and hc 897* ⟩ Used in section 894. ⟨ Sort p into the list starting at rover and advance p to rlink (p) 132 ⟩ Used in section 131. ⟨ Sort the hyphenation op tables into proper order 945 ⟩ Used in section 952*.

⟨ Split off part of a vertical box, make cur box point to it 1082* ⟩ Used in section 1079*. ⟨ Split the context line display 1611* ⟩ Used in section 317*. ⟨ Squeeze the equation as much as possible; if there is an equation number that should go on a separate line

by itself, set e ← 0 1201 ⟩ Used in section 1199*. ⟨ Start a new current page 991* ⟩ Used in sections 215* and 1017.

⟨ Store additional data for this feasible break 1583* ⟩ Used in section 855*. ⟨ Store additional data in the new active node 1584* ⟩ Used in section 845*.

⟨ Store cur box in a box register 1077* ⟩ Used in section 1075*.

⟨ Store maximum values in the hyf table 924 ⟩ Used in section 923. ⟨ Store save stack [save ptr ] in eqtb[p], unless eqtb[p] holds a global value 283 ⟩ Used in section 282*.

⟨ Store all current lc code values 1589* ⟩ Used in section 1588*.

⟨ Store hyphenation codes for current language 1588* ⟩ Used in section 960*. ⟨ Store the current token, but goto continue if it is a blank space that would become an undelimited

parameter 393 ⟩ Used in section 392. ⟨ Subtract glue from break width 838 ⟩ Used in section 837.

⟨ Subtract the width of node v from break width 841 ⟩ Used in section 840. ⟨ Suppress expansion of the next token 369 ⟩ Used in section 367*. ⟨ Swap the subscript and superscript into box x 742 ⟩ Used in section 738. ⟨ Switch to a larger accent if available and appropriate 740 ⟩ Used in section 738. ⟨ Tell the user what has run away and try to recover 338 ⟩ Used in section 336. ⟨ Terminate an LSE diagnostic report 1606* ⟩ Used in section 311*. ⟨ Terminate the current conditional and skip to 510* ⟩ Used in section 367*. ⟨ Test box register status 505* ⟩ Used in section 501*. ⟨ Test if an integer is odd 504 ⟩ Used in section 501*. ⟨ Test if two characters match 506 ⟩ Used in section 501*. ⟨ Test if two macro texts match 508 ⟩ Used in section 507. ⟨ Test if two tokens match 507 ⟩ Used in section 501*. ⟨ Test relation between integers or dimensions 503 ⟩ Used in section 501*.

⟨ The em width for cur font 558 ⟩ Used in section 455. ⟨ The x-height for cur font 559 ⟩ Used in section 455.

⟨ Tidy up the parameter just scanned, and tuck it away 400 ⟩ Used in section 392. ⟨ Transfer node p to the adjustment list 655 ⟩ Used in section 651*. ⟨ Transplant the post-break list 884 ⟩ Used in section 882. ⟨ Transplant the pre-break list 885 ⟩ Used in section 882.

⟨ Treat cur chr as an active character 1152 ⟩ Used in sections 1151 and 1155.

⟨ Try the final line break at the end of the paragraph, and goto done if the desired breakpoints have been

found 873 ⟩ Used in section 863*.

⟨ Try to allocate within node p and its physical successors, and goto found if allocation was possible 127 ⟩

Used in section 125.

⟨ Try to break after a discretionary fragment, then goto done5 869 ⟩ Used in section 866*. ⟨ Try to get a different log file name 535* ⟩ Used in section 534*. ⟨ Try to hyphenate the following word 894 ⟩ Used in section 866*. ⟨ Try to recover from mismatched 1192* ⟩ Used in section 1191*.

⟨ Types in the outer block 18, 25*, 38, 101, 109*, 113*, 150, 212*, 269, 300, 548, 594, 920, 925, 1412*, 1623*, 1626*,

1630*, 1634*, 1636*, 1639* ⟩ Used in section 4*.

⟨ Undump a couple more things and the closing check word 1327 ⟩ Used in section 1303. ⟨ Undump constants for consistency check 1308* ⟩ Used in section 1303.

⟨ Undump regions 1 to 6 of eqtb 1317 ⟩ Used in section 1314. ⟨ Undump the ε-TEX state 1389* ⟩ Used in section 1308*.

⟨ Undump the array info for internal font number k 1323 ⟩ Used in section 1321. ⟨ Undump the dynamic memory 1312* ⟩ Used in section 1303. ⟨ Undump the font information 1321 ⟩ Used in section 1303.

⟨ Undump the hash table 1319 ⟩ Used in section 1314.

⟨ Undump the hyphenation tables 1325* ⟩ Used in section 1303.

⟨ Undump the string pool 1310 ⟩ Used in section 1303.

⟨ Undump the table of equivalents 1314 ⟩ Used in section 1303. ⟨ Upcase the equivalence string 1653* ⟩ Used in section 1652*. ⟨ Update the active widths, since the first active node has been deleted 861 ⟩ Used in section 860. ⟨ Update the current height and depth measurements with respect to a glue or kern node p 976 ⟩

Used in section 972.

⟨ Update the current marks for fire up 1563* ⟩ Used in section 1014*. ⟨ Update the current marks for vsplit 1560* ⟩ Used in section 979*. ⟨ Update the current page measurements with respect to the glue or kern specified by node p 1004 ⟩

Used in section 997.

⟨ Update the value of printed node for symbolic displays 858 ⟩ Used in section 829*.

⟨ Update the values of first mark and bot mark 1016 ⟩ Used in section 1014*.

⟨ Update the values of last glue, last penalty , and last kern 996* ⟩ Used in section 994. ⟨ Update the values of max h and max v ; but if the page is too large, goto done 641 ⟩ Used in section 640. ⟨ Update width entry for spanned columns 798 ⟩ Used in section 796. ⟨ Use code c to distinguish between generalized fractions 1182 ⟩ Used in section 1181. ⟨ Use node p to update the current height and depth measurements; if this node is not a legal breakpoint,

goto not found or update heights , otherwise set pi to the associated penalty at the break 973 ⟩

Used in section 972.

⟨ Use size fields to allocate font information 566 ⟩ Used in section 562.

⟨ VMS procedures 34*, 1618*, 1625*, 1627*, 1629*, 1631*, 1632*, 1633*, 1635*, 1640* ⟩ Used in section 4*. ⟨ Variables for edit file 1657*, 1660*, 1663* ⟩ Used in section 1651*.

⟨ Wipe out the whatsit node p and goto done 1358 ⟩ Used in section 202. ⟨ Wrap up the box specified by node r, splitting node p if called for; set wait ← true if node p holds a

remainder after splitting 1021* ⟩ Used in section 1020.

Section Page

1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 3 2. The character set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 10 3. Input and output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 11 4. String handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 18 5. On-line and off-line printing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 20 6. Reporting errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 24 7. Arithmetic with scaled dimensions . . . . . . . . . . . . . . . . . . . . . . . . 99 27 8. Packed data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 28 9. Dynamic memory allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 30 10. Data structures for boxes and their friends . . . . . . . . . . . . . . . 133 30 11. Memory layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 31 12. Displaying boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 31 13. Destroying boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 33 14. Copying boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 33 15. The command codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 33 16. The semantic nest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 36 17. The table of equivalents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 38 18. The hash table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256 47 19. Saving and restoring equivalents . . . . . . . . . . . . . . . . . . . . . . . . 268 51 20. Token lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289 55 21. Introduction to the syntactic routines . . . . . . . . . . . . . . . . . . . . 297 57 22. Input stacks and states . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 300 59 23. Maintaining the input stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . 321 64 24. Getting the next token . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332 65 25. Expanding the next token . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366 66 26. Basic scanning subroutines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402 70 27. Building token lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464 76 28. Conditional processing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487 80 29. File names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 511 84 30. Font metric data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 92 31. Device-independent file format . . . . . . . . . . . . . . . . . . . . . . . . . . 583 94 32. Shipping pages out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 592 94 33. Packaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644 102 34. Data structures for math mode . . . . . . . . . . . . . . . . . . . . . . . . . 680 103 35. Subroutines for math mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 699 105 36. Typesetting math formulas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 719 105 37. Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 768 107 38. Breaking paragraphs into lines . . . . . . . . . . . . . . . . . . . . . . . . . . 813 110 39. Breaking paragraphs into lines, continued . . . . . . . . . . . . . . . . 862 115 40. Pre-hyphenation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 891 121 41. Post-hyphenation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 900 124 42. Hyphenation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 919 124 43. Initializing the hyphenation tables . . . . . . . . . . . . . . . . . . . . . . . 942 125 44. Breaking vertical lists into pages . . . . . . . . . . . . . . . . . . . . . . . . 967 127 45. The page builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 980 129 46. The chief executive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1029 133 47. Building boxes and lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1055 133 48. Building math lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1136 138 49. Mode-independent processing . . . . . . . . . . . . . . . . . . . . . . . . . . 1208 145 50. Dumping and undumping the tables . . . . . . . . . . . . . . . . . . . . 1299 155 51. The main program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1330 160 52. Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1338 165 53. Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1340 165 53a. The extended features of ε-TEX . . . . . . . . . . . . . . . . . . . . . . . . 1379 166 54. System-dependent changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1600 230 55. Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1667 256