summaryrefslogtreecommitdiff
path: root/web/nuweb/msdos/nuweb.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 /web/nuweb/msdos/nuweb.tex
Initial commit
Diffstat (limited to 'web/nuweb/msdos/nuweb.tex')
-rw-r--r--web/nuweb/msdos/nuweb.tex3897
1 files changed, 3897 insertions, 0 deletions
diff --git a/web/nuweb/msdos/nuweb.tex b/web/nuweb/msdos/nuweb.tex
new file mode 100644
index 0000000000..3f3c3906d7
--- /dev/null
+++ b/web/nuweb/msdos/nuweb.tex
@@ -0,0 +1,3897 @@
+\documentstyle{report}
+
+\setlength{\oddsidemargin}{0in}
+\setlength{\evensidemargin}{0in}
+\setlength{\topmargin}{0in}
+\addtolength{\topmargin}{-\headheight}
+\addtolength{\topmargin}{-\headsep}
+\setlength{\textheight}{8.9in}
+\setlength{\textwidth}{6.5in}
+\setlength{\marginparwidth}{0.5in}
+
+\title{Nuweb \\ A Simple Literate Programming Tool}
+\author{\sl Preston Briggs}
+\date{(Version 0.6pc)}
+
+\begin{document}
+\maketitle
+\tableofcontents
+
+\chapter{Introduction}
+
+In 1984, Knuth introduced the idea of {\em literate programming\/} and
+described a pair of tools to support the practise~\cite{knuth:84}.
+His approach was to combine Pascal code with \TeX\ documentation to
+produce a new language, {\tt WEB}, that offered programmers a superior
+approach to programming. He wrote several programs in {\tt WEB},
+including {\tt weave} and {\tt tangle}, the programs used to support
+literate programming.
+The idea was that a programmer wrote one document, the web file, that
+combined documentation (written in \TeX~\cite{texbook}) with code
+(written in Pascal).
+
+Running {\tt tangle} on the web file would produce a complete
+Pascal program, ready for compilation by an ordinary Pascal compiler.
+The primary function of {\tt tangle} is to allow the programmer to
+present elements of the program in any desired order, regardless of
+the restrictions imposed by the programming language. Thus, the
+programmer is free to present his program in a top-down fashion,
+bottom-up fashion, or whatever seems best in terms of promoting
+understanding and maintenance.
+
+Running {\tt weave} on the web file would produce a \TeX\ file, ready
+to be processed by \TeX\@. The resulting document included a variety of
+automatically generated indices and cross-references that made it much
+easier to navigate the code. Additionally, all of the code sections
+were automatically pretty printed, resulting in a quite impressive
+document.
+
+Knuth also wrote the programs for \TeX\ and {\small\sf METAFONT}
+entirely in {\tt WEB}, eventually publishing them in book
+form~\cite{tex:program,metafont:program}. These are probably the
+largest programs ever published in a readable form.
+
+Inspired by Knuth's example, many people have experimented with
+{\tt WEB}\@. Some people have even built web-like tools for their own
+favorite combinations of programming language and typesetting
+language. For example, {\tt CWEB}, Knuth's current system of choice,
+works with a combination of C and \TeX~\cite{levy:90}. Another system,
+FunnelWeb, is independent of any programming language and only mildly
+dependent on \TeX~\cite{funnelweb}. Inspired by the versatility
+of FunnelWeb and by the daunting size of its documentation, I decided
+to write my own, very simple, tool for literate programming.%
+\footnote{There is another system similar to mine, written by Norman
+Ramsey, called {\em noweb}~\cite{noweb}. It perhaps suffers from being
+overly Unix-dependent and requiring several programs to use. On the
+other hand, its command syntax is very nice. In any
+case, nuweb certainly owes its name to his inspiration.}
+
+
+\section{Nuweb}
+
+Nuweb works with any programming language and \LaTeX~\cite{latex}. I
+wanted to use \LaTeX\ because it supports a multi-level sectioning
+scheme and has facilities for drawing figures. I wanted to be able to
+work with arbitrary programming languages because my friends and I
+write programs in many languages (and sometimes combinations of
+several languages), {\em e.g.,} C, Fortran, C++, yacc, lex, Scheme,
+assembly, Postscript, and so forth. The need to support arbitrary
+programming languages has many consequences:
+\begin{description}
+\item[No pretty printing] Both {\tt WEB} and {\tt CWEB} are able to
+ pretty print the code sections of their documents because they
+ understand the language well enough to parse it. Since we want to use
+ {\em any\/} language, we've got to abandon this feature.
+\item[No index of identifiers] Because {\tt WEB} knows about Pascal,
+ it is able to construct an index of all the identifiers occurring in
+ the code sections (filtering out keywords and the standard type
+ identifiers). Unfortunately, this isn't as easy in our case. We don't
+ know what an identifiers looks like in each language and we certainly
+ don't know all the keywords. (On the other hand, see the end of
+ Section~1.3)
+\end{description}
+Of course, we've got to have some compensation for our losses or the
+whole idea would be a waste. Here are the advantages I can see:
+\begin{description}
+\item[Simplicity] The majority of the commands in {\tt WEB} are
+ concerned with control of the automatic pretty printing. Since we
+ don't pretty print, many commands are eliminated. A further set of
+ commands is subsumed by \LaTeX\ and may also be eliminated. As a
+ result, our set of commands is reduced to only four members (explained
+ in the next section). This simplicity is also reflected in
+ the size of this tool, which is quite a bit smaller than the tools
+ used with other approaches.
+\item[No pretty printing] Everyone disagrees about how their code
+ should look, so automatic formatting annoys many people. One approach
+ is to provide ways to control the formatting. Our approach is simpler
+ -- we perform no automatic formatting and therefore allow the
+ programmer complete control of code layout.
+\item[Control] We also offer the programmer complete control of the
+ layout of his output files (the files generated during tangling). Of
+ course, this is essential for languages that are sensitive to layout;
+ but it is also important in many practical situations, {\em e.g.,}
+ debugging.
+\item[Speed] Since nuweb doesn't do to much, the nuweb tool runs
+ quickly. I combine the functions of {\tt tangle} and {\tt weave} into
+ a single program that performs both functions at once.
+\item[Multiple file output] The programmer may specify more than one
+ output file in a single nuweb file. This is required when constructing
+ programs in a combination of languages (say, Fortran and C)\@. It's also
+ an advantage when constructing very large programs that would require
+ a lot of compile time.
+\end{description}
+This last point is very important. By allowing the creation of
+multiple output files, we avoid the need for monolithic programs.
+Thus we support the creation of very large programs by groups of
+people.
+
+A further reduction in compilation time is achieved by first
+writing each output file to a temporary location, then comparing the
+temporary file with the old version of the file. If there is no
+difference, the temporary file can be deleted. If the files differ,
+the old version is deleted and the temporary file renamed. This
+approach works well in combination with {\tt make} (or similar tools),
+since {\tt make} will avoid recompiling untouched output files.
+
+
+\section{Writing Nuweb}
+
+The bulk of a nuweb file will be ordinary \LaTeX\@. In fact, any \LaTeX\
+file can serve as input to nuweb and will be simply copied through
+unchanged to the {\tt .tex} file -- unless a nuweb command is
+discovered. All nuweb commands begin with an ``at-sign'' ({\tt @}).
+Therefore, a file without at-signs will be copied unchanged.
+Nuweb commands are used to specify {\em output files,} define
+{\em macros,} and delimit {\em scraps}. These are the basic features
+of interest to the nuweb tool -- all else is simply text to be copied
+to the {\tt .tex} file.
+
+\subsection{The Major Commands}
+
+Files and macros are defined with the following commands:
+\begin{description}
+\item[\tt @o {\em file-name flags scrap\/}] Output a file. The file name is
+ terminated by whitespace.
+\item[\tt @d {\em macro-name scrap\/}] Define a macro. The macro name
+ is terminated by a return or the beginning of a scrap.
+\end{description}
+A specific file may be specified several times, with each definition
+being written out, one after the other, in the order they appear.
+The definitions of macros may be similarly divided.
+
+\subsubsection{Scraps}
+
+Scraps have specific begin markers and end markers to allow precise
+control over the contents and layout. Note that any amount of
+whitespace (including carriage returns) may appear between a name and
+the beginning of a scrap.
+\begin{description}
+\item[\tt @\{{\em anything\/}@\}] where the scrap body includes every
+ character in {\em anything\/} -- all the blanks, all the tabs, all the
+ carriage returns.
+\end{description}
+Inside a scrap, we may invoke a macro.
+\begin{description}
+\item[\tt @<{\em macro-name\/}@>] Causes the macro {\em macro-name\/}
+ to be expanded inline as the code is written out to a file. It is an
+ error to specify recursive macro invocations.
+\end{description}
+Note that macro names may be abbreviated, either during invocation or
+definition. For example, it would be very tedious to have to
+repeatedly type the macro name
+\begin{quote}
+{\tt @d Check for terminating at-sequence and return name if found}
+\end{quote}
+Therefore, we provide a mechanism (stolen from Knuth) of indicating
+abbreviated names.
+\begin{quote}
+{\tt @d Check for terminating...}
+\end{quote}
+Basically, the programmer need only type enough characters to uniquely
+identify the macro name, followed by three periods. An abbreviation
+may even occur before the full version; nuweb simply preserves the
+longest version of a macro name. Note also that blanks and tabs are
+insignificant in a macro name; any string of them are replaced by a
+single blank.
+
+When scraps are written to an output or {\tt .tex} file, tabs are
+expanded into spaces by default. Currently, I assume tab stops are set
+every eight characters. Furthermore, when a macro is expanded in a scrap,
+the body of the macro is indented to match the indentation of the
+macro invocation. Therefore, care must be taken with languages
+({\em e.g.,} Fortran) that are sensitive to indentation.
+These default behaviors may be changed for each output file (see
+below).
+
+\subsubsection{Flags}
+
+When defining an output file, the programmer has the option of using
+flags to control output of a particular file. The flags are intended
+to make life a little easier for programmers using certain languages.
+They introduce little language dependences; however, they do so only
+for a particular file. Thus it is still easy to mix languages within a
+single document. There are three ``per-file'' flags:
+\begin{description}
+\item[\tt -d] Forces the creation of \verb|#line| directives in the
+ output file. These are useful with C (and sometimes C++ and Fortran) on
+ many Unix systems since they cause the compiler's error messages to
+ refer to the web file rather than the output file. Similarly, they
+ allow source debugging in terms of the web file.
+\item[\tt -i] Suppresses the indentation of macros. That is, when a
+ macro is expanded in a scrap, it will {\em not\/} be indented to
+ match the indentation of the macro invocation. This flag would seem
+ most useful for Fortran programmers.
+\item[\tt -t] Suppresses expansion of tabs in the output file. This
+ feature seems important when generating {\tt make} files.
+\end{description}
+
+
+\subsection{The Minor Commands}
+
+We have two very low-level utility commands that may appear anywhere
+in the web file.
+\begin{description}
+\item[\tt @@] Causes a single ``at sign'' to be copied into the output.
+\item[\tt @i {\em file-name\/}] Includes a file. Includes may be
+ nested, though there is currently a limit of 10~levels. The file name
+ should be complete (no extension will be appended) and should be
+ terminated by a carriage return.
+\end{description}
+Finally, there are three commands used to create indices to the macro
+names, file definitions, and user-specified identifiers.
+\begin{description}
+\item[\tt @f] Create an index of file names.
+\item[\tt @m] Create an index of macro name.
+\item[\tt @u] Create an index of user-specified identifiers.
+\end{description}
+I usually put these in their own section
+in the \LaTeX\ document; for example, see Chapter~\ref{indices}.
+
+Identifiers must be explicitely specified for inclusion in the
+{\tt @u} index. By convention, each identifier is marked at the point
+of its definition; all references to each identifier (inside scraps)
+will be discovered automatically. To ``mark'' an identifier for
+inclusion in the index, we must mention it at the end of a scrap.
+For example,
+\begin{quote}
+\begin{verbatim}
+@d a scrap @{
+Let's pretend we're declaring the variables FOO and BAR
+inside this scrap.
+@| FOO BAR @}
+\end{verbatim}
+\end{quote}
+I've used alphabetic identifiers in this example, but any string of
+characters (not including whitespace) will do. Therefore, it's
+possible to add index entries for things like {\tt <<=} if desired.
+An identifier may be declared in more than one scrap.
+
+In the generated index, each identifier appears with a list of all the
+scraps using and defining it, where the defining scraps are
+distinguished by underlining. Note that the identifier doesn't
+actually have to appear in the defining scrap; it just has to be in
+the list of definitions at the end of a scrap.
+
+
+\section{Running Nuweb}
+
+Nuweb is invoked using the following command:
+\begin{quote}
+{\tt nuweb} {\em flags file-name}\ldots
+\end{quote}
+One or more files may be processed at a time. If a file name has no
+extension, {\tt .w} will be appended. While a file name may specify a
+file in another directory, the resulting {\tt .tex} file will always
+be created in the current directory. For example,
+\begin{quote}
+{\tt nuweb /foo/bar/quux}
+\end{quote}
+will take as input the file {\tt /foo/bar/quux.w} and will create the
+file {\tt quux.tex} in the current directory.
+
+By default, nuweb performs both tangling and weaving at the same time.
+Normally, this is not a bottleneck in the compilation process;
+however, it's possible to achieve slightly faster throughput by
+avoiding one or another of the default functions using command-line
+flags. There are currently three possible flags:
+\begin{description}
+\item[\tt -t] Suppress generation of the {\tt .tex} file.
+\item[\tt -o] Suppress generation of the output files.
+\item[\tt -c] Avoid testing output files for change before updating them.
+\end{description}
+Thus, the command
+\begin{quote}
+{\tt nuweb -to /foo/bar/quux}
+\end{quote}
+would simply scan the input and produce no output at all.
+
+
+\section{Restrictions and Extensions}
+
+Because nuweb is intended to be a simple tool, I've established a few
+restrictions. Over time, some of these may be eliminated; others seem
+fundamental.
+\begin{itemize}
+\item The scraps don't print well with older versions of \TeX\
+ (pre~3.0). I'm not sure why and I'm not sure it's always true
+ (I don't have a version to experiment with).
+\item The handling of errors is not completely ideal. In some cases, I
+ simply warn of a problem and continue; in other cases I halt
+ immediately. This behavior should be regularized.
+\item I warn about references to macros that haven't been defined, but
+ don't halt. This seems most convenient for development, but may change
+ in the future.
+\item File names and index entries should not contain any {\tt @}
+ signs.
+\item Macro names may be (almost) any well-formed \TeX\ string.
+ It makes sense to change fonts or use math mode; however, care should
+ be taken to ensure matching braces, brackets, and dollar signs.
+\item Anything is allowed in the body of a scrap; however, very
+ long scraps (horizontally or vertically) may not typeset well.
+\end{itemize}
+Very long scraps may be allowed to break across a page if declared
+with {\tt @O} or {\tt @D} (instead of {\tt @o} or {\tt @d}).
+This doesn't work very well as a default, since far too many short
+scraps will be broken across pages; however, as a user-controlled
+option, it seems very useful.
+
+
+\chapter{The Overall Structure}
+
+Processing a web requires three major steps:
+\begin{enumerate}
+\item Read the source, accumulating file names, macro names, scraps,
+and lists of cross-references.
+\item Reread the source, copying out to the {\tt .tex} file, with
+protection and cross-reference information for all the scraps.
+\item Traverse the list of files names. For each file name:
+\begin{enumerate}
+\item Dump all the defining scraps into a temporary file.
+\item If the file already exists and is unchanged, delete the
+temporary file; otherwise, rename the temporary file.
+\end{enumerate}
+\end{enumerate}
+
+
+\section{Files}
+
+I have divided the program into several files for quicker
+recompilation during development. Rather than use {\tt .h} files
+for shared declarations, I'll simply create a shared scrap containing
+all the global declarations. This isn't really best from the point of
+view of disk space; but it does simplify the makefile (and allow me to
+play with my new toy).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Shared declarations {\footnotesize 1}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@$\langle$Include files {\footnotesize 2}$\rangle$\verb@@\\
+\verb@@$\langle$Type declarations {\footnotesize 3}$\rangle$\verb@@\\
+\verb@@$\langle$Global variables {\footnotesize 13}$\rangle$\verb@@\\
+\verb@@$\langle$Function prototypes {\footnotesize 23}$\rangle$\verb@@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 4, 5, 6, 7, 8, 9 and~10.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+We'll need at least two of the standard system include files.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Include files {\footnotesize 2}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@#include <stdio.h>@\\
+\verb@#include <string.h>@\\
+\verb@#include <ctype.h>@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 1 and~11.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\newpage
+\noindent
+I also like to use {\tt TRUE} and {\tt FALSE} in my code.
+I'd use an {\tt enum} here, except that some systems seem to provide
+definitions of {\tt TRUE} and {\tt FALSE} be default. The following
+code seems to work on all the local systems.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Type declarations {\footnotesize 3}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@#ifndef FALSE@\\
+\verb@#define FALSE 0@\\
+\verb@#endif@\\
+\verb@#ifndef TRUE@\\
+\verb@#define TRUE (!0)@\\
+\verb@#endif@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 3, 100 and~101.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{The Main Files}
+
+The code is divided into four main files (introduced here) and five
+support files (introduced in the next section).
+The file {\tt main.c} will contain the driver for the whole program
+(see Section~\ref{main-routine}).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"main.c"@ {\footnotesize 4 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@$\langle$Shared declarations {\footnotesize 1}$\rangle$\verb@@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 4 and~12.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The first pass over the source file is contained in {\tt pass1.c}.
+It handles collection of all the file names, macros names, and scraps
+(see Section~\ref{pass-one}).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"pass1.c"@ {\footnotesize 5 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@$\langle$Shared declarations {\footnotesize 1}$\rangle$\verb@@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 5 and~24.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The {\tt .tex} file is created during a second pass over the source
+file. The file {\tt latex.c} contains the code controlling the
+construction of the {\tt .tex} file
+(see Section~\ref{latex-file}).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"latex.c"@ {\footnotesize 6 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@$\langle$Shared declarations {\footnotesize 1}$\rangle$\verb@@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 6, 32, 33, 44, 45, 52 and~58.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The code controlling the creation of the output files is in {\tt output.c}
+(see Section~\ref{output-files}).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"output.c"@ {\footnotesize 7 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@$\langle$Shared declarations {\footnotesize 1}$\rangle$\verb@@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 7 and~61.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Support Files}
+
+The support files contain a variety of support routines used to define
+and manipulate the major data abstractions.
+The file {\tt input.c} holds all the routines used for referring to
+source files (see Section~\ref{source-files}).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"input.c"@ {\footnotesize 8 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@$\langle$Shared declarations {\footnotesize 1}$\rangle$\verb@@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 8, 66, 67, 68 and~73.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Creation and lookup of scraps is handled by routines in {\tt scraps.c}
+(see Section~\ref{scraps}).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 9 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@$\langle$Shared declarations {\footnotesize 1}$\rangle$\verb@@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The handling of file names and macro names is detailed in {\tt names.c}
+(see Section~\ref{names}).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 10 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@$\langle$Shared declarations {\footnotesize 1}$\rangle$\verb@@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Memory allocation and deallocation is handled by routines in {\tt arena.c}
+(see Section~\ref{memory-management}). I don't bother including all
+the shared declarations since they aren't required.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"arena.c"@ {\footnotesize 11 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@$\langle$Include files {\footnotesize 2}$\rangle$\verb@@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 11, 131, 132, 133 and~136.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\section{The Main Routine} \label{main-routine}
+
+The main routine is quite simple in structure.
+It wades through the optional command-line arguments,
+then handles any files listed on the command line.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"main.c"@ {\footnotesize 12 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void main(argc, argv)@\\
+\verb@ int argc;@\\
+\verb@ char **argv;@\\
+\verb@{@\\
+\verb@ int arg = 1;@\\
+\verb@ @$\langle$Interpret command-line arguments {\footnotesize 14}$\rangle$\verb@@\\
+\verb@ @$\langle$Process the remaining arguments (file names) {\footnotesize 19}$\rangle$\verb@@\\
+\verb@ exit(0);@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 4 and~12.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Command-Line Arguments}
+
+There are three possible command-line arguments:
+\begin{description}
+\item[{\tt -t}] Suppresses generation of the {\tt .tex} file.
+\item[{\tt -o}] Suppresses generation of the output files.
+\item[{\tt -c}] Forces output files to overwrite old files of the same
+name without comparing for equality first.
+\item[{\tt -v}] Prints the current version of {\tt nuweb}.
+\end{description}
+Global flags are declared for each of the arguments.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Global variables {\footnotesize 13}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@int tex_flag; /* if FALSE, don't emit the .tex file */@\\
+\verb@int output_flag; /* if FALSE, don't emit the output files */@\\
+\verb@int compare_flag; /* if FALSE, overwrite without comparison */@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 13, 15, 65 and~102.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\newpage
+\noindent
+The flags are all initialized to {\tt TRUE} for correct default behavior.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Interpret command-line arguments {\footnotesize 14}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@tex_flag = TRUE;@\\
+\verb@output_flag = TRUE;@\\
+\verb@compare_flag = TRUE;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 14, 16 and~17.\\[-1ex]
+Macro referenced in scrap 12.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+We save the invocation name of the command in a global variable
+{\tt command\_name} for use in error messages.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Global variables {\footnotesize 15}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@char *command_name;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 13, 15, 65 and~102.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The invocation name is conventionally passed in {\tt argv[0]}.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Interpret command-line arguments {\footnotesize 16}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@command_name = argv[0];@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 14, 16 and~17.\\[-1ex]
+Macro referenced in scrap 12.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+We need to examine the remaining entries in {\tt argv}, looking for
+command-line arguments.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Interpret command-line arguments {\footnotesize 17}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@while (arg < argc) {@\\
+\verb@ char *s = argv[arg];@\\
+\verb@ if (*s++ == '-') {@\\
+\verb@ @$\langle$Interpret the argument string {\tt s} {\footnotesize 18}$\rangle$\verb@@\\
+\verb@ arg++;@\\
+\verb@ }@\\
+\verb@ else break;@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 14, 16 and~17.\\[-1ex]
+Macro referenced in scrap 12.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\newpage
+\noindent
+Several flags can be stacked behind a single minus sign; therefore,
+we've got to loop through the string, handling them all.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Interpret the argument string {\tt s} {\footnotesize 18}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ char c = *s++;@\\
+\verb@ while (c) {@\\
+\verb@ switch (c) {@\\
+\verb@ case 'c': compare_flag = FALSE;@\\
+\verb@ break;@\\
+\verb@ case 'o': output_flag = FALSE;@\\
+\verb@ break;@\\
+\verb@ case 't': tex_flag = FALSE;@\\
+\verb@ break;@\\
+\verb@ case 'v': printf("nuweb version 0.6\n");@\\
+\verb@ break;@\\
+\verb@ default: fprintf(stderr, "%s: unexpected argument ignored. ",@\\
+\verb@ command_name);@\\
+\verb@ fprintf(stderr, "Usage is: %s [-cot] file...\n",@\\
+\verb@ command_name);@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@ c = *s++;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 17.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{File Names}
+
+We expect at least one file name. While a missing file name might be
+ignored without causing any problems, we take the opportunity to report
+the usage convention.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Process the remaining arguments (file names) {\footnotesize 19}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@if (arg < argc)@\\
+\verb@ do {@\\
+\verb@ @$\langle$Handle the file name in {\tt argv[arg]} {\footnotesize 20}$\rangle$\verb@@\\
+\verb@ arg++;@\\
+\verb@ } while (arg < argc);@\\
+\verb@else {@\\
+\verb@ fprintf(stderr, "%s: expected a file name. ", command_name);@\\
+\verb@ fprintf(stderr, "Usage is: %s [-cot] file-name...\n", command_name);@\\
+\verb@ exit(-1);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 12.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\newpage
+\noindent
+The code to handle a particular file name is rather more tedious than
+the actual processing of the file. A file name may be an arbitrarily
+complicated path name, with an optional extension. If no extension is
+present, we add {\tt .w} as a default. The extended path name will be
+kept in a local variable {\tt source\_name}. The resulting {\tt .tex}
+file will be written in the current directory; its name will be kept
+in the variable {\tt tex\_name}.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Handle the file name in {\tt argv[arg]} {\footnotesize 20}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ char source_name[100];@\\
+\verb@ char tex_name[100];@\\
+\verb@ @$\langle$Build {\tt source\_name} and {\tt tex\_name} {\footnotesize 21}$\rangle$\verb@@\\
+\verb@ @$\langle$Process a file {\footnotesize 22}$\rangle$\verb@@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 19.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+I bump the pointer {\tt p} through all the characters in {\tt argv[arg]},
+copying all the characters into {\tt source\_name} (via the pointer
+{\tt q}).
+
+At each slash, I update {\tt trim} to point just past the
+slash in {\tt source\_name}. The effect is that {\tt trim} will point
+at the file name without any leading directory specifications.
+
+The pointer {\tt dot} is made to point at the file name extension, if
+present. If there is no extension, we add {\tt .w} to the source name.
+In any case, we create the {\tt tex\_name} from {\tt trim}, taking
+care to get the correct extension.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Build {\tt source\_name} and {\tt tex\_name} {\footnotesize 21}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ char *p = argv[arg];@\\
+\verb@ char *q = source_name;@\\
+\verb@ char *trim = q;@\\
+\verb@ char *dot = NULL;@\\
+\verb@ char c = *p++;@\\
+\verb@ while (c) {@\\
+\verb@ *q++ = c;@\\
+\verb@ if (c == '/') {@\\
+\verb@ trim = q;@\\
+\verb@ dot = NULL;@\\
+\verb@ }@\\
+\verb@ else if (c == '.')@\\
+\verb@ dot = q - 1;@\\
+\verb@ c = *p++;@\\
+\verb@ }@\\
+\verb@ *q = '\0';@\\
+\verb@ if (dot) {@\\
+\verb@ *dot = '\0';@\\
+\verb@ sprintf(tex_name, "%s.tex", trim);@\\
+\verb@ *dot = '.';@\\
+\verb@ }@\\
+\verb@ else {@\\
+\verb@ sprintf(tex_name, "%s.tex", trim);@\\
+\verb@ *q++ = '.';@\\
+\verb@ *q++ = 'w';@\\
+\verb@ *q = '\0';@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 20.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Now that we're finally ready to process a file, it's not really too
+complex. We bundle most of the work into three routines {\tt pass1}
+(see Section~\ref{pass-one}), {\tt write\_tex} (see
+Section~\ref{latex-file}), and {\tt write\_files} (see
+Section~\ref{output-files}). After we're finished with a
+particular file, we must remember to release its storage (see
+Section~\ref{memory-management}).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Process a file {\footnotesize 22}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ pass1(source_name);@\\
+\verb@ if (tex_flag)@\\
+\verb@ write_tex(source_name, tex_name);@\\
+\verb@ if (output_flag)@\\
+\verb@ write_files(file_names);@\\
+\verb@ arena_free();@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 20.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\section{Pass One} \label{pass-one}
+
+During the first pass, we scan the file, recording the definitions of
+each macro and file and accumulating all the scraps.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Function prototypes {\footnotesize 23}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void pass1();@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 23, 31, 60, 64, 77, 103 and~130.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The routine {\tt pass1} takes a single argument, the name of the
+source file. It opens the file, then initializes the scrap structures
+(see Section~\ref{scraps}) and the roots of the file-name tree, the
+macro-name tree, and the tree of user-specified index entries (see
+Section~\ref{names}). After completing all the
+necessary preparation, we make a pass over the file, filling in all
+our data structures. Next, we seach all the scraps for references to
+the user-specified index entries. Finally, we must reverse all the
+cross-reference lists accumulated while scanning the scraps.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"pass1.c"@ {\footnotesize 24 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void pass1(file_name)@\\
+\verb@ char *file_name;@\\
+\verb@{@\\
+\verb@ source_open(file_name);@\\
+\verb@ init_scraps();@\\
+\verb@ macro_names = NULL;@\\
+\verb@ file_names = NULL;@\\
+\verb@ user_names = NULL;@\\
+\verb@ @$\langle$Scan the source file, looking for at-sequences {\footnotesize 25}$\rangle$\verb@@\\
+\verb@ if (tex_flag)@\\
+\verb@ search();@\\
+\verb@ @$\langle$Reverse cross-reference lists {\footnotesize 30}$\rangle$\verb@@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 5 and~24.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\newpage
+\noindent
+The only thing we look for in the first pass are the command
+sequences. All ordinary text is skipped entirely.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Scan the source file, looking for at-sequences {\footnotesize 25}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ int c = source_get();@\\
+\verb@ while (c != EOF) {@\\
+\verb@ if (c == '@{\tt @}\verb@')@\\
+\verb@ @$\langle$Scan at-sequence {\footnotesize 26}$\rangle$\verb@@\\
+\verb@ c = source_get();@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 24.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Only four of the at-sequences are interesting during the first pass.
+We skip past others immediately; warning if unexpected sequences are
+discovered.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Scan at-sequence {\footnotesize 26}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ c = source_get();@\\
+\verb@ switch (c) {@\\
+\verb@ case 'O':@\\
+\verb@ case 'o': @$\langle$Build output file definition {\footnotesize 27}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case 'D':@\\
+\verb@ case 'd': @$\langle$Build macro definition {\footnotesize 28}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case '@{\tt @}\verb@':@\\
+\verb@ case 'u':@\\
+\verb@ case 'm':@\\
+\verb@ case 'f': /* ignore during this pass */@\\
+\verb@ break;@\\
+\verb@ default: fprintf(stderr,@\\
+\verb@ "%s: unexpected @{\tt @}\verb@ sequence ignored (%s, line %d)\n",@\\
+\verb@ command_name, source_name, source_line);@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 25.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Accumulating Definitions}
+
+There are three steps required to handle a definition:
+\begin{enumerate}
+\item Build an entry for the name so we can look it up later.
+\item Collect the scrap and save it in the table of scraps.
+\item Attach the scrap to the name.
+\end{enumerate}
+We go through the same steps for both file names and macro names.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Build output file definition {\footnotesize 27}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Name *name = collect_file_name(); /* returns a pointer to the name entry */@\\
+\verb@ int scrap = collect_scrap(); /* returns an index to the scrap */@\\
+\verb@ @$\langle$Add {\tt scrap} to {\tt name}'s definition list {\footnotesize 29}$\rangle$\verb@@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 26.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Build macro definition {\footnotesize 28}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Name *name = collect_macro_name();@\\
+\verb@ int scrap = collect_scrap();@\\
+\verb@ @$\langle$Add {\tt scrap} to {\tt name}'s definition list {\footnotesize 29}$\rangle$\verb@@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 26.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Since a file or macro may be defined by many scraps, we maintain them
+in a simple linked list. The list is actually built in reverse order,
+with each new definition being added to the head of the list.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Add {\tt scrap} to {\tt name}'s definition list {\footnotesize 29}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Scrap_Node *def = (Scrap_Node *) arena_getmem(sizeof(Scrap_Node));@\\
+\verb@ def->scrap = scrap;@\\
+\verb@ def->next = name->defs;@\\
+\verb@ name->defs = def;@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 27 and~28.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Fixing the Cross References}
+
+Since the definition and reference lists for each name are accumulated
+in reverse order, we take the time at the end of {\tt pass1} to
+reverse them all so they'll be simpler to print out prettily.
+The code for {\tt reverse\_lists} appears in Section~\ref{names}.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Reverse cross-reference lists {\footnotesize 30}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ reverse_lists(file_names);@\\
+\verb@ reverse_lists(macro_names);@\\
+\verb@ reverse_lists(user_names);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 24.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\section{Writing the Latex File} \label{latex-file}
+
+The second pass (invoked via a call to {\tt write\_tex}) copies most of
+the text from the source file straight into a {\tt .tex} file.
+Definitions are formatted slightly and cross-reference information is
+printed out.
+
+Note that all the formatting is handled in this section.
+If you don't like the format of definitions or indices or whatever,
+it'll be in this section somewhere. Similarly, if someone wanted to
+modify nuweb to work with a different typesetting system, this would
+be the place to look.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Function prototypes {\footnotesize 31}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void write_tex();@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 23, 31, 60, 64, 77, 103 and~130.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\newpage
+\noindent
+We need a few local function declarations before we get into the body
+of {\tt write\_tex}.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"latex.c"@ {\footnotesize 32 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static void copy_scrap(); /* formats the body of a scrap */@\\
+\verb@static void print_scrap_numbers(); /* formats a list of scrap numbers */@\\
+\verb@static void format_entry(); /* formats an index entry */@\\
+\verb@static void format_user_entry();@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 6, 32, 33, 44, 45, 52 and~58.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The routine {\tt write\_tex} takes two file names as parameters: the
+name of the web source file and the name of the {\tt .tex} output file.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"latex.c"@ {\footnotesize 33 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void write_tex(file_name, tex_name)@\\
+\verb@ char *file_name;@\\
+\verb@ char *tex_name;@\\
+\verb@{@\\
+\verb@ FILE *tex_file = fopen(tex_name, "w");@\\
+\verb@ if (tex_file) {@\\
+\verb@ source_open(file_name);@\\
+\verb@ @$\langle$Copy {\tt source\_file} into {\tt tex\_file} {\footnotesize 34}$\rangle$\verb@@\\
+\verb@ fclose(tex_file);@\\
+\verb@ }@\\
+\verb@ else@\\
+\verb@ fprintf(stderr, "%s: can't open %s\n", command_name, tex_name);@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 6, 32, 33, 44, 45, 52 and~58.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+We make our second (and final) pass through the source web, this time
+copying characters straight into the {\tt .tex} file. However, we keep
+an eye peeled for {\tt @}~characters, which signal a command sequence.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Copy {\tt source\_file} into {\tt tex\_file} {\footnotesize 34}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ int scraps = 1;@\\
+\verb@ int c = source_get();@\\
+\verb@ while (c != EOF) {@\\
+\verb@ if (c == '@{\tt @}\verb@')@\\
+\verb@ @$\langle$Interpret at-sequence {\footnotesize 35}$\rangle$\verb@@\\
+\verb@ else {@\\
+\verb@ putc(c, tex_file);@\\
+\verb@ c = source_get();@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 33.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Interpret at-sequence {\footnotesize 35}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ int big_definition = FALSE;@\\
+\verb@ c = source_get();@\\
+\verb@ switch (c) {@\\
+\verb@ case 'O': big_definition = TRUE;@\\
+\verb@ case 'o': @$\langle$Write output file definition {\footnotesize 36}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case 'D': big_definition = TRUE;@\\
+\verb@ case 'd': @$\langle$Write macro definition {\footnotesize 37}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case 'f': @$\langle$Write index of file names {\footnotesize 50}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case 'm': @$\langle$Write index of macro names {\footnotesize 51}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case 'u': @$\langle$Write index of user-specified names {\footnotesize 57}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case '@{\tt @}\verb@': putc(c, tex_file);@\\
+\verb@ default: c = source_get();@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 34.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Formatting Definitions}
+
+We go through a fair amount of effort to format a file definition.
+I've derived most of the \LaTeX\ commands experimentally; it's quite
+likely that an expert could do a better job. The \LaTeX\ for
+the previous macro definition should look like this (perhaps modulo
+the scrap numbers):
+\begin{verbatim}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Interpret at-sequence {\footnotesize 35}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ c = source_get();@\\
+\verb@ switch (c) {@\\
+\verb@ case 'O': big_definition = TRUE;@\\
+\verb@ case 'o': @$\langle$Write output file definition {\footnotesize 36}$\rangle$\verb@@\\
+\end{verbatim}
+\vdots
+\begin{verbatim}
+\verb@ case '@{\tt @}\verb@': putc(c, tex_file);@\\
+\verb@ default: c = source_get();@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 34.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\end{verbatim}
+The {\em flushleft\/} environment is used to avoid \LaTeX\ warnings
+about underful lines. The {\em minipage\/} environment is used to
+avoid page breaks in the middle of scraps. The {\em verb\/} command
+allows arbitrary characters to be printed (however, note the special
+handling of the {\tt @} case in the switch statement).
+
+Macro and file definitions are formatted nearly identically.
+I've factored the common parts out into separate scraps.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write output file definition {\footnotesize 36}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Name *name = collect_file_name();@\\
+\verb@ @$\langle$Begin the scrap environment {\footnotesize 38}$\rangle$\verb@@\\
+\verb@ fprintf(tex_file, "\\verb@{\tt @}\verb@\"%s\"@{\tt @}\verb@", name->spelling);@\\
+\verb@ fprintf(tex_file, " {\\footnotesize %d }$\\equiv$\n", scraps++);@\\
+\verb@ @$\langle$Fill in the middle of the scrap environment {\footnotesize 39}$\rangle$\verb@@\\
+\verb@ @$\langle$Write file defs {\footnotesize 41}$\rangle$\verb@@\\
+\verb@ @$\langle$Finish the scrap environment {\footnotesize 40}$\rangle$\verb@@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 35.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+I don't format a macro name at all specially, figuring the programmer
+might want to use italics or bold face in the midst of the name.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write macro definition {\footnotesize 37}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Name *name = collect_macro_name();@\\
+\verb@ @$\langle$Begin the scrap environment {\footnotesize 38}$\rangle$\verb@@\\
+\verb@ fprintf(tex_file, "$\\langle$%s", name->spelling);@\\
+\verb@ fprintf(tex_file, " {\\footnotesize %d}$\\rangle\\equiv$\n", scraps++);@\\
+\verb@ @$\langle$Fill in the middle of the scrap environment {\footnotesize 39}$\rangle$\verb@@\\
+\verb@ @$\langle$Write macro defs {\footnotesize 42}$\rangle$\verb@@\\
+\verb@ @$\langle$Write macro refs {\footnotesize 43}$\rangle$\verb@@\\
+\verb@ @$\langle$Finish the scrap environment {\footnotesize 40}$\rangle$\verb@@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 35.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Begin the scrap environment {\footnotesize 38}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ fputs("\\begin{flushleft}\n", tex_file);@\\
+\verb@ if (!big_definition)@\\
+\verb@ fputs("\\begin{minipage}{\\linewidth}\n", tex_file);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 36 and~37.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+The interesting things here are the $\Diamond$ inserted at the end of
+each scrap and the various spacing commands. The diamond helps to
+clearly indicate the end of a scrap. The spacing commands were derived
+empirically; they may be adjusted to taste.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Fill in the middle of the scrap environment {\footnotesize 39}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ fputs("\\vspace{-1.5ex}\n\\begin{quote}\n", tex_file);@\\
+\verb@ copy_scrap(tex_file);@\\
+\verb@ fputs("$\\Diamond$\n\\end{quote}\n\\vspace{-2ex}\n", tex_file);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 36 and~37.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\newpage
+\noindent
+We've got one last spacing command, controlling the amount of white
+space after a scrap.
+
+Note also the whitespace eater. I use it to remove any blank lines
+that appear after a scrap in the source file. This way, text following
+a scrap will not be indented. Again, this is a matter of personal taste.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Finish the scrap environment {\footnotesize 40}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (!big_definition)@\\
+\verb@ fputs("\\end{minipage}\\\\[4ex]\n", tex_file);@\\
+\verb@ fputs("\\end{flushleft}\n", tex_file);@\\
+\verb@ do@\\
+\verb@ c = source_get();@\\
+\verb@ while (isspace(c));@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 36 and~37.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsubsection{Formatting Cross References}
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write file defs {\footnotesize 41}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (name->defs->next) {@\\
+\verb@ fputs("{\\footnotesize File defined by scraps ", tex_file);@\\
+\verb@ print_scrap_numbers(tex_file, name->defs);@\\
+\verb@ fputs("}\n", tex_file);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 36.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write macro defs {\footnotesize 42}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ fputs("{\\footnotesize ", tex_file);@\\
+\verb@ if (name->defs->next) {@\\
+\verb@ fputs("Macro defined by scraps ", tex_file);@\\
+\verb@ print_scrap_numbers(tex_file, name->defs);@\\
+\verb@ fputs("\\\\[-1ex]\n", tex_file);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 37.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write macro refs {\footnotesize 43}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (name->uses) {@\\
+\verb@ if (name->uses->next) {@\\
+\verb@ fputs("Macro referenced in scraps ", tex_file);@\\
+\verb@ print_scrap_numbers(tex_file, name->uses);@\\
+\verb@ fputs("}\n", tex_file);@\\
+\verb@ }@\\
+\verb@ else@\\
+\verb@ fprintf(tex_file, "Macro referenced in scrap %d.}\n", name->uses->scrap);@\\
+\verb@ }@\\
+\verb@ else {@\\
+\verb@ fputs("Macro never referenced.}\n", tex_file);@\\
+\verb@ fprintf(stderr, "%s: <%s> never referenced.\n",@\\
+\verb@ command_name, name->spelling);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 37.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"latex.c"@ {\footnotesize 44 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static void print_scrap_numbers(tex_file, scraps)@\\
+\verb@ FILE *tex_file;@\\
+\verb@ Scrap_Node *scraps;@\\
+\verb@{@\\
+\verb@ fprintf(tex_file, "%d", scraps->scrap);@\\
+\verb@ scraps = scraps->next;@\\
+\verb@ while (scraps->next) {@\\
+\verb@ fprintf(tex_file, ", %d", scraps->scrap);@\\
+\verb@ scraps = scraps->next;@\\
+\verb@ }@\\
+\verb@ fprintf(tex_file, " and~%d.", scraps->scrap);@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 6, 32, 33, 44, 45, 52 and~58.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsubsection{Formatting a Scrap}
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"latex.c"@ {\footnotesize 45 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static void copy_scrap(file)@\\
+\verb@ FILE *file;@\\
+\verb@{@\\
+\verb@ int indent = 0;@\\
+\verb@ int c = source_get();@\\
+\verb@ fputs("\\verb@{\tt @}\verb@", file);@\\
+\verb@ while (1) {@\\
+\verb@ switch (c) {@\\
+\verb@ case '@{\tt @}\verb@': @$\langle$Check at-sequence for end-of-scrap {\footnotesize 47}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case '\n': fputs("@{\tt @}\verb@\\\\\n\\verb@{\tt @}\verb@", file);@\\
+\verb@ indent = 0;@\\
+\verb@ break;@\\
+\verb@ case '\t': @$\langle$Expand tab into spaces {\footnotesize 46}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ default: putc(c, file);@\\
+\verb@ indent++;@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@ c = source_get();@\\
+\verb@ }@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 6, 32, 33, 44, 45, 52 and~58.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Expand tab into spaces {\footnotesize 46}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ int delta = 8 - (indent % 8);@\\
+\verb@ indent += delta;@\\
+\verb@ while (delta > 0) {@\\
+\verb@ putc(' ', file);@\\
+\verb@ delta--;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 45 and~97.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Check at-sequence for end-of-scrap {\footnotesize 47}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ c = source_get();@\\
+\verb@ switch (c) {@\\
+\verb@ case '@{\tt @}\verb@': fputs("@{\tt @}\verb@{\\tt @{\tt @}\verb@}\\verb@{\tt @}\verb@", file);@\\
+\verb@ break;@\\
+\verb@ case '|': @$\langle$Skip over index entries {\footnotesize 48}$\rangle$\verb@@\\
+\verb@ case '}': putc('@{\tt @}\verb@', file);@\\
+\verb@ return;@\\
+\verb@ case '<': @$\langle$Format macro name {\footnotesize 49}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ default: /* ignore these since pass1 will have warned about them */@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 45.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+There's no need to check for errors here, since we will have already
+pointed out any during the first pass.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Skip over index entries {\footnotesize 48}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ do {@\\
+\verb@ do@\\
+\verb@ c = source_get();@\\
+\verb@ while (c != '@{\tt @}\verb@');@\\
+\verb@ c = source_get();@\\
+\verb@ } while (c != '}');@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 47.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Format macro name {\footnotesize 49}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Name *name = collect_scrap_name();@\\
+\verb@ fprintf(file, "@{\tt @}\verb@$\\langle$%s {\\footnotesize ", name->spelling);@\\
+\verb@ if (name->defs)@\\
+\verb@ fprintf(file, "%d", name->defs->scrap);@\\
+\verb@ else {@\\
+\verb@ putc('?', file);@\\
+\verb@ fprintf(stderr, "%s: scrap never defined <%s>\n",@\\
+\verb@ command_name, name->spelling);@\\
+\verb@ }@\\
+\verb@ fputs("}$\\rangle$\\verb@{\tt @}\verb@", file);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 47.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Generating the Indices}
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write index of file names {\footnotesize 50}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (file_names) {@\\
+\verb@ fputs("\n\\begin{list}{}{\\setlength{\\itemsep}{-\\parsep}}\n", tex_file);@\\
+\verb@ format_entry(file_names, tex_file, TRUE);@\\
+\verb@ fputs("\\end{list}", tex_file);@\\
+\verb@ }@\\
+\verb@ c = source_get();@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 35.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write index of macro names {\footnotesize 51}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (macro_names) {@\\
+\verb@ fputs("\n\\begin{list}{}{\\setlength{\\itemsep}{-\\parsep}}\n", tex_file);@\\
+\verb@ format_entry(macro_names, tex_file, FALSE);@\\
+\verb@ fputs("\\end{list}", tex_file);@\\
+\verb@ }@\\
+\verb@ c = source_get();@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 35.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"latex.c"@ {\footnotesize 52 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static void format_entry(name, tex_file, file_flag)@\\
+\verb@ Name *name;@\\
+\verb@ FILE *tex_file;@\\
+\verb@ int file_flag;@\\
+\verb@{@\\
+\verb@ while (name) {@\\
+\verb@ format_entry(name->llink, tex_file, file_flag);@\\
+\verb@ @$\langle$Format an index entry {\footnotesize 53}$\rangle$\verb@@\\
+\verb@ name = name->rlink;@\\
+\verb@ }@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 6, 32, 33, 44, 45, 52 and~58.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Format an index entry {\footnotesize 53}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ fputs("\\item \\hspace{-\\leftmargin}", tex_file);@\\
+\verb@ if (file_flag) {@\\
+\verb@ fprintf(tex_file, "\\verb@{\tt @}\verb@\"%s\"@{\tt @}\verb@ ", name->spelling);@\\
+\verb@ @$\langle$Write file's defining scrap numbers {\footnotesize 54}$\rangle$\verb@@\\
+\verb@ }@\\
+\verb@ else {@\\
+\verb@ fprintf(tex_file, "$\\langle$%s {\\footnotesize ", name->spelling);@\\
+\verb@ @$\langle$Write defining scrap numbers {\footnotesize 55}$\rangle$\verb@@\\
+\verb@ fputs("}$\\rangle$ ", tex_file);@\\
+\verb@ @$\langle$Write referencing scrap numbers {\footnotesize 56}$\rangle$\verb@@\\
+\verb@ }@\\
+\verb@ putc('\n', tex_file);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 52.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write file's defining scrap numbers {\footnotesize 54}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Scrap_Node *p = name->defs;@\\
+\verb@ fputs("{\\footnotesize Defined by scrap", tex_file);@\\
+\verb@ if (p->next) {@\\
+\verb@ fputs("s ", tex_file);@\\
+\verb@ print_scrap_numbers(tex_file, p);@\\
+\verb@ }@\\
+\verb@ else@\\
+\verb@ fprintf(tex_file, " %d.", p->scrap);@\\
+\verb@ putc('}', tex_file);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 53.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write defining scrap numbers {\footnotesize 55}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Scrap_Node *p = name->defs;@\\
+\verb@ if (p) {@\\
+\verb@ while (1) {@\\
+\verb@ fprintf(tex_file, "%d", p->scrap);@\\
+\verb@ p = p->next;@\\
+\verb@ if (!p) break;@\\
+\verb@ fputs(", ", tex_file);@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@ else@\\
+\verb@ putc('?', tex_file);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 53.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write referencing scrap numbers {\footnotesize 56}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Scrap_Node *p = name->uses;@\\
+\verb@ fputs("{\\footnotesize ", tex_file);@\\
+\verb@ if (p) {@\\
+\verb@ fputs("Referenced in scrap", tex_file);@\\
+\verb@ if (p->next) {@\\
+\verb@ fputs("s ", tex_file);@\\
+\verb@ print_scrap_numbers(tex_file, p);@\\
+\verb@ }@\\
+\verb@ else@\\
+\verb@ fprintf(tex_file, " %d.", p->scrap);@\\
+\verb@ }@\\
+\verb@ else@\\
+\verb@ fputs("Not referenced.", tex_file);@\\
+\verb@ putc('}', tex_file);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 53.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write index of user-specified names {\footnotesize 57}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (user_names) {@\\
+\verb@ fputs("\n\\begin{list}{}{\\setlength{\\itemsep}{-\\parsep}}\n", tex_file);@\\
+\verb@ format_user_entry(user_names, tex_file);@\\
+\verb@ fputs("\\end{list}", tex_file);@\\
+\verb@ }@\\
+\verb@ c = source_get();@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 35.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"latex.c"@ {\footnotesize 58 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static void format_user_entry(name, tex_file)@\\
+\verb@ Name *name;@\\
+\verb@ FILE *tex_file;@\\
+\verb@{@\\
+\verb@ while (name) {@\\
+\verb@ format_user_entry(name->llink, tex_file);@\\
+\verb@ @$\langle$Format a user index entry {\footnotesize 59}$\rangle$\verb@@\\
+\verb@ name = name->rlink;@\\
+\verb@ }@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 6, 32, 33, 44, 45, 52 and~58.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Format a user index entry {\footnotesize 59}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Scrap_Node *uses = name->uses;@\\
+\verb@ Scrap_Node *defs = name->defs;@\\
+\verb@ fprintf(tex_file, "\\item \\hspace{-\\leftmargin}\\verb@{\tt @}\verb@%s@{\tt @}\verb@: ",@\\
+\verb@ name->spelling);@\\
+\verb@ do {@\\
+\verb@ if (uses && (!defs || uses->scrap < defs->scrap)) {@\\
+\verb@ fprintf(tex_file, "%d", uses->scrap);@\\
+\verb@ uses = uses->next;@\\
+\verb@ }@\\
+\verb@ else if (defs && (!uses || defs->scrap <= uses->scrap)) {@\\
+\verb@ if (uses && defs->scrap == uses->scrap)@\\
+\verb@ uses = uses->next;@\\
+\verb@ fprintf(tex_file, "\\underline{%d}", defs->scrap);@\\
+\verb@ defs = defs->next;@\\
+\verb@ }@\\
+\verb@ if (uses || defs) fputs(", ", tex_file);@\\
+\verb@ } while (uses || defs);@\\
+\verb@ fputs(".\n", tex_file);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 58.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\section{Writing the Output Files} \label{output-files}
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Function prototypes {\footnotesize 60}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void write_files();@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 23, 31, 60, 64, 77, 103 and~130.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"output.c"@ {\footnotesize 61 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void write_files(files)@\\
+\verb@ Name *files;@\\
+\verb@{@\\
+\verb@ while (files) {@\\
+\verb@ write_files(files->llink);@\\
+\verb@ @$\langle$Write out {\tt files->spelling} {\footnotesize 62}$\rangle$\verb@@\\
+\verb@ files = files->rlink;@\\
+\verb@ }@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 7 and~61.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Due to the filename restrictions on the PC, just use {\tt nuweb~~~.tmp} as
+the temporary filename. Since files are processed serially, this should
+cause any harm to unix platforms.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Write out {\tt files->spelling} {\footnotesize 62}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ FILE *temp_file;@\\
+\verb@ char temp_name[12]="nuweb~~~.tmp";@\\
+\verb@/* sprintf(temp_name, "%s~", files->spelling); */@\\
+\verb@ temp_file = fopen(temp_name, "w");@\\
+\verb@ if (temp_file) {@\\
+\verb@ char indent_chars[500];@\\
+\verb@ write_scraps(temp_file, files->defs, 0, indent_chars,@\\
+\verb@ files->debug_flag, files->tab_flag, files->indent_flag);@\\
+\verb@ fclose(temp_file);@\\
+\verb@ if (compare_flag)@\\
+\verb@ @$\langle$Compare the temp file and the old file {\footnotesize 63}$\rangle$\verb@@\\
+\verb@ else@\\
+\verb@ rename(temp_name, files->spelling);@\\
+\verb@ }@\\
+\verb@ else {@\\
+\verb@ fprintf(stderr, "%s: can't open %s\n", command_name, temp_name);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 61.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Compare the temp file and the old file {\footnotesize 63}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ FILE *old_file = fopen(files->spelling, "r");@\\
+\verb@ if (old_file) {@\\
+\verb@ int x, y;@\\
+\verb@ temp_file = fopen(temp_name, "r");@\\
+\verb@ do {@\\
+\verb@ x = getc(old_file);@\\
+\verb@ y = getc(temp_file);@\\
+\verb@ } while (x == y && x != EOF);@\\
+\verb@ fclose(old_file);@\\
+\verb@ fclose(temp_file);@\\
+\verb@ if (x == y)@\\
+\verb@ unlink(temp_name);@\\
+\verb@ else@\\
+\verb@ rename(temp_name, files->spelling);@\\
+\verb@ }@\\
+\verb@ else@\\
+\verb@ rename(temp_name, files->spelling);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 62.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\chapter{The Support Routines}
+
+\section{Source Files} \label{source-files}
+
+\subsection{Global Declarations}
+
+We need two routines to handle reading the source files.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Function prototypes {\footnotesize 64}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void source_open(); /* pass in the name of the source file */@\\
+\verb@int source_get(); /* no args; returns the next char or EOF */@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 23, 31, 60, 64, 77, 103 and~130.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+There are also two global variables maintained for use in error
+messages and such.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Global variables {\footnotesize 65}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@char *source_name; /* name of the current file */@\\
+\verb@int source_line; /* current line in the source file */@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 13, 15, 65 and~102.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Local Declarations}
+
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"input.c"@ {\footnotesize 66 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static FILE *source_file; /* the current input file */@\\
+\verb@static int source_peek;@\\
+\verb@static int double_at;@\\
+\verb@static int include_depth;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 8, 66, 67, 68 and~73.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"input.c"@ {\footnotesize 67 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@struct {@\\
+\verb@ FILE *file;@\\
+\verb@ char *name;@\\
+\verb@ int line;@\\
+\verb@} stack[10];@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 8, 66, 67, 68 and~73.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Reading a File}
+
+The routine {\tt source\_get} returns the next character from the
+current source file. It notices newlines and keeps the line counter
+{\tt source\_line} up to date. It also catches {\tt EOF} and watches
+for {\tt @} characters. All other characters are immediately returned.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"input.c"@ {\footnotesize 68 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@int source_get()@\\
+\verb@{@\\
+\verb@ int c = source_peek;@\\
+\verb@ switch (c) {@\\
+\verb@ case EOF: @$\langle$Handle {\tt EOF} {\footnotesize 72}$\rangle$\verb@@\\
+\verb@ return c;@\\
+\verb@ case '@{\tt @}\verb@': @$\langle$Handle an ``at'' character {\footnotesize 69}$\rangle$\verb@@\\
+\verb@ return c;@\\
+\verb@ case '\n': source_line++;@\\
+\verb@ default: source_peek = getc(source_file);@\\
+\verb@ return c;@\\
+\verb@ }@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 8, 66, 67, 68 and~73.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+This whole {\tt @}~character handling mess is pretty annoying.
+I want to recognize {\tt @i} so I can handle include files correctly.
+At the same time, it makes sense to recognize illegal {\tt @}~sequences
+and complain; this avoids ever having to check anywhere else.
+Unfortunately, I need to avoid tripping over the {\tt @@}~sequence;
+hence this whole unsatisfactory {\tt double\_at} business.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Handle an ``at'' character {\footnotesize 69}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ c = getc(source_file);@\\
+\verb@ if (double_at) {@\\
+\verb@ source_peek = c;@\\
+\verb@ double_at = FALSE;@\\
+\verb@ c = '@{\tt @}\verb@';@\\
+\verb@ }@\\
+\verb@ else@\\
+\verb@ switch (c) {@\\
+\verb@ case 'i': @$\langle$Open an include file {\footnotesize 70}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case 'f': case 'm': case 'u':@\\
+\verb@ case 'd': case 'o': case 'D': case 'O':@\\
+\verb@ case '{': case '}': case '<': case '>': case '|':@\\
+\verb@ source_peek = c;@\\
+\verb@ c = '@{\tt @}\verb@';@\\
+\verb@ break;@\\
+\verb@ case '@{\tt @}\verb@': source_peek = c;@\\
+\verb@ double_at = TRUE;@\\
+\verb@ break;@\\
+\verb@ default: fprintf(stderr, "%s: bad @{\tt @}\verb@ sequence (%s, line %d)\n",@\\
+\verb@ command_name, source_name, source_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 68.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Open an include file {\footnotesize 70}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (include_depth < 10) {@\\
+\verb@ char name[100];@\\
+\verb@ @$\langle$Collect include-file name {\footnotesize 71}$\rangle$\verb@@\\
+\verb@ stack[include_depth].name = source_name;@\\
+\verb@ stack[include_depth].file = source_file;@\\
+\verb@ stack[include_depth].line = source_line + 1;@\\
+\verb@ include_depth++;@\\
+\verb@ source_line = 1;@\\
+\verb@ source_name = save_string(name);@\\
+\verb@ source_file = fopen(source_name, "r");@\\
+\verb@ if (!source_file) {@\\
+\verb@ fprintf(stderr, "%s: can't open include file %s\n",@\\
+\verb@ command_name, source_name);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@ source_peek = getc(source_file);@\\
+\verb@ c = source_get();@\\
+\verb@ }@\\
+\verb@ else {@\\
+\verb@ fprintf(stderr, "%s: include nesting too deep (%s, %d)\n",@\\
+\verb@ command_name, source_name, source_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 69.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Collect include-file name {\footnotesize 71}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ char *p = name;@\\
+\verb@ do @\\
+\verb@ c = getc(source_file);@\\
+\verb@ while (c == ' ' || c == '\t');@\\
+\verb@ while (isgraph(c)) {@\\
+\verb@ *p++ = c;@\\
+\verb@ c = getc(source_file);@\\
+\verb@ }@\\
+\verb@ *p = '\0';@\\
+\verb@ if (c != '\n') {@\\
+\verb@ fprintf(stderr, "%s: unexpected characters after file name (%s, %d)\n",@\\
+\verb@ command_name, source_name, source_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 70.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+If an {\tt EOF} is discovered, the current file must be closed and
+input from the next stacked file must be resumed. If no more files are
+on the stack, the {\tt EOF} is returned.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Handle {\tt EOF} {\footnotesize 72}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ fclose(source_file);@\\
+\verb@ if (include_depth) {@\\
+\verb@ include_depth--;@\\
+\verb@ source_file = stack[include_depth].file;@\\
+\verb@ source_line = stack[include_depth].line;@\\
+\verb@ source_name = stack[include_depth].name;@\\
+\verb@ source_peek = getc(source_file);@\\
+\verb@ c = source_get();@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 68.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Opening a File}
+
+The routine {\tt source\_open} takes a file name and tries to open the
+file. If unsuccessful, it complains and halts. Otherwise, it sets
+{\tt source\_name}, {\tt source\_line}, and {\tt double\_at}.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"input.c"@ {\footnotesize 73 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void source_open(name)@\\
+\verb@ char *name;@\\
+\verb@{@\\
+\verb@ source_file = fopen(name, "r");@\\
+\verb@ if (!source_file) {@\\
+\verb@ fprintf(stderr, "%s: couldn't open %s\n", command_name, name);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@ source_name = name;@\\
+\verb@ source_line = 1;@\\
+\verb@ source_peek = getc(source_file);@\\
+\verb@ double_at = FALSE;@\\
+\verb@ include_depth = 0;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 8, 66, 67, 68 and~73.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\section{Scraps} \label{scraps}
+
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 74 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@#define SLAB_SIZE 500@\\
+\verb@@\\
+\verb@typedef struct slab {@\\
+\verb@ struct slab *next;@\\
+\verb@ char chars[SLAB_SIZE];@\\
+\verb@} Slab;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 75 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@typedef struct {@\\
+\verb@ char *file_name;@\\
+\verb@ int file_line;@\\
+\verb@ Slab *slab;@\\
+\verb@} ScrapEntry;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 76 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@ScrapEntry *SCRAP[256];@\\
+\verb@@\\
+\verb@#define scrap_array(i) SCRAP[(i) >> 8][(i) & 255]@\\
+\verb@@\\
+\verb@int scraps;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Function prototypes {\footnotesize 77}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void init_scraps();@\\
+\verb@int collect_scrap();@\\
+\verb@int write_scraps();@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 23, 31, 60, 64, 77, 103 and~130.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 78 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void init_scraps()@\\
+\verb@{@\\
+\verb@ scraps = 1;@\\
+\verb@ SCRAP[0] = (ScrapEntry *) arena_getmem(256 * sizeof(ScrapEntry));@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 79 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@typedef struct {@\\
+\verb@ Slab *scrap;@\\
+\verb@ int index;@\\
+\verb@} Manager;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 80 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static void push(c, manager)@\\
+\verb@ char c;@\\
+\verb@ Manager *manager;@\\
+\verb@{@\\
+\verb@ Slab *scrap = manager->scrap;@\\
+\verb@ int index = manager->index;@\\
+\verb@ scrap->chars[index++] = c;@\\
+\verb@ if (index == SLAB_SIZE) {@\\
+\verb@ Slab *new = (Slab *) arena_getmem(sizeof(Slab));@\\
+\verb@ scrap->next = new;@\\
+\verb@ manager->scrap = new;@\\
+\verb@ index = 0;@\\
+\verb@ }@\\
+\verb@ manager->index = index;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 81 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static void pushs(s, manager)@\\
+\verb@ char *s;@\\
+\verb@ Manager *manager;@\\
+\verb@{@\\
+\verb@ while (*s)@\\
+\verb@ push(*s++, manager);@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 82 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@int collect_scrap()@\\
+\verb@{@\\
+\verb@ Manager writer;@\\
+\verb@ @$\langle$Create new scrap, managed by {\tt writer} {\footnotesize 83}$\rangle$\verb@@\\
+\verb@ @$\langle$Accumulate scrap and return {\tt scraps++} {\footnotesize 84}$\rangle$\verb@@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Create new scrap, managed by {\tt writer} {\footnotesize 83}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Slab *scrap = (Slab *) arena_getmem(sizeof(Slab));@\\
+\verb@ if ((scraps & 255) == 0)@\\
+\verb@ SCRAP[scraps >> 8] = (ScrapEntry *) arena_getmem(256 * sizeof(ScrapEntry));@\\
+\verb@ scrap_array(scraps).slab = scrap;@\\
+\verb@ scrap_array(scraps).file_name = save_string(source_name);@\\
+\verb@ scrap_array(scraps).file_line = source_line;@\\
+\verb@ writer.scrap = scrap;@\\
+\verb@ writer.index = 0;@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 82.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Accumulate scrap and return {\tt scraps++} {\footnotesize 84}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ int c = source_get();@\\
+\verb@ while (1) {@\\
+\verb@ switch (c) {@\\
+\verb@ case EOF: fprintf(stderr, "%s: unexpect EOF in scrap (%s, %d)\n",@\\
+\verb@ command_name, scrap_array(scraps).file_name,@\\
+\verb@ scrap_array(scraps).file_line);@\\
+\verb@ exit(-1);@\\
+\verb@ case '@{\tt @}\verb@': @$\langle$Handle at-sign during scrap accumulation {\footnotesize 85}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ default: push(c, &writer);@\\
+\verb@ c = source_get();@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 82.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Handle at-sign during scrap accumulation {\footnotesize 85}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ c = source_get();@\\
+\verb@ switch (c) {@\\
+\verb@ case '@{\tt @}\verb@': pushs("@{\tt @}\verb@@{\tt @}\verb@", &writer);@\\
+\verb@ c = source_get();@\\
+\verb@ break;@\\
+\verb@ case '|': @$\langle$Collect user-specified index entries {\footnotesize 86}$\rangle$\verb@@\\
+\verb@ case '}': push('\0', &writer);@\\
+\verb@ return scraps++;@\\
+\verb@ case '<': @$\langle$Handle macro invocation in scrap {\footnotesize 87}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ default : fprintf(stderr, "%s: unexpected @{\tt @}\verb@%c in scrap (%s, %d)\n",@\\
+\verb@ command_name, c, source_name, source_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 84.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Collect user-specified index entries {\footnotesize 86}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ do {@\\
+\verb@ char new_name[100];@\\
+\verb@ char *p = new_name;@\\
+\verb@ do @\\
+\verb@ c = source_get();@\\
+\verb@ while (isspace(c));@\\
+\verb@ if (c != '@{\tt @}\verb@') {@\\
+\verb@ Name *name;@\\
+\verb@ do {@\\
+\verb@ *p++ = c;@\\
+\verb@ c = source_get();@\\
+\verb@ } while (c != '@{\tt @}\verb@' && !isspace(c));@\\
+\verb@ *p = '\0';@\\
+\verb@ name = name_add(&user_names, new_name);@\\
+\verb@ if (!name->defs || name->defs->scrap != scraps) {@\\
+\verb@ Scrap_Node *def = (Scrap_Node *) arena_getmem(sizeof(Scrap_Node));@\\
+\verb@ def->scrap = scraps;@\\
+\verb@ def->next = name->defs;@\\
+\verb@ name->defs = def;@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@ } while (c != '@{\tt @}\verb@');@\\
+\verb@ c = source_get();@\\
+\verb@ if (c != '}') {@\\
+\verb@ fprintf(stderr, "%s: unexpected @{\tt @}\verb@%c in scrap (%s, %d)\n",@\\
+\verb@ command_name, c, source_name, source_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 85.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Handle macro invocation in scrap {\footnotesize 87}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Name *name = collect_scrap_name();@\\
+\verb@ @$\langle$Save macro name {\footnotesize 88}$\rangle$\verb@@\\
+\verb@ @$\langle$Add current scrap to {\tt name}'s uses {\footnotesize 89}$\rangle$\verb@@\\
+\verb@ c = source_get();@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 85.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Save macro name {\footnotesize 88}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ char *s = name->spelling;@\\
+\verb@ int len = strlen(s) - 1;@\\
+\verb@ pushs("@{\tt @}\verb@<", &writer);@\\
+\verb@ while (len > 0) {@\\
+\verb@ push(*s++, &writer);@\\
+\verb@ len--;@\\
+\verb@ }@\\
+\verb@ if (*s == ' ')@\\
+\verb@ pushs("...", &writer);@\\
+\verb@ else@\\
+\verb@ push(*s, &writer);@\\
+\verb@ pushs("@{\tt @}\verb@>", &writer);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 87.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Add current scrap to {\tt name}'s uses {\footnotesize 89}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (!name->uses || name->uses->scrap != scraps) {@\\
+\verb@ Scrap_Node *use = (Scrap_Node *) arena_getmem(sizeof(Scrap_Node));@\\
+\verb@ use->scrap = scraps;@\\
+\verb@ use->next = name->uses;@\\
+\verb@ name->uses = use;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 87.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 90 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static char pop(manager)@\\
+\verb@ Manager *manager;@\\
+\verb@{@\\
+\verb@ Slab *scrap = manager->scrap;@\\
+\verb@ int index = manager->index;@\\
+\verb@ char c = scrap->chars[index++];@\\
+\verb@ if (index == SLAB_SIZE) {@\\
+\verb@ manager->scrap = scrap->next;@\\
+\verb@ index = 0;@\\
+\verb@ }@\\
+\verb@ manager->index = index;@\\
+\verb@ return c;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 91 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static Name *pop_scrap_name(manager)@\\
+\verb@ Manager *manager;@\\
+\verb@{@\\
+\verb@ char name[100];@\\
+\verb@ char *p = name;@\\
+\verb@ int c = pop(manager);@\\
+\verb@ while (TRUE) {@\\
+\verb@ if (c == '@{\tt @}\verb@')@\\
+\verb@ @$\langle$Check for end of scrap name and return {\footnotesize 92}$\rangle$\verb@@\\
+\verb@ else {@\\
+\verb@ *p++ = c;@\\
+\verb@ c = pop(manager);@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Check for end of scrap name and return {\footnotesize 92}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ c = pop(manager);@\\
+\verb@ if (c == '@{\tt @}\verb@') {@\\
+\verb@ *p++ = c;@\\
+\verb@ c = pop(manager);@\\
+\verb@ }@\\
+\verb@ else if (c == '>') {@\\
+\verb@ if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') {@\\
+\verb@ p[-3] = ' ';@\\
+\verb@ p -= 2;@\\
+\verb@ }@\\
+\verb@ *p = '\0';@\\
+\verb@ return prefix_add(&macro_names, name);@\\
+\verb@ }@\\
+\verb@ else {@\\
+\verb@ fprintf(stderr, "%s: found an internal problem (1)\n", command_name);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 91.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 93 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@int write_scraps(file, defs, global_indent, indent_chars,@\\
+\verb@ debug_flag, tab_flag, indent_flag)@\\
+\verb@ FILE *file;@\\
+\verb@ Scrap_Node *defs;@\\
+\verb@ int global_indent;@\\
+\verb@ char *indent_chars;@\\
+\verb@ char debug_flag;@\\
+\verb@ char tab_flag;@\\
+\verb@ char indent_flag;@\\
+\verb@{@\\
+\verb@ int indent = 0;@\\
+\verb@ while (defs) {@\\
+\verb@ @$\langle$Copy {\tt defs->scrap} to {\tt file} {\footnotesize 94}$\rangle$\verb@@\\
+\verb@ defs = defs->next;@\\
+\verb@ }@\\
+\verb@ return indent + global_indent;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Copy {\tt defs->scrap} to {\tt file} {\footnotesize 94}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ char c;@\\
+\verb@ Manager reader;@\\
+\verb@ int line_number = scrap_array(defs->scrap).file_line;@\\
+\verb@ @$\langle$Insert debugging information if required {\footnotesize 95}$\rangle$\verb@@\\
+\verb@ reader.scrap = scrap_array(defs->scrap).slab;@\\
+\verb@ reader.index = 0;@\\
+\verb@ c = pop(&reader);@\\
+\verb@ while (c) {@\\
+\verb@ switch (c) {@\\
+\verb@ case '@{\tt @}\verb@': @$\langle$Check for macro invocation in scrap {\footnotesize 98}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case '\n': putc(c, file);@\\
+\verb@ line_number++;@\\
+\verb@ @$\langle$Insert appropriate indentation {\footnotesize 96}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case '\t': @$\langle$Handle tab characters on output {\footnotesize 97}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ default: putc(c, file);@\\
+\verb@ indent_chars[global_indent + indent] = ' ';@\\
+\verb@ indent++;@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@ c = pop(&reader);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 93.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Insert debugging information if required {\footnotesize 95}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@if (debug_flag) {@\\
+\verb@ fprintf(file, "\n#line %d \"%s\"\n",@\\
+\verb@ line_number, scrap_array(defs->scrap).file_name);@\\
+\verb@ @$\langle$Insert appropriate indentation {\footnotesize 96}$\rangle$\verb@@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 94 and~98.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Insert appropriate indentation {\footnotesize 96}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (indent_flag) {@\\
+\verb@ if (tab_flag)@\\
+\verb@ for (indent=0; indent<global_indent; indent++)@\\
+\verb@ putc(' ', file);@\\
+\verb@ else@\\
+\verb@ for (indent=0; indent<global_indent; indent++)@\\
+\verb@ putc(indent_chars[indent], file);@\\
+\verb@ }@\\
+\verb@ indent = 0;@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 94 and~95.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Handle tab characters on output {\footnotesize 97}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (tab_flag)@\\
+\verb@ @$\langle$Expand tab into spaces {\footnotesize 46}$\rangle$\verb@@\\
+\verb@ else {@\\
+\verb@ putc('\t', file);@\\
+\verb@ indent_chars[global_indent + indent] = '\t';@\\
+\verb@ indent++;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 94.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Check for macro invocation in scrap {\footnotesize 98}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ c = pop(&reader);@\\
+\verb@ switch (c) {@\\
+\verb@ case '@{\tt @}\verb@': putc(c, file);@\\
+\verb@ indent_chars[global_indent + indent] = ' ';@\\
+\verb@ indent++;@\\
+\verb@ break;@\\
+\verb@ case '<': @$\langle$Copy macro into {\tt file} {\footnotesize 99}$\rangle$\verb@@\\
+\verb@ @$\langle$Insert debugging information if required {\footnotesize 95}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ default: /* ignore, since we should already have a warning */@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 94.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Copy macro into {\tt file} {\footnotesize 99}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Name *name = pop_scrap_name(&reader);@\\
+\verb@ if (name->mark) {@\\
+\verb@ fprintf(stderr, "%s: recursive macro discovered involving <%s>\n",@\\
+\verb@ command_name, name->spelling);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@ if (name->defs) {@\\
+\verb@ name->mark = TRUE;@\\
+\verb@ indent = write_scraps(file, name->defs, global_indent + indent,@\\
+\verb@ indent_chars, debug_flag, tab_flag, indent_flag);@\\
+\verb@ indent -= global_indent;@\\
+\verb@ name->mark = FALSE;@\\
+\verb@ }@\\
+\verb@ else if (!tex_flag)@\\
+\verb@ fprintf(stderr, "%s: macro never defined <%s>\n",@\\
+\verb@ command_name, name->spelling);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 98.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\section{Names} \label{names}
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Type declarations {\footnotesize 100}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@typedef struct scrap_node {@\\
+\verb@ struct scrap_node *next;@\\
+\verb@ int scrap;@\\
+\verb@} Scrap_Node;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 3, 100 and~101.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Type declarations {\footnotesize 101}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@typedef struct name {@\\
+\verb@ char *spelling;@\\
+\verb@ struct name *llink;@\\
+\verb@ struct name *rlink;@\\
+\verb@ Scrap_Node *defs;@\\
+\verb@ Scrap_Node *uses;@\\
+\verb@ int mark;@\\
+\verb@ char tab_flag;@\\
+\verb@ char indent_flag;@\\
+\verb@ char debug_flag;@\\
+\verb@} Name;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 3, 100 and~101.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Global variables {\footnotesize 102}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@Name *file_names;@\\
+\verb@Name *macro_names;@\\
+\verb@Name *user_names;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 13, 15, 65 and~102.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Function prototypes {\footnotesize 103}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@Name *collect_file_name();@\\
+\verb@Name *collect_macro_name();@\\
+\verb@Name *collect_scrap_name();@\\
+\verb@Name *name_add();@\\
+\verb@Name *prefix_add();@\\
+\verb@char *save_string();@\\
+\verb@void reverse_lists();@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 23, 31, 60, 64, 77, 103 and~130.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 104 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@enum { LESS, GREATER, EQUAL, PREFIX, EXTENSION };@\\
+\verb@@\\
+\verb@static int compare(x, y)@\\
+\verb@ char *x;@\\
+\verb@ char *y;@\\
+\verb@{@\\
+\verb@ int len, result;@\\
+\verb@ int xl = strlen(x);@\\
+\verb@ int yl = strlen(y);@\\
+\verb@ int xp = x[xl - 1] == ' ';@\\
+\verb@ int yp = y[yl - 1] == ' ';@\\
+\verb@ if (xp) xl--;@\\
+\verb@ if (yp) yl--;@\\
+\verb@ len = xl < yl ? xl : yl;@\\
+\verb@ result = strncmp(x, y, len);@\\
+\verb@ if (result < 0) return GREATER;@\\
+\verb@ else if (result > 0) return LESS;@\\
+\verb@ else if (xl < yl) {@\\
+\verb@ if (xp) return EXTENSION;@\\
+\verb@ else return LESS;@\\
+\verb@ }@\\
+\verb@ else if (xl > yl) {@\\
+\verb@ if (yp) return PREFIX;@\\
+\verb@ else return GREATER;@\\
+\verb@ }@\\
+\verb@ else return EQUAL;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 105 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@char *save_string(s)@\\
+\verb@ char *s;@\\
+\verb@{@\\
+\verb@ char *new = (char *) arena_getmem((strlen(s) + 1) * sizeof(char));@\\
+\verb@ strcpy(new, s);@\\
+\verb@ return new;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 106 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@Name *prefix_add(root, spelling)@\\
+\verb@ Name **root;@\\
+\verb@ char *spelling;@\\
+\verb@{@\\
+\verb@ Name *node = *root;@\\
+\verb@ while (node) {@\\
+\verb@ switch (compare(node->spelling, spelling)) {@\\
+\verb@ case GREATER: root = &node->rlink;@\\
+\verb@ break;@\\
+\verb@ case LESS: root = &node->llink;@\\
+\verb@ break;@\\
+\verb@ case EQUAL: return node;@\\
+\verb@ case EXTENSION: node->spelling = save_string(spelling);@\\
+\verb@ return node;@\\
+\verb@ case PREFIX: @$\langle$Check for ambiguous prefix {\footnotesize 107}$\rangle$\verb@@\\
+\verb@ return node;@\\
+\verb@ }@\\
+\verb@ node = *root;@\\
+\verb@ }@\\
+\verb@ @$\langle$Create new name entry {\footnotesize 111}$\rangle$\verb@@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Since a very short prefix might match more than one macro name, I need
+to check for other matches to avoid mistakes. Basically, I simply
+continue the search down {\em both\/} branches of the tree.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Check for ambiguous prefix {\footnotesize 107}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (ambiguous_prefix(node->llink, spelling) ||@\\
+\verb@ ambiguous_prefix(node->rlink, spelling))@\\
+\verb@ fprintf(stderr,@\\
+\verb@ "%s: ambiguous prefix @{\tt @}\verb@<%s...@{\tt @}\verb@> (%s, line %d)\n",@\\
+\verb@ command_name, spelling, source_name, source_line);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 106.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 108 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static int ambiguous_prefix(node, spelling)@\\
+\verb@ Name *node;@\\
+\verb@ char *spelling;@\\
+\verb@{@\\
+\verb@ while (node) {@\\
+\verb@ switch (compare(node->spelling, spelling)) {@\\
+\verb@ case GREATER: node = node->rlink;@\\
+\verb@ break;@\\
+\verb@ case LESS: node = node->llink;@\\
+\verb@ break;@\\
+\verb@ case EQUAL:@\\
+\verb@ case EXTENSION:@\\
+\verb@ case PREFIX: return TRUE;@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@ return FALSE;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Rob Shillingsburg suggested that I organize the index of
+user-specified identifiers more traditionally; that is, not relying on
+strict {\small ASCII} comparisons via {\tt strcmp}. Ideally, we'd like
+to see the index ordered like this:
+\begin{quote}
+\begin{flushleft}
+aardvark \\
+Adam \\
+atom \\
+Atomic \\
+atoms
+\end{flushleft}
+\end{quote}
+The function {\tt robs\_strcmp} implements the desired predicate.
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 109 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static int robs_strcmp(x, y)@\\
+\verb@ char *x;@\\
+\verb@ char *y;@\\
+\verb@{@\\
+\verb@ char *xx = x;@\\
+\verb@ char *yy = y;@\\
+\verb@ int xc = toupper(*xx);@\\
+\verb@ int yc = toupper(*yy);@\\
+\verb@ while (xc == yc && xc) {@\\
+\verb@ xx++;@\\
+\verb@ yy++;@\\
+\verb@ xc = toupper(*xx);@\\
+\verb@ yc = toupper(*yy);@\\
+\verb@ }@\\
+\verb@ if (xc != yc) return xc - yc;@\\
+\verb@ xc = *x;@\\
+\verb@ yc = *y;@\\
+\verb@ while (xc == yc && xc) {@\\
+\verb@ x++;@\\
+\verb@ y++;@\\
+\verb@ xc = *x;@\\
+\verb@ yc = *y;@\\
+\verb@ }@\\
+\verb@ if (isupper(xc) && islower(yc))@\\
+\verb@ return xc * 2 - (toupper(yc) * 2 + 1);@\\
+\verb@ if (islower(xc) && isupper(yc))@\\
+\verb@ return toupper(xc) * 2 + 1 - yc * 2;@\\
+\verb@ return xc - yc;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 110 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@Name *name_add(root, spelling)@\\
+\verb@ Name **root;@\\
+\verb@ char *spelling;@\\
+\verb@{@\\
+\verb@ Name *node = *root;@\\
+\verb@ while (node) {@\\
+\verb@ int result = robs_strcmp(node->spelling, spelling);@\\
+\verb@ if (result > 0)@\\
+\verb@ root = &node->llink;@\\
+\verb@ else if (result < 0)@\\
+\verb@ root = &node->rlink;@\\
+\verb@ else@\\
+\verb@ return node;@\\
+\verb@ node = *root;@\\
+\verb@ }@\\
+\verb@ @$\langle$Create new name entry {\footnotesize 111}$\rangle$\verb@@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Create new name entry {\footnotesize 111}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ node = (Name *) arena_getmem(sizeof(Name));@\\
+\verb@ node->spelling = save_string(spelling);@\\
+\verb@ node->mark = FALSE;@\\
+\verb@ node->llink = NULL;@\\
+\verb@ node->rlink = NULL;@\\
+\verb@ node->uses = NULL;@\\
+\verb@ node->defs = NULL;@\\
+\verb@ node->tab_flag = TRUE;@\\
+\verb@ node->indent_flag = TRUE;@\\
+\verb@ node->debug_flag = FALSE;@\\
+\verb@ *root = node;@\\
+\verb@ return node;@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 106 and~110.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Name terminated by whitespace. Also check for ``per-file'' flags. Keep
+skipping white space until we reach scrap.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 112 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@Name *collect_file_name()@\\
+\verb@{@\\
+\verb@ Name *new_name;@\\
+\verb@ char name[100];@\\
+\verb@ char *p = name;@\\
+\verb@ int start_line = source_line;@\\
+\verb@ int c = source_get();@\\
+\verb@ while (isspace(c))@\\
+\verb@ c = source_get();@\\
+\verb@ while (isgraph(c)) {@\\
+\verb@ *p++ = c;@\\
+\verb@ c = source_get();@\\
+\verb@ }@\\
+\verb@ if (p == name) {@\\
+\verb@ fprintf(stderr, "%s: expected file name (%s, %d)\n",@\\
+\verb@ command_name, source_name, start_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@ *p = '\0';@\\
+\verb@ new_name = name_add(&file_names, name);@\\
+\verb@ @$\langle$Handle optional per-file flags {\footnotesize 113}$\rangle$\verb@@\\
+\verb@ if (c == '@{\tt @}\verb@' && source_get() == '{')@\\
+\verb@ return new_name;@\\
+\verb@ else {@\\
+\verb@ fprintf(stderr, "%s: expected @{\tt @}\verb@{ after file name (%s, %d)\n",@\\
+\verb@ command_name, source_name, start_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Handle optional per-file flags {\footnotesize 113}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ while (1) {@\\
+\verb@ while (isspace(c))@\\
+\verb@ c = source_get();@\\
+\verb@ if (c == '-') {@\\
+\verb@ c = source_get();@\\
+\verb@ do {@\\
+\verb@ switch (c) {@\\
+\verb@ case 't': new_name->tab_flag = FALSE;@\\
+\verb@ break;@\\
+\verb@ case 'd': new_name->debug_flag = TRUE;@\\
+\verb@ break;@\\
+\verb@ case 'i': new_name->indent_flag = FALSE;@\\
+\verb@ break;@\\
+\verb@ default : fprintf(stderr, "%s: unexpected per-file flag (%s, %d)\n",@\\
+\verb@ command_name, source_name, source_line);@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@ c = source_get();@\\
+\verb@ } while (!isspace(c));@\\
+\verb@ }@\\
+\verb@ else break;@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 112.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Name terminated by \verb+\n+ or \verb+@{+; but keep skipping until \verb+@{+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 114 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@Name *collect_macro_name()@\\
+\verb@{@\\
+\verb@ char name[100];@\\
+\verb@ char *p = name;@\\
+\verb@ int start_line = source_line;@\\
+\verb@ int c = source_get();@\\
+\verb@ while (isspace(c))@\\
+\verb@ c = source_get();@\\
+\verb@ while (c != EOF) {@\\
+\verb@ switch (c) {@\\
+\verb@ case '@{\tt @}\verb@': @$\langle$Check for terminating at-sequence and return name {\footnotesize 115}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case '\t':@\\
+\verb@ case ' ': *p++ = ' ';@\\
+\verb@ do@\\
+\verb@ c = source_get();@\\
+\verb@ while (c == ' ' || c == '\t');@\\
+\verb@ break;@\\
+\verb@ case '\n': @$\langle$Skip until scrap begins, then return name {\footnotesize 117}$\rangle$\verb@@\\
+\verb@ default: *p++ = c;@\\
+\verb@ c = source_get();@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@ fprintf(stderr, "%s: expected macro name (%s, %d)\n",@\\
+\verb@ command_name, source_name, start_line);@\\
+\verb@ exit(-1);@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Check for terminating at-sequence and return name {\footnotesize 115}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ c = source_get();@\\
+\verb@ switch (c) {@\\
+\verb@ case '@{\tt @}\verb@': *p++ = c;@\\
+\verb@ break;@\\
+\verb@ case '{': @$\langle$Cleanup and install name {\footnotesize 116}$\rangle$\verb@@\\
+\verb@ default: fprintf(stderr,@\\
+\verb@ "%s: unexpected @{\tt @}\verb@%c in macro name (%s, %d)\n",@\\
+\verb@ command_name, c, source_name, start_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 114.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Cleanup and install name {\footnotesize 116}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ if (p > name && p[-1] == ' ')@\\
+\verb@ p--;@\\
+\verb@ if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') {@\\
+\verb@ p[-3] = ' ';@\\
+\verb@ p -= 2;@\\
+\verb@ }@\\
+\verb@ if (p == name || name[0] == ' ') {@\\
+\verb@ fprintf(stderr, "%s: empty scrap name (%s, %d)\n",@\\
+\verb@ command_name, source_name, source_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@ *p = '\0';@\\
+\verb@ return prefix_add(&macro_names, name);@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scraps 115, 117 and~119.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Skip until scrap begins, then return name {\footnotesize 117}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ do@\\
+\verb@ c = source_get();@\\
+\verb@ while (isspace(c));@\\
+\verb@ if (c == '@{\tt @}\verb@' && source_get() == '{')@\\
+\verb@ @$\langle$Cleanup and install name {\footnotesize 116}$\rangle$\verb@@\\
+\verb@ else {@\\
+\verb@ fprintf(stderr, "%s: expected @{\tt @}\verb@{ after macro name (%s, %d)\n",@\\
+\verb@ command_name, source_name, start_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 114.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Terminated by \verb+@>+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 118 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@Name *collect_scrap_name()@\\
+\verb@{@\\
+\verb@ char name[100];@\\
+\verb@ char *p = name;@\\
+\verb@ int c = source_get();@\\
+\verb@ while (c == ' ' || c == '\t')@\\
+\verb@ c = source_get();@\\
+\verb@ while (c != EOF) {@\\
+\verb@ switch (c) {@\\
+\verb@ case '@{\tt @}\verb@': @$\langle$Look for end of scrap name and return {\footnotesize 119}$\rangle$\verb@@\\
+\verb@ break;@\\
+\verb@ case '\t':@\\
+\verb@ case ' ': *p++ = ' ';@\\
+\verb@ do@\\
+\verb@ c = source_get();@\\
+\verb@ while (c == ' ' || c == '\t');@\\
+\verb@ break;@\\
+\verb@ default: if (isgraph(c)) {@\\
+\verb@ *p++ = c;@\\
+\verb@ c = source_get();@\\
+\verb@ }@\\
+\verb@ else {@\\
+\verb@ fprintf(stderr,@\\
+\verb@ "%s: unexpected character in macro name (%s, %d)\n",@\\
+\verb@ command_name, source_name, source_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@ break;@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@ fprintf(stderr, "%s: unexpected end of file (%s, %d)\n",@\\
+\verb@ command_name, source_name, source_line);@\\
+\verb@ exit(-1);@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Look for end of scrap name and return {\footnotesize 119}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ c = source_get();@\\
+\verb@ switch (c) {@\\
+\verb@ case '@{\tt @}\verb@': *p++ = c;@\\
+\verb@ c = source_get();@\\
+\verb@ break;@\\
+\verb@ case '>': @$\langle$Cleanup and install name {\footnotesize 116}$\rangle$\verb@@\\
+\verb@ default: fprintf(stderr,@\\
+\verb@ "%s: unexpected @{\tt @}\verb@%c in macro name (%s, %d)\n",@\\
+\verb@ command_name, c, source_name, source_line);@\\
+\verb@ exit(-1);@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 118.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 120 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static Scrap_Node *reverse(); /* a forward declaration */@\\
+\verb@@\\
+\verb@void reverse_lists(names)@\\
+\verb@ Name *names;@\\
+\verb@{@\\
+\verb@ while (names) {@\\
+\verb@ reverse_lists(names->llink);@\\
+\verb@ names->defs = reverse(names->defs);@\\
+\verb@ names->uses = reverse(names->uses);@\\
+\verb@ names = names->rlink;@\\
+\verb@ }@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+Just for fun, here's a non-recursive version of the traditional list
+reversal code. Note that it reverses the list in place; that is, it
+does no new allocations.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"names.c"@ {\footnotesize 121 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static Scrap_Node *reverse(a)@\\
+\verb@ Scrap_Node *a;@\\
+\verb@{@\\
+\verb@ if (a) {@\\
+\verb@ Scrap_Node *b = a->next;@\\
+\verb@ a->next = NULL;@\\
+\verb@ while (b) {@\\
+\verb@ Scrap_Node *c = b->next;@\\
+\verb@ b->next = a;@\\
+\verb@ a = b;@\\
+\verb@ b = c;@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@ return a;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\section{Searching for Index Entries} \label{search}
+
+Given the array of scraps and a set of index entries, we need to
+search all the scraps for occurences of each entry. The obvious
+approach to this problem would be quite expensive for large documents;
+however, there is an interesting paper describing an efficient
+solution~\cite{aho:75}.
+
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 122 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@\\
+\verb@typedef struct name_node {@\\
+\verb@ struct name_node *next;@\\
+\verb@ Name *name;@\\
+\verb@} Name_Node;@\\
+\verb@@\\
+\verb@typedef struct goto_node {@\\
+\verb@ struct goto_node *next; /* next goto node with same depth */@\\
+\verb@ struct goto_node *fail;@\\
+\verb@ struct move_node *moves;@\\
+\verb@ Name_Node *output;@\\
+\verb@} Goto_Node;@\\
+\verb@@\\
+\verb@typedef struct move_node {@\\
+\verb@ struct move_node *next;@\\
+\verb@ Goto_Node *state;@\\
+\verb@ char c;@\\
+\verb@} Move_Node;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 123 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@\\
+\verb@static Goto_Node *root[128];@\\
+\verb@static int max_depth;@\\
+\verb@static Goto_Node **depths;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 124 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static Goto_Node *goto_lookup(c, g)@\\
+\verb@ char c;@\\
+\verb@ Goto_Node *g;@\\
+\verb@{@\\
+\verb@ Move_Node *m = g->moves;@\\
+\verb@ while (m && m->c != c)@\\
+\verb@ m = m->next;@\\
+\verb@ if (m)@\\
+\verb@ return m->state;@\\
+\verb@ else@\\
+\verb@ return NULL;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Building the Automata}
+
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 125 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@@\\
+\verb@static void build_gotos();@\\
+\verb@@\\
+\verb@void search()@\\
+\verb@{@\\
+\verb@ int i;@\\
+\verb@ for (i=0; i<128; i++)@\\
+\verb@ root[i] = NULL;@\\
+\verb@ max_depth = 10;@\\
+\verb@ depths = (Goto_Node **) arena_getmem(max_depth * sizeof(Goto_Node *));@\\
+\verb@ for (i=0; i<max_depth; i++)@\\
+\verb@ depths[i] = NULL;@\\
+\verb@ build_gotos(user_names);@\\
+\verb@ @$\langle$Build failure functions {\footnotesize 128}$\rangle$\verb@@\\
+\verb@ @$\langle$Search scraps {\footnotesize 129}$\rangle$\verb@@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"scraps.c"@ {\footnotesize 126 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@static void build_gotos(tree)@\\
+\verb@ Name *tree;@\\
+\verb@{@\\
+\verb@ while (tree) {@\\
+\verb@ @$\langle$Extend goto graph with {\tt tree->spelling} {\footnotesize 127}$\rangle$\verb@@\\
+\verb@ build_gotos(tree->rlink);@\\
+\verb@ tree = tree->llink;@\\
+\verb@ }@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Extend goto graph with {\tt tree->spelling} {\footnotesize 127}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ int depth = 2;@\\
+\verb@ char *p = tree->spelling;@\\
+\verb@ char c = *p++;@\\
+\verb@ Goto_Node *q = root[c];@\\
+\verb@ if (!q) {@\\
+\verb@ q = (Goto_Node *) arena_getmem(sizeof(Goto_Node));@\\
+\verb@ root[c] = q;@\\
+\verb@ q->moves = NULL;@\\
+\verb@ q->fail = NULL;@\\
+\verb@ q->moves = NULL;@\\
+\verb@ q->output = NULL;@\\
+\verb@ q->next = depths[1];@\\
+\verb@ depths[1] = q;@\\
+\verb@ }@\\
+\verb@ while (c = *p++) {@\\
+\verb@ Goto_Node *new = goto_lookup(c, q);@\\
+\verb@ if (!new) {@\\
+\verb@ Move_Node *new_move = (Move_Node *) arena_getmem(sizeof(Move_Node));@\\
+\verb@ new = (Goto_Node *) arena_getmem(sizeof(Goto_Node));@\\
+\verb@ new->moves = NULL;@\\
+\verb@ new->fail = NULL;@\\
+\verb@ new->moves = NULL;@\\
+\verb@ new->output = NULL;@\\
+\verb@ new_move->state = new;@\\
+\verb@ new_move->c = c;@\\
+\verb@ new_move->next = q->moves;@\\
+\verb@ q->moves = new_move;@\\
+\verb@ if (depth == max_depth) {@\\
+\verb@ int i;@\\
+\verb@ Goto_Node **new_depths =@\\
+\verb@ (Goto_Node **) arena_getmem(2*depth*sizeof(Goto_Node *));@\\
+\verb@ max_depth = 2 * depth;@\\
+\verb@ for (i=0; i<depth; i++)@\\
+\verb@ new_depths[i] = depths[i];@\\
+\verb@ depths = new_depths;@\\
+\verb@ for (i=depth; i<max_depth; i++)@\\
+\verb@ depths[i] = NULL;@\\
+\verb@ }@\\
+\verb@ new->next = depths[depth];@\\
+\verb@ depths[depth] = new;@\\
+\verb@ }@\\
+\verb@ q = new;@\\
+\verb@ depth++;@\\
+\verb@ }@\\
+\verb@ q->output = (Name_Node *) arena_getmem(sizeof(Name_Node));@\\
+\verb@ q->output->next = NULL;@\\
+\verb@ q->output->name = tree;@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 126.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Build failure functions {\footnotesize 128}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ int depth;@\\
+\verb@ for (depth=1; depth<max_depth; depth++) {@\\
+\verb@ Goto_Node *r = depths[depth];@\\
+\verb@ while (r) {@\\
+\verb@ Move_Node *m = r->moves;@\\
+\verb@ while (m) {@\\
+\verb@ char a = m->c;@\\
+\verb@ Goto_Node *s = m->state;@\\
+\verb@ Goto_Node *state = r->fail;@\\
+\verb@ while (state && !goto_lookup(a, state))@\\
+\verb@ state = state->fail;@\\
+\verb@ if (state)@\\
+\verb@ s->fail = goto_lookup(a, state);@\\
+\verb@ else@\\
+\verb@ s->fail = root[a];@\\
+\verb@ if (s->fail) {@\\
+\verb@ Name_Node *p = s->fail->output;@\\
+\verb@ while (p) {@\\
+\verb@ Name_Node *q = (Name_Node *) arena_getmem(sizeof(Name_Node));@\\
+\verb@ q->name = p->name;@\\
+\verb@ q->next = s->output;@\\
+\verb@ s->output = q;@\\
+\verb@ p = p->next;@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@ m = m->next;@\\
+\verb@ }@\\
+\verb@ r = r->next;@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 125.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Searching the Scraps}
+
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Search scraps {\footnotesize 129}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ for (i=1; i<scraps; i++) {@\\
+\verb@ char c;@\\
+\verb@ Manager reader;@\\
+\verb@ Goto_Node *state = NULL;@\\
+\verb@ reader.scrap = scrap_array(i).slab;@\\
+\verb@ reader.index = 0;@\\
+\verb@ c = pop(&reader);@\\
+\verb@ while (c) {@\\
+\verb@ while (state && !goto_lookup(c, state))@\\
+\verb@ state = state->fail;@\\
+\verb@ if (state)@\\
+\verb@ state = goto_lookup(c, state);@\\
+\verb@ else@\\
+\verb@ state = root[c];@\\
+\verb@ if (state && state->output) {@\\
+\verb@ Name_Node *p = state->output;@\\
+\verb@ do {@\\
+\verb@ Name *name = p->name;@\\
+\verb@ if (!name->uses || name->uses->scrap != i) {@\\
+\verb@ Scrap_Node *new_use =@\\
+\verb@ (Scrap_Node *) arena_getmem(sizeof(Scrap_Node));@\\
+\verb@ new_use->scrap = i;@\\
+\verb@ new_use->next = name->uses;@\\
+\verb@ name->uses = new_use;@\\
+\verb@ }@\\
+\verb@ p = p->next;@\\
+\verb@ } while (p);@\\
+\verb@ }@\\
+\verb@ c = pop(&reader);@\\
+\verb@ }@\\
+\verb@ }@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 125.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\section{Memory Management} \label{memory-management}
+
+I manage memory using a simple scheme inspired by Hanson's idea of
+{\em arenas\/}~\cite{hanson:90}.
+Basically, I allocate all the storage required when processing a
+source file (primarily for names and scraps) using calls to
+{\tt arena\_getmem(n)}, where {\tt n} specifies the number of bytes to
+be allocated. When the storage is no longer required, the entire arena
+is freed with a single call to {\tt arena\_free()}. Both operations
+are quite fast.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Function prototypes {\footnotesize 130}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void *arena_getmem();@\\
+\verb@void arena_free();@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro defined by scraps 23, 31, 60, 64, 77, 103 and~130.\\[-1ex]
+Macro referenced in scrap 1.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"arena.c"@ {\footnotesize 131 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@typedef struct chunk {@\\
+\verb@ struct chunk *next;@\\
+\verb@ char *limit;@\\
+\verb@ char *avail;@\\
+\verb@} Chunk;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 11, 131, 132, 133 and~136.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+We define an empty chunk called {\tt first}. The variable {\tt arena} points
+at the current chunk of memory; it's initially pointed at {\tt first}.
+As soon as some storage is required, a ``real'' chunk of memory will
+be allocated and attached to {\tt first->next}; storage will be
+allocated from the new chunk (and later chunks if necessary).
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"arena.c"@ {\footnotesize 132 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@Chunk first = { NULL, NULL, NULL };@\\
+\verb@Chunk *arena = &first;@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 11, 131, 132, 133 and~136.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Allocating Memory}
+
+The routine {\tt arena\_getmem(n)} returns a pointer to (at least)
+{\tt n} bytes of memory. Note that {\tt n} is rounded up to ensure
+that returned pointers are always aligned.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"arena.c"@ {\footnotesize 133 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void *arena_getmem(n)@\\
+\verb@ int n;@\\
+\verb@{@\\
+\verb@ char *q;@\\
+\verb@ char *p = arena->avail;@\\
+\verb@ n = (n + 3) & ~3; /* ensuring alignment to 4 bytes */@\\
+\verb@ q = p + n;@\\
+\verb@ if (q <= arena->limit) {@\\
+\verb@ arena->avail = q;@\\
+\verb@ return p;@\\
+\verb@ }@\\
+\verb@ @$\langle$Find a new chunk of memory {\footnotesize 134}$\rangle$\verb@@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 11, 131, 132, 133 and~136.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+If the current chunk doesn't have adequate space (at least {\tt n}
+bytes) we examine the rest of the list of chunks (starting at
+{\tt arena->next}) looking for a chunk with adequate space. If {\tt n}
+is very large, we may not find it right away or we may not find a
+suitable chunk at all.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Find a new chunk of memory {\footnotesize 134}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ Chunk *ap = arena;@\\
+\verb@ Chunk *np = ap->next;@\\
+\verb@ while (np) {@\\
+\verb@ char *v = sizeof(Chunk) + (char *) np;@\\
+\verb@ if (v + n <= np->limit) {@\\
+\verb@ np->avail = v + n;@\\
+\verb@ arena = np;@\\
+\verb@ return v;@\\
+\verb@ }@\\
+\verb@ ap = np;@\\
+\verb@ np = ap->next;@\\
+\verb@ }@\\
+\verb@ @$\langle$Allocate a new chunk of memory {\footnotesize 135}$\rangle$\verb@@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 133.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+If there isn't a suitable chunk of memory on the free list, then we
+need to allocate a new one.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+$\langle$Allocate a new chunk of memory {\footnotesize 135}$\rangle\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@{@\\
+\verb@ int m = n + 10000;@\\
+\verb@ np = (Chunk *) malloc(m);@\\
+\verb@ np->limit = m + (char *) np;@\\
+\verb@ np->avail = n + sizeof(Chunk) + (char *) np;@\\
+\verb@ np->next = NULL;@\\
+\verb@ ap->next = np;@\\
+\verb@ arena = np;@\\
+\verb@ return sizeof(Chunk) + (char *) np;@\\
+\verb@}@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize Macro referenced in scrap 134.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\subsection{Freeing Memory}
+
+To free all the memory in the arena, we need only point {\tt arena}
+back to the first empty chunk.
+\begin{flushleft}
+\begin{minipage}{\linewidth}
+\verb@"arena.c"@ {\footnotesize 136 }$\equiv$
+\vspace{-1.5ex}
+\begin{quote}
+\verb@void arena_free()@\\
+\verb@{@\\
+\verb@ arena = &first;@\\
+\verb@}@\\
+\verb@@$\Diamond$
+\end{quote}
+\vspace{-2ex}
+{\footnotesize File defined by scraps 11, 131, 132, 133 and~136.}
+\end{minipage}\\[4ex]
+\end{flushleft}
+\chapter{Indices} \label{indices}
+
+Three sets of indices can be created automatically: an index of file
+names, an index of macro names, and an index of user-specified
+identifiers. An index entry includes the name of the entry, where it
+was defined, and where it was referenced.
+
+
+
+\section{Files}
+
+
+\begin{list}{}{\setlength{\itemsep}{-\parsep}}
+\item \hspace{-\leftmargin}\verb@"arena.c"@ {\footnotesize Defined by scraps 11, 131, 132, 133 and~136.}
+\item \hspace{-\leftmargin}\verb@"input.c"@ {\footnotesize Defined by scraps 8, 66, 67, 68 and~73.}
+\item \hspace{-\leftmargin}\verb@"latex.c"@ {\footnotesize Defined by scraps 6, 32, 33, 44, 45, 52 and~58.}
+\item \hspace{-\leftmargin}\verb@"main.c"@ {\footnotesize Defined by scraps 4 and~12.}
+\item \hspace{-\leftmargin}\verb@"names.c"@ {\footnotesize Defined by scraps 10, 104, 105, 106, 108, 109, 110, 112, 114, 118, 120 and~121.}
+\item \hspace{-\leftmargin}\verb@"output.c"@ {\footnotesize Defined by scraps 7 and~61.}
+\item \hspace{-\leftmargin}\verb@"pass1.c"@ {\footnotesize Defined by scraps 5 and~24.}
+\item \hspace{-\leftmargin}\verb@"scraps.c"@ {\footnotesize Defined by scraps 9, 74, 75, 76, 78, 79, 80, 81, 82, 90, 91, 93, 122, 123, 124, 125 and~126.}
+\end{list}
+
+\section{Macros}
+
+
+\begin{list}{}{\setlength{\itemsep}{-\parsep}}
+\item \hspace{-\leftmargin}$\langle$Accumulate scrap and return {\tt scraps++} {\footnotesize 84}$\rangle$ {\footnotesize Referenced in scrap 82.}
+\item \hspace{-\leftmargin}$\langle$Add current scrap to {\tt name}'s uses {\footnotesize 89}$\rangle$ {\footnotesize Referenced in scrap 87.}
+\item \hspace{-\leftmargin}$\langle$Add {\tt scrap} to {\tt name}'s definition list {\footnotesize 29}$\rangle$ {\footnotesize Referenced in scraps 27 and~28.}
+\item \hspace{-\leftmargin}$\langle$Allocate a new chunk of memory {\footnotesize 135}$\rangle$ {\footnotesize Referenced in scrap 134.}
+\item \hspace{-\leftmargin}$\langle$Begin the scrap environment {\footnotesize 38}$\rangle$ {\footnotesize Referenced in scraps 36 and~37.}
+\item \hspace{-\leftmargin}$\langle$Build failure functions {\footnotesize 128}$\rangle$ {\footnotesize Referenced in scrap 125.}
+\item \hspace{-\leftmargin}$\langle$Build macro definition {\footnotesize 28}$\rangle$ {\footnotesize Referenced in scrap 26.}
+\item \hspace{-\leftmargin}$\langle$Build output file definition {\footnotesize 27}$\rangle$ {\footnotesize Referenced in scrap 26.}
+\item \hspace{-\leftmargin}$\langle$Build {\tt source\_name} and {\tt tex\_name} {\footnotesize 21}$\rangle$ {\footnotesize Referenced in scrap 20.}
+\item \hspace{-\leftmargin}$\langle$Check at-sequence for end-of-scrap {\footnotesize 47}$\rangle$ {\footnotesize Referenced in scrap 45.}
+\item \hspace{-\leftmargin}$\langle$Check for ambiguous prefix {\footnotesize 107}$\rangle$ {\footnotesize Referenced in scrap 106.}
+\item \hspace{-\leftmargin}$\langle$Check for end of scrap name and return {\footnotesize 92}$\rangle$ {\footnotesize Referenced in scrap 91.}
+\item \hspace{-\leftmargin}$\langle$Check for macro invocation in scrap {\footnotesize 98}$\rangle$ {\footnotesize Referenced in scrap 94.}
+\item \hspace{-\leftmargin}$\langle$Check for terminating at-sequence and return name {\footnotesize 115}$\rangle$ {\footnotesize Referenced in scrap 114.}
+\item \hspace{-\leftmargin}$\langle$Cleanup and install name {\footnotesize 116}$\rangle$ {\footnotesize Referenced in scraps 115, 117 and~119.}
+\item \hspace{-\leftmargin}$\langle$Collect include-file name {\footnotesize 71}$\rangle$ {\footnotesize Referenced in scrap 70.}
+\item \hspace{-\leftmargin}$\langle$Collect user-specified index entries {\footnotesize 86}$\rangle$ {\footnotesize Referenced in scrap 85.}
+\item \hspace{-\leftmargin}$\langle$Compare the temp file and the old file {\footnotesize 63}$\rangle$ {\footnotesize Referenced in scrap 62.}
+\item \hspace{-\leftmargin}$\langle$Copy macro into {\tt file} {\footnotesize 99}$\rangle$ {\footnotesize Referenced in scrap 98.}
+\item \hspace{-\leftmargin}$\langle$Copy {\tt defs->scrap} to {\tt file} {\footnotesize 94}$\rangle$ {\footnotesize Referenced in scrap 93.}
+\item \hspace{-\leftmargin}$\langle$Copy {\tt source\_file} into {\tt tex\_file} {\footnotesize 34}$\rangle$ {\footnotesize Referenced in scrap 33.}
+\item \hspace{-\leftmargin}$\langle$Create new name entry {\footnotesize 111}$\rangle$ {\footnotesize Referenced in scraps 106 and~110.}
+\item \hspace{-\leftmargin}$\langle$Create new scrap, managed by {\tt writer} {\footnotesize 83}$\rangle$ {\footnotesize Referenced in scrap 82.}
+\item \hspace{-\leftmargin}$\langle$Expand tab into spaces {\footnotesize 46}$\rangle$ {\footnotesize Referenced in scraps 45 and~97.}
+\item \hspace{-\leftmargin}$\langle$Extend goto graph with {\tt tree->spelling} {\footnotesize 127}$\rangle$ {\footnotesize Referenced in scrap 126.}
+\item \hspace{-\leftmargin}$\langle$Fill in the middle of the scrap environment {\footnotesize 39}$\rangle$ {\footnotesize Referenced in scraps 36 and~37.}
+\item \hspace{-\leftmargin}$\langle$Find a new chunk of memory {\footnotesize 134}$\rangle$ {\footnotesize Referenced in scrap 133.}
+\item \hspace{-\leftmargin}$\langle$Finish the scrap environment {\footnotesize 40}$\rangle$ {\footnotesize Referenced in scraps 36 and~37.}
+\item \hspace{-\leftmargin}$\langle$Format a user index entry {\footnotesize 59}$\rangle$ {\footnotesize Referenced in scrap 58.}
+\item \hspace{-\leftmargin}$\langle$Format an index entry {\footnotesize 53}$\rangle$ {\footnotesize Referenced in scrap 52.}
+\item \hspace{-\leftmargin}$\langle$Format macro name {\footnotesize 49}$\rangle$ {\footnotesize Referenced in scrap 47.}
+\item \hspace{-\leftmargin}$\langle$Function prototypes {\footnotesize 23, 31, 60, 64, 77, 103, 130}$\rangle$ {\footnotesize Referenced in scrap 1.}
+\item \hspace{-\leftmargin}$\langle$Global variables {\footnotesize 13, 15, 65, 102}$\rangle$ {\footnotesize Referenced in scrap 1.}
+\item \hspace{-\leftmargin}$\langle$Handle an ``at'' character {\footnotesize 69}$\rangle$ {\footnotesize Referenced in scrap 68.}
+\item \hspace{-\leftmargin}$\langle$Handle at-sign during scrap accumulation {\footnotesize 85}$\rangle$ {\footnotesize Referenced in scrap 84.}
+\item \hspace{-\leftmargin}$\langle$Handle macro invocation in scrap {\footnotesize 87}$\rangle$ {\footnotesize Referenced in scrap 85.}
+\item \hspace{-\leftmargin}$\langle$Handle optional per-file flags {\footnotesize 113}$\rangle$ {\footnotesize Referenced in scrap 112.}
+\item \hspace{-\leftmargin}$\langle$Handle tab characters on output {\footnotesize 97}$\rangle$ {\footnotesize Referenced in scrap 94.}
+\item \hspace{-\leftmargin}$\langle$Handle the file name in {\tt argv[arg]} {\footnotesize 20}$\rangle$ {\footnotesize Referenced in scrap 19.}
+\item \hspace{-\leftmargin}$\langle$Handle {\tt EOF} {\footnotesize 72}$\rangle$ {\footnotesize Referenced in scrap 68.}
+\item \hspace{-\leftmargin}$\langle$Include files {\footnotesize 2}$\rangle$ {\footnotesize Referenced in scraps 1 and~11.}
+\item \hspace{-\leftmargin}$\langle$Insert appropriate indentation {\footnotesize 96}$\rangle$ {\footnotesize Referenced in scraps 94 and~95.}
+\item \hspace{-\leftmargin}$\langle$Insert debugging information if required {\footnotesize 95}$\rangle$ {\footnotesize Referenced in scraps 94 and~98.}
+\item \hspace{-\leftmargin}$\langle$Interpret at-sequence {\footnotesize 35}$\rangle$ {\footnotesize Referenced in scrap 34.}
+\item \hspace{-\leftmargin}$\langle$Interpret command-line arguments {\footnotesize 14, 16, 17}$\rangle$ {\footnotesize Referenced in scrap 12.}
+\item \hspace{-\leftmargin}$\langle$Interpret the argument string {\tt s} {\footnotesize 18}$\rangle$ {\footnotesize Referenced in scrap 17.}
+\item \hspace{-\leftmargin}$\langle$Look for end of scrap name and return {\footnotesize 119}$\rangle$ {\footnotesize Referenced in scrap 118.}
+\item \hspace{-\leftmargin}$\langle$Open an include file {\footnotesize 70}$\rangle$ {\footnotesize Referenced in scrap 69.}
+\item \hspace{-\leftmargin}$\langle$Process a file {\footnotesize 22}$\rangle$ {\footnotesize Referenced in scrap 20.}
+\item \hspace{-\leftmargin}$\langle$Process the remaining arguments (file names) {\footnotesize 19}$\rangle$ {\footnotesize Referenced in scrap 12.}
+\item \hspace{-\leftmargin}$\langle$Reverse cross-reference lists {\footnotesize 30}$\rangle$ {\footnotesize Referenced in scrap 24.}
+\item \hspace{-\leftmargin}$\langle$Save macro name {\footnotesize 88}$\rangle$ {\footnotesize Referenced in scrap 87.}
+\item \hspace{-\leftmargin}$\langle$Scan at-sequence {\footnotesize 26}$\rangle$ {\footnotesize Referenced in scrap 25.}
+\item \hspace{-\leftmargin}$\langle$Scan the source file, looking for at-sequences {\footnotesize 25}$\rangle$ {\footnotesize Referenced in scrap 24.}
+\item \hspace{-\leftmargin}$\langle$Search scraps {\footnotesize 129}$\rangle$ {\footnotesize Referenced in scrap 125.}
+\item \hspace{-\leftmargin}$\langle$Shared declarations {\footnotesize 1}$\rangle$ {\footnotesize Referenced in scraps 4, 5, 6, 7, 8, 9 and~10.}
+\item \hspace{-\leftmargin}$\langle$Skip over index entries {\footnotesize 48}$\rangle$ {\footnotesize Referenced in scrap 47.}
+\item \hspace{-\leftmargin}$\langle$Skip until scrap begins, then return name {\footnotesize 117}$\rangle$ {\footnotesize Referenced in scrap 114.}
+\item \hspace{-\leftmargin}$\langle$Type declarations {\footnotesize 3, 100, 101}$\rangle$ {\footnotesize Referenced in scrap 1.}
+\item \hspace{-\leftmargin}$\langle$Write defining scrap numbers {\footnotesize 55}$\rangle$ {\footnotesize Referenced in scrap 53.}
+\item \hspace{-\leftmargin}$\langle$Write file defs {\footnotesize 41}$\rangle$ {\footnotesize Referenced in scrap 36.}
+\item \hspace{-\leftmargin}$\langle$Write file's defining scrap numbers {\footnotesize 54}$\rangle$ {\footnotesize Referenced in scrap 53.}
+\item \hspace{-\leftmargin}$\langle$Write index of file names {\footnotesize 50}$\rangle$ {\footnotesize Referenced in scrap 35.}
+\item \hspace{-\leftmargin}$\langle$Write index of macro names {\footnotesize 51}$\rangle$ {\footnotesize Referenced in scrap 35.}
+\item \hspace{-\leftmargin}$\langle$Write index of user-specified names {\footnotesize 57}$\rangle$ {\footnotesize Referenced in scrap 35.}
+\item \hspace{-\leftmargin}$\langle$Write macro definition {\footnotesize 37}$\rangle$ {\footnotesize Referenced in scrap 35.}
+\item \hspace{-\leftmargin}$\langle$Write macro defs {\footnotesize 42}$\rangle$ {\footnotesize Referenced in scrap 37.}
+\item \hspace{-\leftmargin}$\langle$Write macro refs {\footnotesize 43}$\rangle$ {\footnotesize Referenced in scrap 37.}
+\item \hspace{-\leftmargin}$\langle$Write out {\tt files->spelling} {\footnotesize 62}$\rangle$ {\footnotesize Referenced in scrap 61.}
+\item \hspace{-\leftmargin}$\langle$Write output file definition {\footnotesize 36}$\rangle$ {\footnotesize Referenced in scrap 35.}
+\item \hspace{-\leftmargin}$\langle$Write referencing scrap numbers {\footnotesize 56}$\rangle$ {\footnotesize Referenced in scrap 53.}
+\end{list}
+
+\section{Identifiers}
+
+Knuth prints his index of indentifiers in a two-column format.
+I could force this automatically by emitting the \verb|\twocolumn|
+command; but this has the side effect of forcing a new page.
+Therefore, it seems better to leave it this up to the user.
+
+
+\begin{list}{}{\setlength{\itemsep}{-\parsep}}
+\item \hspace{-\leftmargin}\verb@arena@: 22, 29, 78, 80, 83, 86, 89, 105, 111, 125, 127, 128, 129, 130, \underline{132}, 133, 134, 135, 136.
+\item \hspace{-\leftmargin}\verb@arena_free@: 22, 130, \underline{136}.
+\item \hspace{-\leftmargin}\verb@arena_getmem@: 29, 78, 80, 83, 86, 89, 105, 111, 125, 127, 128, 129, 130, \underline{133}.
+\item \hspace{-\leftmargin}\verb@build_gotos@: 125, \underline{126}.
+\item \hspace{-\leftmargin}\verb@Chunk@: \underline{131}, 132, 134, 135.
+\item \hspace{-\leftmargin}\verb@collect_file_name@: 27, 36, 103, \underline{112}.
+\item \hspace{-\leftmargin}\verb@collect_macro_name@: 28, 37, 103, \underline{114}.
+\item \hspace{-\leftmargin}\verb@collect_scrap@: 27, 28, 49, 77, \underline{82}, 87, 103, 118.
+\item \hspace{-\leftmargin}\verb@collect_scrap_name@: 49, 87, 103, \underline{118}.
+\item \hspace{-\leftmargin}\verb@command_name@: \underline{15}, 16, 18, 19, 26, 33, 43, 49, 62, 69, 70, 71, 73, 84, 85, 86, 92, 99, 107, 112, 113, 114, 115, 116, 117, 118, 119.
+\item \hspace{-\leftmargin}\verb@compare@: 13, 14, 18, 62, \underline{104}, 106, 108.
+\item \hspace{-\leftmargin}\verb@compare_flag@: \underline{13}, 14, 18, 62.
+\item \hspace{-\leftmargin}\verb@copy_scrap@: 32, 39, \underline{45}.
+\item \hspace{-\leftmargin}\verb@double_at@: \underline{66}, 69, 73.
+\item \hspace{-\leftmargin}\verb@EQUAL@: \underline{104}, 106, 108.
+\item \hspace{-\leftmargin}\verb@exit@: \underline{2}, 12, 19, 62, 69, 70, 71, 73, 84, 85, 86, 92, 99, 112, 114, 115, 116, 117, 118, 119.
+\item \hspace{-\leftmargin}\verb@EXTENSION@: \underline{104}, 106, 108.
+\item \hspace{-\leftmargin}\verb@FALSE@: \underline{3}, 13, 18, 35, 51, 69, 73, 99, 108, 111, 113.
+\item \hspace{-\leftmargin}\verb@fclose@: \underline{2}, 33, 62, 63, 72.
+\item \hspace{-\leftmargin}\verb@FILE@: \underline{2}, 33, 44, 45, 52, 58, 62, 63, 66, 67, 93.
+\item \hspace{-\leftmargin}\verb@file_names@: 22, 24, 30, 50, \underline{102}, 112.
+\item \hspace{-\leftmargin}\verb@first@: \underline{132}, 136.
+\item \hspace{-\leftmargin}\verb@fopen@: \underline{2}, 33, 62, 63, 70, 73.
+\item \hspace{-\leftmargin}\verb@format_entry@: 32, 50, 51, \underline{52}.
+\item \hspace{-\leftmargin}\verb@format_user_entry@: 32, 57, \underline{58}.
+\item \hspace{-\leftmargin}\verb@fprintf@: \underline{2}, 18, 19, 26, 33, 36, 37, 43, 44, 49, 53, 54, 55, 56, 59, 62, 69, 70, 71, 73, 84, 85, 86, 92, 95, 99, 107, 112, 113, 114, 115, 116, 117, 118, 119.
+\item \hspace{-\leftmargin}\verb@fputs@: \underline{2}, 38, 39, 40, 41, 42, 43, 45, 47, 49, 50, 51, 53, 54, 55, 56, 57, 59.
+\item \hspace{-\leftmargin}\verb@getc@: \underline{2}, 63, 68, 69, 70, 71, 72, 73.
+\item \hspace{-\leftmargin}\verb@goto_lookup@: \underline{124}, 127, 128, 129.
+\item \hspace{-\leftmargin}\verb@Goto_Node@: \underline{122}, 123, 124, 125, 127, 128, 129.
+\item \hspace{-\leftmargin}\verb@GREATER@: \underline{104}, 106, 108.
+\item \hspace{-\leftmargin}\verb@include_depth@: \underline{66}, 70, 72, 73.
+\item \hspace{-\leftmargin}\verb@init_scraps@: 24, 77, \underline{78}.
+\item \hspace{-\leftmargin}\verb@isgraph@: \underline{2}, 71, 112, 118.
+\item \hspace{-\leftmargin}\verb@islower@: \underline{2}, 109.
+\item \hspace{-\leftmargin}\verb@isspace@: \underline{2}, 40, 86, 112, 113, 114, 117.
+\item \hspace{-\leftmargin}\verb@isupper@: \underline{2}, 109.
+\item \hspace{-\leftmargin}\verb@LESS@: \underline{104}, 106, 108.
+\item \hspace{-\leftmargin}\verb@macro_names@: 24, 30, 51, 92, \underline{102}, 116.
+\item \hspace{-\leftmargin}\verb@main@: \underline{12}.
+\item \hspace{-\leftmargin}\verb@Manager@: \underline{79}, 80, 81, 82, 90, 91, 94, 129.
+\item \hspace{-\leftmargin}\verb@max_depth@: \underline{123}, 125, 127, 128.
+\item \hspace{-\leftmargin}\verb@Move_Node@: \underline{122}, 124, 127, 128.
+\item \hspace{-\leftmargin}\verb@Name@: 27, 28, 36, 37, 49, 52, 58, 61, 86, 87, 91, 99, \underline{101}, 102, 103, 106, 108, 110, 111, 112, 114, 118, 120, 122, 126, 127, 128, 129.
+\item \hspace{-\leftmargin}\verb@name_add@: 86, 103, \underline{110}, 112.
+\item \hspace{-\leftmargin}\verb@Name_Node@: \underline{122}, 127, 128, 129.
+\item \hspace{-\leftmargin}\verb@output_flag@: \underline{13}, 14, 18, 22.
+\item \hspace{-\leftmargin}\verb@pass1@: 22, 23, \underline{24}, 47.
+\item \hspace{-\leftmargin}\verb@pop@: \underline{90}, 91, 92, 94, 98, 99, 129.
+\item \hspace{-\leftmargin}\verb@pop_scrap_name@: \underline{91}, 99.
+\item \hspace{-\leftmargin}\verb@PREFIX@: \underline{104}, 106, 108.
+\item \hspace{-\leftmargin}\verb@prefix_add@: 92, 103, \underline{106}, 116.
+\item \hspace{-\leftmargin}\verb@print_scrap_numbers@: 32, 41, 42, 43, \underline{44}, 54, 56.
+\item \hspace{-\leftmargin}\verb@push@: \underline{80}, 81, 84, 85, 88.
+\item \hspace{-\leftmargin}\verb@pushs@: \underline{81}, 85, 88.
+\item \hspace{-\leftmargin}\verb@putc@: \underline{2}, 34, 35, 45, 46, 47, 49, 53, 54, 55, 56, 94, 96, 97, 98.
+\item \hspace{-\leftmargin}\verb@reverse@: 30, 103, 120, \underline{121}.
+\item \hspace{-\leftmargin}\verb@reverse_lists@: 30, 103, \underline{120}.
+\item \hspace{-\leftmargin}\verb@robs_strcmp@: \underline{109}, 110.
+\item \hspace{-\leftmargin}\verb@root@: 106, 110, 111, \underline{123}, 125, 127, 128, 129.
+\item \hspace{-\leftmargin}\verb@save_string@: 70, 83, 103, \underline{105}, 106, 111.
+\item \hspace{-\leftmargin}\verb@SCRAP@: \underline{76}, 78, 83.
+\item \hspace{-\leftmargin}\verb@ScrapEntry@: \underline{75}, 76, 78, 83.
+\item \hspace{-\leftmargin}\verb@scraps@: 24, 34, 36, 37, 41, 42, 43, 44, 62, \underline{76}, 77, 78, 82, 83, 84, 85, 86, 89, 93, 99, 125, 129.
+\item \hspace{-\leftmargin}\verb@scrap_array@: \underline{76}, 83, 84, 94, 95, 129.
+\item \hspace{-\leftmargin}\verb@Scrap_Node@: 29, 44, 54, 55, 56, 59, 86, 89, 93, \underline{100}, 101, 120, 121, 129.
+\item \hspace{-\leftmargin}\verb@search@: 24, \underline{125}.
+\item \hspace{-\leftmargin}\verb@Slab@: \underline{74}, 75, 79, 80, 83, 90.
+\item \hspace{-\leftmargin}\verb@SLAB_SIZE@: \underline{74}, 80, 90.
+\item \hspace{-\leftmargin}\verb@source_file@: \underline{66}, 68, 69, 70, 71, 72, 73.
+\item \hspace{-\leftmargin}\verb@source_get@: 25, 26, 34, 35, 40, 45, 47, 48, 50, 51, 57, 64, \underline{68}, 70, 72, 84, 85, 86, 87, 112, 113, 114, 115, 117, 118, 119.
+\item \hspace{-\leftmargin}\verb@source_line@: 26, \underline{65}, 68, 69, 70, 71, 72, 73, 83, 85, 86, 107, 112, 113, 114, 116, 118, 119.
+\item \hspace{-\leftmargin}\verb@source_name@: 20, 21, 22, 26, \underline{65}, 69, 70, 71, 72, 73, 83, 85, 86, 107, 112, 113, 114, 115, 116, 117, 118, 119.
+\item \hspace{-\leftmargin}\verb@source_open@: 24, 33, 64, \underline{73}.
+\item \hspace{-\leftmargin}\verb@source_peek@: \underline{66}, 68, 69, 70, 72, 73.
+\item \hspace{-\leftmargin}\verb@stack@: \underline{67}, 70, 72.
+\item \hspace{-\leftmargin}\verb@stderr@: \underline{2}, 18, 19, 26, 33, 43, 49, 62, 69, 70, 71, 73, 84, 85, 86, 92, 99, 107, 112, 113, 114, 115, 116, 117, 118, 119.
+\item \hspace{-\leftmargin}\verb@strlen@: \underline{2}, 88, 104, 105.
+\item \hspace{-\leftmargin}\verb@tex_flag@: \underline{13}, 14, 18, 22, 24, 99.
+\item \hspace{-\leftmargin}\verb@toupper@: \underline{2}, 109.
+\item \hspace{-\leftmargin}\verb@TRUE@: \underline{3}, 14, 35, 50, 69, 91, 99, 108, 111, 113.
+\item \hspace{-\leftmargin}\verb@user_names@: 24, 30, 57, 86, \underline{102}, 125.
+\item \hspace{-\leftmargin}\verb@write_files@: 22, 60, \underline{61}.
+\item \hspace{-\leftmargin}\verb@write_scraps@: 62, 77, \underline{93}, 99.
+\item \hspace{-\leftmargin}\verb@write_tex@: 22, 31, \underline{33}.
+\end{list}
+
+\bibliographystyle{plain}
+\bibliography{literate}
+
+\end{document}