summaryrefslogtreecommitdiff
path: root/macros/lamstex/doc/wiz6.tex
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/lamstex/doc/wiz6.tex
Initial commit
Diffstat (limited to 'macros/lamstex/doc/wiz6.tex')
-rw-r--r--macros/lamstex/doc/wiz6.tex3196
1 files changed, 3196 insertions, 0 deletions
diff --git a/macros/lamstex/doc/wiz6.tex b/macros/lamstex/doc/wiz6.tex
new file mode 100644
index 0000000000..f15dd1becf
--- /dev/null
+++ b/macros/lamstex/doc/wiz6.tex
@@ -0,0 +1,3196 @@
+\part Front and\\ Back Matter\label{FBM}\endpart
+
+
+\chapter Front Matter\\(Table of Contents, List of Figures, Tables, etc.)
+\label{FRONTMATTER}\endchapter
+\runningchapter{Front Matter}
+
+Now that we've covered all the formatting of the paper proper, we only have
+to worry about the formatting of the *.toc* and *.tic* files for the front
+matter, and the *.ndx* file for the index.
+
+As we've seen in section~\Sref{STYF}, the
+*\predocstyle* and *\postdocstyle* commands simply *\input* files with
+the extension *.stf* and *.stb*, respectively. In the default style,
+we say
+**
+\predocstyle{lamstex}
+**
+to *\input lamstex.stf*, and
+**
+\postdostyle{lamstex}
+**
+to *\input lamstex.stb*. In this chapter we consider the file *lamstex.stf*,
+while the next chapter considers *lamstex.stb*.
+
+As in section~\Sref{GENDEFS}, we will be using double horizontal lines
+for code from these subsidiary files.
+
+\section{{\tt lamstex.stf} preliminaries} The file
+*lamstex.stf*, although it is only a
+particular example of a front matter style file, nevertheless illustrates all
+the main points we have to consider.
+
+As usual, we begin with
+\CC**
+\catcode`\@=11
+**
+Since we are going to be introducing some *\newdimen*'s, we first
+\CC**
+\let\alloc@=\alloc@@
+**
+(compare page~\ref{NEWALLOC}).
+
+
+\medskip
+
+ In the default style, we will be setting entries like
+\bigskip
+\line{\qquad\bf
+Chapter 1. Introduction\leaders\hbox to10pt{\rm\hfil.\hfil}\hfil
+ \kern10pt\hbox{\rm3}\qquad}
+\bigskip
+\noindent
+using dot leaders. This, of course, is merely a style decision, and some
+modern style designers eschew dot leaders, on the grounds that blank space
+will work just as well. I suspect, however, that many such supposedly
+aesthetic decisions were really influenced by the difficulty of handling dot
+leaders correctly. In any case, the default style uses dot leaders, giving us
+the opportunity to address the question of long entries, where we will need
+to use something like
+\bigskip
+\line{\qquad\bf Chapter 1. This chapter has such a long title that it will
+ be \hfil}
+\line{\qquad\bf\setbox0\hbox{Chapter 1.}\hskip10pt\hskip\wd0
+ necessary to split it into two parts\leaders\hbox
+to10pt{\rm\hfil.\hfil}\hfil\kern10pt \rm3\qquad}
+\bigskip
+
+For the moment, we simply define our leaders,
+\CC**
+\def\dotleaders{\leaders\hbox to10pt{\rm\hfil.\hfil}\hfil}
+**
+We also want to define the formatting for page numbers.
+The *.toc* and *.tic* files contain lines like
+**
+\Page {3}{\arabic }{}{}
+**
+to handle the page number, the numbering style, and possible pre- and
+post-page material. The routine *\Page@#1#2#3#4* tells how these will
+be combined when typeset:
+\CC**
+\def\Page@#1#2#3#4{\kern10pt\hbox{\rm#3#2{#1}#4}}
+**
+Thus, for example,
+**
+\Page {3}{\roman }{A-}{}
+**
+will be printed as `A-iii', with at least 10~points of space between the
+leaders and the number.
+
+\section{Setting an entry\label{SETENTRY}}
+We begin with a test
+**
+\widerthanhsize@#1#2#3#4
+**
+to determine
+ whether
+the material for an entry is longer than *\hsize*.
+In the example given above, *#1* will be the `\hbox{\bf Chapter 1. }' part of
+the heading,
+ *#2* will be the title `{\bf This chapter \dots into two parts}', *#3* will
+be the *\dotleaders*, and *#4* will be the suitable `*\Page@...*'.
+
+ Displayed formulas and other
+such nonsense aren't allowed in heading levels, but captions, at any rate,
+could have more than one paragraph of text; moreover, in the *.toc* file
+ we might well want
+to use *\newline* to force a short line when our entry is so long
+that only one or
+two of the dot leaders appear.
+So we will use a test similar to
+the *\widerthanisland@* test of section~\Sref{FMTC}:
+\CC**
+\long\def\widerthanhsize@#1#2#3#4{%
+ \test@true
+ \setbox0=\vbox{\hsize=\maxdimen
+ \rm\noindent@#1#2#3#4\par\setbox0=\lastbox}%
+ \ifdim\wd0=0pt
+ \setbox0=\hbox{\rm#1#2#3#4}%
+ \ifdim\wd0 > \hsize\else\test@false\fi
+ \fi}
+**
+We use *\noindent@* instead of the more complicated *\noindent@@* here
+because we will be setting *\everypar{}* while the table of contents is
+being made. (Actually, even the *\noindent@* is unnecessary, since we will
+also be setting *\parindent=0pt*.)
+Instead of *\rm*, other style files
+might need to insert something like *\tenpoint* (just
+in case the user has, for example, added
+ *\eightpoint* material at the beginning of the *.toc* file).
+
+
+Then we define the routine *\setentry@#1#2#3#4*,
+ which sets the entry with parts *#1*, \dots, *#4* properly; when the
+entry will have to be set on more than one line, we call the routine
+*\longentry@*:
+\CC**
+\long\def\setentry@#1#2#3#4{%
+ \widerthanhsize@{#1}{#2}{#3}{#4}%
+ \iftest@
+ \longentry@{#1}{#2}{#3}{#4}%
+ \else
+ \hbox to\hsize{\rm\strut#1#2#3#4\strut}%
+ \fi}
+**
+Notice that we added the *\strut*'s after the *\rm*; other styles
+might have to specify something like *\tenpoint* instead of the *\rm*.
+
+Because our lines have *\strut*'s, which already make the baselines *12pt*
+apart,
+it is essential that we have
+**
+\lineskiplimit=0pt "8USELIMITPROB"8
+**
+while we are setting the table of contents,
+so that additional *\lineskip* glue isn't inserted between lines
+(compare page~\ref{LIMITPROB}). However, instead of making this assignment
+now, we will make it later, within the definition of *\maketoc*.
+
+
+For entries that are longer than one line,
+the default style uses hanging indentation, so that
+ lines after the first are indented by 10~points more than
+the width of argument *#1*. We will declare a \<dimen\> register
+*\thehang@*
+for the necessary amount of hanging indentation, which will be determined by
+**
+\setbox0=\hbox{#1}
+\thehang@=\wd0 \advance\thehang@ by 10pt
+**
+
+ All lines before the last will be made shorter
+than *\hsize*, so that they don't overlap the width of the page number.
+The default style leaves an extra 20~points leeway, which we arrange with
+**
+\setbox0=\hbox{#4}
+\advance\hsize by -\wd0 \advance\hsize by -20pt
+ \hangafter 1 \hangindent=\thehang@
+**
+Now the idea is to set a *\vbox* that looks like
+\medskip
+\line{\qquad\bf Chapter 1. This chapter has such a long title that it will
+ be necessary\hfil}
+\line{\qquad\bf\setbox0\hbox{Chapter 1.}\hskip10pt\hskip\wd0
+ to split it into two parts\hfil}
+\medskip
+\noindent
+and then use *\lastbox* to extract the last line, to which we will finally
+add the dot leaders and the page number:
+**
+\long\def\longentry@#1#2#3#4{%
+ \setbox0=\hbox{#1} \thehang@=\wd0 \advance\thehang@ by 10pt
+ \setbox0=\hbox{#4}
+ \setbox0=\vbox{\advance\hsize by -\wd0
+ \advance\hsize by -20pt
+ \hangafter 1 \hangindent=\thehang@
+ \rm\noindent@\strut\hbox{#1}#2\vphantom{#3#4}\strut}
+ . . .
+**
+We put *#1* inside an *\hbox* so that any glue within it will have only
+its natural width, without any
+ stretch or shrink; this is necessary in order to insure that our hanging
+indentation will truly be the width of *#1* plus 10~points.
+The *\vphantom{#3#4}* is added so that the height and depth of the
+last line of *\box0* won't
+change when we add the dot leaders (*#3*) and the page number (*#4*).
+As mentioned before, other styles might have to specify something like
+*\tenpoint* rather than *\rm*; the *\strut* should come after that,
+{\it and also after the\/} *\noindent@* (so that it doesn't start
+a paragraph prematurely).
+
+As with footnotes (section~\Sref{VF}), we will actually want to replace
+the first *\strut* with
+**
+\vbox to\ht\strutbox{}
+**
+and the last *\strut* with
+**
+\lower\dp\strutbox\vbox to\dp\strutbox{}
+**
+The latter combination will appear
+ more than once, so we adopt an abbreviation:
+\CC**
+\def\endstrut@{\lower\dp\strutbox\vbox to\dp\strutbox{}}
+**
+
+Although we will have *\lineskiplimit=0pt* when *\longentry@* is
+being used,
+within our *\vbox* we want to declare
+**
+\normalbaselines
+**
+so that the standard value of *\lineskiplimit* is used there. (In the default
+style *\normallineskiplimit* happens to be ~*0pt*, so that this is actually
+superfluous, but in other styles that is not necessarily the case.)
+
+Now we start to make a new box, in which we *\unvbox0*:
+**
+\setbox0=\vbox{\unvbox0
+ \setbox0=\lastbox
+ . . .
+**
+This makes the inner *\box0* the last line of the
+paragraph, a ``short'' line that ends with *\parfillskip* glue,
+and then yet another glue, namely *\rightskip*. So we need
+**
+\unhbox0 \unskip\unskip
+**
+to get rid of this extra glue, before we
+ add *#3* and *#4*.
+ In addition,
+the hanging indentation does not insert glue or a kern at the beginning of
+this box---instead, it merely shifts it to the right in the vertical list.
+So we use
+**
+\setbox0=\vbox{\unvbox0
+ \setbox0=\lastbox
+ \hbox to\hsize{\kern\thehang@
+ \unhbox0 \unskip\unskip#3#4\endstrut@}
+ }
+**
+ to create the desired final line.
+And then we
+simply *\unvbox0*:
+\CC**
+\newdimen\thehang@
+"slip
+\long\def\longentry@#1#2#3#4{\setbox0=\hbox{#1}%
+ \thehang@=\wd0 \advance\thehang@ by 10pt
+"2
+ \setbox0=\hbox{#4}%
+"2
+ \setbox0=\vbox{\advance\hsize by -\wd0
+ \advance\hsize by -20pt
+ \normalbaselines
+ \hangafter1 \hangindent=\thehang@
+"2
+ \vskip-\parskip
+ \rm\noindent@\vbox to\ht\strutbox{}%
+ \hbox{#1}#2\vphantom{#3#4}\endstrut@}%
+"2
+ \setbox0=\vbox{\unvbox0
+ \setbox0=\lastbox
+ \hbox to\hsize{\kern\thehang@
+ \unhbox0 \unskip\unskip #3#4\endstrut@}%
+ }%
+ \unvbox0 }
+**
+Note that in the last *\setbox0=\vbox* there is no extra glue between the
+*\unvbox0* and the *\hbox to\hsize* (compare the footnote on page~\ref{NEXG});
+that is why it is important to have the *\vphantom{#3#4}*, to insure
+that the *\hbox to\hsize* has the same height as the *\lastbox* that it is
+replacing.
+
+
+\section{Further preliminaries for the table of contents}
+The *\maketoc* command is going to *\input* the appropriate *.toc* file,
+which will have entries like
+\setbox0\hbox{and}
+\setbox1\hbox{\<word\>}
+\setbox2\hbox{\<formatted heading number\>}
+**
+\HL {1}{"copy1}{"box2} "8HLILLUS"8
+ . . .
+\Page ...
+**
+and/or entries like
+\setbox0\hbox{and}
+\setbox1\hbox{\<word\>}
+\setbox2\hbox{\<formatted heading number\>}
+**
+\chapter {"copy1}{"box2}
+ . . .
+\Page ...
+**
+(in which case an extra line like
+**
+\NameHL 1\chapter
+**
+should appear at the beginning), and similarly for *\hl*.
+
+We will therefore be redefining *\HL* and *\hl* so that such lines
+print proper lines for the table of contents.
+But
+a few preliminaries are needed to deal with the
+ possibility that something like *""B""*, or even
+*""\style B""* occurs instead of a \<formatted heading number\>.
+First, we want a flag
+\CC**
+\newif\ifemptynumber@
+**
+which will be set true precisely in the case where we have *""""* (in the
+paper proper, this happens when *\thelabel@@* is *\empty*). When it comes
+time to properly print the argument `*...*'
+of *\HL* that represents the heading
+number, we will use
+**
+\Style@...\Style@
+**
+so that *\Style@* can use a *\futurelet* to see if `*...*' begins with
+a *""* (we use *\Style@* because *\style@* is already used, as part of the
+definition of *\style*).
+We begin with
+\CC**
+\def\Style@{\emptynumber@false\futurelet\next\Style@@}
+\def\Style@@{\ifx\next""\expandafter\Style@@@
+ \else\expandafter\Style@@@@\fi}
+**
+For *\Style@@@*, when no *""* occurs, we might expect to use
+**
+\def\Style@@@#1\Style@{#1}
+**
+Instead, however, we will use
+\CC**
+\def\Style@@@@#1\Style@{\style{#1}}
+**
+so that each heading level can temporarily define `*\style*' to produce
+whatever sort of formatting for the number that we want.
+On the other hand, *\Style@@@* is defined by
+\CC**
+\def\Style@@@""#1""\Style@{%
+ \def\next@{#1}\ifx\next@\emtpy
+ \emptynumber@true\else#1\fi}
+**
+Thus, in the special case that our original argument is *""""*,
+we simply set *\emptynumber@true*; otherwise we
+ print the argument *#1*. Notice that if this argument happens
+to be something like *""\style B""*, the `*B*' will be formatted according
+to the manner in which this heading level has temporarily defined
+*\style* to operate.
+
+For setting *\hl1* entries,
+we will also declare a new dimension *\digits*,
+\CC**
+\newdimen\digits "8DIGITS"8
+\setbox0\hbox{0.00}
+\digits=\wd0
+**
+so that *\digits* is the width of a double-digit number like `1.12' (the
+user could reset *\digits* if necessary to accommodate even more digits).
+
+We also want to define
+\CC**
+\def\maketoc@W{CONTENTS}
+**
+so that *\newword\maketoc* can be used to choose a different word.
+
+\section{Starting the \CS{maketoc} command}
+The *\maketoc* command first uses *\checkmainfile@* (page~\ref{CHECKMF})
+to issue an error message if no *\mainfile* command has appeared in the front
+matter file, since it will have to *\input \mainfile@.toc*, where
+*\mainfile@* has been defined by *\mainfile*.
+Then it
+ starts a new page,
+in case something like a Preface precedes it (the default front
+matter style file *lamstex.stf*
+doesn't have special constructions for Prefaces, etc., but
+the *book* style, for example, does).
+\footnote{We don't simply put *\checkmainfile@* at the beginning of
+our file, since a user might omit the *\mainfile* line when
+simply checking that something like a Preface looks right.}
+Then we produce a centered bold heading `{\bf CONTENTS}', followed by
+some space.
+
+Now we want to
+*\input* the appropriate *.toc* file, which
+is when everything interesting will happen. Certain subsidiary definitions
+will be needed, so
+ we will start with
+*\begingroup* and add an *\endgroup* after the *\input*, to keep these all
+local.
+
+Any
+ *\label* or *\pagelabel* in a heading level or a
+caption will have been written
+ to the *.toc* or *.tic* file (there's no practical
+way to eliminate them), but they play no further role, and
+we simply want to ignore them. The same is true of any *\Reset* or
+*\Offset*. So after the *\begingroup* we want to add
+**
+\noset@ \unlabel@
+**
+(section~\Sref{relax} and ~\Sref{relax2}).
+Any *\nopunct* or *\nospace* or *\overlong* in the main file
+will also show up in the *.tic* file. Some styles might want to make
+use of these (presumably having them set certain flags), but in the default
+front matter style *lamstex.stf*, we simply want to
+**
+\let\nopunct=\relax \let\nospace=\relax
+\let\overlong=\relax
+**
+We also add
+**
+\everypar={}\parindent=0pt
+**
+for good measure.
+
+Furthermore, as mentioned previously (page~\ref{USELIMITPROB}), it is
+essential that we
+ set
+*\lineskiplimit=0pt*.
+So our definition of *\maketoc* will start
+**
+\def\maketoc{\checkmainfile@
+ \par\vfill\break
+ \noset@ \unlabel@
+ \let\nopunct=\relax \let\nospace=\relax
+ \let\overlong=\relax
+ \everypar={}\parindent=0pt
+ \lineskiplimit=0pt
+**
+
+
+\section{Redefining \CS{HL} and \CS{hl}}
+Next we have to redefine *\HL* and *\hl* so that *\HL* and *\hl* entries
+will be properly set for the table of contents.
+
+To redefine *\HL*, recall (page~\ref{HLILLUS})
+that it will occur in a combination like
+\setbox0\hbox{\<heading level\>}
+\setbox1\hbox{\<formatted heading number\>}
+\setbox3\hbox{\<heading word\>}
+\setbox2\hbox{\<The heading\>}
+**
+\HL {"box0}{"box3}{"box1}
+ "box2
+\Page{...}{...}{...}{...}
+**
+so that we need a definition like
+**
+\def\HL#1#2#3#4\Page#5#6#7#8{ . . . "87ARGS"8
+**
+(except that *#1* will be *##1*, etc., since this entire definition will be
+made within the definition of *\maketoc*).
+
+The definition should always begin
+**
+\def\HL#1#2#3#4\Page#5#6#7#8{\def\HLlevel@{#1}
+ . . .
+**
+so that subsequent constructions can know which heading level is being
+considered. For the default front matter style we will be using
+**
+\def\HL#1#2#3#4\Page#5#6#7#8{\def\HLlevel@{#1}
+ \ifnum\HLlevel@ = 1
+ . . .
+ . . .
+ \else
+ \Err@{\string\HL#1 not defined in this style}%
+ \fi}
+**
+so that an error message will be given if *\HL {*\<number\>*}* occurs
+for any \<number\>${}\ne{}$*1*. (Theoretically this shouldn't happen, since
+the *.toc* file is generated by the main file, which only recognizes
+*\HL1*; but we might as well add this precaution in case the *.toc* file
+has been edited.)
+
+When *\HLlevel@* is~*1*, we want to use *\setentry@* with
+the appropriate data,
+\setbox1\hbox{\<arg$_{\text1}$\>}
+\setbox2\hbox{\<arg$_{\text2}$\>}
+\setbox3\hbox{\<arg$_{\text3}$\>}
+\setbox4\hbox{\<arg$_{\text4}$\>}
+**
+\setentry@{"box1}{"box2}{"box3}{"box4}
+**
+In terms of the original arguments *#1*, *#2*, *#3*, \dots, *#8*
+ of *\HL* (see~ \recentpageref{7ARGS}{above}{the previous page}{}),
+\<arg$_{\text2}$\> will be
+**
+\bf\ignorespaces#4\unskip
+**
+\<arg$_{\text3}$\> will be *\dotleaders*, and
+\<arg$_{\text4}$\> will be
+**
+\Page@{#5}{#6}{#7}{#8}
+**
+
+As for
+\<arg$_{\text1}$\>, it will essentially be
+\setbox0\hbox{\<word\>}
+**
+\bf #2 #3
+**
+More precisely, it will be
+**
+\bf \def\next@{#2}\ifx\next@\empty\else#2\space\fi
+ \let\style=\HL@@S \Style@#3\Style@
+ \ifemptynumber@\else\space\fi
+**
+So the \<word\> *#2* is followed by a space, if it is non-empty. Moreover,
+ when *\Style@...\Style@* uses *\style* to
+produce the formatting of the number, this *\style*
+ will be *\HL@@S* (i.e.,
+`*\HL@S1*', since *\Hllevel@* was defined to be~*1*). And we also
+add a space after this number,
+ except in the case of an empty number. Naturally, other
+style files might do things differently. Note, moreover, that although
+`*\HL@S1*' has been defined in *lamstex.tex*, if *\newstyle\HL1* appears
+in the main file, it will also have to be added to the *.toc* file to
+produce the same effect. (In practice, of course, only style file designers
+will use *\newstyle\HL*, except perhaps for transient effects.)
+
+A multi-level *\HL1* heading will have *\\* in it. Although that should
+probably be edited out, we can at least give *\\* a provisional definition as
+\linebreak
+`*\unskip\space\ignorespaces*'.
+ The only other thing to worry about is the spacing around the heading:
+**
+\def\HL#1#2#3#4\Page#5#6#7#8{\def\HLlevel@{#1}%
+ \ifnum\HLlevel@ = 1
+"2
+ \bigbreak
+"2
+ \begingroup
+ \def\\{\unskip\space\ignorespaces}%
+"2
+ \setentry@
+ {\bf\def\next@{##2}\ifx\next@\empty\else##2\space\fi
+ \let\style=\HL@@S \Style@#3\Style@
+ \ifemptynumber@\else\space\fi}%
+ {\bf\ignorespaces#4\unskip}%
+ \dotleaders
+ {\Page@{#5}{#6}{#7}{#8}}
+"2
+ \endgroup
+ \nobreak\smallskip
+"2
+ \else
+ \Err@{\string\HL#1 not defined in this style}%
+ \fi}
+**
+
+\newdimen\digits
+\setbox0\hbox{0.00}
+\digits=\wd0
+
+The default style for *\hl1* headers is
+\medskip
+\line{\quad\qquad\hbox to\wd0{1.12}\enspace A short section
+ \leaders\hbox to10pt{\rm\hfil.\hfil}\hfil\kern10pt79\qquad}
+\medskip
+\noindent
+where we indent a *\quad* from the left margin, and
+ leave room for a double-digit number like `*1.12*', followed by
+an *\enspace*, before the section title.
+
+We have already introduced *\digits* (page~\ref{DIGITS}),
+and the definition of *\hl* introduces nothing especially new:
+**
+\def\hl#1#2#3#4\Page#5#6#7#8{\def\hllevel@{#1}%
+ \ifnum\hllevel@ = 1
+"2
+ \setentry@
+ {\rm\quad \let\style=\hl@@S
+ \hbox to\digits{\Style@#3\Style@\hfil}\enspace}%
+ {\rm\ignorespaces#4\unskip}%
+ \dotleaders
+ {\Page@{#5}{#6}{#7}{#8}}%
+"2
+ \else
+ \Err@{\string\hl#1 not defined in this style}%
+ \fi}
+**
+In the default style, not only is `*\hl@W1*' empty, but *\hl1* doesn't
+print this \<word\>, even if it has been changed by *\newword*; so
+we also don't bother about printing it in the table of contents.
+
+
+\section{\CS{NameHL} and \CS{Namehl}}
+Finally, *\maketoc* has to deal with alternate names like *\chapter* and
+*\section*. If the main file has
+**
+\NameHL 1 \chapter
+\Namehl 1 \section
+**
+then these lines should also appear in the *.toc* file (before the use
+of *\chapter* or *\section*, respectively).
+
+
+First of all, we have to redefine *\NameHL* so that, for example,
+\setbox0\hbox{\<word\>}
+**
+\chapter {"box0}{2}
+ . . .
+\Page...
+**
+will typeset the same thing as
+\setbox0\hbox{\<word\>}
+**
+\HL {1}{"box0}{2}
+ . . .
+\Page...
+**
+In other words, we want to
+**
+"hskip-20pt\def\chapter#1#2#3\Page{\HL{1}{#1}{#2}#3\Page}
+**
+(we don't need braces around the second *#3*, since it is delimited by
+*\Page*). So in general we want *\NameHL#1#2* to mean
+**
+\def#2##1##2##3\Page{\HL{#1}{##1}{##2}##3\Page}
+**
+and, similarly, we want
+*\Namehl#1#2* to mean
+**
+\def#2##1##2##3\Page{\hl{#1}{##1}{##2}##3\Page}}
+**
+
+\section{\CS{maketoc}}Putting all this together, our definition of
+*\maketoc* is:
+\CC**
+\def\maketoc{\checkmainfile@ "8STFMAKETOC"8
+ \par\vfill\break
+"2
+ \begingroup
+ \noset@ \unlabel@
+"2
+ \let\nopunct=\relax \let\nospace= \relax
+"2
+ \let\overlong=\relax
+"2
+ \everypar{}\parindent=0pt
+ \lineskiplimit=0pt
+"2
+ \def\HL##1##2##3##4\Page##5##6##7##8{%
+ \def\HLlevel@{##1}%
+"2
+ \ifnum\HLlevel@=1
+ \bigbreak
+"2
+ \begingroup
+ \def\\{\unskip\space\ignorespaces}%
+"2
+ \setentry@{\bf\def\next@{##2}\ifx\next@\empty
+ \else##2\space\fi
+ \let\style=\HL@@S \Style@##3\Style@
+ \ifemptynumber@\else\space\fi}%
+ {\bf\ignorespaces##4\unskip}\dotleaders
+ {\Page@{##5}{##6}{##7}{##8}}%
+"2
+ \endgroup
+"2
+ \nobreak\smallskip
+"2
+ \else
+ \Err@{\string\HL##1 not defined in this style}%
+ \fi}%
+"2
+ \def\hl##1##2##3##4\Page##5##6##7##8{%
+ \def\hllevel@{##1}%
+"2
+ \ifnum\hllevel@=1
+"2
+ \setentry@{\rm\quad\let\style=\hl@@S
+ \hbox to\digits{\Style@##3\Style@\hfil}\enspace}%
+ {\rm\ignorespaces##4\unskip}\dotleaders
+ {\Page@{##5}{##6}{##7}{##8}}%
+"2
+ \else
+ \Err@{\string\hl##1 not defined in this style}%
+ \fi}%
+"2
+ \def\NameHL##1##2{\def##2####1####2####3\Page
+ {\HL{##1}{####1}{####2}####3\Page}}%
+"2
+ \def\Namehl##1##2{\def##2####1####2####3\Page
+ {\hl{##1}{####1}{####2}####3\Page}}%
+"2
+ \centerline{\bf\maketoc@W}%
+ \vskip30pt plus10pt minus10pt
+ \input\mainfile@.toc
+ \endgroup}
+**
+
+\nopunct\section{Lists of Figures, Tables, etc.}
+The commands
+**
+\makelistFigures
+\makelistTables
+**
+are defined directly in terms of the more general *\makelist* command,
+\CC**
+\def\makelistFigures{\makelist\c{F}List of
+ Figures\endmakelist}
+\def\makelistTables{\makelist\c{T}List of
+ Tables\endmakelist}
+**
+The syntax has been changed from that of the \lamstex~Manual, page~92,
+to conform with the general \amstex\ and \lamstex\ syntax for constructions
+that allow *\\* to be used to indicate line breaks.
+
+*\makelist\c#1#2\endmakelist*,
+ like *\maketoc*, first uses the test\linebreak *\checkmainfile@*, and then
+ends the previous page. After this we want to add
+**
+\noset@ \unlabel@
+\let\nopunct=\relax \let\nospace=\relax
+\let\overlong=\relax
+\everypar={}\parindent=0pt
+\lineskiplimit=0pt
+**
+just as in *\maketoc*.
+Then
+*\makelist* will
+**
+\def\listclass@{#1}
+**
+so that, when we *\input* the *.tic* file we will know which of the
+*\island*'s to process.
+
+Next *\makelist* must redefine *\island*.
+In the case of *\HL#1...*,
+once we had defined *\HLlevel@* as *#1*,
+the style control sequence *\HL@@S* was defined, so that we could
+*\let\style=\HL@@S* in our definition of *\HL*. A construction
+ introduced with *\NameHL1* is basically just a synonym for *\HL1*,
+so we did not need to consider *\HL@@@S*, defined in terms of *\HLtype@*.
+But the situation is different for *\island*'s, where we have only
+*\island@@@S*, defined in terms of *\islandtype@*, which is *\island* for
+an explicitly typed *\island*, but *\Figure* for a *\Figure*, etc.
+
+To deal with this situation,
+\setbox0\hbox{\<Figure number\>}
+\setbox1\hbox{\<caption\>}
+**
+\Figure {"box0}
+ "copy1
+\Page ...
+**
+ in the *.tic* file will translate
+to
+\setbox0\hbox{\<Figure number\>}
+\setbox1\hbox{\<caption\>}
+\Litbox2=**
+\island \at@\Figure \c{F}{Figure}{"copy0}
+ "copy1
+\Page ...
+**
+$$\vcenter{\box2}\tag"\style{\bf A}"$$
+---here *\at@* is simply an arbitrarily chosen \lamstex\ control sequence
+that the user can't insert---%
+while an explicitly typed *\island*, like
+\setbox0\hbox{\<map number\>}
+**
+\island \c{M}{Map}{"box0}
+**
+will be regarded as
+\setbox0\hbox{\<map number\>}
+**
+\island \at@\island \c{M}{Map}{"box0}
+**
+so that eventually everything reduces to a common case.
+
+We begin by redefining *\island* in terms of a *\futurelet*, to see whether
+*\at@* follows:
+**
+\def\island{\futurelet\next\island@}
+\def\island@{\ifx\next\at@\expandafter\island@@\else
+ \expandafter\island@@@\fi}
+**
+
+*\island@@*, where *\at@* follows, has 9 arguments:
+**
+\long\def\island@@\at@#1\c#2#3#4#5\Page#6#7#8#9
+**
+For example, in ({\bf A}), *#1* is `*\Figure*', *#2* is `*F*', *#3* is
+`*Figure*', *#4* is the \<Figure number\>, and *#5* is the \<caption\>.
+
+The definition of *\island@@*
+is similar to
+the definition of *\HL* except that:
+\list\item we use argument *#1* to define
+*\islandtype@*, rather than *\HLlevel@*;
+\item we print *#3* rather than the \<word\> before the \<Figure number\>;
+\item
+we process only those *\island*'s whose class *#2* is the *\listclass@* for
+the list we are printing.\endlist
+**
+\long\def\island@@\at@#1\c#2#3#4#5\Page#6#7#8#9{%
+ \def\islandtype@{#1}%
+"2
+ \def\next@{#2}%
+"2
+ \ifx\next@\listclass@
+"2
+ \setentry@
+ {\rm#3" \let\style=\island@@@S \Style@#4\Style@
+ \ifemptynumber@\else\space\fi}%
+ {\rm\ignorespaces#5\unskip}%
+ \dotleaders
+ {\Page@{#6}{#7}{#8}{#9}}%
+ \fi}
+**
+
+The definition of *\island@@@*, when no *\at@* follows, is reduced to
+the case where *\at@\island* follows:
+**
+\long\def\island@@@\c#1#2#3#4\Page#5#6#7#8{%
+ \island@@\at@\island
+ \c{#1}{#2}{#3}#4\Page{#5}{#6}{#7}{#8}}
+**
+
+\bigskip
+
+When something like
+**
+\newisland\map\c{M}{Map}
+**
+appears, an occurrence of
+\setbox0\hbox{\<map number\>}
+\setbox1\hbox{\<caption\>}
+**
+\map {"box0}
+ "box1
+\Page ...
+**
+should translate to
+\setbox0\hbox{\<map number\>}
+\setbox1\hbox{\<caption\>}
+**
+\island \at@\map \c{M}{Map}{"box0}
+ "box1
+\Page ...
+**
+In other words, we should
+**
+\long\def\map#1#2\Page#3#4#5#6{\island \at@\map
+ \c{M}{Map}{#1}#2\Page{#3}{#4}{#5}{#6}}
+**
+
+So in general, we want to
+**
+\def\newisland#1\c#2#3{%
+ \long\def#1##1##2\Page##3##4##5##6{%
+ \island\at@#1\c{#2}{#3}{##1}##2%
+ \Page{##3}{##4}{##5}{##6}}}
+**
+
+Since *\Figure* and *\Table* are *\island* classes that are assumed to
+be present in all styles, we should also add
+**
+\newisland\Figure\c{F}{Figure}
+\newisland\Table\c{T}{Table}
+**
+
+Putting this all together, we have
+\CC**
+\def\makelist\c#1#2\endmakelist{\checkmainfile@
+ \par\vfill\break
+"2
+ \begingroup
+"2
+ \noset@ \unlabel@
+"2
+ \let\nopunct=\relax \let\nospace=\relax
+ \let\overlong=\relax
+"2
+ \everypar{}\parindent=0pt
+ \lineskiplimit=0pt
+"2
+ \def\listclass@{#1}%
+ \def\island{\futurelet\next@\island@}%
+"2
+ \def\island@{\ifx\next\at@\expandafter\island@@\else
+ \expandafter\island@@@\fi}%
+"2
+ \long\def\island@@\at@##1\c##2##3##4##5\Page##6##7##8##9{%
+ \def\islandtype@{##1}%
+ \def\next@{##2}%
+"2
+ \ifx\next@\listclass@
+"2
+ \setentry@{\rm##3
+ \let\style=\island@@@S \Style@##4\Style@
+ \ifemptynumber@\else\space\fi}%
+ {\rm\ignorespaces##5\unskip}\dotleaders
+ {\Page@{##6}{##7}{##8}{##9}}%
+"2
+ \fi}%
+"2
+ \long\def\island@@@\c##1##2##3##4\Page##5##6##7##8{%
+ \island@@\at@\island\c{##1}{##2}{##3}##4\Page
+ {##5}{##6}{##7}{##8}}%
+"2
+ \def\newisland##1\c##2##3{\long\def##1####1####2\Page
+ ####3####4####5####6{%
+ \island\at@##1\c{##2}{##3}{####1}####2\Page
+ {####3}{####4}{####5}{####6}}}%
+"2
+ \newisland\Figure\c{F}{Figure}%
+ \newisland\Table\c{T}{Table}%
+"2
+ \vbox{\Let@\tabskip\centering@\halign to\hsize
+ {\bf\hfil\ignorespaces##\unskip\hfil\cr#2\crcr}}%
+ \vskip30pt plus10pt minus10pt
+ \input\mainfile@.tic
+ \endgroup}
+**
+
+\section{Fini}Then, as in section~\Sref{DONE},
+we finish with
+\CC**
+\def\alloc@#1#2#3#4#5{\global\advance\count1#1by\@ne
+ \ch@ck#1#4#2\allocationnumber=\count1#1
+ \global#3#5=\allocationnumber
+ \wlog{\string#5=\string#2\the\allocationnumber}}
+\catcode`\@=\active
+**
+
+
+
+
+\chapter Back matter\\The index\endchapter
+\runningchapter{Back matter; the index}
+Although the ``back matter'' may include the bibliography, and other matter,
+the default style file *lamstex.stb* is used only for the index. As explained
+in Chapter~13 of the \lamstex~Manual, the *\makeindex* command is going to
+read in an *.xdx* ``expanded index file'', which is produced by the *index*
+program from the *.ndx* file that \lamstex\ writes. The *index* program is
+discussed in the next chapter. In this chapter, we are only concerned with
+typesetting the *.xdx* file. In the default style, we will be using a
+two-column format, with balanced columns at the end.
+
+Page 114 of The \lamstex~Manual
+gives
+a sample piece from an
+*.xdx* file that illustrates almost all the features that we have to
+consider;
+ the only additional feature is *\PageSpan*, mentioned on page~117.
+
+
+\section{Preliminaries\label{BMPRE}}As with *lamstex.stf*, we begin with
+\CC**
+\catcode`\@=11
+\let\alloc@=\alloc@@
+**
+Since *"1* has a special role of indicating options in
+ index entries, if an index entry actually had a \ast\ in it that symbol
+will appear as *\asterisk*. So we will need to state
+\dotC**
+\let\asterisk="1
+**
+so that *\asterisk* will print out a \ast\,. We've printed dotted lines
+around this definition, since it will
+actually
+ only be made within the definition
+of *\makeindex*---for any
+material inserted before or after *\makeindex*, the control sequence
+*\asterisk* will simply be
+undefined.
+
+As with the bibliography (section~\Sref{SBMACS}),
+ we will be redefining *\lkerns@* and
+ *\nkerns@*
+for properly placing punctuation before line-breaking penalties,
+\dotC**
+\def\lkerns@{\null\kern-1sp\kern1sp}
+\def\nkerns@{\null\kern-2sp\kern2sp}
+**
+(we don't really need the *\null*'s that occurred previously, since we're not
+setting *\vbox*'s, but for simplicity we might as well stick to the old
+definitions).
+Once again, we use dotted lines,
+since the redefinitions will only be made later,
+by *\makeindex*, so that line
+breaking commands won't change their meaning until we are actually setting
+the index.
+On the other hand, we can give
+ a definition of *\adjustpunct@*
+(section~\Sref{BIBMACS}) right now; it differs from the previous definition
+only in the omission of
+ *\closequotes@*:
+\CC**
+\def\adjustpunct@#1{\count@\lastkern
+ \ifnum\count@=0 #1\else
+ \ifnum\count@>2 #1\else
+ \ifnum\count@<-2 #1\else
+ \unkern\unkern\setbox0=\lastbox
+ \skip@=\lastskip \unskip
+ \count@@=\lastpenalty \unpenalty
+ \ifnum\count@ = 2 \unskip \setbox0=\lastbox\fi
+ \ifdim\skip@ = 0pt \else \hskip\skip@ \fi
+ #1%
+ \ifnum\count@=2 \null\hfill\fi
+ \penalty\count@@
+ \fi\fi\fi}
+**
+(Since *\adjustpunct@* is stated within *lamstex.tex* itself,
+we could simply state
+*\let\closequotes@=\relax*, but restating the definition is preferable
+in case *\purge{bib}* has been used.)
+
+In all the commands appearing in the *.xdx* file,
+\setbox0\hbox{etc.,}
+**
+\Entry 10{acetyl-CoA}{}{}{}{}
+\Page {34}
+"box0
+**
+we are going to want to ignore the space after the last *}*.
+In addition, since blank lines might be introduced during editing,
+or by ``error messages'',
+we will want to skip over any such blank lines---we can't afford to
+introduce a *\par* until we know that there are no more page numbers left to
+be printed.
+\footnote{In version~*1* of \lamstex@,
+ the *index* program was careful not to introduce
+any blank lines, inserting a~ *%* before an otherwise blank line if
+necessary, and users were warned not to introduce blank lines. However,
+it seems preferable to have the macros
+skip the blank lines, since they can make the
+*.xdx* file look so much nicer.}
+ So we will use *\FNSS@* to get the first non-space token, and then
+use a
+*\futurelet\next* to see if the next token is
+*\par*, which should also be discarded:
+\CC**
+\def\ignorepars@{\FNSS@\ignorepars@@}
+\def\ignorepars@@{\ifx\next\par
+ \def\next@\par{\futurelet\next\ignorepars@@}\else
+ \let\next@=\relax\fi\next@}
+**
+
+One of the main tasks of the *lamstex.stb* macros is to provide suitable
+*\mark*'s so that appropriate ``continuation'' lines may be written at the
+top of a page
+when a page
+break has occurred within an index entry, or subentry, etc. And because of
+this,
+column-breaking penalties will require more care.
+
+
+The
+*\columnbreak* command was not mentioned in the Manual, but
+ was added for the
+*paper* style, and mentioned in the Installation~Manual. In version~*2*
+we are also supplying *\nocolumnbreak* and *\newcolumn* (for a short
+column), although *\columnbreak* is really the only important one.
+Although these commands
+essentially insert penalties in vertical mode, we have to make sure
+that the penalties occur at the proper time with respect to the
+*\mark*'s that are emitted by the *\LETTER* and *\Entry* construction.
+
+The column-breaking macros work quite differently from the line-breaking
+macros because a penalty cannot be removed once it has been placed on the
+main vertical list:
+they
+will not insert any penalties directly, but
+will simply set the value of a counter, for later use. We declare the counter
+now,
+\CC**
+\newcount\ctype@
+**
+but the definitions
+\dotC**
+\def\nocolumnbreak{\ctype@=1 }
+\def\columnbreak{\ctype@=2 }
+\def\newcolumn{\ctype@=3 }
+**
+will only be given within the definition of *\makeindex*.
+We also need to
+declare a new counter to store the value of *\ctype@*, for use by the
+*\output* routine, after other constructions have returned *\ctype@* to~*0*:
+\CC**
+\newcount\Ctype@
+**
+
+It also turns out that column breaks have to be treated quite differently
+depending on whether they are inserted in the left column or the right
+column, and we will need a flag
+\CC**
+\newif\ifleftcolbreak@
+**
+
+Now we define a routine *\cbreak@#1#2* that uses the value of *\ctype@*,
+before resetting it to ~*0*.
+The definition begins
+**
+\def\cbreak@#1#2{\ifcase\ctype@#1\or\nobreak#2\else
+ . . .
+**
+Thus, if *\ctype@* is *0* (the usual situation, when no column-breaking
+command has recently been given), we simply insert *#1*, which will normally
+be penalty and glue. If *\ctype@* is~*1* (because a *\nocolumnbreak*
+command has recently been given), we instead insert *\nobreak* and then
+*#2* (which would normally be *#1*
+without the penalty). If *\ctype@* is *2* or *3* (because a *\columnbreak*
+or *\newcolumn* command has recently been given), we simply insert a
+*\break*. Then we reset *\ctype@* to~*0*. Before doing that last step,
+however, we store *\ctype@* in *\Ctype@*. Moreover, we set
+*\ifleftcolbreak@* to be false if $\hbox{*\pagetotal*}>\hbox{*\pageheight*}$
+(i.e., we already have enough on the page for the first column), but
+true otherwise:
+\CC**
+\def\cbreak@#1#2{%
+ \ifcase\ctype@#1\or
+"2
+ \nobreak#2\else
+"2
+ \global\leftcolbreak@true
+ \ifdim\pagetotal > \pageheight@
+ \global\leftcolbreak@false
+ \fi
+"2
+ \global\Ctype@=\ctype@
+ \break
+ \fi
+ \ctype@=0 }
+**
+The value of *\Ctype@* will be used by the *\output* routine, which will
+then globally reset *\Ctype@* to ~*0*.
+
+
+We have another flag
+\CC**
+\newif\ifshortlastcolumn@
+**
+for a final index feature not mentioned in the \lamstex~Manual,
+\dotC**
+\def\shortlastcolumn{\shortlastcolumn@true}
+**
+if we want the right
+column on the last page of the index
+to end short, instead of being spread out to match
+the height of the left column.
+
+\section{\CS{LETTER} and \CS{Entry}}
+The first *\Entry* after a *\LETTER* will be treated somewhat specially, so
+we will need a flag
+\CC**
+\newif\ifletter@
+**
+to tell when a *\LETTER* line has just been set.
+
+ *\LETTER* will
+end the previous paragraph (in which the various page numbers for a previous
+entry are being set) and
+emit a *\mark{}* to clear the marks.
+ Then we want
+**
+\penalty-200
+\bigskip
+**
+to encourage a page break (which really means a column break, since we will
+be setting in double columns).
+More precisely, we will use
+**
+\cbreak@{\penalty-200 \bigskip}\bigskip
+**
+Thus, when a *\nocolumnbreak* command has just appeared, we insert only the
+*\bigskip*, and when a *\columnbreak* or *\newcolumnbreak* command
+has just appeared, we just insert a *\break*.
+Then we set *\ifletter@* to be true,
+center the letter in bold face in its column, and finally
+add a\linebreak *\nobreak\medskip*:
+\dotC**
+\def\LETTER#1{\par
+ \mark{}%
+ \cbreak@{\penalty-200 \bigskip}\bigskip
+ \letter@true
+ \centerline{\bf#1}%
+ \nobreak\medskip}
+**
+As usual, the dotted lines indicate that
+this is a definition that will actually be included within the
+definition of *\makeindex*.
+
+
+To deal with the necessary *\mark*'s to be provided by
+*\Entry*, it will be convenient to have five token lists:
+\CC**
+\newtoks\marktoks@i
+\newtoks\marktoks@ii
+\newtoks\marktoks@iii
+\newtoks\marktoks@iv
+\newtoks\marktoks@v
+**
+Moreover, we will use a flag
+\CC**
+\newif\ifentry@
+**
+which *\Entry* will set true, and each *\Page* will set false.
+
+
+\def\di{{\it d}$_{\text1}$}
+\def\dii{{\it d}$_{\text2}$}
+
+Some aspects of our *\Entry* macro are particular to the default style,
+namely the particular manner in which entries and subentries are typeset.
+But the really
+ interesting aspect of *\Entry* is the way that
+it uses the first
+two arguments (\di, \dii, in the notation of
+page~115 of the \lamstex~Manual), to determine which *\mark*'s should be
+emitted; these *\mark*'s can be used by any style to define ``continuation
+lines'' of any desired sort. To deal with all possibilities, we will need a
+new counter
+\CC**
+\newcount\dii@
+**
+which will hold the value of \dii\ for the {\it previous\/}
+*\Entry*.
+
+The definition begins
+**
+\def\Entry#1#2#3#4#5#6#7{\par\entry@true
+ \marktoks@i={#3}\marktoks@ii={#4}\marktoks@iii={#5}%
+ \marktoks@iv={#6}\marktoks@v={#7}%
+ \ifcase#1%
+ \or
+ . . .
+**
+Thus, since the
+ case $\hbox{*#1*}=\hbox{\di}=\hbox{0}$
+is not supposed to occur, we consider first
+the case $\hbox{*#1*}=\hbox{\di}=\hbox{1}$,
+ which means that we have a first order entry, i.e.,
+ *#4*, \dots, *#7* are empty;
+ in this case $\hbox{*#2*}=\hbox{\dii}$
+ should be 0, since this new first order
+entry can't have any number of groups agreeing with the previous entry.
+
+We begin with
+**
+\ifletter@\else\mark{}\fi
+\cbreak@\relax\relax
+\noindent@
+\mark{10{\the\marktoks@i}}%
+\hangafter 1 \hangindent=.5em{#3}%
+**
+Thus:
+\list\item
+ We issue a *\mark{}* to clear the marks, unless the *\Entry* comes
+right after a *\LETTER*, which has already done this.
+\item If a *\nocolumnbreak* appeared right before the *\Entry* we
+add a *\nobreak*; and if a *\columnbreak* or *\newcolumn* appeared,
+we add a *\break*, and also set *\ifleftcolbreak@* to the appropriate value
+and store *\ctype@* in *\Ctype@* before restoring *\ctype@* to~ *0*.
+\item
+Then we start an unindented paragraph, which begins
+with a *\mark*,
+**
+\mark{10{\the\marktoks@i}}%
+**
+containing *#1#2*, and then a single group containing
+*#3* (without any expansion).
+The
+**
+\hangafter1 \hangindent=.5em{#3}%
+**
+means
+that after the entry *#3* is printed we are set up for printing the
+various page numbers, with hanging indentation if there are so many that they
+won't fit on a line. We enclose *#3* in a group, in case it involves a font
+change command, and are careful not to allow a space after *{#3}*, since
+punctuation still has to be added.
+\endlist
+
+When the paragraph with this entry is completed,
+the *\mark{10{...}}*\linebreak will migrate out so that it occurs right after
+the first line (before any\linebreak *\baselineskip* glue); consequently,
+there will be no legal breakpoint between the *\mark* and this first line,
+containing the typeset *{#3}*.
+If a page break occurs after this entry, but
+ before another entry, which contributes a new *\mark*,
+then after the
+page has been *\output* the value of
+*\botmark*
+will be
+**
+10{#3}
+**
+When a style file has to add continuation lines at the beginning of the next
+page, the *10* will tell it that the style broke at a main entry, which will
+be contained in the next group.
+ (Actually, we will be using *\splitbotmark* rather than
+*\botmark* when we do two-column setting.)
+
+
+In summary, our definition begins:
+**
+\def\Entry#1#2#3#4#5#6#7{\par\entry@true
+ \marktoks@i={#3}\marktoks@ii={#4}\marktoks@iii={#5}%
+ \marktoks@iv={#6}\marktoks@v={#7}%
+ \ifcase#1%
+ \or
+ \ifletter@\else\mark{}\fi
+ \cbreak@\relax\relax
+ \noindent@
+ \mark{10\the\marktoks@i}%
+ \hangafter1 \hangindent=.5em{#3}%
+ \or
+**
+
+Now let's consider the next case, $\hbox{\di}=\hbox{*#1*}=\hbox{2}$,
+so that we have a first order
+subentry. In this case $\hbox{\dii}=\hbox{*#2*}$
+ may be either ~0 or~1. When $\hbox{*#2*}=\hbox{0}$, we
+have a subentry that does {\it not\/} have the same main entry as the
+previous line, like the situation
+**
+\Entry 10{abracadabra}{}{}{}{}
+\Page {5}
+\Entry 20{acetyl-CoA}{action of}{}{}{}
+\page {32}
+**
+As mentioned on page~116 of the \lamstex~Manual, in some styles this might
+be printed as
+ {\bigskip\eightpoint\leftskip=30pt \noindent
+ abracadabra, 5\newline
+ acetyl-CoA, action of, 32
+\bigskip}
+\noindent
+In the default style, we will still print
+ {\bigskip\eightpoint\leftskip=30pt \noindent
+ abracadabra, 5\newline
+ acetyl-CoA\newline
+ \null\hskip5pt action of, 32
+\bigskip}
+\noindent
+but we still have to treat the *\mark*'s differently for the
+cases $\hbox{\dii}=\hbox{*#2*}=\hbox{0}$ and $\hbox{\dii}=\hbox{*#2*}=
+\hbox{1}$.
+
+For the case $\hbox{*#2*}=\hbox{0}$ we want
+**
+\ifletter@\else\mark{}\fi
+\cbreak@\relax\relax
+\noindent
+\mark{20{\the\marktoks@i}{\the\marktoks@ii}}%
+\hangafter1 \hangindent=.5em{#3}\par\nobreak
+\noindent\hangafter1 \hangindent=1.5em\quad{#4}%
+**
+Thus:
+\list\item
+We clear the previous mark (the one for *abracadabra*).
+\item We emit the mark
+\setbox0\hbox
+ {$\bigl[$*20{acetyl-CoA}{action of}*, in the above example$\bigr]$}
+**
+20{#3}{#4} "box0
+**
+ and then set up the proper format for printing things.
+If the page breaks in the middle of this entry, then *\botmark* will have
+the value
+**
+20{#3}{#4}
+**
+and the *\output* routine will be clued in as to
+what sort of continuation lines to
+add.
+\endlist
+
+The other case, when $\hbox{*#2*}=\hbox{1}$,
+corresponds to the more common situation
+where we have something like
+**
+\Entry 10{acetyl-CoA}{}{}{}{}
+\Page {32}
+\Entry 21{acetyl-Coa}{action of}{}{}{}
+\Page {45}
+**
+Here we will use
+**
+\mark{10{\the\marktoks@i}}%
+\cbreak@\relax\relax
+\noindent@
+\mark{21{\the\marktoks@i}{\the\marktoks@ii}}%
+\hangafter 1 \hangindent=1.5em\quad{#4}
+**
+
+Even when the *\cbreak@* contributes nothing (the usual situation), there
+is a legal break point between the first *\mark* and the *\noindent@*'ed
+paragraph that follows, because of the *\parskip* glue (possibly *0pt*)
+before this paragraph.
+If the page breaks at this point, then *\botmark* will be this first
+**
+\mark{10{acetyl-CoA}}
+**
+which is precisely right: we have broken in the middle of a first level
+entry. If the page breaks after the sub-entry begins, but before a new
+*\Entry*, which contributes a new *\mark*, then *\botmark* will be
+**
+21{acetyl-CoA}{action of}
+**
+again giving the *\output* routine all the information it needs to decide
+what sort of continuation lines to insert.
+
+\small
+Although we are using *\cbreak@\relax\relax* in all clauses of our
+*\Entry* definition, other styles might give more detailed choices. For
+example, it might be considered
+ better to break right before an entry than right before
+a subentry. We might use something like
+**
+\cbreak@{\ifletter@\else\penalty-20 \fi}\relax
+**
+for the case $\hbox{*#1*}=1$, thereby slightly encouraging a column break
+before main entries, except those immediately following a *\LETTER*.
+\endsmall
+
+
+The case $\hbox{\di}=\hbox{*#1*}=\hbox{3}$
+ begins similarly: When $\hbox{*#2*}=\hbox{0}$ we use
+**
+\ifletter@\else\mark{}\fi
+\cbreak@\relax\relax
+\noindent
+\mark{30{\the\marktoks@i}{\the\marktoks@ii}{\the\marktoks@iii}}%
+\hangafter1 \hangindent=.5em{#3}\par\nobreak
+\noindent@\hangafter1 \hangindent=1.5em\quad{#4}\par\nobreak
+\noindent@\hangafter1 \hangindent=2.5em\qquad{#5}%
+**
+and when $\hbox{*#2*}=\hbox{1}$ we use
+**
+\mark{10{\the\marktoks@i}}%
+\cbreak@\relax\relax
+\noindent@
+\mark{31{\the\marktoks@i}{\the\marktoks@ii}{\the\marktok@iii}}%
+\hangafter1 \hangindent=1.5em\quad{#4}\par\nobreak
+\noindent@\hangafter1 \hangindent=2.5em\qquad{#5}%
+**
+
+But the case $\hbox{*#2*}=\hbox{2}$
+ is a little different, because the previous entry
+might have been an *\Entry 20* or an *\Entry 21*, and to provide the style
+with all possible information, we want to supply the correct result. So we
+use
+**
+\mark{2"9\number\dii@"9{\the\marktoks@i}{\the\marktoks@ii}}%
+\cbreak@\relax\relax
+\noindent@
+\mark{32{\the\marktoks@i}{\the\marktoks@ii}{\the\marktoks@iii}}%
+\hangafter1 \hangindent=2.5em\qquad{#5}%
+**
+where *\dii@* will have the proper value, because, at the very end of
+this long *\ifcase* (with sub *\ifcase*'s)
+we finish off the whole definition of *\Entry* with
+**
+\dii@=#2\relax
+\letter@false\ignorepars@}
+**
+
+We won't bother writing out the whole definition, since these parts explain
+everything interesting that is going on (moreover, the whole definition
+appears only within the definition of *\makeindex*).
+
+\nopunct\section{\CS{Page}, etc.\label{IPAGE}}
+Using *\adjustpunct@* (section~\Sref{BMPRE}), we will define
+*\Page* for the index setting by
+\dotC**
+\def\Page#1{\ifentry@\adjustpunct@,\enspace\else
+ \adjustpunct@, \fi\entry@false{#1}\ignorepars@}
+**
+In other words, the first *\Page* after an *\Entry*, when *\ifentry@* is
+still true,
+ will add a comma after
+the entry, and then an *\enspace*, while successive *\Page*'s, for which
+*\ifentry@* will be false,
+ will simply
+add a comma after that page number and then an ordinary space
+(with suitable juggling of line-breaking penalties).
+We put *#1* in a group in case it involves a font change.
+
+The *\Pagespan*, *\Topage* combination requires a bit more
+ manipulation, because
+the *index* program may have produced something like
+**
+\Pagespan {123}
+\Topage {123}
+**
+which should be printed simply as `123', rather than as `123@--123'.
+
+We begin with
+\dotC**
+\def\Pagespan#1{\ifentry@\adjustpunct@,\enspace\else
+ \adjustpunct@, \fi
+ \entry@false\def\frompage@{#1}{#1}\ignorepars@}
+**
+Thus, we supply punctuation just as with *\Page*, and before printing
+*#1* we also
+ store
+*#1* in *\frompage@*, for use with *\Topage*, defined by
+\dotC**
+\def\Topage#1{\def\next@{#1}\ifx\next@\frompage@
+ \else\hbox{--}{#1}\fi\ignorepars@}
+**
+The *\hbox{--}* gives an en-dash at which a line break can't occur
+ (it is what the
+\lamstex\ construction *@--* produces).
+
+The variant *\PageSpan#1#2*, which has a control sequence as
+its first argument, puts in punctuation in the same manner as
+ *\Pagespan*, and also
+ stores the page argument, *#2*, in *\frompage@*, as well as the
+control sequence, *#1*, in *\pagecs@*. Then it begins a group in which
+the definition of *\Topage* will be changed, so that the *\Topage* following
+*\PageSpan* can act differently than when it follows *\Pagespan*:
+\dotC**
+\def\PageSpan#1#2{\ifentry@\adjustpunct@,\enspace
+ \else\adjustpunct@, \fi\entry@false
+ \def\pagecs@{#1}\def\frompage@{#2}%
+ \bgroup\let\Topage=\Topage@\ignorepars@}
+**
+Then *\Topage@* will apply *\pagecs@* to the pages spanned (or to
+a single page if the two numbers are the same), and supply the *\egroup* to
+match the *\bgroup*:
+\CC**
+\def\Topage@#1#2{\def\next@{#2}\ifx\next@\frompage@
+ \pagecs@{\frompage@}\else
+ \pagecs@{\frompage@\hbox{--}#2}\fi
+ \egroup\ignorepars@}
+**
+We use *\pagecs@{...}*
+in case *\pagecs@* is a control sequence with
+an argument; the *\bgroup* and *\egroup* provide the necessary extra level of
+grouping in case *\pagecs@* is a font change instruction. We might as
+well give the definition of *\Topage@* now, rather than within the
+definition of *\makeindex*, since *\Topage@* can't be typed by the user
+anyway.
+
+
+\nopunct\section{\CS{Xref}, etc.}
+The description of the *"1x* option
+on page~108 of the \lamstex~Manual, and the output it supposedly produces in
+the *.xdx* file, as described on page~115 of the Manual, is incorrect.
+\footnote{As mentioned on pages~8--9 of the \lamstex\
+Installation Manual.}
+There are actually {\it two\/} options, *"1x* and *"1X*. The *"1x* option
+is to be used
+when only a cross-reference is desired, and not a reference to the page on
+which the entry is marked, while the *"1X* option indicates a reference to
+the page on which the entry is marked, together with a cross reference.
+
+If an entry is always marked with the *"1x* option, then the pages on which
+it is marked are completely irrelevant, and it will give rise to an
+*\Entryxref* line in the *.xdx* file (possibly followed by various
+*\Morexref* lines). Otherwise, it will give rise to something like
+\Litbox0=**
+\Entry ...
+\Xref ...
+\Morexref ...
+ . . .
+\Page ...
+\Page ...
+\Xref ...
+\Morexref ...
+ . . .
+**
+$$\vcenter{\box0}\tag"\style{\bf A}"$$
+with *\Xref...* material occurring both before and after the *\Page*'s because
+some styles might want to print the `{\it see also\/}' before the page
+numbers instead of after them.
+
+In any case, as the Manual shows on page~115, each *\Xref*, *\Morexref*,
+and *\Entryxref* will contain *\See*, which can be defined as needed.
+
+In the default style we will be ignoring the *\Xref* and *\Morexref*'s in
+({\bf A}) that come before the first *\Page*;
+this means that we want
+ *\Xref* and *\Morexref* to operate only when *\ifentry@* is false.
+
+
+*\Xref*, which will occur after some *\Page*, will add a semi-colon after
+the page, and then print `{\it see also\/} ' before its argument.
+As with the bibliography macros, we use *\semicolon@* instead of~ *;* for
+the benefit of French styles (section~\Sref{SEMICOL}), and we add *\/* before
+it,
+\dotC**
+\def\Xref#1{\ifentry@\else
+ \def\See##1{\/\adjustpunct@\semicolon@\space
+ {\it see~also\/}~##1}{#1}\fi\ignorepars@}
+**
+while *\Morexref* will simply add a comma after the previous
+cross-reference page, and then a space:
+\dotC**
+\def\Morexref#1{\ifentry@\else
+ \def\See##1{\adjustpunct@, ##1}{#1}\fi\ignorepars@}
+**
+
+An *\Entryxref* is basically just an *\Entry*, after which we
+add the final argument rather than succeeding *\Page*'s.
+\dotC**
+\def\Entryxref#1#2#3#4#5#6#7#8{%
+ \Entry{#1}{#2}{#3}{#4}{#5}{#6}{#7}%
+ \def\See##1{\adjustpunct@, {\it see\/}~##1}%
+ {#8}\ignorepars@}
+**
+(The *\adjustpunct@* is added in case the user adds a line-breaking
+command, like
+**
+\Entryxref 10{adrenalin}{}{}{}{}{\linebreak\See {epinephrine}}
+**
+by hand.)
+
+
+\small
+Suppose that we want to print the `{\it see also }'
+before the page numbers instead of after them, which means that
+we need to
+use the *\Xref*'s and *\Morexref*'s that
+appear before the first *\Page*,
+ignoring *\Xref*'s and *\Morexref*'s
+following a *\Page*.
+
+For this we would introduce a new flag
+**
+\newif\ifxref@
+**
+which *\Xref* would set true and *\Entry* would set false, and then
+we could use definitions like
+**
+\def\Xref#1{\ifentry@
+ \def\See##1{ {\it see also\/} ##1}{#1}\fi\ignorepars@}
+\def\Morexref#1{\ifentry@
+ \def\See##1{\adjustpunct@, ##1}{#1}\fi\ignorepars@}
+\def\Page#1{\ifxref@\newline\else
+ \ifentry@\adjustpunct@,\enspace\else
+ \adjustpucnt@, \fi\fi\entry@false{#1}\ignorepars@}
+**
+Then entries without cross-references would appear as before, while
+entries with cross-references would appear as
+{\bigskip\eightpoint\leftskip30pt
+ acetyl-CoA {\it see also\/} derivative, pyruvate
+ \hskip5pt 30, 56, 78
+\bigskip}
+\noindent Instead of the *\newline* we might prefer `*. *' or
+perhaps *\Xref* would add `*({\it see also\/} *' while
+*\Page* would add `*) *' instead of *\newline*.
+
+\andsmall
+Similarly,
+any punctuation after the last page number would have to be added by
+the next *\Entry* (the definition
+of *\makeindex* would also have to take care of the last *\Entry* specially).
+ But
+no one ever adds this punctuation, so why worry about it.
+\endsmall
+
+
+
+\section{Preliminaries for double columns}
+We first declare
+a \<dimen\> register to store *\vsize*,
+\CC**
+\newdimen\pageheight@
+\pageheight@=\vsize
+**
+since *\vsize* will be changed when
+we are storing material for double columns,
+and a dimension *\doublepageheight@*, which is a little more than twice
+*\pageheight@*,
+\CC**
+\newdimen\doublepageheight@
+\doublepageheight@=2\pageheight@
+\advance\doublepageheight@ by 1 pc
+**
+
+We also declare a \<dimen\> register
+ to store the original *\hsize*,
+\CC**
+\newdimen\pagewidth@
+\pagewidth@=\hsize
+**
+
+The *\makeindex* routine will be setting columns 3~inches wide, so we will be
+changing *\hsize*. Consequently, we must redefine *\makeheadline* and
+*\makefootline* from *plain* \tex@, so that *\line* ($=${}*\hbox to\hsize*)
+is replaced by *\hbox to\pagewidth@*:
+\CC**
+\def\makeheadline{\vbox to 0pt{\vskip-22.5pt
+ \hbox to\pagewidth@{\vbox to 8.5pt{}\the\headline}\vss}%
+ \nointerlineskip}%
+\def\makefootline{\baselineskip=24pt
+ \hbox to\pagewidth@{\the\footline}}%
+**
+(The definition of *\makeheadline* isn't really needed for the default style,
+ since we are going to keep *\headline={}*, but we might as well take care of
+the general mechanism.)
+
+As in Appendix E of {\it The \tex book}, page~417,
+we will be setting ``pages''
+of
+length *\doublepageheight@*, so that we can
+automatically balance the columns on the last page.
+We need another flag
+\CC**
+\newif\iffirstindexpage@
+**
+since the first page of the index is special, having a header `{\bf INDEX}'
+that extends across both columns.
+
+\section{\CS{makeindex}}
+The *\makeindex* routine begins
+\setbox0\hbox{\<all previous definitions enclosed in dotted lines}
+\setbox1\hbox{\qquad(including the definition of *\Entry*)\>}
+**
+\def\makeindex{\checkmainfile@\par\vfill\break
+ \begingroup
+ "box0
+ "box1
+ \hsize=3in
+**
+Of course all *#*'s in any of those \<previous definitions\> are changed to
+*##*'s.
+
+Next we set
+**
+\global\vsize=\doublepageheight@
+**
+so that we will have
+accumulated slightly more than we need to fill both columns of the page
+before the *\output* routine is called (we use *\global* here because
+it will be required later, when we set *\vsize* within the *\ouput* routine).
+And
+we set
+**
+\maxdepth=\maxdimen
+**
+ so that the depth of
+*\box255* will always be the actual depth of its last line; this is
+needed at one point later (compare {\it The \tex book}, page~262@--263).
+
+Then we set
+**
+\global\firstindexpage@true
+\global\advance\vsize by -60pt
+**
+The
+60~points is need to leave room for a 30~point heading above both columns.
+
+Next,
+ we
+set
+**
+\everypar={}\parindent=0pt
+**
+just as a precaution, and then
+**
+\rightskip=0pt plus3em \spaceskip=.3333em \xspaceskip=.5em
+**
+for ragged
+right setting (we allow even more ``raggedness'' than the definition of
+*\raggedright* in *plain* \tex)@.
+
+And then we want to change the *\output* routine to one called
+**
+\doublecolumns@
+**
+before reading in the appropriate *.xdx* file; after this file has been
+read we will issue an empty *\mark{}*,
+change the *\ouput* routine to one called
+*\balancecolumns@*, for the final page of the index, and then supply
+the *\endgroup* that matches the *\begingroup* at the beginning of the
+definition. For anything that follows the *\makeindex*, we will once
+again have *\output="allowbreak{\plainoutput}*. However, *\vsize* has
+been globally changed, so we must reset it to *\pageheight@*.
+\setbox0\hbox{\<definitions from before\>}
+\CC**
+\def\makeindex{\checkmainfile@
+ \par\vfill\break
+ \begingroup
+ "box0
+ \hsize=3in
+"2
+ \global\vsize=\doublepageheight@
+"2
+ \maxdepth=\maxdimen
+"2
+ \global\firstindexpage@true
+"2
+ \global\advance\vsize by -60pt
+"2
+ \everypar={}\parindent=0pt
+"2
+ \rightskip=0pt plus3em \spaceskip=.3333em \xspaceskip=.5em
+"2
+ \output={\doublecolumns@}%
+ \input\mainfile@.xdx
+ \mark{}%
+ \output={\balancecolumns@}%
+ \vfil\break
+ \endgroup
+ \global\vsize=\pageheight@}
+**
+
+
+\section{\CS{combinecols\@}}
+Both *\doublecolumns@* and *\balancecolumns@* will store the two columns
+in *\box0* and *\box2* and then
+ use the routine
+*\combinecolumns@*, which prints these boxes
+side by side, together with the proper headline and footline.
+**
+\def\makeindex@W{Index}
+"slip
+\def\combinecolumns@{%
+"2
+ \setbox\outbox@=\vbox{\makeheadline
+"2
+ \vbox to\pageheight@{\boxmaxdepth=\maxdepth
+"2
+ \iffirstindexpage@
+"2
+ \vbox to30pt{\vskip10pt
+ \hbox to\pagewidth@{\hfil\bf
+ \uppercase\expandafter{\makeindex@W}\hfil}\vfil}
+"2
+ \nointerlineskip
+ \fi
+"2
+ \wd0=\hsize \wd2=\hsize
+ \setbox0=\hbox to\pagewidth@{\box0 \kern.5in\box2}
+ \dimen@=\dp0 \box0 \kern-\dimen@\vfill}
+ \makefootline}
+ {\noexpands@ \let\style=\relax
+ \shipout@\box\outbox@
+ }
+ . . .
+**
+
+This is like the *\shipout@* occurring in our definition of
+*\plainoutput* (page~\ref{DEFPLOUT}),
+except that the *\pagebody* must be replaced by
+a *\vbox to*\linebreak*\pageheight@*,
+ containing the two boxes with a separation
+of *.5in*. There are also two minor adjustments to be made:
+\list
+\item
+We must explicitly declare the widths of *\box0* and *\box2*
+to be *\hsize* (*\hsize* is simply the width of paragraphs within
+these boxes; an inserted *\box* in vertical mode could be any width---compare
+the footnote on page~\ref{MAXD}).
+\item
+Our *\vbox to\pageheight@* ends with the
+**
+\hbox to\pagewidth@{\box0 \kern.5in\box2}
+**
+followed by
+*\vfill* (preceded by a *\kern*).
+ That is because on the last page, where we balance
+columns, this *\hbox* will generally be smaller than *\pageheight@*.
+Most of the time, of course, the *\vfill* will be irrelevant, except that
+we have to be sure to insert the *\kern* before the *\vfill*, so that
+the depth of the *\hbox* will not cause an *Overfull* box (compare
+page~\ref{KMPR}).\pagelabel{USEKMPR}
+\endlist
+
+In addition, on the first page of the
+index, our two columns, *\box0* and *\box2*
+will have been made 30~points smaller
+than *\pageheight@*, in order to accommodate the
+**
+\vbox to30pt{\vskip10pt
+ \hbox to\pagewidth@{\hfil\bf
+ \uppercase\expandafter{\makeindex@W}\hfil}\vfil}%
+ \nointerlineskip
+**
+that we insert. We use *\makeindex@W*, so that *\newword* can be used
+to determine the heading that will be printed.
+
+ Notice that we have the *\noexpands@...\shipout@* in a
+group, so that the *\noexpands@* won't interfere with
+font change instructions in
+``continuation'' lines contributed later
+ (see page~\ref{CONLINES}) by the *\output* routine. (Compare
+page~\ref{SHIPOUTGROUP}.)
+
+After all this, we simply declare *\iffirstindexpage@* to be false,
+set *\vsize* to *\doublepageheight@*, its proper value for all index pages
+after the first, and *\advancepageno*:
+\CC**
+\def\makeindex@W{Index}
+"slip
+\def\combinecolumns@{%
+"2
+ \setbox\outbox@=\vbox{\makeheadline
+"2
+ \vbox to\pageheight@{\boxmaxdepth=\maxdepth
+"2
+ \iffirstindexpage@
+"2
+ \vbox to30pt{\vskip10pt
+ \hbox to\pagewidth@{\hfil\bf
+ \uppercase\expandafter{\makeindex@W}\hfil}%
+ \vfil}%
+"2
+ \nointerlineskip
+"2
+ \fi
+"2
+ \wd0=\hsize \wd2=\hsize
+ \setbox0=\hbox to\pagewidth@{\box0 \kern.5in\box2}%
+"2
+ \dimen@=\dp0 \box0 \kern-\dimen@\vfill}%
+ \makefootline}%
+ {\noexpands@ \let\style=\relax
+ \shipout@\box\outbox@
+ }%
+ \global\vsize=\doublepageheight@
+ \global\firstindexpage@false
+ \advancepageno}
+**
+
+
+\section{\CS{doublecolumns\@}}
+For the
+ *\doublecolumns@* routine, used for all but the last page, we will need
+a new \<dimen\> register
+\CC**
+\newdimen\prevcoldepth@
+**
+The routine
+begins
+with
+**
+\dimen@=\pageheight@
+\iffirstindexpage@ \advance\dimen@ by -30pt \fi
+**
+so that *\dimen@* is the height of the columns we want for the page.
+
+Now we have to consider the possibility that a *\columnbreak* or a\linebreak
+*\newcolumn*
+command caused the *\output* routine to be invoked. More precisely, we
+want to insert the code
+**
+\ifleftcolbreak@
+ \global\leftcolbreak@false
+ . . .
+\else
+ _ _ _
+\fi
+**
+The flag *\ifleftcolbreak@* is set true (by *\cbreak@*) when
+a *\columnbreak* or *\newcolumn* command has been issued
+when we are setting the left column,
+\footnote{I.e., when *\pagetotal* is
+ $\le\hbox{*\pageheight@*}$.}
+and it is used only in the current
+test; since we immediately reset it to be false, this means that
+*\ifleftcolbreak@* is true precisely when we have forced a break in the left
+column. We will simply let `\hbox{*. . .*}' for this case be
+**
+\vbox to\dimen@{\dimen@=\dp255 \unvbox255
+ \ifnum\Ctype@=3 \kern-\dimen@\vfill\fi}
+\allowbreak
+**
+In other words, when our *\output* routine has been forced while we
+still have only enough material for the first column, we do not do any
+*\shipout*, but simply put material back on the main vertical list.
+What we put back is a *\vbox to\dimen@* (remember that *\dimen@* is
+the desired height of columns for this page), containing all the material
+in *\box255*, either stretched out, when we had a *\columnbreak* (so that
+*\Ctype@* is~*2*), or filled with empty space at the bottom, when we had
+a *\newcolumn* (so that *\Ctype@* is~*3*). As before (page~\ref{USEKMPR}),
+ we need to add a
+*\kern* before the *\vfill*.
+
+
+ The next time the *\output*
+routine is called, *\doublecolumns@* will use the rest of the routine, still
+to be defined, which splits the full *\box255* into two boxes of height
+*\dimen@*; the first part will then have to be this *\vbox to\dimen@* that
+we have just added to the main vertical list.
+\footnote{The only problem here is that the *\output* routine could
+conceivably be *\balancecolumns* the next time it is called---see
+the discussion on page~\ref{CBBAL}~ff.}
+
+Having gotten that consideration out of the way, let's consider the
+other situation, where we haven't forced a break in a left-hand column.
+Now we want to *\vsplit* *\box255* into two boxes of height *\dimen@*.
+During the process we will set *\splittopskip=\topskip* and
+*\splitmaxdepth=\maxdepth* (this assignment will be local, since the
+*\output* routine, *\doublecolumns*, is implicitly enclosed in a group).
+Splitting off the first column requires no special work,
+**
+\splittopskip=\topskip \splitmaxdepth=\maxdepth
+\setbox0=\vsplit255 to\dimen@
+**
+But for the second column, we can't simply
+**
+\setbox2=\vsplit255 to\dimen@
+**
+This works when *\Ctype@* is~*0* or ~*1* (no column-breaking commands,
+except perhaps a *\nocolumnbreak*,
+were given). But when *\Ctype@* is~
+*2* or~ *3*
+(a *\columnbreak* or *\newcolumn*
+command was given) the *\vsplit*'ing is irrelevant---we
+should simply let *\box2* be *\box255*.
+And when *\Ctype@* is~*3*
+(the *\newcolumn* case), we need to add *\vfill* at the
+bottom of the box.
+For a later step, we also want to store the depth of the last line
+of the second column in *\prevcoldepth@*.
+
+Since the cases when *\Ctype@* is *0* and *1* are treated the same,
+we consolidate the cases by first stating
+**
+\ifnum\Ctype@=0 \global\Ctype@=1 \fi
+**
+Then we can use
+**
+\ifcase\Ctype@ \or % case 1 (originally 0 or 1)
+ \setbox2=\vsplit255 to\dimen@
+ \global\prevcoldepth@=\dp2
+ \or % cases 2 and 3
+ \global\prevcoldepth@=\dp255 % store the depth first
+ \setbox2=\vbox to\dimen@{\unvbox255
+ \ifnum\Ctype@=3 \vfill\kern-\prevcoldepth@\vfill\fi}
+ \fi
+**
+
+Once we've determined the columns, *\box0* and *\box2*, in this way,
+we use
+**
+\combinecolumns@
+**
+to *\shipout* the desired page.
+
+Now we have reached the point where we want the *\output* routine to
+add ``continuation'' lines\pagelabel{CONLINES}
+ (these lines, inserted by the *\output* routine,
+will go before anything remaining in *\box255*, since we will add these
+lines before we *\unvbox255*; and both go before anything else that happens
+to remain on the main vertical list when the page break was chosen).
+
+The default routine adds continuation lines at the beginning of the left
+column on
+a new page
+to reflect the *\mark*'s at the end of the right column on the previous page.
+This means that we will want to use *\splitbotmark* when *\box2* was
+obtained as a *\vsplit255 to\dimen@*, but *\botmark* otherwise.
+The specific continuation lines to be constructed from these marks will
+be contributed by a routine, to be defined shortly,
+\setbox0\hbox{\<the *\mark*'s\>}
+**
+\continue@ "box0 \continue@
+**
+It will be convenient to consider *\continue@* to be followed by at least
+~7 (possibly empty) arguments,
+ and we will use
+**
+\ifcase\Ctype@ \or % case 1, where \vsplit was used
+\expandafter\continue@\splitbotmark{}\relax\relax\relax
+ \relax\relax\relax\continue@
+\else % cases 2 and 3
+\epxandafter\continue@\botmark{}\relax\relax\relax
+ \relax\relax\relax\continue@
+\fi
+**
+As we will see in a minute, *\continue@* will also attend to an important
+detail about spacing.
+
+After these continuation lines, we simply use
+**
+\ifvoid255 \else \unvbox255 \penalty\outputpenalty\fi
+**
+to finish the *\else* clause of our definition. And, finally, after the
+entire *\if...\else...\fi* has been done, we reset *\Ctype@* to be~*0*:
+\CC**
+\def\doublecolumns@{%
+ \dimen@=\pageheight@
+ \iffirstindexpage@ \advance\dimen@ by -30pt \fi
+"2
+ \ifleftcolbreak@
+ \global\leftcolbreak@false
+ \vbox to\dimen@{\dimen@=\dp255
+ \unvbox255 \ifnum\Ctype@=3 \kern-\dimen@\vfill\fi}%
+ \allowbreak
+"2
+ \else
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \setbox0=\vsplit255 to\dimen@
+"2
+ \ifnum\Ctype@=0 \global\Ctype@=1 \fi
+"2
+ \ifcase\Ctype@ \or
+ \setbox2=\vsplit255 to\dimen@
+ \global\prevcoldepth@=\dp2
+"2
+ \else
+ \global\prevcoldepth@=\dp255
+ \setbox2=\vbox to\dimen@{\unvbox255
+ \ifnum\Ctype@=3 \kern-\prevcoldepth@\vfill\fi}%
+ \fi
+"2
+ \combinecolumns@
+"2
+ \ifcase\Ctype@ \or \expandafter
+ \continue@\splitbotmark{}\relax\relax\relax
+ \relax\relax\relax\continue@
+ \else
+ \expandafter\continue@\botmark{}\relax\relax\relax
+ \relax\relax\relax\continue@
+ \fi
+"2
+ \ifvoid255 \else \unvbox255 \penalty\outputpenalty \fi
+ \fi
+ \global\Ctype@=0 }
+**
+
+\medskip
+The *\continue@* routine is followed by at least~7 (possibly empty) arguments,
+**
+\def\continue@#1#2#3#4#5#6#7#8\continue@
+**
+Since *\continue@* is used in a combination
+\setbox0\hbox{\<value of *\splitbotmark* or *\botmark*\>}
+**
+\continue@"box0{}\relax\relax\relax
+ \relax\relax\relax\continue@
+**
+the test
+**
+\def\next@{#1}\ifx\next@\empty
+**
+isolates the case where the *\mark* is empty (in all other cases the
+mark will begin with a digit).
+ When this is not the case,
+we want
+**
+\noindent@#3 ({\it continued\/})\par
+**
+as the first continuation line. The default style also introduces
+slightly differently formatted continuation lines for any sub-entries, where
+the number of levels of sub-entries is known from the value of *#1*,
+**
+\ifnum#1>1 \noindent@\enspace(#4 {\it continued\/})\par\fi
+ . . .
+\ifnum#1>4 \noindent@\enspace(#7 {\it continued\/})\par\fi
+**
+
+
+After these continuation lines are added, we have to attend to the detail
+mentioned on page~263 of {\it The \tex book}, except that
+now we have to consider two different cases:
+
+{\bf (1)} Suppose first that all of *\box255* has been used up, and that the
+first box waiting to be placed
+on the new current page
+has height {\it h}.
+This box
+ will be preceded by interline glue {\it g}, since the page break
+that created it broke right before the glue. If
+that box
+were the first thing to be placed on the new page,
+ the glue {\it g\/} would be irrelevant,
+since \tex\ discards glue when the current page does not contain any
+boxes ({\it The \tex book}, page~112); instead of this glue, \tex\ would
+simply insert the glue determined by *\topskip*.
+ But this glue will {\it not\/}
+ be discarded if
+continuation lines have already been added.
+
+ We have stored the depth of the line
+preceding this first box in\linebreak
+ *\prevcoldepth@*; thus, the glue {\it
+g\/}
+satisfies
+\Math\hbox{*\prevcoldepth@*}+\hbox{\it g}+\hbox{\it h}
+ =\hbox{*\baselineskip*}\endMath
+But now we need new glue {\it g}$'$ such that
+\Math
+\hbox{*\prevdepth*}+\hbox{\it g}'+\hbox{\it h}=\hbox{*\baselineskip*}\endMath
+So we need to add $\hbox{*\prevcoldepth@*}-
+ \hbox{*\prevdepth*}$ glue; thus, when continuation lines are added,
+we need to
+**
+\global\advance\prevcoldepth@ by -\prevdepth \kern\prevcoldepth@
+**
+(We can change *\prevcoldepth@* like this, instead of using the more
+complicated code
+**
+"hskip-20pt\dimen@=\prevcoldepth@ \advance\dimen@ by -\prevdepth \kern\dimen@
+**
+because *\prevcoldepth@* won't be used any more.)
+
+{\bf(2)} When *\box255* has not been used up, however, the situation is quite
+different, since this *\box255* is what remains from a *\vsplit*,
+so that the glue {\it g\/} is simply enough to make
+\Math
+\hbox{\it g}+\hbox{\it h}=\hbox{*\topskip*}
+\endMath
+We want glue {\it g}$'$ such that
+\Math
+\hbox{\it g}'+\hbox{\it h}+\hbox{*\prevdepth*}=\hbox{*\baselineskip*}
+\endMath
+so we need to add
+\Math\hbox{*\baselineskip*}-\hbox{*\prevdepth*}-\hbox{*\topskip*}
+\endMath
+extra glue.
+
+Actually, in both cases {\bf(1)} and {\bf(2)}, *\baselineskip* should really
+be\linebreak
+$\hbox{*\baselineskip*}+\hbox{*\parskip*}$, though this
+doesn't make any difference in the final result for {\bf(1)}.
+
+The whole definition is thus
+\CC**
+\def\continue@#1#2#3#4#5#6#7#8\continue@{%
+ \def\next@{#1}\ifx\next@\empty
+"2
+ \else
+ \noindent@#3 ({\it continued\/})\par
+"2
+ \ifnum#1>1 \noindent@\enspace(#4 {\it continued\/})\par\fi
+"2
+ \ifnum#1>2 \noindent@\enspace(#5 {\it continued\/})\par\fi
+"2
+ \ifnum#1>3 \noindent@\enspace(#6 {\it continued\/})\par\fi
+"2
+ \ifnum#1>4 \noindent@\enspace(#7 {\it continued\/})\par\fi
+ \ifvoid 255
+ \global\advance\prevcoldepth@ by -\prevdepth \kern\prevcoldepth@
+ \else
+ \skip@=\baselineskip \advance\skip@ by \parskip
+ \advance\skip@ by -\prevdepth
+ \advance\skip@ by -\topskip
+ \vskip\skip@
+ \fi
+ \fi}
+**
+
+\small If we had also
+wanted continuation lines at the top of right hand columns,
+ *\doublecolumns@* would have to be more complicated:
+\setbox0\hbox{\<the *\else* part of old *\doublecolumns@* routine\>}
+\setbox1\hbox{\<set *\dimen@* as before\>}
+\setbox2\hbox{\<corresponding part of old *\doublecolumns@* routine\>}
+\setbox3\hbox{\<add continuation lines,}
+\setbox4\hbox{\ \ \ adjusting space using *\leftcoldepth@*\>}
+\setbox5\hbox{\ \ \ adjusting space using *\prevcoldepth@*\>}
+**
+\newif\ifleftcol@
+\newdimen\leftcoldepth@
+"slip
+\def\doublecolumns@{"box1
+ \ifleftcol@
+ \global\leftcolfalse@
+ \ifleftcolbreak@
+ \global\leftcoldepth@=\dp255
+ "box2
+ "copy3
+ "box4
+"2
+ \else
+ {\splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \global\setbox1=\vsplit255 to\dimen@
+ \global\prevcoldepth@=\dp1 }
+ \box1 \allowbreak
+ "copy3
+ "box5
+ \fi
+"2
+ \else
+ \global\leftcol@true
+ "box0
+ \fi
+ \global\Ctype@=0 }
+**
+ Thus, *\doublecolumns@* would
+end up
+being
+ called twice for each page, even if there was no column break in the left
+column.
+\endsmall
+
+
+
+
+\section{\CS{balancecolumns\@}}
+The *\balancecolumns@* routine basically
+follows that of page~417 of {\it The \tex
+book}, except that we have to be a little more careful about the final
+glue (the routine in {\it The \tex\ book\/} was used for setting
+{\it The \tex book}, where the balanced columns are then followed by
+more material), and we also have to allow for a short last column.
+
+We begin with
+**
+\setbox0=\vbox{\unvbox255 \unskip}
+\dimen@=\ht0
+**
+using *\unskip* to completely eliminate *\vfill* that may have been
+added by the *\bye* (this *\vfill* might not be there if the page break
+actually occurs before the final line); this prevents the depth of *\box255*
+from being counted in the height of *\box0*.
+
+Now we basically want to divide *\dimen@* by 2, and split *\box0* into
+two pieces of that height. But we make a slight adjustment:
+When we split *\box0* into two pieces, the top line of the second piece,
+which currently has *\baselineskip* glue before it, should only get
+*\topskip* glue. So we use
+**
+\advance\dimen@ by \topskip
+\advance\dimen@ by -\baselineskip
+\divide\dimen@ by 2
+**
+---now *\dimen@* is the ideal height for the two pieces into which we
+hope to split *\box0*.
+
+Then we set
+**
+\splittopskip=\topskip
+**
+and use a *\loop* for splitting. This *\loop* will operate inside a group
+with *\vbadness=10000*, so that *Underfull \vbox*'es won't be reported
+unless the columns are actually bad after the balancing act:
+**
+{\vbadness=10000
+ \loop
+ \global\setbox3=\copy 0
+ \global\setbox1=\vsplit3 to\dimen@
+ \ifdim\ht3 > \dimen@ \global\advance\dimen@ by 1pt
+ \repeat}
+**
+Briefly, we try splitting to the ideal *\dimen@*, but if we can't get
+two columns of the same height we want the left column to be the bigger;
+so, if the right column turns out to be bigger, we keep increasing *\dimen@*
+by 1~point until we get a split where the left column is at least as big as
+the right column.
+We always *\split* a copy of *\box0* rather than *\box0* itself, so that
+*\box0* is always available for the next iteration of the *\loop*.
+
+We used *\global\advance* here because we need to know the final value of
+*\dimen@*. But to keep assignments of *\dimen@* local, we will modify this
+code to
+**
+\global\dimen@i=\dimen@
+{\vbadness=10000
+ \loop
+ \global\setbox3=\copy 0
+ \global\setbox1=\vsplit3 to\dimen@i
+ \ifdim\ht3 > \dimen@ \global\advance\dimen@i by 1pt
+ \repeat}
+**
+so that *\dimen@i* is the final dimension we are interested in.
+
+
+Now we have to set each of
+*\box0* and *\box2*, which will be used by\linebreak *\combinecolumns@*,
+to a *\vbox to\dimen@i* (at this point we may get an *Underfull \vbox*
+message):
+**
+\setbox0=\vbox to\dimen@i{\unvbox1}
+\setbox2=\vbox to\dimen@i{\dimen@=\dp3 \unvbox3
+ \ifshortlastcolumn@ \kern-\dimen@ \vfill\fi}
+**
+The second column, *\box2* is supplied with *\vfill* when we want
+it to be short; as usual (compare page~\ref{KMPR} and~\ref{USEKMPR}),
+ a
+ *\kern* is required before the *\vfill* to prevent the depth of
+the box from being counted as part of the height, possibly producing
+a spurious *Overfull* box.
+
+The complete code is:
+\CC**
+\def\balancecolumns@{%
+ \setbox0=\vbox{\unvbox255 \unskip}%
+"2
+ \dimen@=\ht0 \advance\dimen@ by \topskip
+ \advance\dimen@ by -\baselineskip
+ \divide\dimen@ by 2
+"2
+ \splittopskip=\topskip
+ \global\dimen@i=\dimen@
+"2
+ {\vbadness=10000
+ \loop
+"2
+ \global\setbox3=\copy 0
+ \global\setbox1=\vsplit 3 to\dimen@i
+ \ifdim\ht3 > \dimen@i \global\advance\dimen@i by 1pt
+ \repeat}%
+"2
+ \setbox0=\vbox to\dimen@i{\unvbox1}%
+ \setbox2=\vbox to\dimen@i{\dimen@=\dp3 \unvbox3
+ \ifshortlastcolumn@ \kern-\dimen@ \vfill\fi}%
+ \combinecolumns@}
+**
+
+That completes all the routines from *lamstex.stb*, so we end, as in
+*lamstex.tex* itself, with
+\CC**
+\def\alloc@#1#2#3#4#5{\global\advance\count1#1by\@ne
+ \ch@ck#1#4#2\allocationnumber\count1#1
+ \global#3#5\allocationnumber
+ \wlog{\string#5\string#2\the\allocationnumber}}
+\catcode`\@=\active
+**
+
+\small
+Balancing an index can be problematical because of final letters with only a
+few entries. \pagelabel{CBBAL}
+ For example, an index might end
+\bigskip
+\setbox0\vbox{\hsize10pc
+ \centerline{\bf Z}
+\vskip6pt
+\leftline{zap,\enspace 13--18}
+\leftline{$z$-axis,\enspace 12, 256, 300}
+\leftline{zebra,\enspace 121}
+\leftline{zed,\enspace 103, 105}
+\leftline{Zen,\enspace iii, vi, 122}
+\leftline{zenith,\enspace 97,103}
+\leftline{zero,\enspace 11, 14, 56, 79}
+\leftline{zero-sum,\enspace 118}
+\leftline{zeta ($\zeta$),\enspace 133}
+\leftline{zilch, {\it see\/} zero}
+\leftline{zone,\enspace 204, 208}
+\leftline{Zorn's lemma\enspace 112, 145}
+}
+\setbox1=\vbox to\ht0{\hsize10pc \advance\baselineskip 0pt plus2pt
+\leftline{yak ({\it continued\/})}
+\leftline{\quad habitat of,\enspace 124}
+\leftline{yam,\enspace 124}
+\leftline{yang,\enspace 187}
+\leftline{$y$-axis,\enspace 89, 345}
+\leftline{yclept,\enspace 102}
+\leftline{yellow,\enspace 103}
+\leftline{yellow fever,\enspace108}
+\leftline{Yellow Pages,\enspace223}
+\leftline{yeti,\enspace301}
+\leftline{yin,\enspace186}
+\leftline{yodel,\enspace224}
+}
+\line{\hfil\box1 \kern1pc\box0 \hfil}
+\bigskip
+\noindent with the first column *Underfull*.
+This is the best *\vsplit*, for
+if the left column were any
+bigger it would have
+to include the {\bf Z} and the space after it, and at
+least one more line (not to mention all the extra space that would normally
+go {\it before\/} the {\bf Z}).
+
+ If we added a *\newcolumn* right before the *zebra* *\Entry*
+in the *.xdx* file (and also specified *\shortlastcolumn*),
+the output would look acceptable,
+\bigskip
+\setbox2\vtop{\hsize10pc
+\leftline{zebra,\enspace 121}
+\leftline{zed,\enspace 103, 105}
+\leftline{Zen,\enspace iii, vi, 122}
+\leftline{zenith,\enspace 97,103}
+\leftline{zero,\enspace 11, 14, 56, 79}
+\leftline{zero-sum,\enspace 118}
+\leftline{zeta ($\zeta$),\enspace 133}
+\leftline{zilch, {\it see\/} zero}
+\leftline{zone,\enspace 204, 208}
+\leftline{Zorn's lemma\enspace 112, 145}
+}
+\setbox3=\vtop{\hsize=10pc
+\leftline{yak ({\it continued\/})}
+\leftline{\quad habitat of,\enspace 124}
+\leftline{yam,\enspace 124}
+\leftline{yang,\enspace 187}
+\leftline{$y$-axis,\enspace 89, 345}
+\leftline{yclept,\enspace 102}
+\leftline{yellow,\enspace 103}
+\leftline{yellow fever,\enspace108}
+\leftline{Yellow Pages,\enspace223}
+\leftline{yeti,\enspace301}
+\leftline{yin,\enspace186}
+\leftline{yodel,\enspace224}
+\vskip12pt
+\centerline{\bf Z}
+\vskip6pt
+\leftline{zap,\enspace13--18}
+\leftline{$z$-axis,\enspace 12, 256, 300}
+}
+\line{\hfil\box3 \kern1pc\box2 \hfil}
+\bigskip
+\noindent
+although we would get *Overfull \vbox* messages
+(the *\newcolumn* causes the *\output* routine to be invoked
+while we still have *\output={\doublecolumns}*, so the left column
+will be made into a *\vbox to\pageheight@*).
+
+If we added the *\newcolumn* before the
+*\LETTER Z*
+(and also had specified\linebreak *\shortlastcolumn*), we would get
+\bigskip
+\setbox0\vtop{\hsize10pc
+ \centerline{\bf Z}
+\vskip6pt
+\leftline{zap,\enspace13--18}
+\leftline{$z$-axis,\enspace 12, 256, 300}
+\leftline{zebra,\enspace 121}
+\leftline{zed,\enspace 103, 105}
+\leftline{Zen,\enspace iii, vi, 122}
+\leftline{zenith,\enspace 97,103}
+\leftline{zero,\enspace 11, 14, 56, 79}
+\leftline{zero-sum,\enspace 118}
+\leftline{zeta ($\zeta$),\enspace 133}
+\leftline{zilch, {\it see\/} zero}
+\leftline{zone,\enspace 204, 208}
+\leftline{Zorn's lemma\enspace 112, 145}
+}
+\setbox1=\vtop{\hsize=10pc
+\leftline{yak ({\it continued\/})}
+\leftline{\quad habitat of,\enspace 124}
+\leftline{yam,\enspace 124}
+\leftline{yang,\enspace 187}
+\leftline{$y$-axis,\enspace 89, 345}
+\leftline{yclept,\enspace 102}
+\leftline{yellow,\enspace 103}
+\leftline{yellow fever,\enspace108}
+\leftline{Yellow Pages,\enspace223}
+\leftline{yeti,\enspace301}
+\leftline{yin,\enspace186}
+\leftline{yodel,\enspace224}
+}
+\line{\hfil\box1 \kern1pc\box0 \hfil}
+\bigskip
+\noindent (again with *Overfull \vbox* messages).
+
+
+Of course, the most reasonable thing would probably be to add a
+*\columnbreak* a little before the *yak* entry, so that the left column
+on the final page would be a little longer.
+
+\endsmall
+
+\chapter The {\tt index} program\label{IPROG}\endchapter
+
+The *index* program takes the raw data in an *.ndx* file and creates
+an *.xdx* file. Specifically, it is invoked as
+\setbox0\hbox{\<filename\>}
+**
+index "box0
+**
+to operate on \<filename\>*.ndx*, producing \<filename\>*.xdx*.
+Among its many tasks, the *index* file essentially sorts entries
+alphabetically. As indicated below, the *"1a{*\<string\>*}*
+ option is used to indicate
+that for purposes of alphabetizing, the entry should be treated as if it were
+ \<string\>.
+
+
+The *index* program
+was originally written in Microsoft~C, for MS-DOS machines. Porting to other
+machines will presumably be done by modifying this code. However, this
+chapter presents the complete specifications for the *index* program, in case
+any one wants to write it from scratch.
+
+
+It should be pointed out that currently
+the alphabetizing part of the program is essentially set up for
+English spelling, with the presumption that ``foreign''
+words (e.g., those with accented letters)
+ will be given an *"1a{*\<string\>*}* option. There should obviously
+be versions (or perhaps switches)
+for other languages that will provide
+transparent alphabetizing for words in those languages, so that the *"1a*
+option will only be needed for words that are ``foreign'' to those languages.
+
+It might also
+be mentioned that the current version of the program specifically
+assumes that the final line ends with a \<carriage-return\>, which should be
+true of the *.ndx* files that \tex\ writes. Some systems might want to
+modify this assumption.
+
+\def\controlseq{\hbox{\rm\<control sequence\>}}
+
+\section{The {\tt.ndx} file}
+The *.ndx* file may contain certain lines
+**
+\define"controlseq . . .
+**
+that come from *\idefine*'s in the main file, as well as certain lines
+**
+\abbrev"1"controlseq{...}
+**
+that come from *\iabbrev*'s in the main file. Moreover, as explained on
+page~113 of the \lamstex~Manual, a sequence of commands of the form
+\setbox0\hbox{\<pre page material\>}
+\setbox1\hbox{\<post page material\>}
+\setbox2\hbox{\<order\>}
+**
+"hskip-40pt\pageorder"controlseq{"box0}{"box1}{"box2}
+**
+may have been inserted
+at the very beginning of the
+*.ndx* file (after the *.ndx* file was automatically made by \tex);
+here each \controlseq\ is some
+ numbering style command, and the \<order\>'s are
+*1*, *2*, *3*, \dots, in that sequence.
+
+
+Aside from this, the *.ndx* file
+should consist of pairs of lines
+\setbox0\hbox{\<entry\>}
+\setbox1\hbox{\<options\>}
+\setbox2\hbox{\<number\>}
+\setbox3\hbox{*\controlseq*}
+\setbox4\hbox{\<prefix\>}
+\setbox5\hbox{\<postfix\>}
+**
+"""box0"box1""
+{"box2}{"controlseq}{"box4}{"box5}
+**
+where \<number\> is a decimal number, \controlseq\ is some numbering
+style
+control sequence
+ (followed by a space, because \tex\ will always add the
+space when it writes to the *.ndx* file),
+ and \<prefix\> and \<postfix\> are arbitrary, possibly
+empty, strings. The \controlseq\ is normally `*\arabic" *'.
+
+Actually, the *index* program as currently written does not assume
+that *""* is the delimiter
+appearing at the beginning and end of the \<entry\> lines. It is
+perfectly legitimate (compare section~\Sref{OTHERD})
+to have something like
+\setbox0\hbox{\<entry\>}
+\setbox1\hbox{\<options\>}
+\setbox2\hbox{\<number\>}
+\setbox3\hbox{*\controlseq*}
+\setbox4\hbox{\<prefix\>}
+\setbox5\hbox{\<postfix\>}
+**
+<"box0"box1>
+{"box2}{"controlseq}{"box4}{"box5}
+**
+Any left delimiter other than *{* or *\* may be used;
+the *index* program takes the \<entry\>\<option\>
+combination to be everything between the first
+symbol and the last non-space symbol on the line.
+
+
+Each \<entry\> has one of the forms
+\setbox1\hbox{\<entry\>$_{\text1}$}
+\setbox2\hbox{\<entry\>$_{\text2}$}
+\setbox3\hbox{\<entry\>$_{\text3}$}
+\setbox4\hbox{\<entry\>$_{\text4}$}
+\setbox5\hbox{\<entry\>$_{\text5}$}
+**
+"copy1
+"copy1, "copy2
+"copy1, "copy2, "copy3
+"copy1, "copy2, "copy3, "copy4
+"copy1, "copy2, "copy3, "copy4, "copy5
+**
+
+The \<options\> are a possibly empty sequence of
+ the following types of entries, where \<n\>
+stands for *2*, *3*, *4* or *5*. Actually, *1* is also allowed, but simply
+treated as if the *1* weren't there.
+There are optional spaces between such
+entries, including an optional space at the beginning and end of the
+\<options\>:
+\Math
+\vcenter{\halign{#\hfil&\qquad#\hfil\cr
+ *"1a{*\<string\>*}*&(alphabetize as)\cr
+ *"1*\<*n*\>*a{*\<string\>*}*&(same for subentry at level \<*n*\>)\cr
+ *"1-{*\<string\>*}*&(print before entry)\cr
+ *"1*\<*n*\>*-{*\<string\>*}*&(same for subentry at level \<*n*\>)\cr
+ *"1+{*\<string\>*}*&(print after entry)\cr
+ *"1*\<*n*\>*+{*\<string\>*}*&(same for subentry at level \<*n*\>)\cr
+ *"1e*\<control sequence\>&(apply control sequence to entry)\cr
+ *"1*\<*n*\>*e*\<control sequence\>&(same for subentry at level \<*n*\>)\cr
+ *"1p*\<control sequence\>&(apply control sequence to page number)\cr
+ *"1f*&(begin page span)\cr
+ *"1F*&(begin page span, variant form)\cr
+ *"1t*&(end page span)\cr
+ *"1x{*\<string\>*}*&(cross reference as)\cr
+ *"1X{*\<string\>*}*&(list and cross reference as)\cr}}
+\endMath
+
+In each
+**
+\abbrev"1"controlseq{...}
+**
+line, the `*...*' string should also be a sequence of these possible options,
+and error messages should be given if it is not, or if *\abbrev* is otherwise
+used incorrectly.
+
+The *"1x* and *"1X* options are meant to be mutually exclusive, so an error
+message should be given if both occur in the same \<options\> list.
+
+
+
+\section{The {\tt index} program}
+Here now are the steps taken by the *index* program.
+
+\medskip
+
+\noindent({\bf I}) {\bf Preprocessing:}
+
+\smallskip
+
+(1) The *index* program first uses any *\pageorder* lines at the beginning,
+\setbox1\hbox{$_{\text1}$}
+\setbox2\hbox{$_{\text2}$}
+\setbox3\hbox{pre\copy1}
+\setbox4\hbox{post\copy1}
+\setbox5\hbox{pre\copy2}
+\setbox6\hbox{post\copy2}
+**
+\pageorder"controlseq"copy1{"copy3}{"copy4}1
+\pageorder"controlseq"copy2{"copy5}{"copy6}2
+ . . .
+**
+to
+set up an ordering for arrays of the form
+\setbox2\hbox{\<number\>}
+\setbox3\hbox{\<controlseq\>}
+\setbox4\hbox{\<prefix\>}
+\setbox5\hbox{\<postfix\>}
+**
+{"box2} {"controlseq} {"box4} {"box5}
+**
+Namely, all arrays
+\setbox1\hbox{$_{\text1}$}
+\setbox2\hbox{$_{\text2}$}
+\setbox3\hbox{pre\copy1}
+\setbox4\hbox{post\copy1}
+\setbox5\hbox{pre\copy2}
+\setbox6\hbox{post\copy2}
+\setbox7\hbox{\<number\>}
+**
+{"copy7}{"controlseq"copy1}{"copy3}{"copy4}
+**
+come first, with the ordering then determined by the \<number\>'s,
+all arrays
+**
+{"copy7} {"controlseq"copy2} {"copy5} {"copy6}
+**
+come next, \dots. All other arrays come after these, and are simply ordered
+first by the order of the \<number\>, and then purely alphabetically by
+the remaining fields.
+
+Error messages presumably
+ought to be given if any *\pageorder* line has the wrong
+form, if the \<order\>'s don't occur in the proper order, or if two different
+\<order\>'s are assigned to identical material.
+
+(2) Next we consider all lines
+**
+\abbrev"1"controlseq{...}
+**
+(which may appear anywhere in the *.ndx* file).
+
+In each case, any
+occurrence of *"1"controlseq* in any entry line is replaced by
+`*...*'; then the *\abbrev* lines are eliminated.
+
+
+(3) All *\define* lines anywhere in the *.ndx* file are stored
+in a safe place, before being removed; they will be written at the beginning
+of the *.xdx* file.
+
+\medskip
+
+\noindent({\bf II}) {\bf Sorting:}
+
+\medskip
+
+\def\1{$_{\text1}$}\def\5{$_{\text2}$}
+\def\3{$_{\text3}$}\def\4{$_{\text4}$}\def\5{$_{\text5}$}
+\def\n{$_{\text\it n}$}
+
+\def\entrybar{$\overline{\hbox{\rm entry}}$}
+
+
+(1) For each
+\setbox0\hbox{\<entry\>}
+\setbox1\hbox{\<options\>}
+**
+"""box0"box1""
+**
+line,
+if *"1a{*\<string\>*}* appears, replace \<entry\1\> by \<string\>,
+and define \<\entrybar\1\> to be the old \<entry\1\>.
+ Otherwise define
+\<\entrybar\1\> to be empty.
+
+Similarly, if
+*"1*\<*n*\>*a{*\<string\>*}* appears, replace \<entry\n\> by \<string\>,
+and define \<\entrybar\n\> to be the old
+ \<entry\n\>. Otherwise define \<\entrybar\n\>
+to be empty.
+
+
+
+\setbox0\hbox{\<entry\>}
+\setbox1\hbox{\<options\>}
+\setbox2\hbox{\<number\>}
+\setbox3\hbox{*\nstyle*}
+\setbox4\hbox{\<prefix\>}
+\setbox5\hbox{\<postfix\>}
+
+\smallskip
+
+(2) Each pair of lines
+**
+"""box0"box1""
+{"box2}{"controlseq}{"box4}{"box5}
+**
+now gives rise to a collection $\Cal F$ of fields:
+
+*E1* is \<entry\1\> followed by one space.
+
+*E1+* is empty unless *"1-{*\<string\>*}* appears, in which case it is
+\<string\> followed by one space (note that
+\<string\> may already have one space at
+the end).
+
+*E1-* is empty unless *"1+{*\<string\>*}* appears, in which case it is
+\<string\> followed by one space.
+
+*E2* is \<entry\5\> followed by one space (hence just a space if
+\<entry\5\> is empty).
+
+*E2-* is empty unless *"12-{*\<string\>*}* appears, in which case it is
+\<string\> followed by one space.
+
+*E2+* is empty unless *"12+{*\<string\>*}* appears, in which case it is
+\<string\> followed by one space.
+
+*E3*, *E3+*, *E3-*, \dots, *E5*, *E5+*, *E5-* are similar.
+
+*P#* is \<number\>.
+
+*Pn* is \controlseq\ (usually `*\arabic" *').
+
+*P-* is the \<prefix\>.
+
+*P+* is the \<postfix\>.
+
+\def\EE{$\overline{\hbox{\tt E}}$}
+
+*"EE1*, \dots, *"EE5* are \<\entrybar\1\>, \dots, \<\entrybar\5\>.
+
+*E1c* is empty unless *"1e*\<control sequence\> appears, in which case it
+is \<control sequence\>, followed by one space.
+
+*E2c* is empty unless *"12e*\<control sequence\> appears, in which case it
+is \<control sequence\>, followed by one space.
+
+*E3c*, *E4c*, *E5c* are similar, using *"13e*, *"14e* and *"15e*.
+
+*Pc* is empty unless *"1p*\<control sequence\> appears, in which case it
+is \<control sequence\>, followed by one space.
+
+*PT* (page type) is *f* if *"1f* appeared, *F* if *"1F* appeared, *t*
+if *"1t* appeared, and *s* (for single page) otherwise.
+
+*x* is empty unless *"1x{*\<string\>*}* appears, in which case it is
+\<string\>, followed by one space.
+
+*X* is empty unless *"1X{*\<string\>*}* appears, in which case it is
+\<string\>, followed by one space.
+
+
+\medskip
+(3)
+We first sort these collections $\Cal F$
+alphabetically on *E1*, then among those with
+identical *E1* on *E1-*, then on *E1+*, then on *E2*, \dots, *E5+*.
+If we ignore the *-* and *+* fields for the moment,
+this just alphabetizes the entries and subentries.
+ The spaces that were added after each
+\<entry\n\> are meant to ensure that these entries are really sorted
+alphabetically; for example, it produces the order
+**
+Time
+Time table
+Time tables
+Times
+Times tables
+**
+which will eventually appear in the index as
+\bigskip\begingroup\parindent0pt\parskip0pt
+\hskip30pt Time\par\nobreak
+\hskip30pt \hskip10pt table\par\nobreak
+\hskip30pt \hskip10pt tables\par\nobreak
+\hskip30pt Times\par\nobreak
+\hskip30pt \hskip10pt tables\par\nobreak
+\endgroup\bigskip
+
+
+The other fields, *E1-*, *E1+*, \dots, allow entries with
+additional elements to appear in the proper order. For example, for the entry
+**
+""Time "1-{``} "1+{''}""
+**
+*E1* is *Time* and *E1-* is *``*. This
+will come after the entry line
+**
+""Time""
+**
+where *E1* is also *Time* but *E1-* is empty,
+ so that we will obtain the order
+\bigskip\begingroup\parindent0pt\parskip0pt
+\hskip30pt Time\par\nobreak
+\hskip30pt ``Time''\par
+\endgroup\bigskip
+\noindent in the index.
+
+
+After using these fields for sorting, we next use the fields
+**
+P# Pn P- P+
+**
+where
+ the sorting order for these arrays
+is just that described in step (1) of ({\bf I}).
+
+There may be certain collections $\Cal F$ that are distinct, but agree for
+all the fields so far. They can be left in any order, say the order in which
+they appear in the *.ndx* file, or further sorted purely alphabetically
+according to the remaining fields *"EE1*, \dots, *"EE5*, *E1c*, \dots,
+*E5c* and *Pc*.
+
+The *PT*, *x* and *X*
+ fields are important for further processing, but need not be
+considered in the sorting.
+
+After the sorting is completed, the additional spaces added to various fields
+are no longer needed, and they are deleted in the next step.
+
+\medskip
+
+
+\noindent ({\bf III}) {\bf Writing the *.xdx* file:}
+\medskip
+
+(1) First, as indicated in step (3) of part ({\bf I}), all *\define* lines
+originally in the *.ndx* file are written to the *.xdx* file.
+
+(2) The remaining material in the *.xdx* file will be in sections, each
+preceded by a blank line, then a line
+**
+\LETTER ...
+**
+and then another blank line.
+The line
+**
+\LETTER A
+**
+will normally be the first of these, and will precede all entries that begin
+with *a* or *A*;
+**
+\LETTER B
+**
+will precede all entries that begin with *b* or *B*; etc. No such line
+appears for a letter if there are no entries beginning with this
+letter. Things like \hbox{*\LETTER !*} can appear if entries begin with
+~ *!* (though normally one would expect the *"1a* option to be used for such
+entries).
+
+
+
+(2) In most cases,
+each collection $\Cal F$ gives rise to a pair of lines in the *.xdx*
+file:
+\def\di{{\it d}$_{\text1}$}
+\def\dii{{\it d}$_{\text2}$}
+**
+\Entry "di"dii{...}{...}{...}{...}{...}
+\Page {...}
+**
+except that if several collections have the exact same *\Entry* line, then
+the corresponding *\Page* lines are listed under it in order, with
+modifications to be mentioned in a minute, involving
+the *PT*, *x* and *X* fields.
+
+For the first *{...}* in the *\Entry* line, `*...*' is
+\def\F#1.{\hbox{\rm\<field #1\>}}
+**
+{E1-}{E1c{E1}}{E1+}
+**
+except that *E1* is replaced by *"EE1*
+if this is non-empty.
+
+Note that there are braces around *E1* (or *"EE1*)
+so that it will be the
+argument of the control sequence *E1c*. However, these braces are
+omitted if *E1c* is empty. Moreover,
+all other unnecessary
+braces are omitted: the first set of braces is omitted if *E1-* is
+empty, the third set is omitted if *E1+* is empty, and the middle set is
+also omitted if both are empty.
+ (Remember that this entire sequence, with
+extraneous braces removed, is enclosed in the first set of braces in the
+*\Entry* line.)
+
+The second *{...}* in the *\Entry* line is similar, using fields
+*E2-*, *E2c*, *E2* and *E2+*. And similarly for the other groups.
+
+
+\di\ is the number of *{...}* that are non-empty, i.e., not of the form
+*{}*.
+
+\dii\ is the number of *{...}* {\it that agree with the most recent *\Entry*
+line}.
+
+\medskip
+
+
+Normally,
+the *\Page* lines have the form
+\def\FF{$\overline{\hbox{\rm\<field 17\>}}$}
+**
+\Page {Pc{{P-}{Pn{P#}}{P+}}}
+**
+But *Pn* is omitted when it is `*\arabic" *' (the usual case).
+ Moreover, superfluous braces are removed, as before, when
+fields are empty.
+
+Duplicate *\Page* lines for the same entry are eliminated. But if
+duplicates actually come from lines for which *Pc* is different, then
+each *\Page* line after the first is printed as
+{\advance\litindent-60pt
+**
+%% ////////////////////////////////////////////////////////////////////////
+%
+% \Page {Pc}{...}}
+% Duplicate page number formatted differently
+%
+%% \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+**
+where *Pc* is the control sequence for that line. For readability,
+there should be
+a blank line before and after this ``error message''
+(the current version of the *index*
+program actually prints things slightly differently).}
+
+
+When *PT* is *f*, however, *\Page* is replaced by *\Pagespan*. And
+if *PT* is *F*, then *\Page* is replaced by *\PageSpan*; moreover, the
+line is then written in the form
+**
+\PageSpan {Pc}{{P-}{Pn{P#}}{P+}}
+**
+with the *Pc* as a separate argument.
+ Extraneous braces are removed, as usual.
+
+When *PT* is *t*, *\Page* is replaced by *\Topage*. However, if it was
+preceded by a line for which *PT* is *F*, then once again we write
+**
+\Topage {Pc}{{P-}{Pn{P#}}{P+}}
+**
+with the *Pc* as a separate argument.
+
+When a *\Page* line for which *PT* is *s* is encountered between lines
+for which *PT* is *f* or *F* and the corresponding line for which *PT* is
+*t*, it is ignored, {\it unless it has\/} a different *Pc*. In this case
+the new *\Page* line is printed as the error message
+{\advance\litindent-60pt
+\setbox0\hbox{new}
+\setbox1\hbox{old}
+**
+%% ////////////////////////////////////////////////////////////////////////
+%
+% \Page {"copy0 Pc{...}}
+% Page {"copy0 Pc{...}} within span starting at "copy1 Pc{...}
+%
+%% \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+**
+
+Other such error} messages that should be issued
+are indicated on pages 118@--119 of the \lamstex~ Manual.
+
+
+\bigskip
+This description is complete only
+for entries that do not have an *"1x* or *"1X* option. For entries that do
+have these options, the processing is somewhat different.
+Recall that
+*"1x* indicates a cross-reference without a reference to the page on
+which the entry is marked, while *"1X* indicates a cross-reference together
+with a reference to the page.
+
+The situation where at least one occurrence of \<entry\> has an *"1x* or
+*"1X* option can happen in different ways:
+
+\medskip
+
+\noindent Case 1: Every occurrence of the \<entry\> involves *"1x* (and thus
+ not
+ *"1X*):
+\setbox0\hbox{\<entry\>}
+\setbox1\hbox{\<string\1\>}
+\setbox2\hbox{\<string\5\>}
+\setbox3\hbox{\<string\3\>}
+**
+"copy0 ... "1x{"copy1}
+"copy0 ... "1x{"copy2}
+"copy0 ... "1x{"copy3}
+**
+In this case the *.xdx* file
+should contain
+**
+\Entryxref "di"dii{...}{...}{...}{...}{...}{\See {"copy1}}
+\Morexref {\See {"copy2}}
+ . . .
+**
+
+\medskip
+
+\noindent Case 2: The opposite case, in which at least one of the following
+occurs:
+
+(1) \<entry\> occurs at least once with the *"1X* option, so that the
+corresponding page number should appear. Other occurrences of \<entry\>
+ may or may not have
+*"1x* options.
+
+(2) \<entry\> occurs at least once with {\it neither\/} *"1x* nor *"1X*, and
+thus there is at least one page number that should appear because no
+cross-referencing is involved at all. Other occurrences of \<entry\> may have
+either *"1x* or *"1X* options.
+
+\smallskip
+In these cases,
+let \<string\1\>, \<string\5\>, \dots, be all the \<string\>'s, in
+alphabetical order, that
+occur in either *"1x* or *"1X* options, and
+let
+**
+\Page {...}
+\Page {...}
+ . . .
+\Page {...}
+**
+be the lines that would be written considering all instances that do not
+involve the *"1x* option (but possibly the *"1X* option). These lines
+may actually involve *\Pagespan*, *\PageSpan* and *\Topage*.
+
+
+Then the *.xdx* file should contain
+\setbox1\hbox{\<string\1\>}
+\setbox2\hbox{\<string\5\>}
+
+**
+\Entry "di"dii{...}{...}{...}{...}{...}
+\Xref {\See {"copy1}}
+\Morexref {\See {"copy2}}
+ . . .
+\Page {...}
+\Page {...}
+ . . .
+\Page {...}
+\Xref {\See {"copy1}}
+\Morexref {\See {"copy2}}
+ . . .
+**
+
+
+
+