summaryrefslogtreecommitdiff
path: root/web/latexspider
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/latexspider
Initial commit
Diffstat (limited to 'web/latexspider')
-rw-r--r--web/latexspider/awkmake5
-rw-r--r--web/latexspider/cmake5
-rw-r--r--web/latexspider/cspider.dif17
-rw-r--r--web/latexspider/docstrip.cmd11
-rw-r--r--web/latexspider/latexweb.tex80
-rw-r--r--web/latexspider/readme69
-rw-r--r--web/latexspider/spider.ltx107
-rw-r--r--web/latexspider/tangle.ltx78
-rw-r--r--web/latexspider/tie.web1276
-rw-r--r--web/latexspider/tiedoc.tex138
-rw-r--r--web/latexspider/weave.ltx700
-rw-r--r--web/latexspider/web.doc955
-rw-r--r--web/latexspider/web.sty277
-rw-r--r--web/latexspider/web.tex13
-rw-r--r--web/latexspider/webmakefile172
15 files changed, 3903 insertions, 0 deletions
diff --git a/web/latexspider/awkmake b/web/latexspider/awkmake
new file mode 100644
index 0000000000..02cc270328
--- /dev/null
+++ b/web/latexspider/awkmake
@@ -0,0 +1,5 @@
+/bin/make -f ../master/WebMakefile CPUTYPE=`cputype`\
+ THETANGLE=awktangle THEWEAVE=awkweave SPIDER=awk.spider \
+SPIDERCHANGEFILE=../master/spider.ltx WEAVECHANGEFILE=../master/weave.ltx \
+TANGLECHANGEFILE=../master/tangle.ltx \
+CFLAGS='-O1 -DC_FLOATING_POINT -DLaTeX' LaTeX=1 $*
diff --git a/web/latexspider/cmake b/web/latexspider/cmake
new file mode 100644
index 0000000000..d2853dbaa1
--- /dev/null
+++ b/web/latexspider/cmake
@@ -0,0 +1,5 @@
+#!/bin/csh -f
+/bin/make -f ../master/WebMakefile CPUTYPE=`cputype`\
+CFLAGS="-O1 -DC_FLOATING_POINT -DLaTeX" LaTeX=1 THETANGLE=ceetangle \
+THEWEAVE=ceeweave SPIDER=c.spider TANGLECHANGEFILE=../master/tangle.ltx \
+WEAVECHANGEFILE=../master/weave.ltx SPIDERCHANGEFILE=../master/spider.ltx $*
diff --git a/web/latexspider/cspider.dif b/web/latexspider/cspider.dif
new file mode 100644
index 0000000000..1ed829d428
--- /dev/null
+++ b/web/latexspider/cspider.dif
@@ -0,0 +1,17 @@
+*** c/c.spider Mon Feb 19 03:47:06 1990
+--- /home/users0/fx/ltxspiderweb/c/c.spider Wed Mar 13 11:58:35 1991
+***************
+*** 326,330 ****
+
+ # control sequence \8 puts things on the left margin
+! <force-"\\8"> sharp <"{\\let\\\\=\\bf"-space> (simp|if|else) <"}"-indent-"{}"-space> --> preproc
+ preproc backslash <force-"\\8\\hskip1em"-space> newline --> preproc
+ preproc <force-outdent> newline --> ignore_scrap
+--- 326,332 ----
+
+ # control sequence \8 puts things on the left margin
+! #<force-"\\8"> sharp <"{\\let\\\\=\\bf"-space> (simp|if|else) <"}"-indent-"{}"-space> --> preproc
+! # changed to work with LaTeX as well:
+! <force-"\\8"> sharp <"{\\let\\idfont=\\reservedfont"-space> (simp|if|else) <"}"-indent-"{}"-space> --> preproc
+ preproc backslash <force-"\\8\\hskip1em"-space> newline --> preproc
+ preproc <force-outdent> newline --> ignore_scrap
diff --git a/web/latexspider/docstrip.cmd b/web/latexspider/docstrip.cmd
new file mode 100644
index 0000000000..6997d1251a
--- /dev/null
+++ b/web/latexspider/docstrip.cmd
@@ -0,0 +1,11 @@
+\preamble
+You are not allowed to distribute this file without the corresponding
+`.doc' version containing the documentation.
+
+\endpreamble
+
+\postamble
+\string\endinput
+\endpostamble
+
+%\generatefile{web.sty}{f}{\from{web.doc}}
diff --git a/web/latexspider/latexweb.tex b/web/latexspider/latexweb.tex
new file mode 100644
index 0000000000..325ba5dae0
--- /dev/null
+++ b/web/latexspider/latexweb.tex
@@ -0,0 +1,80 @@
+\documentstyle[ltugboat]{article}
+
+\let\tensl=\sl
+\title{\WEB{} Adapted to \LaTeX{} --- a First Attempt}
+\author{David Love}
+\netaddress{d.love@daresbury.ac.uk}
+\begin{document}
+\maketitle
+\noindent
+Following Knuth's original Pascal/TeX{} \WEB{} system a number of
+\WEB-like systems have been developed. Mostly these use the same
+plain \TeX{} formatting system and differ in the languages supported
+(although Thimbleby's CWEB system uses Troff and there are non-\WEB{}
+literate programming systems like Scheme\TeX{} and {\tt doc.sty} that
+use \LaTeX)\footnote{For a \WEB{} bibliography, see Lisa M. C. Smith
+and Mansur Samadzadeh, {\sl SIGPLAN Notices\/} {\bf 26} (1991) 14}\@.
+There are two advantages to using \LaTeX{} rather than plain \TeX{}
+for formatting:
+\begin{itemize}
+\item greater accessibility for many (familiarity and ease of use)
+which may encourage more people to use it;
+\item the availability of extra intrinsic \LaTeX{} facilities and
+especially style options. These might, for instance, support setting
+your formal specification material as well as the code refined from
+it, and in non-CM fonts.
+\end{itemize}
+This note describes a first attempt at integrating \LaTeX{} with
+\WEB\ (actually Ramsey's Spider system for
+`language-independent' \WEB s\footnote{Sometimes Spider doesn't do the
+whole job for you: non-Algol-like languages may need the lexing
+routines hacking. This gives the complication of
+amalgamating the basic \WEAVE{} change file for \LaTeX{} formatting
+with changes for the lexical routines etc.}).
+
+I have made minimal changes necessary for Spidery \WEB s to work with
+\LaTeX\@. These take the form of change files for the base {\tt
+weave.web}, {\tt tangle.web} and {\tt spider.web} (which generates the
+language-dependent parts), conversion of the {\tt webkernel.tex} macro
+file to a \LaTeX{} sub-style and trivial updates to the make files. A
+trivial change to the {\tt c.spider} file that describes the
+prettyprinting grammar for C was also necessary. The result of
+merging the change files with the original webs would be a {\tt
+weave.web} that can be built for use with either plain \TeX\ or
+\LaTeX\ using a makefile flag and a {\tt spider.web} that produces a
+{\tt spider.awk} with a run-time switch to determine the formatter.
+(\WEAVE\ cannot change the formatter assumed at run time, although it
+would not be difficult to make it do so.) \WEB\ files can be woven
+with either a plain or \LaTeX\ \WEAVE\ if they avoid using
+incompatible macros or define them appropriately in limbo
+according to whether the \LaTeX\ macros are present.
+
+The changes to {\tt spider.web} are minor; changes to {\tt weave.web}
+and the macros are more extensive. Many of the original \WEB{} macros
+clash with \LaTeX{} names or conventions and have been changed
+appropriately, but only where necessary. The formatting style is
+essentially unchanged apart from the use of the \LaTeX\ page headers
+and contents list. {\tt web.sty} is documented with {\tt doc.sty}
+since it is a pity not to use literate techniques to build literate
+programming tools---the bulk of the work! There are some remaining
+infelicities, such as floats being disrupted by the way the sectioning
+code avoids page breaks and a lot of messiness due to the assumptions
+of existing Spider descriptions.
+
+This hack could be developed in other directions, for instance:
+\begin{itemize}
+\item proper parameterisation of the formatting commands, perhaps
+modelled after {\tt makeindex};
+\item adapting the formatting macros more to the \LaTeX{} style;
+\item inclusion of a proper multi-level sectioning scheme. I think
+the extra structure would be helpful in large webs, but implementing
+it would require considerable attention to the guts of \TANGLE{} and
+\WEAVE\@. (It affects \TANGLE{} through the comments it writes in the
+code);
+\item replacing the index processing with {\tt makeindex}.
+\end{itemize}
+
+The changes should be available from the Aston archive as {\tt
+[.web.spiderweb]latexmods.shar}.
+
+\makesignature
diff --git a/web/latexspider/readme b/web/latexspider/readme
new file mode 100644
index 0000000000..c5fcd13e33
--- /dev/null
+++ b/web/latexspider/readme
@@ -0,0 +1,69 @@
+This is a collection of files to enable you to use Spidery Web with
+LaTeX as the formatter rather than plain TeX. It is copyright D.Love,
+SERC Daresbury Laboratory 1991 under the same conditions as the Spider
+distribution.
+
+--------------------------------------------------------------------
+#include <disclaimer.h>
+Snail mail: | JANET: d.love@uk.ac.dl
+Dr. David Love, | modern BIT/INTERNET: d.love@dl.ac.uk
+SERC Daresbury Laboratory, | old UUCP: ...!ukc!daresbury!d.love
+Warrington WA4 4AD, | alternative BITNET: d.love%dl@ukacrl
+UK | alternative ARPA: d.love%dl@nsfnet-relay.ac.uk
+ 'Phone: (+44/0)925 603573, Telex: ...925 629609, FAX: ...925 603173
+
+
+Here is a contents list. You will need to copy the files to the
+correct sub-directories of the spider source (once you are sure you
+want to) and invoke, for instance, `make weave' in the C directory to
+make a LaTeX version of weave. See web.doc for definitive information
+on the TeX aspect of things.
+
+* README This file;
+
+* latexweb.tex A short LaTeX document describing this stuff,
+ intended for submission to TUGboat;
+
+* weave.ltx A change file for $MASTER/weave.web which
+ inserts #defines to allow it to be compiled
+ for LaTeX-compatible output;
+
+* tangle.ltx Trivial change file for $MASTER/tangle.web to
+ allow woven output from it to be printed with
+ either LaTeX or plain;
+
+* spider.ltx Change file for $MASTER/spider.web to allow it
+ to produce output for a plain or LaTeX weave;
+
+* WebMakefile Changed version of $MASTER/WebMakefile
+ to cope with the change files above and the
+ different possible versions (also with my
+ filenames wired in);
+
+* web.doc Self-documenting LaTeX sub-style for use
+ instead of webkernel.tex. Probably needs
+ Mittelbach's newdoc.sty, v1.6d or later to
+ produce documentation -- instructions at the
+ front of it;
+
+* web.sty web.doc with comments stripped;
+
+* web.tex Driver file to print web.doc;
+
+* docstrip.cmd Used by the .doc->.sty process;
+
+* cmake Changed version of $SPIDER/c/make to produce
+ LaTeX ceeweave;
+
+* awkmake Changed version of $SPIDER/awk/make to produce
+ LaTeX awkweave;
+
+* cspider.dif Trivial diff from $SPIDER/c/c.spider to allow
+ it to work with LaTeX or plain;
+
+* tie.web Translation of the TIE processor to spidery
+ C-web. This allows you to merge change files
+ with the original or with other change files,
+ which may be useful for combining the LaTeX
+ changes with any you already have;
+
diff --git a/web/latexspider/spider.ltx b/web/latexspider/spider.ltx
new file mode 100644
index 0000000000..6e26a5304e
--- /dev/null
+++ b/web/latexspider/spider.ltx
@@ -0,0 +1,107 @@
+% this is spider.ch $Header: /home/users0/fx/ltxspiderweb/master/spider.ltx,v 1.3 91/03/22 11:19:54 fx Exp $
+% for a LaTeX version of spider
+% d.love@daresbury.ac.uk
+
+l 5 (don't want batchmode for debugging; only print changes; for
+ LaTeX: want \documentstyle and fix use of \. and \title)
+#x
+\message{OK, entering \string\batchmode...}
+\batchmode
+#y
+\ifx\enddocument\undefined \else % check for LaTeX
+ \documentstyle[web]{article}
+ \let\maybe\iffalse
+ \let\.=\str
+ \def\LaTeX{{\rm L\kern-.36em\raise.3ex\hbox{\sc a}\kern-.15em
+ T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}
+\fi
+#z
+
+l 13 (change title page stuff)
+#x
+\def\title{SPIDER}
+
+\def\topofcontents{\null\vfill
+ \titlefalse % include headline on the contents page
+ \def\rheader{\hfil}
+ \centerline{\titlefont The {\ttitlefont SPIDER} processor}
+ \vfill}
+#y
+\ifx\enddocument\undefined % check for LaTeX
+\def\title{SPIDER}
+
+\def\topofcontents{\null\vfill
+ \titlefalse % include headline on the contents page
+ \def\rheader{\hfil}
+ \centerline{\titlefont The {\ttitlefont SPIDER} processor}
+ \vfill}
+\else
+ \title{The {\tt SPIDER} processor} \date{}
+\fi
+#z
+
+l 39
+#x
+The unusual lexical requirements of FORTRAN are probably beyond it, at
+least until the lexical analysis is modernized.)
+#y
+The unusual lexical requirements of FORTRAN are probably beyond it, at
+least until the lexical analysis is modernized.)
+
+This version of Spider has been changed to be able to produce a
+\.{WEAVE} suitable for use with \LaTeX{} rather than plain \TeX{}.
+The changes are minor and can be found by looking up ``LaTeX'' in the
+index. You get the \LaTeX{} version by defining |LaTeX=1| or
+something (the variable |LaTeX| should be non-null) on
+the \.{awk} command line when you run Spider. The limbo part will sort
+itself out for \LaTeX{} or plain when you weave this file.
+#z
+
+l 188 (bug fix)
+#x
+#<Set init...#>=
+ scrapfile = "scraps.web"
+ print "@*Scrap code generated by {\tt SPIDER}." > scrapfile
+ ttokfile = "outtoks.web"
+ print "@*Token code generated by {\tt SPIDER}." > scrapfile
+#y
+#<Set init...#>=
+ scrapfile = "scraps.web"
+ print "@*Scrap code generated by {\\tt SPIDER}." > scrapfile
+ ttokfile = "outtoks.web"
+ print "@*Token code generated by {\\tt SPIDER}." > scrapfile
+#z
+
+l 211 (bug fix)
+#x
+ grammarfile = "grammar.web"
+ print "@*Grammar code generated by {\tt SPIDER}." > grammarfile
+#y
+ grammarfile = "grammar.web"
+ print "@*Grammar code generated by {\\tt SPIDER}." > grammarfile
+#z
+
+l 2108 (change for LaTeX)
+#x
+ printf "*out_ptr='x'; tex_printf(\"\\\\input %sweb.te\");\n", \
+ extension > wlang
+#y
+ if (LaTeX=="") { #^LaTeX#>
+ printf "*out_ptr='x'; tex_printf(\"\\\\input %sweb.te\");\n", \
+ extension > wlang
+ }else{
+ printf "*out_ptr='}'; tex_printf(\"\\\\def\\\\webmacs{%sweb.tex\");\n", \
+ extension > wlang
+ }
+#z
+
+l 2121 (change for LaTeX)
+#x
+#<Write the first line of the macro file#>=
+ macrofile = extension "web.tex"
+ print "\\input webkernel.tex" > macrofile
+#y
+#<Write the first line of the macro file#>=
+ macrofile = extension "web.tex"
+ if (LaTeX=="") print "\\input webkernel.tex" > macrofile #^LaTeX#>
+#z
diff --git a/web/latexspider/tangle.ltx b/web/latexspider/tangle.ltx
new file mode 100644
index 0000000000..f603f8769b
--- /dev/null
+++ b/web/latexspider/tangle.ltx
@@ -0,0 +1,78 @@
+this is tangle.latex-ch to fix tangle.web so that it can be woven with
+the LaTeX version of weave
+$Header: /home/users0/fx/ltxspiderweb/master/tangle.ltx,v 1.1 91/03/22 11:32:59 fx Exp $
+d.love@daresbury.ac.uk
+
+l 12 (fix for use with LaTeX or plain)
+@x
+% Here is TeX material that gets inserted after \input webmac
+
+\message{OK, entering \string\batchmode...}
+\batchmode
+
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps
+\def\cee{C}
+\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
+\def\v{\char'174} % vertical (|) in typewriter font
+\def\ceeref{{\it The C Reference Manual}}
+\mathchardef\RA="3221 % right arrow
+\mathchardef\BA="3224 % double arrow
+
+\def\title{Spidery TANGLE}
+\def\contentspagenumber{1} % should be odd
+\def\topofcontents{\null\vfill
+ \titlefalse % include headline on the contents page
+ \def\rheader{\hfil}
+ \centerline{\titlefont The {\ttitlefont Spidery TANGLE} processor}
+ \vfill
+}
+@y
+% Here is TeX material that gets inserted after \documentstyle
+
+% \message{OK, entering \string\batchmode...}
+% \batchmode
+
+\ifx\enddocument\undefined % LaTeX?
+\font\ninerm=cmr9 % no...
+\let\mc=\ninerm % medium caps (not actually used)
+\def\title{Spidery TANGLE}
+\def\contentspagenumber{1} % should be odd
+\def\topofcontents{\null\vfill
+ \titlefalse % include headline on the contents page
+ \def\rheader{\hfil}
+ \centerline{\titlefont The {\ttitlefont Spidery TANGLE} processor}
+ \vfill
+}
+\else % yes...
+\documentstyle[web]{article}
+\title{Spidery TANGLE}\date{}
+\let\.=\str
+\fi
+
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\def\cee{C}
+\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
+\def\v{\char'174} % vertical (|) in typewriter font
+\def\ceeref{{\it The C Reference Manual}}
+\mathchardef\RA="3221 % right arrow
+\mathchardef\BA="3224 % double arrow
+@z
+
+l 1296 (fix \item)
+@x
+\yskip \item{a)}Module names are not allowed in macros;
+in fact, the appearance of a module name terminates such macros and denotes
+the name of the current module.
+
+\item{b)}The symbols \.{@@d} and \.{@@f} and \.{@@u} are not allowed after
+module names, while they terminate macro definitions.
+@y
+\begin{itemize}
+ \item[a)]Module names are not allowed in macros;
+in fact, the appearance of a module name terminates such macros and denotes
+the name of the current module.
+\item[b)]The symbols \.{@@d} and \.{@@f} and \.{@@u} are not allowed after
+module names, while they terminate macro definitions.
+\end{itemize}
diff --git a/web/latexspider/tie.web b/web/latexspider/tie.web
new file mode 100644
index 0000000000..3739558e19
--- /dev/null
+++ b/web/latexspider/tie.web
@@ -0,0 +1,1276 @@
+% This is TIE.CWB as of 25 Oct 89
+%---------------------------------------------------------
+% (c) 1989 by THD/ITI. Put into the public domain.
+
+%
+% Version 1.7 was built alike TIE.WEB Version 1.6 (89-01-27)
+% but used a command line interface only
+% Version 2.0 was revised to include optional tab expansion (89-02-01)
+% Version 2.1 deleted WEB relicts. (-js) (89-10-25)
+%
+
+% Converted to spidery web Dave Love Feb 91 & bug fixed at line 990
+% and took out a couple of `@+' after `*' which break spidery weave
+
+% Here is TeX material that gets inserted after \input cwebmac
+
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\font\mc=cmr9
+\def\PASCAL{Pascal}
+\def\Cl{{\rm C}}
+\def\ASCII{{\mc ASCII}}
+
+\def\title{TIE}
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The {\ttitlefont TIE} processor}
+ \vskip 15pt
+ \centerline{(CWEB Version 2.1)}
+ \vfill}
+\def\botofcontents{
+\null\vfill
+\item{$\copyright$}1989
+ by Technische Hochschule Darmstadt,\hfill\break
+Fachbereich Informatik, Institut f\"ur Theoretische Informatik\hfill\break
+All rights reserved.\hfill\break
+This program is put into the public domain and may be used freely
+for any non commercial purposes.
+}
+
+
+
+
+
+@* Introduction.
+
+\noindent Whenever a programmer wants to change a given
+\.{WEB} or \.{CWEB} program (referred to as a \.{WEB} program throughout
+this program) because of system dependencies, he will
+create a new change file. In addition there may be a second
+change file to modify system independent modules of the
+program. But the \.{WEB} file cannot be tangled and weaved
+with more than one change file simultaneously. Therefore,
+we introduce the present program to merge a \.{WEB} file and
+several change files producing a new \.{WEB} file. Since
+the input files are tied together, the program is called
+\.{TIE}. Furthermore, the program can be used to merge
+several change files giving a new single change file. This
+method seems to be more important because it doesn't modify
+the original source file. The use of \.{TIE} can be
+expanded to other programming languages since this processor
+only knows about the structure of change files and does not
+interpret the master file at all.
+
+The program \.{TIE} has to read lines from several input
+files to bring them in some special ordering. For this
+purpose an algorithm is used which looks a little bit
+complicated. But the method used only needs one buffer line
+for each input file. Thus the storage requirement of
+\.{TIE} does not depend on the input data.
+
+The program is written in \Cl\ and uses only few features of a
+particular environment that may need to be changed in other
+installations.
+E.g.\ it will not use the |enum| type declarations.
+The changes needed may refer to the access of the command line
+if this can be not supported by any \Cl\ compiler.
+
+The ``banner line'' defined here should be changed whenever
+\.{TIE} is modified. This program is put into the public
+domain. Nevertheless the copyright notice must not be
+replaced or modified.
+
+@d banner="This is TIE, CWEB Version 2.1."
+@d copyright=
+ "Copyright (c) 1989 by THD/ITI. All rights reserved."
+
+
+@ The main outline of the program is given in the next section.
+This can be used more or less for any \Cl\ program.
+@c
+@<Global |#include|s@>
+@<Global constants@>
+@<Global types@>
+@<Global variables@>
+@<Error handling functions@>
+@<Internal functions@>
+@<The main function@>
+
+@ Here are some macros for common programming idioms.
+
+@d incr(a) = a+=1 /* increase a variable by unity */
+@d decr(a) = a-=1 /* decrease a variable by unity */
+@d loop = @+ while (1)@+ /* repeat over and over until a |break| happens */
+@d do_nothing = /* empty statement */
+@f loop repeat
+
+
+@ Furthermore we include the additional types |boolean| and |string|.
+
+@<Global types@>=
+#define @!false 0
+#define @!true 1
+typedef int @!boolean;
+typedef char* string;
+
+
+@ The following parameters should be sufficient for most
+applications of \.{TIE}.
+@^system dependencies@>
+
+@<Global constants@>=
+#define @!buf_size 512 /* maximum length of one input line */
+#define @!max_file_index 9
+/* we don't think that anyone needs more than 9 change files,
+ but \dots\ just change it */
+
+
+@ We introduce a history variable that allows us to set a
+return code if the operating system can use it.
+First we introduce the coded values for the history.
+This variable must be initialized.
+(We do this even if the value given may be the default for
+variables, just to document the need for the initial value.)
+@d spotless=0
+@d troublesome=1
+@d fatal=2
+
+@<Global variables@>=
+int @!history=spotless;
+
+
+
+@* The character set.
+
+\noindent One of the main goals in the design of \.{TIE} has
+been to make it readily portable between a wide variety of
+computers. Yet \.{TIE} by its very nature must use a
+greater variety of characters than most computer programs
+deal with, and character encoding is one of the areas in
+which existing machines differ most widely from each other.
+
+To resolve this problem, all input to \.{TIE} is converted to an
+internal seven-bit code that is essentially standard \ASCII{}, the
+``American Standard Code for Information Interchange.'' The conversion
+is done immediately when each character is read in. Conversely,
+characters are converted from \ASCII{} to the user's external
+representation just before they are output. But the algorithm is
+prepared for the usage of eight-bit data.
+
+\noindent Here is a table of the standard visible \ASCII{} codes:
+$$\def\:{\char\count255\global\advance\count255 by 1}
+\count255='40
+\vbox{
+\hbox{\hbox to 40pt{\it\hfill0\/\hfill}%
+\hbox to 40pt{\it\hfill1\/\hfill}%
+\hbox to 40pt{\it\hfill2\/\hfill}%
+\hbox to 40pt{\it\hfill3\/\hfill}%
+\hbox to 40pt{\it\hfill4\/\hfill}%
+\hbox to 40pt{\it\hfill5\/\hfill}%
+\hbox to 40pt{\it\hfill6\/\hfill}%
+\hbox to 40pt{\it\hfill7\/\hfill}}
+\vskip 4pt
+\hrule
+\def\^{\vrule height 10.5pt depth 4.5pt}
+\halign{\hbox to 0pt{\hskip -24pt\O{#0}\hfill}&\^
+\hbox to 40pt{\tt\hfill#\hfill\^}&
+&\hbox to 40pt{\tt\hfill#\hfill\^}\cr
+04&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+05&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+06&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+07&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+10&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+11&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+12&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+13&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+14&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+15&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+16&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+17&\:&\:&\:&\:&\:&\:&\:\cr}
+\hrule width 280pt}$$
+(Actually, of course, code @'040 is an invisible blank space.) Code @'136
+was once an upward arrow (\.{\char'13}), and code @'137 was
+once a left arrow (\.^^X), in olden times when the first draft
+of ASCII code was prepared; but \.{TIE} works with today's standard
+ASCII in which those codes represent circumflex and underline as shown.
+The maximum value used is also defined, it must be changed if an
+extended \ASCII{} is used.
+
+If the \Cl\ compiler is not able to process \&{unsigned char}'s, you
+should define |ASCII_Code| as \&{short}.
+@^system dependencies@>
+
+@<Global types@>=
+#define max_ASCII @`~'+1
+typedef unsigned char @!ASCII_Code;
+ /* eight-bit numbers, a subrange of the integers */
+
+
+@ \Cl\ was first implemented on a machine that uses the
+\ASCII{} representation for characters. But to make it readily
+available also for other machines (big brother is watching?)\
+we add a conversion that may be undone for most installations.
+\.{TIE} assumes that it is being used
+with a character set that contains at least the
+characters of standard \ASCII{} as listed above.
+
+In order to accommodate this difference, we shall use the
+name |text_char| to stand for the data type of the
+characters in the input and output files. We shall also
+assume that |text_char| consists of the elements
+|first_text_char| through |last_text_char|,
+inclusive. The following definitions should be adjusted if
+necessary.
+@^system dependencies@>
+
+@d text_char = @+ unsigned char /* the data type of characters in text files */
+@d first_text_char=0 /* ordinal number of the smallest element of |text_char|*/
+@d last_text_char=255 /* ordinal number of the largest element of |text_char|*/
+@f FILE int
+
+@<Global types@>=
+typedef FILE* @!text_file;
+
+
+@ The \.{TIE} processor converts between \ASCII{} code and
+the user's external character set by means of arrays |xord|
+and |xchr| that are analogous to \PASCAL's |ord| and |chr|
+functions.
+
+The mapping may be disabled by changing the following macro
+definitions to just a cast. If your \Cl\ compiler does not support
+\&{unsigned char}'s, you should incorporate a binary and with @"ff.
+@^system dependencies@>
+
+@d map_xchr(a)=xchr[a]
+ /* change this to |(text_char)(a)| on \ASCII{} machines */
+@d map_xord(a)=xord[a]
+ /* change this to |(ASCII_Code)(a)| on \ASCII{} machines */
+
+@<Global variables@>=
+ASCII_Code @!xord[last_text_char+1];
+ /* specifies conversion of input characters */
+text_char @!xchr[max_ASCII+1];
+ /* specifies conversion of output characters */
+
+
+@ If we assume that every system using \.{WEB} is able to
+read and write the visible characters of standard \ASCII{}
+(although not necessarily using the \ASCII{} codes to
+represent them), the following assignment statements
+initialize most of the |xchr| array properly, without
+needing any system-dependent changes. For example, the
+statement |xchr[@`A']='A'| that appears in the present
+\.{WEB} file might be encoded in, say, {\mc EBCDIC} code on
+the external medium on which it resides, but \.{CTANGLE} will
+convert from this external code to \ASCII{} and back again.
+Therefore the assignment statement |xchr[65]='A'| will
+appear in the corresponding \Cl\ file, and \Cl\ will
+compile this statement so that |xchr[65]| receives the
+character \.A in the external code. Note that it
+would be quite incorrect to say |xchr[@`A']=@`A'|, because
+|@`A'| is a constant of type |int| not \&{char}, and
+because we have |@`A'==65| regardless of the external
+character set.
+
+@<Set initial values@>=
+xchr[@` ']=' ';
+xchr[@`!']='!';
+xchr[@`"']='"';
+xchr[@`#']='#';@/
+xchr[@`$']='$';
+xchr[@`%']='%';
+xchr[@`&']='&';
+xchr[@`'']='\'';@/
+xchr[@`(']='(';
+xchr[@`)']=')';
+xchr[@`*']='*';
+xchr[@`+']='+';@/
+xchr[@`,']=',';
+xchr[@`-']='-';
+xchr[@`.']='.';
+xchr[@`/']='/';@/
+xchr[@`0']='0';
+xchr[@`1']='1';
+xchr[@`2']='2';
+xchr[@`3']='3';@/
+xchr[@`4']='4';
+xchr[@`5']='5';
+xchr[@`6']='6';
+xchr[@`7']='7';@/
+xchr[@`8']='8';
+xchr[@`9']='9';
+xchr[@`:']=':';
+xchr[@`;']=';';@/
+xchr[@`<']='<';
+xchr[@`=']='=';
+xchr[@`>']='>';
+xchr[@`?']='?';@/
+xchr[@`@@']='@@';
+xchr[@`A']='A';
+xchr[@`B']='B';
+xchr[@`C']='C';@/
+xchr[@`D']='D';
+xchr[@`E']='E';
+xchr[@`F']='F';
+xchr[@`G']='G';@/
+xchr[@`H']='H';
+xchr[@`I']='I';
+xchr[@`J']='J';
+xchr[@`K']='K';@/
+xchr[@`L']='L';
+xchr[@`M']='M';
+xchr[@`N']='N';
+xchr[@`O']='O';@/
+xchr[@`P']='P';
+xchr[@`Q']='Q';
+xchr[@`R']='R';
+xchr[@`S']='S';@/
+xchr[@`T']='T';
+xchr[@`U']='U';
+xchr[@`V']='V';
+xchr[@`W']='W';@/
+xchr[@`X']='X';
+xchr[@`Y']='Y';
+xchr[@`Z']='Z';
+xchr[@`[']='[';@/
+xchr[@`\\']='\\';
+xchr[@`]']=']';
+xchr[@`^']='^';
+xchr[@`_']='_';@/
+xchr[@`'']='`';
+xchr[@`a']='a';
+xchr[@`b']='b';
+xchr[@`c']='c';@/
+xchr[@`d']='d';
+xchr[@`e']='e';
+xchr[@`f']='f';
+xchr[@`g']='g';@/
+xchr[@`h']='h';
+xchr[@`i']='i';
+xchr[@`j']='j';
+xchr[@`k']='k';@/
+xchr[@`l']='l';
+xchr[@`m']='m';
+xchr[@`n']='n';
+xchr[@`o']='o';@/
+xchr[@`p']='p';
+xchr[@`q']='q';
+xchr[@`r']='r';
+xchr[@`s']='s';@/
+xchr[@`t']='t';
+xchr[@`u']='u';
+xchr[@`v']='v';
+xchr[@`w']='w';@/
+xchr[@`x']='x';
+xchr[@`y']='y';
+xchr[@`z']='z';
+xchr[@`{']='{';@/
+xchr[@`|']='|';
+xchr[@`}']='}';
+xchr[@`~']='~';@/
+xchr[0]=' '; xchr[@"7F]=' '; /* these \ASCII{} codes are not used */
+
+
+@ Some of the \ASCII{} codes below @"20 have been given a
+symbolic name in \.{TIE} because they are used with a special
+meaning.
+
+@d tab_mark = @"09 /* \ASCII{} code used as tab-skip */
+@d nl_mark = @"0A /* \ASCII{} code used as line end marker */
+@d form_feed = @"0C /* \ASCII{} code used as page eject */
+
+
+@ When we initialize the |xord| array and the remaining
+parts of |xchr|, it will be convenient to make use of an
+index variable, |i|.
+
+@<Local variables for initialisation@>=
+int i;
+
+
+@ Here now is the system-dependent part of the character
+set. If \.{TIE} is being implemented on a garden-variety
+\Cl\ for which only standard \ASCII{} codes will appear
+in the input and output files, you don't need to make any
+changes here.
+@^system dependencies@>
+
+Changes to the present module will make \.{TIE} more
+friendly on computers that have an extended character set,
+so that one can type things like \.^^Z. If you have an
+extended set of characters that are easily incorporated into
+text files, you can assign codes arbitrarily here, giving an
+|xchr| equivalent to whatever characters the users of
+\.{TIE} are allowed to have in their input files, provided
+that unsuitable characters do not correspond to special
+codes like |tab_mark| that are listed above.
+
+@<Set init...@>=
+for (i=1;i<@` ';xchr[i++]=' ');
+xchr[tab_mark]='\t';
+xchr[form_feed]='\f';
+xchr[nl_mark]='\n';
+
+
+@ The following system-independent code makes the |xord|
+array contain a suitable inverse to the information in
+|xchr|.
+
+@<Set init...@>=
+for ( i=first_text_char ; i<=last_text_char ; xord[i++]=@` ' ) do_nothing;
+for ( i=1 ; i<=@`~' ; i++ ) xord[xchr[i]] = i;
+
+
+
+
+
+@* Input and output.
+
+\noindent Output for the user is done by writing on file |term_out|,
+which is assumed to consist of characters of type \&{text\_char}. It
+should be linked to |stdout| usually. Terminal input is not needed in
+this version of \.{TIE}. |stdin| and |stdout| are predefined if we
+include the \.{stdio.h} definitions. Although I/O redirection for
+|stdout| is usually available you may lead output to another file if
+you change the definition of |term_out|. Also we define some macros
+for terminating an output line and writing strings to the user. These
+distinguish the number of parameters used to ease translation with a
+\.{CWEB} like Sylvio Levy's that does not support a variable number of
+parameters for macros.
+
+@^system dependencies@>
+@d term_out=stdout
+@d print(a)=fprintf(term_out,a) /* `|print|' means write on the terminal */
+@d print2(a)=fprintf(term_out,a) /* same with two arguments */
+@d print3(a)=fprintf(term_out,a) /* same with three arguments */
+@d print_c(a)=fputc(a,term_out); /* print a single character */
+@d new_line(a)=fputc('\n',a) /* start new line */
+@d term_new_line=new_line(term_out) /* start new line of the terminal */
+@d print_ln(a)={fprintf(term_out,a);term_new_line;}
+ /* `|print|' and then start new line */
+@d print2_ln(a)={print2(a);term_new_line;} /* same with two arguments */
+@d print3_ln(a)={print3(a);term_new_line;} /* same with three arguments */
+@d print_nl(a)= /* print information starting on a new line */
+ {term_new_line; print(a);}
+@d print2_nl(a)= /* same for two arguments */
+ {term_new_line; print2(a);}
+
+@<Global |#include|s@>=
+#include <stdio.h>
+
+
+@ And we need dynamic memory allocation.
+This should cause no trouble in any \Cl\ program.
+@^system dependencies@>
+
+@<Global |#include|s@>=
+extern char *malloc();
+
+
+@ The |update_terminal| function is called when we want to
+make sure that everything we have output to the terminal so
+far has actually left the computer's internal buffers and
+been sent.
+@^system dependencies@>
+
+@d update_terminal = fflush(term_out) /* empty the terminal output buffer */
+
+
+
+
+
+@* Data structures.
+
+\noindent The multiple input files (master file and change
+files) are treated the same way. To organize the
+simultaneous usage of several input files, we introduce the
+data type \&{in\_file\_modes}.
+
+The mode |search| indicates that \.{TIE} searches for a
+match of the input line with any line of an input file in
+|reading| mode. |test| is used whenever a match is found
+and it has to be tested if the next input lines do match
+also. |reading| describes that the lines can be read without
+any check for matching other lines. |ignore| denotes
+that the file cannot be used. This may happen because an
+error has been detected or because the end of the file has
+been found.
+
+\leavevmode |file_types| is used to describe whether a file
+is a master file or a change file. The value |unknown| is added
+to this type to set an initial mode for the output file.
+This enables us to check whether any option was used to select
+the kind of output. (this would even be necessary if we
+would assume a default action for missing options.)
+
+@<Global types@>=
+#define search 0
+#define test 1
+#define reading 2
+#define ignore 3
+typedef int @!in_file_modes; /* should be |enum(search,test,reading,ignore)| */
+#define unknown 0
+#define master 1
+#define chf 2
+typedef int @!file_types; /* should be |enum(unknown,master,chf)| */
+
+
+@ A variable of type |out_md_type| will tell us in what state the output
+change file is during processing. |normal| will be the state, when we
+did not yet start a change, |pre| will be set when we write the lines
+to be changes and |post| will indicate that the replacement lines are
+written.
+
+@<Global types@>=
+#define normal 0
+#define pre 1
+#define post 2
+typedef int @!out_md_type; /* should be |enum(normal,pre,post)| */
+
+
+@ Two more types will indicate variables used as an index into either
+the file buffer or the file table.
+
+@<Global types@>=
+typedef int @!buffer_index; /* |-1..buf_size| */
+typedef int @!file_index; /* |-1..max_file_index+1| */
+
+
+@ The following data structure joins all informations needed to use
+these input files.
+
+@<Global types@>=
+typedef struct _idsc{
+ string @!name_of_file;
+ ASCII_Code @!buffer[buf_size];
+ in_file_modes @!mode;
+ long @!line;
+ file_types @!type_of_file;
+ buffer_index @!limit;
+ text_file the_file;
+ } @!input_description;
+
+
+@ These data types are used in the global variable section.
+They refer to the files in action, the number of change files,
+the mode of operation and the current output state.
+
+@<Global variables@>=
+file_index @!actual_input,@!test_input,@!no_ch;
+file_types @!prod_chf=unknown;
+out_md_type @!out_mode;
+
+
+@ All input files (including the master file) are recorded
+in the following structure.
+Mostly the components are accessed through a local pointer variable.
+This corresponds to \PASCAL's \&{with}-statement
+and results in a one-time-computation of the index expression.
+
+@f input_description int
+
+@<Global variables@>=
+input_description *@!input_organization[max_file_index+1];
+
+
+
+
+
+@* File I/O.
+
+\noindent The basic function |get_line| can be used to get a line from
+an input file. The line is stored in the |buffer| part of the
+descriptor. The components |limit| and |line| are updated. If the
+end of the file is reached |mode| is set to |ignore|. On some systems
+it might be useful to replace tab characters by a proper number of
+spaces since several editors used to create change files insert tab
+characters into a source file not under control of the user. So it
+might be a problem to create a matching change file.
+@^tab character expansion@>
+
+We define |get_line| to read a line from a file specified by
+the corresponding file descriptor.
+
+@<Internal functions@>=
+@h void get_line(i)
+ file_index i;
+{register input_description *inp_desc=input_organization[i];
+ if (inp_desc->mode==ignore) return;
+ if (feof(inp_desc->the_file))
+ @<Handle end of file and return@>;
+ @<Get line into buffer@>;
+}
+
+
+@ End of file is special if this file is the master file.
+Then we set the global flag variable |input_has_ended|.
+
+@<Handle end of file ...@>=
+{
+ inp_desc->mode=ignore;
+ inp_desc->limit=-1; /* mark end-of-file */
+ if (inp_desc->type_of_file==master) input_has_ended=true;
+ return;
+}
+
+
+@ This variable must be declared for global access.
+
+@<Global variables@>=
+static boolean input_has_ended=false;
+
+
+@ Lines must fit into the buffer completely.
+We read all characters sequentially until an end of line is found
+(but do not forget to check for |EOF|!).
+Too long input lines will be truncated.
+This will result in a damaged output if they occur in the
+replacement part of a change file, or in an incomplerte check if the
+matching part is concerned.
+Tab character expansion might be done here.
+@^tab character expansion@>
+
+@<Get line into buffer@>=
+{int final_limit; /* used to delete trailing spaces */
+ int c; /* the actual character read */
+ @<Increment the line number and print a progess report at
+ certain times@>
+ inp_desc->limit=final_limit=0;
+ while (inp_desc->limit<buf_size) {
+ c=fgetc(inp_desc->the_file);
+ @<Check |c| for |EOF|, |return| if line was empty, otherwise
+ |break| to process last line@>
+ inp_desc->buffer[inp_desc->limit++]=c=map_xord(c);
+ if (c==nl_mark) break; /* end of line found */
+ if (c!=@` ' && c!=tab_mark)
+ final_limit=inp_desc->limit;
+ }
+ @<Test for truncated line, skip to end of line@>
+ inp_desc->limit=final_limit;
+}
+
+
+@ This section does what its name says. Every 100 lines
+in the master file we print a dot, every 500 lines the number
+of lines is shown.
+
+@<Increment the line number and print ...@>=
+incr(inp_desc->line);
+if (inp_desc->type_of_file==master && inp_desc->line % 100==0) {
+ if (inp_desc->line % 500 == 0) print2("%ld",inp_desc->line);
+ else print_c('.');
+ update_terminal;
+}
+
+
+@ There may be incomplete lines of the editor used does
+not make sure that the last character before end of file
+is an end of line. In such a case we must process the
+final line. Of the current line is empty, we just can \&{return}.
+Note that this test must be done {\sl before} the character read
+is translated.
+@^system dependencies@>
+
+@<Check |c| for |EOF|...@>=
+ if (c==EOF) {
+ if (inp_desc->limit<=0) {
+ inp_desc->mode=ignore;
+ inp_desc->limit=-1; /* mark end-of-file */
+ if (inp_desc->type_of_file==master) input_has_ended=true;
+ return;
+ } else { /* add end of line mark */
+ c=nl_mark;
+ break;
+ }
+ }
+
+
+@ If the line is truncated we must skip the rest
+(and still watch for |EOF|!).
+@<Test for truncated line, skip to end of line@>=
+if (c!=nl_mark) {
+ err_print("! Input line too long")(i);
+@.Input line too long@>
+ while ( (c=fgetc(inp_desc->the_file)) != EOF && map_xord(c) != nl_mark )
+ do_nothing; /* skip to end */
+ }
+
+
+
+
+
+@* Reporting errors to the user.
+
+\noindent There may be errors if a line in a given change
+file does not match a line in the master file or a
+replacement in a previous change file. Such errors are
+reported to the user by saying
+$$
+ \hbox{|err_print("! Error message")(file_no)|;}
+$$
+where |file_no| is the number of the file which is concerned by the
+error. Please note that no trailing dot is supplied by the error
+message because it is appended by |err_print|.
+
+This function is implemented as a macro. It gives a message and an
+indication of the offending file. The actions to determine the error
+location are provided by a function called |err_loc|.
+
+@d error_loc(a) = err_loc(a); history=troublesome; @+ }
+@d err_print(a) = { @+ print_nl(a); error_loc
+
+@<Error handling...@>=
+@h void err_loc(i) /* prints location of error */
+ int i;
+{
+ print3_ln(" (file %s, l.%ld).",
+ input_organization[i]->name_of_file,
+ input_organization[i]->line);
+}
+
+
+@ Non recoverable errors are handled by calling |fatal_error| that
+outputs a message and then calls `|jump_out|'. |err_print| will print
+the error message followed by an indication of where the error was
+spotted in the source files. |fatal_error| cannot state any files
+because the problem is usually to access these.
+
+@d fatal_error(a) = {
+ print(a); print_c('.'); history=fatal;
+ term_new_line; jump_out();
+ }
+
+
+@ |jump_out| just cuts across all active procedure levels and jumps
+out of the program. It is used when no recovery from a particular
+error has been provided. The return code from this program should be
+regarded by the caller.
+
+@d jump_out(a) = exit(1)
+
+
+
+
+
+@* Handling multiple change files.
+
+\noindent In the standard version we take the name of the
+files from the command line.
+It is assumed that filenames can be used as given in the
+command line without changes.
+
+First there are some sections to open all files.
+If a file is not accessible, the run will be aborted.
+Otherwise the name of the open file will be displayed.
+
+@<Prepare the output file@>=
+{
+ out_file=fopen(out_name,"w");
+ if (out_file==NULL) {
+ fatal_error("! Could not open/create output file");
+@.Could not open/create output file@>
+ }
+}
+
+
+@ The name of the file and the file desciptor are stored in
+global variables.
+
+@<Global variables@>=
+text_file @!out_file;
+string @!out_name;
+
+
+@ For the master file we start just reading its first line
+into the buffer, if we could open it.
+
+@<Get the master file started@>=
+{ input_organization[0]->the_file=
+ fopen(input_organization[0]->name_of_file,"r");
+ if (input_organization[0]->the_file==NULL)
+ fatal_error("! Could not open master file");
+@.Could not open master file@>
+ print2("(%s)",input_organization[0]->name_of_file);
+ term_new_line;
+ input_organization[0]->type_of_file=master;
+ get_line(0);
+}
+
+@ For the change files we must skip the comment part and
+see, whether we can find any change in it.
+This is done by |init_change_file|.
+
+@<Prepare the change files@>=
+{file_index i;
+ i=1;
+ while (i<no_ch) {
+ input_organization[i]->the_file=
+ fopen(input_organization[i]->name_of_file,"r");
+ if (input_organization[i]->the_file==NULL)
+ fatal_error("!Could not open change file");
+@.Could not open change file@>
+ print2("(%s)",input_organization[i]->name_of_file);
+ term_new_line;
+ init_change_file(i,true);
+ incr(i);
+ }
+}
+
+
+
+
+
+@*Input/output organization.
+
+\noindent Here's a simple function that checks if two lines
+are different.
+
+@<Internal functions@>=
+@h boolean lines_dont_match(i,j)
+ file_index i,j;
+{
+ buffer_index k,lmt;
+ if (input_organization[i]->limit != input_organization[j]->limit)
+ return(true);
+ lmt=input_organization[i]->limit;
+ for ( k=0 ; k<lmt ; k++ )
+ if (input_organization[i]->buffer[k] != input_organization[j]->buffer[k])
+ return(true);
+ return(false);
+}
+
+
+@ Function |init_change_file(i,b)| is used to ignore all
+lines of the input file with index |i| until the next change
+module is found. The boolean parameter |b| indicates
+whether we do not want to see \.{@@x} or \.{@@y} entries during
+our skip.
+
+@<Internal functions@>=
+@h void init_change_file(i,b)
+ file_index i; boolean b;
+{register input_description *inp_desc=input_organization[i];
+ @<Skip over comment lines; |return| if end of file@>;
+ @<Skip to the next nonblank line; |return| if end of file@>;
+}
+
+
+@ While looking for a line that begins with \.{@@x} in the
+change file, we allow lines that begin with \.{@@}, as long
+as they don't begin with \.{@@y} or \.{@@z} (which would
+probably indicate that the change file is fouled up).
+
+@<Skip over comment lines...@>=
+loop@+ {ASCII_Code c;
+ get_line(i);
+ if (inp_desc->mode==ignore) return;
+ if (inp_desc->limit<2) continue;
+ if (inp_desc->buffer[0] != @`@@') continue;
+ c=inp_desc->buffer[1];
+ if (c>=@`X' && c<=@`Z')
+ c+=@`z'-@`Z'; /*lowercasify*/
+ if (c==@`x') break;
+ if (c==@`y' || c==@`z')
+ if (b) /* scanning for start of change */
+ err_print("! Where is the matching @@x?")(i);
+@.Where is the match...@>
+}
+
+
+@ Here we are looking at lines following the \.{@@x}.
+
+@<Skip to the next nonblank line...@>=
+do{
+ get_line(i);
+ if (inp_desc->mode==ignore) {
+ err_print("! Change file ended after @@x")(i);
+@.Change file ended...@>
+ return;
+ }
+} while (inp_desc->limit<=0);
+
+
+@ The |put_line| function is used to write a line from
+input buffer |j| to the output file.
+
+@<Internal functions@>=
+@h void put_line(j)
+ file_index j;
+{buffer_index i; /* index into the buffer */
+ buffer_index lmt; /* line length */
+ string p; /* output pointer */
+ lmt=input_organization[j]->limit;
+ p=input_organization[j]->buffer;
+ for (i=0;i<lmt;i++) fputc(map_xchr(*p++),out_file);
+ new_line(out_file);
+}
+
+
+@ The function |e_of_ch_module| returns true if the input
+line from file |i| starts with \.{@@z}.
+
+@<Internal functions@>=
+@h boolean e_of_ch_module(i)
+ file_index i;
+{register input_description *inp_desc=input_organization[i];
+ if (inp_desc->limit<0) {
+ print_nl("! At the end of change file missing @@z ");
+@.At the end of change file...@>
+ print2("%s",input_organization[i]->name_of_file);
+ term_new_line;
+ return(true);
+ } else if (inp_desc->limit>=2) if (inp_desc->buffer[0]==@`@@' &&
+ (inp_desc->buffer[1]==@`Z' || inp_desc->buffer[1]==@`z'))
+ return(true);
+ return(false);
+}
+
+
+@ The function |e_of_ch_preamble| returns |true| if the input
+line from file |i| starts with \.{@@y}.
+
+@<Internal functions@>=
+@h boolean e_of_ch_preamble(i)
+ file_index i;
+{register input_description *inp_desc=input_organization[i];
+ if (inp_desc->limit>=2 && inp_desc->buffer[0]==@`@@')
+ if (inp_desc->buffer[1]==@`Y'||inp_desc->buffer[1]==@`y') return(true);
+ return(false);
+}
+
+
+
+@ To process the input file the next section
+reads a line of the actual input file and updates the
+|input_organization| for all files with index |test_file| greater
+|actual_input|.
+
+@<Process a line, |break| when end of source reached@>=
+{file_index test_file;
+ @<Check the current files for any ends of changes@>
+ if (input_has_ended && actual_input==0) break; /* all done */
+ @<Scan all other files for changes to be done@>
+ @<Handle output@>
+ @<Step to next line@>
+}
+
+
+@ Any of the current change files may have reached the end of change.
+In such a case intermediate lines must be skipped and the next start
+of change is to be found. This may make a change file inactive if
+it reaches end of file.
+
+@<Check the...@>=
+{register input_description *inp_desc;
+while (e_of_ch_module(actual_input)) {
+ inp_desc=input_organization[actual_input];
+ if (inp_desc->type_of_file==master) {
+ /* emergency exit, everything mixed up!*/
+ fatal_error("! This can't happen: change file is master file");
+@.This can't happen...@>
+ }
+ inp_desc->mode=search;
+ init_change_file(actual_input,true);
+ while ((input_organization[actual_input]->mode!=reading
+ && actual_input>0)) decr(actual_input);
+}
+}
+
+
+@ Now we will set |test_input| to the file that has another match
+for the current line. This depends on the state of the other
+change files. If no other file matches, |actual_input| refers to
+a line to write and |test_input| ist set to |none|.
+
+@d none = (max_file_index+1)
+
+@<Scan all other files...@>=
+test_input=none;
+test_file=actual_input;
+while (test_input==none && test_file</*no\_ch*/no_ch-1) { /* bug fix DL */
+ incr(test_file);
+ switch (input_organization[test_file]->mode) {
+ case search: if (lines_dont_match(actual_input,test_file)==false) {
+ input_organization[test_file]->mode=test;
+ test_input=test_file;
+ }
+ break;
+ case test: if (lines_dont_match(actual_input, test_file)==true) {
+ /* error, sections do not match */
+ input_organization[test_file]->mode=search;
+ err_print("! Sections do not match")(actual_input);
+@.Sections do not match@>
+ err_loc(test_file);
+ init_change_file(test_file,false);
+ } else test_input=test_file;
+ break;
+ case reading: do_nothing; /* this can't happen */
+ break;
+ case ignore: do_nothing; /* nothing to do */
+ break;
+ }
+}
+
+
+@ For the output we must distinguish whether we create a new change
+file or a new master file. The change file creation needs some closer
+inspection because we may be before a change, in the pattern part or
+in the replacement part. For a master file we have to write the line
+from the current actual input.
+
+@<Handle output@>=
+if (prod_chf==chf) {
+ loop @+ {
+ @<Test for normal, |break| when done@>
+ @<Test for pre, |break| when done@>
+ @<Test for post, |break| when done@>
+ }
+} else
+if (test_input==none) put_line(actual_input);
+
+
+@ Check whether we have to start a change file entry.
+Without a match nothing must be done.
+
+@<Test for normal...@>=
+if (out_mode==normal) {
+ if (test_input!=none) {
+ fputc(map_xchr(@`@@'),out_file); fputc(map_xchr(@`x'),out_file);
+ new_line(out_file);
+ out_mode=pre;
+ } else break;
+}
+
+
+@ Check whether we have to start the replacement text.
+This is the case when we have no more matching line.
+Otherwise the master file source line must be copied to the
+change file.
+@<Test for pre...@>=
+
+ if (out_mode==pre) {
+ if (test_input==none) {
+ fputc(map_xchr(@`@@'),out_file); fputc(map_xchr(@`y'),out_file);
+ new_line(out_file);
+ out_mode=post;
+ } else {
+ if (input_organization[actual_input]->type_of_file==master)
+ put_line(actual_input);
+ break;
+ }
+ }
+
+
+@ Check whether an entry from a change file is complete.
+If the current change was a change for a change file in effect,
+then this change file line must be written.
+If the actual input has been reset to the master file we
+can finish this change.
+
+@<Test for post...@>=
+ if (out_mode==post) {
+ if (input_organization[actual_input]->type_of_file==chf) {
+ if (test_input==none) put_line(actual_input);
+ break;
+ } else {
+ fputc(map_xchr(@`@@'),out_file); fputc(map_xchr(@`z'),out_file);
+ new_line(out_file);
+ new_line(out_file);
+ out_mode=normal;
+ }
+ }
+
+
+@ If we had a change, we must proceed in the actual file
+to be changed and in the change file in effect.
+
+@<Step to next line@>=
+get_line(actual_input);
+if (test_input!=none) {
+ get_line(test_input);
+ if (e_of_ch_preamble(test_input)==true) {
+ get_line(test_input); /* update current changing file */
+ input_organization[test_input]->mode=reading;
+ actual_input=test_input;
+ test_input=none;
+ }
+}
+
+
+@ To create the new output file we have to scan the whole
+master file and all changes in effect when it ends.
+At the very end it is wise to check for all changes
+to have completed--in case the last line of the master file
+was to be changed.
+
+@<Process the input@>=
+actual_input=0;
+input_has_ended=false;
+while (input_has_ended==false||actual_input!=0)
+ @<Process a line...@>
+if (out_mode==post) { /* last line has been changed */
+ fputc(map_xchr(@`@@'),out_file); fputc(map_xchr(@`z'),out_file);
+ new_line(out_file);
+ }
+
+
+@ At the end of the program, we will tell the user if the
+change file had a line that didn't match any relevant line
+in the master file or any of the change files.
+
+@<Check that all changes have been read@>=
+{file_index i;
+for (i=1;i<no_ch;i++) {/* all change files */
+ if (input_organization[i]->mode!=ignore)
+ err_print("! Change file entry did not match")(i);
+@.Change file entry ...@>
+ }
+}
+
+
+@ We want to tell the user about our command line options. This is
+done by the |usage()| function. It contains merely the necessary
+print statement and exits afterwards.
+
+@<Intern...@>=
+@h void usage()
+{
+ print("Usage: tie -[mc] outfile master changefile(s)");
+ term_new_line;
+ jump_out();
+}
+
+
+@ We must scan through the list of parameters, given in |argv|. The
+number is in |argc|. We must pay attention to the flag parameter. We
+need at least 5~parameters and can handle up to |max_file_index|
+change files. The names fo the file parameters will be inserted into
+the structure of |input_organization|. The first file is special. It
+indicates the output file. When we allow flags at any position, we
+must find out which name is for what purpose. The master file is
+already part of the |input_organization| structure (index~0). As long
+as the number of files found (counted in |no_ch|) is |-1| we have not
+yet found the output file name.
+
+@<Scan the parameters@>=
+{int act_arg,act_orgpart;
+ if ( argc < 5 || argc > max_file_index+4-1 ) usage();
+ no_ch = -1; /* fill this part of |input_organization| */
+ for ( act_arg=1 ; act_arg<argc ; act_arg++ ) {
+ if (argv[act_arg][0]=='-') @<Set a flag@>
+ else @<Get a file name@>
+ }
+ if (no_ch<=0|| prod_chf==unknown) usage();
+}
+
+
+@ The flag is about to determine the processing mode.
+We must make sure that this flag has not been set before.
+Further flags might be introduced to avoid/force overwriting of
+output files.
+Currently we just have to set the processing flag properly.
+
+@<Set a flag@>=
+if (prod_chf!=unknown) usage();
+else
+ switch (argv[act_arg][1]) {
+ case 'c':
+ case 'C': prod_chf=chf; break;
+ case 'm':
+ case 'M': prod_chf=master; break;
+ default: usage();
+ }
+
+
+@ We have to distinguish whether this is the very first file name
+(known if |no_ch==(-1)|) or if the next element of |input_organization|
+must be filled.
+
+@<Get a file name@>=
+{ if (no_ch==(-1)) {
+ out_name=argv[act_arg];
+ } else { register input_description *inp_desc;
+ inp_desc=(input_description *)
+ malloc(sizeof(input_description));
+ if (inp_desc==NULL)
+ fatal_error("! No memory for descriptor");
+@.No memory for descriptor@>
+ inp_desc->mode=search;
+ inp_desc->line=0;
+ inp_desc->type_of_file=chf;
+ inp_desc->limit=0;
+ inp_desc->name_of_file=argv[act_arg];
+ input_organization[no_ch]=inp_desc;
+ }
+ incr(no_ch);
+}
+
+
+@* The main program.
+
+\noindent Here is where \.{TIE} starts, and where it ends.
+
+@<The main function@>=
+@h main(argc,argv)
+ int argc; string *argv;
+{{@<Local variables for initialisation@>
+ @<Set initial...@>
+ }
+ print_ln(banner); /* print a ``banner line'' */
+ print_ln(copyright); /* include the copyright notice */
+ actual_input=0;
+ out_mode=normal;
+ @<Scan the parameters@>
+ @<Prepare the output file@>
+ @<Get the master file started@>;
+ @<Prepare the change files@>
+ @<Process the input@>;
+ @<Check that all changes have been read@>;
+ @<Print the job |history|@>;
+}
+
+@ We want to pass the |history| value to the operating system so that
+it can be used to govern whether or not other programs are started.
+Additionaly we report the history to the user, although this may not
+be ``{\mc UNIX}'' style---but we are in best companion: \.{WEB} and
+\TeX{} do the same.
+@^system dependencies@>
+
+@<Print the job |history|@>=
+{string msg;
+ switch (history) {
+ case spotless: msg="No errors were found"; break;
+ case troublesome: msg="Pardon me, but I think I spotted something wrong.";
+ break;
+ case fatal: msg="That was a fatal error, my friend"; break;
+ } /* there are no other cases */
+ print2_nl("(%s.)",msg); term_new_line;
+ exit ( history == spotless ? 0 : 1 );
+}
+
+
+
+
+
+@* System-dependent changes.
+
+\noindent This section should be replaced, if necessary, by
+changes to the program that are necessary to make \.{TIE}
+work at a particular installation. It is usually best to
+design your change file so that all changes to previous
+modules preserve the module numbering; then everybody's
+version will be consistent with the printed program. More
+extensive changes, which introduce new modules, can be
+inserted here; then only the index itself will get a new
+module number.
+@^system dependencies@>
+
+
+
+
+
+@* Index.
+
+\noindent Here is the cross-reference table for the \.{TIE}
+processor.
+
diff --git a/web/latexspider/tiedoc.tex b/web/latexspider/tiedoc.tex
new file mode 100644
index 0000000000..525ae60b4e
--- /dev/null
+++ b/web/latexspider/tiedoc.tex
@@ -0,0 +1,138 @@
+% tiedoc.tex 25 Oct 89
+
+% adapted to CWEB by J.Schrod on 89-10-25
+
+\documentstyle[a4]{article}
+\font\mc=cmcsc10
+\def\TANGLE{{\tt TANGLE}}
+\def\TIE{{\tt TIE}}
+\def\WEAVE{{\tt WEAVE}}
+\def\WEB{{\tt WEB}}
+\def\CWEB{{\mc cweb}}
+\def\PASCAL{{\mc Pascal}}
+\title{The TIE Processor}
+\author{Klaus Guntermann\\
+TH Darmstadt\\
+Fachbereich Informatik\\
+Institut f\"ur Theoretische Informatik}
+
+\date{October 1989}
+\begin{document}
+\maketitle
+\section{Introduction}
+
+To install a program on a computer usually
+system dependent changes are needed.
+The \WEB\ system allows to describe these changes in a
+so called change file.
+To incorporate the changes into the program \TANGLE\ processes
+the original source file and inserts the changes into the proper places.
+
+Sometimes it is good practice to develop a set of change files to be able to
+distinguish between different changes like
+program enhancements, bug fixes, system dependent changes
+and output device dependent modifications.
+Additionally this allows combinations of changes that can be used with a set of
+programs that share some common features.
+
+The processors \TANGLE\ and \WEAVE\ can handle only one change file.
+The combination of change files is done best in another preprocessing step.
+\TIE\ is able to create either a new master file or a single change file that
+comprises the effect of all change files.
+
+Since \TIE\ does not know anything about \WEB\ programs but only about the
+structure of change files, it is possible to use this program for other
+programming languages as well.
+You just pretend that you want to create a new master file and \TIE\ will go
+and insert all the changes from your change files.
+
+
+
+\section{Application}
+
+The current version of \TIE\ accepts a master file and up to 9 change files.
+Because in general it is important to use the changes in their proper sequence
+the order of the files must be chosen carefully.
+
+The CWEB version of \TIE{} may be called with the following command
+line interface:
+%
+\begin{verbatim}
+ tie -[mc] output_file master_file changefile(s)
+\end{verbatim}
+%
+The option \verb|-m| results in the creation of a new master file,
+\verb|-c| yields a new changefile. Usually wildcards may be used for
+the filenames.
+
+The multiple change files are used as if the single change files were merged
+into the master files step by step.
+Thus more than 9 change files might be incorporated by repeated application of
+\TIE.
+
+Please note that even when multiple change files are processed each of the
+files is read only once.
+For each of the change files and for the master file there is only one line in
+memory at a time (neglecting operating system buffering).
+Thus the storage requirement of \TIE\ does not depend on the size of the change
+files or the size of a single changed section.
+
+\vfill\eject
+\def\eof{$\langle$EOF$\rangle$}
+\section{Example}
+
+To illustrate the actions \TIE\ performs you may inspect the following example
+that exercises some of the border line cases.
+
+$$\vbox{
+\halign{#\hfill\qquad\quad&#\hfill\qquad\quad&#\hfill\qquad\quad&#\hfill\cr
+``master'' &{\tt CF1} &{\tt CF2} &{\tt CF3}\cr
+line 1 &@x &@x &@x\cr
+line 2 &line 2 &line 1 &changed line 4\cr
+line 3 &line 3 &changed line 2 &@y\cr
+line 4 &@y &changed line 3 &final line 4\cr
+line 5 &changed line 2 &inserted line &@z\cr
+line 6 &changed line 3 &line 4 &\eof\cr
+line 7 &inserted line &@y\cr
+line 8 &@z &final line 2\cr
+line 9 & &final line 3\cr
+line 10 &@x &changed line 4\cr
+\eof &line 7 &@z\cr
+ &@y\cr
+ &changed line 7 &@x\cr
+ &@z &changed line 7\cr
+ &\eof &line 8\cr
+ & &@y\cr
+ & &final line 7\cr
+ & &final line 8\cr
+ & &@z\cr
+ & &\eof\cr}
+}$$
+\vfill\eject
+Using these input files and running \TIE\ twice to create a new master file
+and a new change file will result in the following output files:
+
+$$\vbox{
+\halign{#\hfill\qquad\quad&&#\hfill\qquad\quad\cr
+``master'' &``change''\cr
+final line 2 &@x\cr
+final line 3 &line 1\cr
+final line 4 &line 2\cr
+line 5 &line 3\cr
+line 6 &line 4\cr
+final line 7 &@y\cr
+final line 8 &final line 2\cr
+line 9 &final line 3\cr
+line 10 &final line 4\cr
+\eof &@z\cr
+ &\cr
+ &@x\cr
+ &line 7\cr
+ &line 8\cr
+ &@y\cr
+ &final line 7\cr
+ &final line 8\cr
+ &@z\cr
+ &\eof\cr}
+}$$
+\end{document}
diff --git a/web/latexspider/weave.ltx b/web/latexspider/weave.ltx
new file mode 100644
index 0000000000..7b5454fee6
--- /dev/null
+++ b/web/latexspider/weave.ltx
@@ -0,0 +1,700 @@
+% This is `weave.ltx' to fix spidery weave for LaTeX. See
+% `web.doc' for some comments about how it works.
+
+% changes copyright D.Love, SERC Daresbury Laboratory
+% (d.love@daresbury.ac.uk) under the same conditions as the Spider
+% distribution.
+
+%$Header: /home/users0/fx/ltxspiderweb/master/weave.ltx,v 1.4 91/03/22 11:24:35 fx Exp $
+
+ l 11 (remove \batchmode so we can see what's happening)
+@x
+% Here is TeX material that gets inserted after \input webmac
+
+\message{Entering \string\batchmode...}
+\batchmode
+@y
+% Here is TeX material that gets inserted after \documentstyle[web]...
+
+% we turn off batch mode for debugging purposes
+
+%\message{Entering \string\batchmode...}
+%\batchmode
+@z
+
+ l 16 (swicth for LaTeX or plain)
+@x
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps
+\def\cee{C}
+\def\Pascal{Pascal}
+\def\PASCAL{Ada}
+\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
+\def\v{\.{\char'174}} % vertical (|) in typewriter font
+\def\dleft{[\![} \def\dright{]\!]} % double brackets
+\mathchardef\RA="3221 % right arrow
+\mathchardef\BA="3224 % double arrow
+\def\({} % kludge for alphabetizing certain module names
+
+\def\title{Spidery WEAVE}
+\def\contentspagenumber{1} % should be odd
+\def\topofcontents{\null\vfill
+ \titlefalse % include headline on the contents page
+ \def\rheader{\hfil}
+ \centerline{\titlefont The {\ttitlefont Spidery WEAVE} processor}
+ \vfill}
+\pageno=\contentspagenumber \advance\pageno by 1
+\let\maybe=\iftrue
+@y
+\ifx \enddocument\undefined % are we using LaTeX?
+ \font\ninerm=cmr9 % no...
+ \let\mc=\ninerm % medium caps
+
+\def\title{Spidery WEAVE}
+\def\contentspagenumber{1} % should be odd
+\def\topofcontents{\null\vfill
+ \titlefalse % include headline on the contents page
+ \def\rheader{\hfil}
+ \centerline{\titlefont The {\ttitlefont Spidery WEAVE} processor}
+ \vfill}
+ \pageno=\contentspagenumber \advance\pageno by 1
+\def\LaTeX{{\rm L\kern-.36em\raise.3ex\hbox{\sc a}\kern-.15em
+ T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}%
+\else % yes...
+ \documentstyle[web]{article}
+ \let\.=\str % new name
+ \title{Spidery WEAVE} \date{}
+\fi
+
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\def\cee{C}
+\def\Pascal{Pascal}
+\def\PASCAL{Ada}
+\def\pb{$\.|\ldots\.|$} % C brackets (|...|)
+\def\v{\.{\char'174}} % vertical (|) in typewriter font
+\def\dleft{[\![} \def\dright{]\!]} % double brackets
+\mathchardef\RA="3221 % right arrow
+\mathchardef\BA="3224 % double arrow
+\def\({} % kludge for alphabetizing certain module names
+
+\let\maybe=\iffalse % only changed sections -- perhaps you
+ % want to change this if you're
+ % weaving WEAVE for the first time
+
+@z
+
+ l 39
+@x
+@* Introduction.
+\.{CWEAVE} has a fairly straightforward outline. It operates in
+three phases: first it inputs the source file and stores cross-reference
+data, then it inputs the source once again and produces the \TeX\ output
+file, and finally it sorts and outputs the index. It can be compiled
+with certain optional flags, |DEBUG| and |STAT|, the latter being used
+to keep track of how much of \.{WEAVE}'s resources were actually used.
+@y
+@* Introduction.
+\.{CWEAVE} has a fairly straightforward outline. It operates in
+three phases: first it inputs the source file and stores cross-reference
+data, then it inputs the source once again and produces the \TeX\ output
+file, and finally it sorts and outputs the index. It can be compiled
+with certain optional flags, |DEBUG| and |STAT|, the latter being used
+to keep track of how much of \.{WEAVE}'s resources were actually used.
+
+This version has changes to make it work with \LaTeX{} as the
+formatter, rather than plain \TeX\@@. The sections which are changed
+for \LaTeX{} are indicated by |#ifdef LaTeX|, so you can define the
+|LaTeX| switch when you compile it. You could generate a new
+\.{weave.web} using \.{wmerge} or \.{tie} which you could use for
+either plain or \LaTeX, since the limbo section will check for the
+existence of \.{\\enddocument} (which presumably indicates \LaTeX).
+@z
+
+ l 361
+@x
+@d underline = @'176 /* this code will be intercepted without confusion */
+@d param = @'177 /* ASCII delete will not appear */
+/* identifier =200 or octal @'310 */
+@#/* following three must be conseccutive for indexing to work */
+@d xref_roman = (identifier+roman) /* control code for `\.{@@\^}' */
+@y
+@d underline = @'176 /* this code will be intercepted without confusion */
+@d param = @'177 /* ASCII delete will not appear */
+/* identifier =200 or octal |@'310| */
+@#/* following three must be consecutive for indexing to work */
+@d xref_roman = (identifier+roman) /* control code for `\.{@@\^}' */
+@z
+
+ l 1140
+@x
+ for (k=p->byte_start; k<k_end; k++) {
+ if (*k=='$') {out('\\'); out('D'); out('O'); out(' ');}
+ else if (*k=='&') {out('\\'); out('a'); out('m'); out('p');}
+ else {
+ if (*k=='_' || *k=='%' || *k=='#' || *k=='^' || *k=='{' || *k=='}')
+@y
+ for (k=p->byte_start; k<k_end; k++) {
+ if (*k=='$') {out('\\'); out('D'); out('O'); out(' ');}
+ else if (*k=='&') {out('\\'); out('a'); out('m'); out('p'); out(' ');}
+ else {
+ if (*k=='_' || *k=='%' || *k=='#' || *k=='^' || *k=='{' || *k=='}')
+@z
+
+ l 1159
+@x
+No `\.{@@}' signs should occur in such material except in `\.{@@@@}'
+pairs; such pairs are replaced by singletons.
+
+@u copy_limbo()
+@y
+No `\.{@@}' signs should occur in such material except in `\.{@@@@}'
+pairs; such pairs are replaced by singletons.
+For \LaTeX{} we have to introduce the start of the {\tt document}
+environment.@^LaTeX{}@>
+
+@u copy_limbo()
+@z
+
+ l 1172
+@x
+ if (c!='z' && c!='Z') {
+ out(at_sign);
+ if (c!=at_sign) err_print("! Double @@ required outside of sections");
+@.Double \AT! required...@>
+ }
+ }
+ }
+}
+@y
+ if (c!='z' && c!='Z') {
+ out(at_sign);
+ if (c!=at_sign) err_print("! Double @@ required outside of sections");
+@.Double \AT! required...@>
+ }
+ }
+ }
+#ifdef LaTeX
+ out_str("\n\\begin{document}\\maketitle\n");
+#endif LaTeX
+}
+@z
+
+ l 1368
+@x
+\.{\\mathrel\{} and \.{\\mathbin\{}, respectively.
+Also |math_op| to \.{\\mathop\{}.
+Other control sequences in the \TeX\ output will be `\.{\\\\\{}$\,\ldots\,$\.\}'
+surrounding identifiers, `\.{\\\&\{}$\,\ldots\,$\.\}' surrounding
+reserved words, `\.{\\.\{}$\,\ldots\,$\.\}' surrounding strings,
+@y
+\.{\\mathrel\{} and \.{\\mathbin\{}, respectively.
+Also |math_op| to \.{\\mathop\{}.
+Other control sequences in the plain \TeX\ output will be `\.{\\\\\{}$\,\ldots\,$\.\}'
+surrounding identifiers, `\.{\\\&\{}$\,\ldots\,$\.\}' surrounding
+reserved words, `\.{\\.\{}$\,\ldots\,$\.\}' surrounding strings,
+@z
+
+ l 1374
+@x
+`\.{\\X$n$:}$\,\ldots\,$\.{\\X}' surrounding module names, where
+|n| is the module number.
+
+@d math_bin = @'205 /* should these be octal or decimal? */
+@y
+`\.{\\X$n$:}$\,\ldots\,$\.{\\X}' surrounding module names, where
+|n| is the module number.
+@^\LaTeX{}@>
+In the \LaTeX\ output we'll have `\.{\\id\{}$\,\ldots\,$\.\}'
+surrounding identifiers, `\.{\\res\{}$\,\ldots\,$\.\}' surrounding
+reserved words, `\.{\\str\{}$\,\ldots\,$\.\}' surrounding strings,
+`\.{\\cee\{}$\,\ldots\,$\.\}$\,$|force|' surrounding comments, and
+`\.{\\X$n$:}$\,\ldots\,$\.{\\X}' surrounding module names, where
+|n| is the module number.
+@.\\id@>@.\\res@>@.\\str@>
+
+@d math_bin = @'205 /* should these be octal or decimal? */
+@z
+
+ l 1472
+@x
+\yskip\item{$\bullet$}ASCII codes and special codes like |force| and
+|math_rel| represent themselves;
+
+\item{$\bullet$}|id_flag+p| represents \.{\\\\\{{\rm identifier $p$}\}};
+
+\item{$\bullet$}|res_flag+p| represents \.{\\\&\{{\rm identifier $p$}\}};
+
+\item{$\bullet$}|mod_flag+p| represents module name |p|;
+
+\item{$\bullet$}|tok_flag+p| represents token list number |p|;
+
+\item{$\bullet$}|inner_tok_flag+p| represents token list number |p|, to be
+translated without line-break controls.
+@y
+\begin{itemize}
+\item ASCII codes and special codes like |force| and
+|math_rel| represent themselves;
+
+\item |id_flag+p| represents \.{\\\\\{{\rm identifier $p$}\}} in the
+plain \TeX\ version or \.{\\str\{{\rm identifier $p$}\}} in the \LaTeX\
+version;
+
+\item |res_flag+p| represents \.{\\\&\{{\rm identifier $p$}\}} in
+plain or \.{\\id\{{\rm identifier $p$}\}};
+
+\item |mod_flag+p| represents module name |p|;
+
+\item |tok_flag+p| represents token list number |p|;
+
+\item |inner_tok_flag+p| represents token list number |p|, to be
+translated without line-break controls.
+\end{itemize}
+@z
+
+ l 1501
+@x
+ else for (j=*p; j<*(p+1); j++) {
+ r=*j%id_flag;
+ switch (*j/id_flag) {
+ case 1: printf("\\{"); print_id((name_dir+r)); printf("}"); break;
+ /* |id_flag| */
+@y
+ else for (j=*p; j<*(p+1); j++) {
+ r=*j%id_flag;
+#ifdef LaTeX
+ switch (*j/id_flag) {
+ case 1: printf("\id{"); print_id((name_dir+r)); printf("}"); break;
+ /* |id_flag| */
+ case 2: printf("\res{"); print_id((name_dir+r)); printf("}"); break;
+ /* |res_flag| */
+ case 3: printf("<"); print_id((name_dir+r)); printf(">"); break;
+ /* |mod_flag| */
+ case 4: printf("[[%d]]",r); break; /* |tok_flag| */
+ case 5: printf("|[[%d]]|",r); break; /* |inner_tok_flag| */
+ default: @<Print token |r| in symbolic form@>;
+ }
+@.\\id@>@.\\res@>
+#else
+ switch (*j/id_flag) {
+ case 1: printf("\\{"); print_id((name_dir+r)); printf("}"); break;
+ /* |id_flag| */
+@z
+
+ l 1512
+@x
+ default: @<Print token |r| in symbolic form@>;
+ }
+ }
+}
+@y
+ default: @<Print token |r| in symbolic form@>;
+ }
+#endif LaTeX
+ }
+}
+@z
+
+ l 2075
+@x
+
+@<Append a string or...@>=
+if (next_control==constant) app_str("\\O{");
+@.\\O@>
+@y
+
+@<Append a string or...@>=
+#ifdef LaTeX
+if (next_control==constant) app_str("\\const{");
+@.\\const@>
+else if (next_control==string) app_str("\\str{");
+@.\\str@>
+else app_str("\\vstr{");
+@.\\vstr@>
+#else
+if (next_control==constant) app_str("\\O{");
+@.\\O@>
+@z
+
+ l 2079
+@x
+@.\\.@>
+else app_str("\\={");
+@.\\=@>
+while (id_first<id_loc) {
+ if (*id_first==at_sign) {
+@y
+@.\\.@>
+else app_str("\\={");
+@.\\=@> /* verbatim string */
+#endif LaTeX
+while (id_first<id_loc) {
+ if (*id_first==at_sign) {
+@z
+
+ l 2197
+@x
+breaks are inserted after the result of tokens like |break_space| and
+|force|. (d) The final line break should be suppressed, and there should
+be no |force| token output immediately after `\.{\\Y\\P}'.
+
+@ The output process uses a stack to keep track of what is going on at
+@y
+breaks are inserted after the result of tokens like |break_space| and
+|force|. (d) The final line break should be suppressed, and there should
+be no |force| token output immediately after `\.{\\Y\\P}' (or `\.{\\Y\\code}'
+with \LaTeX{}).@^\LaTeX@>
+
+@ The output process uses a stack to keep track of what is going on at
+@z
+
+ l 2394
+@x
+looks slightly better if set in a math-italic font instead of a (slightly
+narrower) text-italic font. Thus we output `\.{\\\char'174a}' but
+`\.{\\\\\{aa\}}'.
+
+@<Output an identifier@>=
+out('\\');
+if (a==identifier)
+ if (length(cur_name)==1) out('|')@;
+@.\\|@>
+@y
+looks slightly better if set in a math-italic font instead of a (slightly
+narrower) text-italic font. Thus we output `\.{\\\char'174a}' but
+`\.{\\\\\{aa\}}'. In \LaTeX\ we use `\.{\\ida a}' and `\.{\\id\{aa\}}'.
+@^\LaTeX{}@>
+
+@<Output an identifier@>=
+#ifdef LaTeX
+out('\\');
+if (a==identifier)
+ if (length(cur_name)==1) out_str("ida ");
+@.\\ida@>
+ else out_str("id");
+@.\\id@>
+else out_str("res"); /* |a==res_word| */
+@.\\res@>
+#else
+out('\\');
+if (a==identifier)
+ if (length(cur_name)==1) out('|')@;
+@.\\|@>
+@z
+
+ l 2045
+@x
+else out('&')@; /* |a==res_word| */
+@.\\\&@>
+if (length(cur_name)==1) out((cur_name->byte_start)[0])@;
+else out_name(cur_name);
+@y
+else out('&')@; /* |a==res_word| */
+@.\\\&@>
+#endif LaTeX
+if (length(cur_name)==1) out((cur_name->byte_start)[0])@;
+else out_name(cur_name);
+@z
+
+ l 2430
+@x
+the largest one is used. A line break also occurs in the output file,
+except at the very end of the translation. The very first line break
+is suppressed (i.e., a line break that follows `\.{\\Y\\P}').
+
+@<Look ahead for st...@>= {
+@y
+the largest one is used. A line break also occurs in the output file,
+except at the very end of the translation. The very first line break
+is suppressed (i.e., a line break that follows `\.{\\Y\\code}').
+@^\LaTeX{}@>
+
+@<Look ahead for st...@>= {
+@z
+
+ l 2442
+@x
+ if ((a!=' ' && a<indent) || a==backup || a>big_force) {
+ if (save_mode==outer) {
+ if (out_ptr>out_buf+3 && strncmp(out_ptr-3,"\\Y\\P",4)==0)
+ goto reswitch;
+ @<Output saved |indent| or |outdent| tokens@>;
+@y
+ if ((a!=' ' && a<indent) || a==backup || a>big_force) {
+ if (save_mode==outer) {
+#ifdef LaTeX
+ if (out_ptr>out_buf+3 && strncmp(out_ptr-3,"\\Y\\code",4)==0)@^\LaTeX{}@>@.\\code@>
+#else
+ if (out_ptr>out_buf+3 && strncmp(out_ptr-3,"\\Y\\P",4)==0)
+#endif LaTeX
+ goto reswitch;
+ @<Output saved |indent| or |outdent| tokens@>;
+@z
+
+ l 2632
+@x
+
+@ @<Translate an octal constant appearing in \TeX\ text@>= {
+out_str("\\O{\\~");
+ while ('0'<=*loc && *loc<'8') out(*loc++);
+out('}');
+@y
+
+@ @<Translate an octal constant appearing in \TeX\ text@>= {
+#ifdef LaTeX
+out_str("\\code{\\~"); /* this occurrence of \.{\~} is OK for \LaTeX\ since
+the control sequence is only defined within the scope of the \.{\\code}
+macro */@^\LaTeX{}@>@.\\code@>
+#else
+out_str("\\O{\\~");
+#endif LaTeX
+ while ('0'<=*loc && *loc<'8') out(*loc++);
+out('}');
+@z
+
+ l 2638
+@x
+
+@ @<Translate a hex constant appearing in \TeX\ text@>= {
+out_str("\\O{\\^");
+ while (isxdigit(*loc)) {
+ out(islower(*loc) ? toupper(*loc):*loc);
+@y
+
+@ @<Translate a hex constant appearing in \TeX\ text@>= {
+#ifdef LaTeX
+out_str("\\code{\\^"); /* OK for \LaTeX{} as above */
+@^\LaTeX{}@>@.\\code@>
+#else
+out_str("\\O{\\^");
+#endif LaTeX
+ while (isxdigit(*loc)) {
+ out(islower(*loc) ? toupper(*loc):*loc);
+@z
+
+ l 2662
+@x
+
+@ The |finish_C| procedure outputs the translation of the current
+scraps, preceded by the control sequence `\.{\\P}' and followed by the
+control sequence `\.{\\par}'. It also restores the token and scrap
+memories to their initial empty state.
+@y
+
+@ The |finish_C| procedure outputs the translation of the current
+scraps, preceded by the control sequence `\.{\\P}' (`\.{\\code}' in
+\LaTeX{}) and followed by the@^\LaTeX{}@>
+control sequence `\.{\\par}'. It also restores the token and scrap
+memories to their initial empty state.
+@z
+
+ l 2674
+@x
+{
+ text_pointer p; /* translation of the scraps */
+ out_str("\\P"); app_tok(force); app_scrap(SP_ignore_scrap,no_math);
+ p=translate();
+@.\\P@>
+@y
+{
+ text_pointer p; /* translation of the scraps */
+#ifdef LaTeX
+ out_str("\\code"); app_tok(force); app_scrap(SP_ignore_scrap,no_math);
+@.\\code@>@^\LaTeX{}@>
+#else
+ out_str("\\P"); app_tok(force); app_scrap(SP_ignore_scrap,no_math);
+#endif LaTeX
+ p=translate();
+@.\\P@>
+@z
+
+ l 2710
+@x
+ token following the parameter list@>;
+ if (next_control==@`=') {
+ small_app('\\'); small_app('S'); /* equivalence sign */
+ @<Set |next_control| to the first non-newline token@>@;
+ } else {
+@y
+ token following the parameter list@>;
+ if (next_control==@`=') {
+#ifdef LaTeX
+@^\LaTeX{}@>@.\\equiv@>
+ small_app('\\'); app_str("equiv");
+#else
+ small_app('\\'); small_app('S'); /* equivalence sign */
+#endif LaTeX
+ @<Set |next_control| to the first non-newline token@>@;
+ } else {
+@z
+
+ l 2823
+@x
+ this_module=name_dir; /*so we won't give cross-reference info here*/
+}
+app_str("\\S"); /* output an equivalence sign */
+@.\\S@>
+app_str("{}$");
+small_app(force);
+@y
+ this_module=name_dir; /*so we won't give cross-reference info here*/
+}
+#ifdef LaTeX
+app_str("\\equiv");@^\LaTeX{}@>@.\\equiv@>
+#else
+app_str("\\S"); /* output an equivalence sign */
+@.\\S@>
+#endif LaTeX
+app_str("{}$");
+small_app(force);
+@z
+
+ l 2950
+@x
+if (no_xref) {
+ finish_line();
+ out_str("\\vfill\\end");
+ finish_line();
+}
+@y
+if (no_xref) {
+ finish_line();
+#ifdef LaTeX
+ out_str("\\end{document}");@^\LaTeX{}@>@.\\end{document}@>
+#else
+ out_str("\\vfill\\end");
+#endif LaTeX
+ finish_line();
+}
+@z
+
+ l 2958
+@x
+ finish_line(); @<Tell about changed modules@>;
+ }
+ finish_line(); out_str("\\inx"); finish_line();
+@.\\inx@>
+ @<Do the first pass of sorting@>;
+ @<Sort and output the index@>;
+ out_str("\\fin"); finish_line();
+@.\\fin@>
+ @<Output all the module names@>;
+ out_str("\\con"); finish_line();
+@.\\con@>
+}
+@y
+ finish_line(); @<Tell about changed modules@>;
+ }
+#if 0
+ finish_line(); out_str("\\begin{theindex}"); finish_line();
+#endif
+ finish_line(); out_str("\\inx"); finish_line();
+@.\\inx@>
+ @<Do the first pass of sorting@>;
+ @<Sort and output the index@>;
+#if 0
+ out_str("\\end{theindex}\\fin"); finish_line();
+#endif
+ out_str("\\fin"); finish_line();
+@.\\fin@>
+ @<Output all the module names@>;
+ out_str("\\con\\end{document}"); finish_line();
+@.\\con@>
+}
+@z
+
+ l 3137
+@x
+@ @<Output the name...@>=
+switch (cur_name->ilk) {
+ case normal: if (length(cur_name)==1) out_str("\\|");
+ else out_str("\\\\"); break;
+@y
+@ @<Output the name...@>=
+switch (cur_name->ilk) {
+#ifdef LaTeX#
+ case normal: if (length(cur_name)==1) out_str("\\ida ");
+ else out_str("\\id"); break;
+@^\LaTeX{}@>@.\\ida@>@.\\id@>
+#else
+ case normal: if (length(cur_name)==1) out_str("\\|");
+ else out_str("\\\\"); break;
+@z
+
+ l 3141
+@x
+@.\\|@>
+@.\\\\@>
+ case roman: break;
+ case wildcard: out_str("\\9"); break;
+@.\\9@>
+ case typewriter: out_str("\\."); break;
+@.\\.@>
+@y
+@.\\|@>
+@.\\\\@>
+#endif LaTeX
+ case roman: break;
+ case wildcard: out_str("\\9"); break;
+@.\\9@>
+#ifdef LaTeX
+ case typewriter: out_str("\\str"); break;
+@.\\str@>
+ default: out_str("\\res");
+@.\\res@>@^\LaTeX{}@>
+#else
+ case typewriter: out_str("\\."); break;
+@.\\.@>
+@z
+
+ l 3148
+@x
+ default: out_str("\\&");
+@.\\\&@>
+}
+out_name(cur_name);
+@y
+ default: out_str("\\&");
+@.\\\&@>
+#endif LaTeX
+}
+out_name(cur_name);
+@z
+
+ l 3152
+@x
+
+@ Section numbers that are to be underlined are enclosed in
+`\.{\\[}$\,\ldots\,$\.]'.
+
+@<Output the cross-references...@>=
+@y
+
+@ Section numbers that are to be underlined are enclosed in
+`\.{\\[}$\,\ldots\,$\.]' or `\.{\\underline}$\,\ldots\,$\.\}' in \LaTeX{}.
+@^\LaTeX{}@>
+
+@<Output the cross-references...@>=
+@z
+
+ l 3159
+@x
+ out_str(", "); cur_val=cur_xref->num;
+ if (cur_val<def_flag) out_mod(cur_val);
+ else {out_str("\\["); out_mod(cur_val%def_flag); out(']');}
+@.\\[@>
+ cur_xref=cur_xref->xlink;
+} while (cur_xref!=xmem);
+@y
+ out_str(", "); cur_val=cur_xref->num;
+ if (cur_val<def_flag) out_mod(cur_val);
+#ifdef LaTeX
+ else {out_str("\\underline{"); out_mod(cur_val%def_flag); out('}');}
+@.\\underline@>@^\LaTeX{}@>
+#else
+ else {out_str("\\["); out_mod(cur_val%def_flag); out(']');}
+@.\\[@>
+#endif LaTeX
+ cur_xref=cur_xref->xlink;
+} while (cur_xref!=xmem);
+@z
diff --git a/web/latexspider/web.doc b/web/latexspider/web.doc
new file mode 100644
index 0000000000..65d9df1ca6
--- /dev/null
+++ b/web/latexspider/web.doc
@@ -0,0 +1,955 @@
+\iffalse % -*-latex-*-
+
+%% Copyright D.Love, SERC Daresbury Laboratory, 1991
+%% The `doc' version of this style is re-distributable and usuable
+%% under conditions of the GNU copyleft, but please mark any changes,
+%% list them here and report any major enhancements to the author.
+
+% This is a self-documenting style. To produce the documentation you
+% might use a driver file like this:
+% \def\webmacs{null} \documentstyle[a4,makeidx,newdoc,web]{article}
+% \EnableCrossrefs \CodelineIndex
+% \begin{document} \DocInput{web.sty} \PrintIndex
+% \end{document}
+% and run `makeindex -s gind.ist doc' in between passes. You need
+% Mittelbach's newdoc.sty at v1.6d or later.
+
+% To produce the .sty file use `latex docstrip' to remove most of the
+% comments. Please don't distribute the .sty file without the .doc
+% file.
+\fi
+
+\iffalse % hack RCS info into a sensible form:
+\fi
+\def\next$#1: #2/#3/#4 #5 ${\def\filedate{#4/#3/#2}\def\filetime{#5}}
+\next$Date: 1991/06/19 10:28:40 $
+
+\def\next$#1: #2 ${\def\fileversion{#2}}
+\next$Revision: 1.2 $
+
+% \title{A a \web{} style file for \LaTeX{}\thanks{This file is version
+% \fileversion\ of \filedate}}
+% \author{David Love\\[2ex]{\it SERC Daresbury Laboratory, Warrington
+% WA4 4AD, UK}\\ \tt d.love@daresbury.ac.uk}
+% \date{}
+%
+% \newcommand{\web}{{\tt WEB}}
+% \newcommand{\weave}{{\tt WEAVE}}
+% \newcommand{\tangle}{{\tt tangle}}
+% \newcommand{\spider}{Spider}
+% \MakeShortVerb{\"}
+
+% \DoNotIndex{\/,\@date,\@ifundefined,\@makefnmark,\@starttoc}
+% \DoNotIndex{\@topnum,\addpenalty,addvspace,\advance,aftergroup}
+% \DoNotIndex{\begin,\begingroup,\bgroup,\char,\def,\egroup,\else,\end}
+% \DoNotIndex{\endgroup,\fi,\fnsymbol,\hfil,\hfill,\hfilneg,\hss,\kern}
+% \DoNotIndex{\let,\lineskip,\newcommand,\protect,\qquad,\quad,\relax}
+% \DoNotIndex{\thanks,\thefootnote,\z@,\@M,\@thanks,\@thefnmark,\hbox}
+% \DoNotIndex{\empty,\mbox}
+
+% \maketitle
+%
+% \begin{abstract} \noindent
+% This style file is for use with a version of the Spidery \weave\ system
+% that has been adapted to use \LaTeX\ rather than plain \TeX\ for the
+% formatting. It is a first attempt.
+% \end{abstract}
+%
+% \section{Assumptions of \weave{} and the {\tt .web} file}
+%
+% We assume we're using the version of Spidery \weave{} \cite{spider}
+% changed for \LaTeX\@. This will write out
+% \begin{quote}"\def\webmacs{"\meta{ext}"web.tex}",\end{quote}
+% (where \meta{ext} is
+% the \spider{} {\tt extension}), then the limbo section, then
+% \begin{quote}"\begin{document}\maketitle" \end{quote}
+% the latter to stop you forgetting it. The "\webmacs" file will be
+% included at the end of this style.
+% After the index (if any), we get
+% "\end{document}". The user thus has to put the "\documentstyle"
+% command in the limbo part and include "web" in the style options to
+% get this stuff and can use other options as appropriate. You're
+% meant to use the "article" main style, although I think "report"
+% would work too.
+%
+% \section{Strategy}
+%
+% The idea was to change the original \spider{} \TeX{} stuff as little
+% as possible, although it has actually been changed quite
+% substantially. Changes are forced where there is a clash of macro
+% names; most of the original one-character control sequences are
+% already used by \LaTeX, for instance. Some features have been
+% converted to a \LaTeX{} equivalent,
+% notably the table of contents mechanism, the title page, running
+% header and double-columning for the index. For safety, "\def"s have
+% been replaced by "\newcommands" where possible since there are
+% probably plenty of possibilities for name clashes.
+% User-visible differences from the plain version are given in
+% appendix~\ref{changes}.
+%
+% \section{Use with old webs}
+%
+% Examples of the use of this style with old webs using the plain
+% conventions can be found in the accompanying changes files for
+% {\tt weave.web} and {\tt spider.web}. You can use the limbo section
+% to check whether the generated ".tex" file is being run through
+% \LaTeX\ or plain \TeX\ by doing something like this:
+% \begin{quote}
+% \begin{verbatim}
+% \ifx\enddocument\undefined
+% % plain things
+% \else
+% % LaTeX things
+% \fi
+% \end{verbatim}
+% \end{quote}
+%
+% \section{Bugs}
+%
+% Floats
+% don't always come out where you'd expect due to interaction with
+% \web's attempts to keep all of a module on one page if possible.
+% "\str" and "\vstr", which
+% might well get used in a moving argument, are
+% fragile. Module titles (after "@*") are moving arguments. I think
+% if you use \web's "|"\dots"|" construction in a
+% moving argument it will break and there's not much you can do about
+% it.
+%
+% \section{Code}
+% \subsection{Preliminaries --- page layout}
+%
+% Let's announce ourselves as usual:
+% \begin{macrocode}
+\typeout{Sub-style `web', version \fileversion\space of \filedate}
+% \end{macrocode}
+% We don't want stretch between paragraphs.
+% \begin{macrocode}
+\parskip \z@
+% \end{macrocode}
+% \begin{macro}{\textwidth}\begin{macro}{\textheight}
+% \begin{macro}{\oddsidemargin} \begin{macro}{\evensidemargin}
+% The default page width should be large for \web\@. This is for
+% non-Americans (A4)---if you want to alter the page dimensions with a
+% suitable style option put it {\em after\/} "web" in the
+% "\documentstyle" list. The width here is too big for decently
+% readable text, but is
+% still less than the $6.5''$ of the original. Note that there's no
+% point in trying to use "\marginpar" at
+% this width since the margins have disappeared! The "twoside" option
+% will work sensibly if you care to use it.\DescribeMacro{twoside} We
+% want to avoid doing this when typesetting the documenttation, hence
+% the test for "\DocInput".
+% \begin{macrocode}
+\ifx\DocInput\undefined
+\ifcase \@ptsize
+ \textheight = 53 \baselineskip
+\or
+ \textheight = 47 \baselineskip
+\or
+ \textheight = 43 \baselineskip
+\fi \advance \textheight by \topskip
+\textwidth=6.27in \oddsidemargin=\z@ \evensidemargin=\z@
+\fi
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}
+% We use the "myheadings" page style with headings containing module
+% information (see below).
+% \begin{macrocode}
+\pagestyle{myheadings}
+% \end{macrocode}
+% If we start off with a "\sectionmark" we won't miss the running
+% header off the first page where it should appear.
+% \begin{macrocode}
+\ifx\DocInput\undefined \sectionmark{1} \fi
+% \end{macrocode}
+%
+% \subsubsection{Font selection}
+%
+% \begin{macro}{\normal@font}
+% We have to check whether we're in the old or new font selection scheme
+% and set up appropriately. "\normal@font" is invoked before the font
+% changes for identifiers, reserved words and strings to make sure
+% that they use the default series and shape in the new scheme. This
+% is actually only necessary if "\id", "\res" or "\str" is used in
+% \TeX\ text that is being set in a different shape or series, not
+% normally in the code. If you use the new selection scheme you can
+% do things like using Concrete or PostScript fonts easily.
+% \begin{macrocode}
+\@ifundefined{selectfont}{%
+ \let\normal@font=\relax} % old scheme
+ {% new scheme
+ \def\normal@font{\series \mediumseriesdefault
+ \shape \normalshapedefault}}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Front matter}
+%
+% We depart from the plain version here. The first page (or pages, if
+% the contents are very long) is produced with the "titlepage"
+% environment. The "\author", "\date" and
+% "\title" \DescribeMacro{\title} can be specified
+% as usual in \LaTeX\@. Note that you now say
+% "\title{"\meta{title}"}" rather than "\def\title{"\meta{title}"}" as
+% in the plain version and this title will be used in the running
+% header.
+%
+% \begin{macro}{\@maketitle}
+% We'll re-define "\@maketitle" to include the "\topofcontents" and
+% "\botofcontents" information, with the contents information in the
+% middle. The normal title, author and date will be put automatically
+% at the top---"\topofcontents" is extra. You get the titling and
+% contents information automatically, since "\maketitle" is inserted
+% by \weave{} immediately after "\begin{document}". If you want to
+% suppress it, "\let\maketitle=\relax" in the limbo part.
+%
+% Of course, you have to make two
+% passes to get the contents printed, unlike the original plain
+% system. This should not be much hardship as one usually reckons on
+% running \LaTeX{} at least twice. (Putting the titlepage at the back
+% won't help, since the ".toc" file only exists after the ".aux" file
+% has been read on the secind pass. One could change the standard
+% behaviour so that the ".toc" file was created at the end of the
+% first pass, I guess.)
+% We first test for "\DocInput" as above to
+% avoid messing things up when typesetting the documentation.
+% \begin{macrocode}
+\ifx\DocInput\undefined
+\def\@maketitle{%
+ \newpage \thispagestyle{empty} \null
+ \begin{center}
+ {\LARGE \@title \par} \vskip 1.5em
+ {\large \lineskip .5em
+ \begin{tabular}[t]{c} \@author \end{tabular} \par}
+ \vskip 1em {\large \@date}
+ \end{center}
+ \par \vskip 1.5em
+ \topofcontents \tableofcontents \par \botofcontents \newpage }
+\fi
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\maketitle}
+% We change "\maketitle" to avoid the "\thispagestyle{plain}" that it
+% otherwise contains, to set the page number to 1 at the end and to
+% avoid losing the definitions of "\@title" and "\@author".
+% ("\@title" is used in the running header.)
+% \begin{macrocode}
+\ifx\DocInput\undefined
+\def\maketitle{%
+ \par \begingroup
+ \pagenumbering{roman} \setcounter{page}{0}
+ \def\thefootnote{\fnsymbol{footnote}}
+ \def\@makefnmark{\hbox to \z@ {$^{\@thefnmark}$\hss}}
+ \if@twocolumn \twocolumn[\@maketitle]
+ \else \newpage \global\@topnum\z@ \@maketitle \fi
+ \@thanks
+ \endgroup
+ \setcounter{footnote}{0} \pagenumbering{arabic}
+ \let\maketitle\relax \let\@maketitle\relax
+ \gdef\@thanks{}\let\thanks\relax}
+\fi
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\@title} \begin{macro}{\@author}
+% We better define these in case they're not supplied:
+% \begin{macrocode}
+\let\@title=\empty \let\@author=\empty
+% \end{macrocode}
+% \end{macro} \end{macro}
+% \begin{macro}{\tableofcontents}
+% "\tableofcontents" is re-defined to produce a header saying
+% ``Section'' and ``Page'' a bit like the plain version, although the
+% section (module) number is at the left.
+% \begin{macrocode}
+\def\tableofcontents{%
+ \noindent Section \hfill Page \par \@starttoc{toc}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\topofcontents} \begin{macro}{\botofcontents}
+% The "\topofcontents" material that comes between the title\slash author
+% information and the contents list and the "\botofcontents" stuff
+% that comes after the contents list are empty initially. I'm not
+% sure it's worth preserving them.
+% \begin{macrocode}
+\def\topofcontents{} \def\botofcontents{}
+% \end{macrocode}
+% \end{macro} \end{macro}
+% \begin{macro}{\ttitlefont} \begin{macro}{\titlefont}
+% These are just for compatibility with the plain version---they
+% should probably go.
+% \begin{macrocode}
+\let\ttitlefont=\tt \let\titlefont=\rm
+% \end{macrocode}
+% \end{macro} \end{macro}
+%
+% \subsection{Prettyprinting stuff}
+% \subsubsection{Identifiers, reserved words and strings}
+%
+% \begin{macro}{\id}\begin{macro}{\ida}\begin{macro}{\idfont}
+% Multi-letter identifiers are set by the macro "\id" in font "\idfont",
+% which is italic by default i.e., \id{identifier}.
+% One-letter identifiers are
+% actually set by "\ida" in math italic as they are supposed to look
+% better that way (\ida{a} rather than \id{a}).
+% \begin{macrocode}
+\newcommand{\id}[1]{\mbox{\idfont #1\/\kern.05em}}
+\newcommand{\ida}[1]{\mbox{$ #1 $}}
+\newcommand{\idfont}{\normal@font \it}
+% \end{macrocode}
+% \end{macro} \end{macro} \end{macro}
+% \begin{macro}{\reservedfont}\begin{macro}{\res}
+% Reserved words are set by macro "\res", using "\reservedfont" which
+% is bold by default i.e., \res{reserved}.
+% \begin{macrocode}
+\newcommand{\reservedfont}{\normal@font \bf}
+\newcommand{\res}[1]{\mbox{\reservedfont#1\/}}
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \begin{macro}{\str}
+% Typewriter type is used for strings, set by "\str" i.e.,
+% \str{string}. The definitions of the escaped characters
+% are given below. I don't understand why the ampersand is treated
+% like this, since "\&" is defined anyway, but quotes and "^" are
+% escaped to avoid
+% ligatures.\footnote{{\tt \char`\^} and {\tt \char`\~} form ligatures
+% in PostScript virtual fonts as well as "'".} It's necessary to do a
+% "\def" of "\^" rather than just
+% "\let\^\CF" to avoid an error with the use of "\^" not matching its
+% definition. Note the use of "\@tempa" below rather than "\XX" as
+% used in the same situation elsewhere---using "\XX", "\str" breaks if
+% it is used in, say, a comment.
+% \begin{macrocode}
+\def\str#1{%
+ \ifmmode \gdef\@tempa{\null$\null}\else \gdef\@tempa{}\fi
+ \@tempa {%
+ \let\\=\BS \let\'=\RQ \let\`=\LQ \let\{=\LB \let\}=\RB
+ \let\~=\TL \let\ =\SP \let\&=\AM \def\^{{\tt \char`\^}}%
+ \leavevmode \normal@font\tt #1}\@tempa}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\AM} \begin{macro}{\BS} \begin{macro}{\LB}
+% \begin{macro}{\LQ} \begin{macro}{\RB} \begin{macro}{\UL}
+% \begin{macro}{\TL}
+% Here are the definitions of the control sequences for strings. The
+% plain version redefined "\#", "\$", "\%" and "\^" globally. "\$"
+% isn't used by awk or C \web s, and has been removed. The others are
+% done only in code, using "\startcodehook" (below).
+% \begin{macrocode}
+\chardef\AM=`\& % ampersand
+\chardef\BS=`\\ % backslash
+\chardef\LB=`\{ % left brace
+\def\LQ{{\tt\char'22}} % left quote
+\chardef\RB=`\} % right brace
+\def\RQ{{\tt\char'23}} % right quote
+\def\UL{{\tt\char`\_}} % underline character in a string
+\def\TL{{\tt\char`\~}} % tilde
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}\end{macro}\end{macro}
+% \end{macro}
+% \begin{macro}{\SP}
+% Strings may be rather long and we want some way of breaking
+% them, so
+% "\SP" produces a visible space (\str{\SP}) and also adds a discretionary
+% break afterwords. If a break occurs, the line is ended with a
+% backslash. Spaces are probably the most sensible place to break
+% strings, especially if they are messages, but one could consider
+% doing the same thing for other of the macros above e.g., "\BS" might
+% check if the next character was "n" and insert a discretionary break
+% after that.
+% \begin{macrocode}
+\newcommand{\SP}{\char`\ \discretionary{\hbox{\char`\\}}{}{}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\vstr}
+% This does a verbatim string (from "@=") using the existing \LaTeX
+% nology rather than the original definition to put a frame around it
+% (\vstr{string}).
+% \begin{macrocode}
+\newcommand{\vstr}[1]{\kern 2pt \fbox{\str{#1}}\kern 2pt}
+\setlength{\fboxsep}{2pt}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\const}
+% This looks after setting octal, hex or decimal constants. The first
+% thing in its argument may be one of the control sequences in the
+% example on the left,
+% producing the result in the middle:
+% \[\begin{tabular}{lll}
+% "\const{\$10}" & $\const{\$10}$ & (long) \\
+% "\const{\_10}" & $\const{\_10}$ & (power of ten)\\
+% "\const{\~10}" & $\const{\~10}$ & (octal) \\
+% "\const{\^AB10}" & $\const{\^AB10}$ & (hex) \\
+% \end{tabular}\]
+% \DeleteShortVerb{\"}
+% \begin{macrocode}
+\def\const#1{{%
+ \def\?{\kern.2em}%
+ \def\${\ell}% long
+ \def\_{\RealConstFormat{\aftergroup}}% power of ten
+ \def\~{\hbox{\rm \char'23\kern-.2em \it \aftergroup\?\aftergroup}}% octal
+% \end{macrocode}
+% The \verb+"+ here was originally \verb+\char'175+ which,
+% unfortunately, is different in PostScript virtual fonts and Computer
+% Modern:
+% \begin{macrocode}
+ \def\^{\hbox{\rm "\tt \aftergroup}}% hex
+ #1}} % (\def{\const})
+% \end{macrocode}
+% \end{macro}
+% \MakeShortVerb{\"}
+% \begin{macro}{\RealConstFormat}
+% I prefer to re-define the decimal style
+% to print as the more code-like `$\mbox{\rm e}10$'. You can
+% do this by using the hook "\RealConstFormat" in your Spider "macros"
+% section:
+% \begin{quote} "\newcommand{\RealConstFormat}{\mbox{\rm e}}" .\end{quote}
+% For a go at a Fortran web, I hacked the lexing so that an "e" or "d" in
+% a real or double-precision constant was transmitted verbatim into the
+% argument of "\const" instead of "\_" and re-defined "\const" to ensure
+% this was set in roman.
+% \begin{macrocode}
+\newcommand{\RealConstFormat}{\cdot 10^}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Indentation and breaks}
+%
+% \begin{macro}{\ind}
+% This counter stores the current indentation in ems.
+% \begin{macrocode}
+\newcount\ind
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\bak} \begin{macro}{\bakk}
+% These backspace one and two ems respectively.
+% \begin{macrocode}
+\newbox\bak \setbox\bak=\hbox to \m@ne em{}
+\newbox\bakk \setbox\bakk=\hbox to -2em{}
+% \end{macrocode}
+% \end{macro}\end{macro}
+% \begin{macro}{\0}
+% A forced break, as from "@/":
+% \begin{macrocode}
+\def\0{%
+ \ifmmode
+ \ifinner$\par\hangindent\ind em\noindent\kern\ind em\ignorespaces$\fi
+ \else
+ \par\hangindent\ind em\noindent \kern\ind em\ignorespaces
+ \fi}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\1}
+% Indent one more notch:
+% \begin{macrocode}
+\newcommand{\1}{\global\advance\ind by 1 \hangindent\ind em}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\2}
+% Indent one less notch:
+% \begin{macrocode}
+\newcommand{\2}{\global\advance\ind by \m@ne }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\3}
+% An optional break within a statement, as from "@|":
+% \begin{macrocode}
+\newcommand{\3}[1]{\hfil \penalty#10 \hfilneg}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\4}
+% Backspace one notch:
+% \begin{macrocode}
+\newcommand{\4}{\copy\bak}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\5}
+% Optional break:
+% \begin{macrocode}
+\newcommand{\5}{\hfil \penalty \m@ne \hfilneg \kern 2.5em \copy\bakk
+ \ignorespaces}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\6}
+% A forced break with no indentation:
+% \begin{macrocode}
+\def\6{\ifmmode \else \par
+ \hangindent\ind em\startline \ignorespaces \fi}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\startline}
+% This is used by "\code" as well as "\6" above.
+% \begin{macrocode}
+\def\startline{\noindent \count255=\ind \advance\count255 by -2
+ \hskip\count255 em}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\7}
+% A forced break and a little extra vertical space, as from "@#":
+% \begin{macrocode}
+\newcommand{\7}{\Y\6}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\8}
+% No indentation. It works only in code, not in "|"\dots"|".
+% \begin{macrocode}
+\newcommand{\8}{\unskip}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\J}
+% \tangle's join operation ("@&"):
+% \begin{macrocode}
+\newcommand{\J}{\str{@\&}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\C}
+% This looks after comments. The hooks are inserted because comments
+% aren't code (see below).
+% \begin{macrocode}
+\def\C#1{\ifmmode\gdef\XX{\null$\null}\else\gdef\XX{}\fi
+ \XX \hfil \penalty \m@ne\hfilneg\quad % original spider
+ $\commentbegin\,$\endcodehook{#1}\startcodehook$\,
+ \commentend$\XX}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Modules}
+%
+% \begin{macro}{\onmaybe} \begin{macro}{\maybe} \begin{macro}{\ifon}
+% These switches are concerned with only printing changed sections if
+% so desired.
+% \begin{macrocode}
+\def\onmaybe{\let\ifon=\maybe} \let\maybe=\iftrue \newif\ifon
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+% \begin{macro}{\M}
+% Beginning of an un-starred section:
+% \begin{macrocode}
+\outer\def\M#1.{%
+ \MN#1.\ifon\vfil\penalty-100\vfilneg
+ \vskip12ptminus3pt \startsection \ignorespaces}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\startsection} \begin{macro}{\lapstar}
+% Some auxilliary definitions:
+% \begin{macrocode}
+\def\startsection{\Q \noindent {\let\*=\lapstar \bf \modstar.\quad }}
+\newcommand{\lapstar}{\rlap{*}}
+% \end{macrocode}
+% \end{macro} \end{macro}
+% \begin{macro}{\N}
+% This introduces a starred section (where "#2" is the title). We
+% have to check the title with "\headcheck" for a leading
+% character indicating a subsection. Then we write a contents entry,
+% change the running header and set the title in bold. "\old@S" is
+% used in the header rather than "\S" since "\S" is probably
+% wrongly-defined at this point (see below).
+% \begin{macrocode}
+\outer\def\N#1.#2.{%
+ \MN#1.\headcheck#2\headcheck
+ \typeout{*\modno} % progress report
+ \addcontentsline{toc}{\headcheck@type}
+ {\hbox to 2em{\modno\hfill} \quad \theopen \relax \themodtitle}
+ \markboth{% running headline
+ {\protect\small \qquad\uppercase{\ignorespaces\themodtitle}}
+ \hfill {\protect\small \@title}\qquad{\rm \old@S \modno}}
+ {\rm \old@S \modno\qquad {\protect\small \@title}\hfill
+ {\protect\small \uppercase{\ignorespaces\themodtitle\qquad}}}
+ \ifon\startsection {\bf \ignorespaces \themodtitle.\quad }\ignorespaces}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\MN}
+
+% Here is some common code for "\M" and "\N"\@.
+% It sets
+% "\sectionmark" for the headers and defines cross-referencing
+% information for the current module.
+% It also
+% looks after the decision about whether or not to set this module if it
+% is not starred.
+% \begin{macrocode}
+\def\MN#1.{%
+ \par {\xdef\modstar{#1}\let\*=\empty\xdef\modno{#1}}%
+ \ifx\modno\modstar \onmaybe \else \ontrue \fi
+ \sectionmark{\modno}
+% \end{macrocode}
+% The following code for setting the currentlabel to the module number
+% is a variation on that in {\tt latex.tex}.
+% \begin{macrocode}
+ \let\@tempa\protect
+ \def\protect{\noexpand\protect\noexpand}%
+ \def\@currentlabel{#1}%
+ \let\protect\@tempa} % def\MN
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\note} \begin{macro}{\A}
+% Auxilliary macros. "\A" is for cross-references for multiply
+% defined section names.
+% \begin{macrocode}
+\def\note#1#2.{\Y \noindent {\hangindent 2em \footnotesize
+ \baselineskip 10pt#1 #2.\par}}
+\newcommand{\A}{\note{See also}}
+% \end{macrocode}
+% \end{macro} \end{macro}
+%
+% \subsubsection{Processing special section headings}
+%
+% This complicated stuff, introduced with \spider{} and modified for the
+% \LaTeX{} version, is to allow an inital =, 1, 2, 3 or 4 in
+% starred module titles to indicate a hierarchy. Their effect is as follows:
+% \[ \begin{tabular}{c|c|c}
+% Introduction & Page eject? & Indentation in contents\\ \hline
+% "@*=" & yes & 0 \\
+% "@*1" & yes & 2 em \\
+% "@*2" & no & 2 em \\
+% "@*3" & yes & 4 em \\
+% "@*4" & no & 4 em \\
+% \end{tabular} \]
+% "@*=" also suppresses a following page eject and emboldens the
+% table of contents entry and puts some extra vertical space before
+% it. Normal starred sections have no indentation in the contents and
+% don't do anything special about page breaks.
+%
+% \begin{macro}{\l@part} \begin{macro}{\l@norm} \begin{macro}{\l@num}
+% Two new sorts of contents entry are defined here and the `part'
+% type re-defined. (See "latex.tex" for details of how this works.)
+% "\l@part" determines the t.o.c.\ entry for a "@*=" section,
+% "\l@norm" the entry for a normal starred section and "\l@num" that
+% for a numbered section. Some penalties are inserted (the normal
+% values for the main style) in case the t.o.c.\ extends over more
+% than one page. The "\headcheck@type" definition is used in the
+% sectioning commands to write the t.o.c.\ entry.
+% \begin{macrocode}
+\def\l@part{\addpenalty{\@secpenalty}
+ \addvspace{3pt plus 1pt} % space above part line
+ \@dottedtocline{0}{\z@ }{4em}}
+\def\l@norm{\addpenalty{\@secpenalty}
+ \@dottedtocline{0}{\z@ }{4em}}
+\def\l@num{\@dottedtocline{0}{0em}{4em}}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+% \begin{macro}{\ifcancel} \begin{macro}{\ifnextchar}
+% \begin{macro}{\ifnch} \begin{macro}{\makethechar}
+% Here's the tricky stuff, presented without further comment!
+% \begin{macrocode}
+\newif\ifcancel \cancelfalse
+\def\ifnextchar#1#2#3{%
+ \let\@tempe=#1\def\@tempa{#2}\def\@tempb{#3}\@ifnch}
+\def\@ifnch{%
+ \ifx \@tempc \@tempe\let\@tempd\@tempa
+ \else \let\@tempd\@tempb
+ \fi
+ \@tempd}
+\def\makethechar#1{\let\@tempc=#1}
+% \end{macrocode}
+% \end{macro} \end{macro} \end{macro} \end{macro}
+% \begin{macro}{\headcheck}
+% ~
+% \begin{macrocode}
+\def\headcheck#1#2\headcheck{%
+ \makethechar{#1}%
+ \def\theskipper{\vfil\penalty-100 % skip before new module
+ \vfilneg\vskip12ptminus3pt}%
+ \def\theopen{}% opening skip in toc entry
+ \def\thetocskip{}% vertical skip before toc entry
+ \def\themodtitle{{#2}}%
+ \def\headcheck@type{num}%
+ \ifnextchar={%
+ \def\theskipper{\newpage} \canceltrue
+ \def\headcheck@type{part} \def\theopen{\bf}%
+ \def\thetocskip{\vskip 3pt plus 1in \penalty-100
+ \vskip \z@ plus -1in}%
+ }{\ifnextchar1{%
+ \cancelfalse \def\theskipper{\newpage}%
+ \def\theopen{\hskip2em}%
+ }{\ifnextchar2{%
+ \cancelfalse \def\theopen{\hskip2em}%
+ }{\ifnextchar3{%
+ \cancelfalse \def\theskipper{\newpage}%
+ \def\theopen{\hskip4em}%
+ }{\ifnextchar4{%
+ \cancelfalse \def\theopen{\hskip4em}%
+ }{% else
+ \ifcancel\else \def\theskipper{\newpage}\fi
+ \cancelfalse \def\headcheck@type{norm}%
+ \def\themodtitle{#1{#2}}%
+ }}}}}%
+ \theskipper }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Starting and ending code sections}
+%
+% \begin{macro}{\code}
+% This takes us into code mode. The old version used infinite hyphen
+% penalty which stopped the discretionary breaks in strings. Extra
+% space is put after ";" with the "\sfcode".
+% \begin{macrocode}
+\newcommand{\code}{%
+ \rightskip=\z@ plus 100pt minus 10pt
+ \sfcode`;=3000 \pretolerance \@M
+ \hyphenpenalty 9999 \exhyphenpenalty \@M
+ \global\ind=2 \1 \startline
+% \end{macrocode}
+% \DescribeMacro{\@}
+% The original says that every web must define "\?", where "?" is the
+% at-sign. Since "\@" is used for end-of-sentence space in \LaTeX, we
+% make sure this is only done in code mode. We need the old and new
+% definitions, "\old@" and "\code@", between which to switch.
+% \spider{} unfortunately uses "\S" instead of "\equiv" and the awk
+% and C \web s assume that "\%" and "\#" translate to typewriter
+% versions, so we have to define these properly in code mode too.
+% \DescribeMacro{\startcodehook} \DescribeMacro{\endcodehook}
+% For convenience, we define token registers
+% "\startcodehook" and "\endcodehook" for this sort of purpose when we
+% go into and out of code mode. These might be altered by the
+% \spider\ description if appropriate.
+% \begin{macrocode}
+ \startcodehook} % \def\code
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\old@}\begin{macro}{\code@}\begin{macro}{\old@S}
+% \begin{macro}{\old@percent} \begin{macro}{\old@hash}
+% Let's store the original definitions of these:
+% \begin{macrocode}
+\let\old@=\@ \let\old@S=\S \let\old@percent=\%
+\let\old@hash=\#
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}\end{macro}
+% \begin{macro}{\code@}\begin{macro}{\tt@percent}\begin{macro}{\tt@hash}
+% And here are replacements for use in code mode.
+% \begin{macrocode}
+\chardef\code@=`\@
+\def\tt@percent{\hbox{\tt\char`\%}} \def\tt@hash{\hbox{\tt\char`\#}}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+% \begin{macro}{\startcodehook}\begin{macro}{\endcodehook}
+% Here are the hooks. Should these be token registers?
+% \begin{macrocode}
+\def\startcodehook{\let\@=\code@ \let\S=\equiv \let\%=\tt@percent
+ \let\#=\tt@hash \def\^{\hbox{\tt\char`\^}}}
+\def\endcodehook{\let\@=\old@ \let\S=\old@S \let\%=\old@percent
+ \let\#=\old@hash \def\^##1{{\accent94 ##1}}}
+% \end{macrocode}
+% \end{macro}\end{macro}
+% \begin{macro}{\Q}
+% This gets us out of code mode, setting things back to normal.
+% \begin{macrocode}
+\def\Q{\rightskip=\z@ \sfcode`;=1500 \pretolerance 200
+ \endcodehook}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\CD} \begin{macro}{\DC}
+% Web text in "|"\dots"|" is woven into text surrounded by
+% "\CD"\dots"\DC"\@. The original definition didn't bother with the
+% grouping if not in math mode, but it's convenient now that the hooks
+% need to be added.
+% \begin{macrocode}
+\def\DC{\endcodehook \egroup}
+\def\CD{\relax
+ \ifmmode \hbox\fi \bgroup \startcodehook}
+% \end{macrocode}
+% \end{macro}\end{macro}
+% \begin{macro}{\U}
+% This provides a cross-reference for uses of sections.
+% \begin{macrocode}
+\newcommand{\U}{\note{This code is used in}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\X}
+% This does modules which introduce the code. Note the usage:
+% "\X"\meta{module number}":"\meta{module name}"\X".
+% \begin{macrocode}
+\def\X#1:#2\X{%
+ \ifmmode \gdef\XX{\null$\null}\else \gdef\XX{}\fi
+ \XX$\langle\,$#2{\footnotesize \kern.5em #1}$\,\rangle$\XX }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\XF}
+% This is for a file module (from "@("):
+% \begin{macrocode}
+\def\XF#1:#2\XF{%
+ \ifmmode \gdef\XX{\null$\null}\else \gdef\XX{}\fi
+ \XX {\tt (#2{\footnotesize \kern.5em #1})}\XX}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\Y} \begin{macro}{\yskip}
+% This does a vertical skip by "\yskip", used in "\note" and "\7".
+% \begin{macrocode}
+\newcommand{\Y}{\par\yskip}
+\let\yskip=\smallskip
+% \end{macrocode}
+% \end{macro}\end{macro}
+%
+% \subsection{Definitions and formats}
+%
+% \begin{macro}{\D} \begin{macro}{\F} \begin{macro}{\defin}
+% "\D" and "\F" deal with macro and format definitions from "@d" and
+% "@f" respectively.
+% \begin{macrocode}
+\newcommand{\D}{\defin{define}} % macro definition
+\newcommand{\F}{\defin{format}} % format definition
+\newcommand{\defin}[1]{\global\advance\ind by 2 \1\res{#1 }}
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}
+%
+% \subsection{Miscellaneous symbols}
+%
+% \begin{macro}{\DO} \begin{macro}{\G} \begin{macro}{\I}
+% \begin{macro}{\K} \begin{macro}{\L} \begin{macro}{\R}
+% \begin{macro}{\TI} \begin{macro}{\V} \begin{macro}{\W}
+% Here are some miscellaneous symbols. I think these should really be
+% defined in the \spider\ descriptions that need them, but they are
+% assumed by the current webs.
+% \begin{macrocode}
+\newcommand{\DO}{\hbox{\sl\char'044}} % slant dollar sign (used by awkweb)
+\let\G=\ge % greater than or equal sign
+\let\I=\ne % unequal sign
+\let\K=\gets % left arrow
+\let\L=\le % less than or equal sign
+\let\R=\lnot % logical not
+\let\TI=\sim % tilde
+\let\V=\lor % logical or
+\let\W=\land % logical and
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}\end{macro}\end{macro}
+% \end{macro}\end{macro}\end{macro}
+% \begin{macro}{\vert} \begin{macro}{\amp} \begin{macro}{\PP}
+% \begin{macro}{\*}
+% And some more: (n.b., the plain \TeX{} definitions of "\vert"
+% and "\*" are over-written, as expected by spidery \weave---maybe this
+% should be changed).
+% \begin{macrocode}
+\def\vert{|} \let\amp=\& \let\PP=\P \let\*=*
+% \end{macrocode}
+% \end{macro}\end{macro}\end{macro}\end{macro}
+% \begin{macro}{\AT!}
+% \changes{v1.2}{10/6/91}{Re-instate trailing !.}
+% This is the `at sign in control
+% text'. I dn't know why it has the trailing "!", but it apears to
+% have bene intentional in the plain version.
+% \begin{macrocode}
+\def\AT!{@}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Indexing}
+%
+% \begin{macro}{\ch}
+% This is used trivially at the start of the index in the case of
+% changes:
+% \begin{macrocode}
+\def\ch{\note{The following sections were changed by the change file:}
+ \let\*=\relax}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\inx} \begin{macro}{\:}
+% The index is set in two-column mode.
+% Each item in each index is introduced by "\:". This is a \LaTeX{}
+% macro but is unlikely to get used in the index and so is preserved
+% from the original.
+% \begin{macrocode}
+\def\inx{%
+ \typeout{Index:}
+ \begin{multicols}{2}
+ \parskip \z@ plus .5pt
+ \parfillskip \z@ plus .6\hsize % try to avoid almost empty lines
+ \outer\def\:##1, {\par\hangindent2em\noindent##1:\kern1em} % index entry
+ \rm \tolerance \@M \let\*=\lapstar
+ \hyphenpenalty \@M \parindent=\z@ }
+% \end{macrocode}
+% \end{macro}\end{macro}
+% \begin{macro}{\fin}
+% This finishes off the name index and starts off the module index.
+% "\:" acts as in "\inx". The modules may be
+% qualified with "\U", which cross-references section uses. The page
+% header is changed appropriately.
+% \begin{macrocode}
+\def\fin{%
+ \end{multicols} \newpage
+ \parfillskip \z@ plus 1fil
+ \markboth{{\protect\small NAMES OF THE SECTIONS}\hfill
+ {\protect\small\@title}}
+ {{\protect\small\@title}\hfill
+ {\protect\small NAMES OF THE SECTIONS\quad}}
+ \typeout{Section names:}
+ \def\note##1##2.{\quad{\footnotesize##1 ##2.}}
+ \def\U{\note{Used in}}%
+ \def\:{\par\hangindent 2em}\let\*=*}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\con}
+% This finishes everything off, rather trivially. (It used to make
+% the contents page.)
+% \begin{macrocode}
+\newcommand{\con}{\end{document}}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Including other files}
+%
+% \DescribeEnv{multicols}
+% We need the {\tt multicols} environment to make a two-column index
+% without a forced page break.
+% \begin{macrocode}
+\input{multicol.sty}
+% \end{macrocode}
+% \DescribeMacro{\webmacs}
+% Finally we include the macros defined by \spider. Doing things this way
+% means that \spider{} can override things done in this file for the
+% \web{} system of a particular language (like the
+% definition of "\res", for instance) and the limbo section can do
+% further overriding for a particular web file. If we're using this
+% file to document itself, "\webmacs" should have been defined in the
+% driver file to be "null"!
+% \begin{macrocode}
+\input{\webmacs}
+% \end{macrocode}
+% "\webmacs" is no further use and we might as well save the space.
+% \begin{macrocode}
+\let\webmacs=\empty
+% \end{macrocode}
+%
+% \appendix
+% \section{Changes from the plain version}\label{changes}
+%
+% \begin{description}
+% \item[{\tt \BS.}] becomes "\str";
+% \item[{\tt \BS\char`\^}] has been removed from the global
+% definitions (where it was assumed by the "c.spider" translation for
+% "^") and put in limbo in "weave.ch";
+% \item[{\tt \BS\%}, {\tt \BS\#} and {\tt \BS\$}] also removed from global
+% definitions and put in "\startcodehook";
+% \item[{\tt \BS\char`\~}] removed globally since it doesn't seem to be used;
+% \item[{\tt \BS\BS} and {\tt \BS|}] become "\id" and "\ida" respectively;
+% \item[{\tt \BS\&}] becomes "\res";
+% \item[{\tt \BS B} and {\tt \BS T}] (for controlled comments) removed
+% since no controlled comments in \spider;
+% \item[{\tt \BS)}] (string pool check sum) removed;
+% \item[{\tt \BS]}] (sign for forced line break) appears not be be
+% used, so removed;
+% \item[{\tt \BS=}] becomes "\vstr";
+% \item[{\tt \BS H}] (hat) removed since it seems not to be used and
+% clashes with \LaTeX;
+% \item[{\tt \BS Z}] replaced by \LaTeX{} contents stuff;
+% \item[{\tt \BS lheader} and {\tt \BS rheader}] replaced by \LaTeX{} marks;
+% \item[output routine stuff] all gone;
+% \item[{\tt \BS rhead}] no longer relevant---use the \LaTeX{} mark
+% mechanism;
+% \item[{\tt \BS title}] should be called as a macro with the title as
+% its argument rather than "\def"ed;
+% \item[{\tt \BS contentspagenumber}, {\tt \BS contentsfile} and {\tt
+% \BS readcontents}] no longer relevant;
+% \item[{\tt \BS pagewidth}, {\tt \BS pageheight} and {\tt \BS
+% fullpageheight}] no longer relevant---use the \LaTeX\ equivalents;
+% \item[{\tt \BS pageshift}] no longer relevant---use "twoside" option;
+% \item[verbatim macros] no longer relevant;
+% \item[{\tt \BS iftitle}] removed---use "\pagestyle{empty}" to
+% suppress page header.
+% \end{description}
+%
+% \begin{thebibliography}{1}
+% \bibitem{spider} N. Ramsey, {\sl Comm. ACM}, {\bf 32} (1989) 1051
+% \end{thebibliography}
diff --git a/web/latexspider/web.sty b/web/latexspider/web.sty
new file mode 100644
index 0000000000..00b93d0cb3
--- /dev/null
+++ b/web/latexspider/web.sty
@@ -0,0 +1,277 @@
+%%
+%% This is file `web.sty' generated
+%% on <1991/6/19> with the docstrip utility (v1.1l test).
+%%
+%% The original source file was `web.doc'.
+%%
+%% You are not allowed to distribute this file without the corresponding
+%% `.doc' version containing the documentation.
+%%
+\iffalse % -*-latex-*-
+
+%% Copyright D.Love, SERC Daresbury Laboratory, 1991
+%% The `doc' version of this style is re-distributable and usuable
+%% under conditions of the GNU copyleft, but please mark any changes,
+%% list them here and report any major enhancements to the author.
+
+
+\fi
+
+\iffalse % hack RCS info into a sensible form:
+\fi
+\def\next$#1: #2/#3/#4 #5 ${\def\filedate{#4/#3/#2}\def\filetime{#5}}
+\next$Date: 91/04/30 19:30:11 $
+
+\def\next$#1: #2 ${\def\fileversion{#2}}
+\next$Revision: 1.1 $
+
+
+
+\typeout{Sub-style `web', version \fileversion\space of \filedate}
+\parskip \z@
+\ifx\DocInput\undefined
+\ifcase \@ptsize
+ \textheight = 53 \baselineskip
+\or
+ \textheight = 47 \baselineskip
+\or
+ \textheight = 43 \baselineskip
+\fi \advance \textheight by \topskip
+\textwidth=6.27in \oddsidemargin=\z@ \evensidemargin=\z@
+\fi
+\pagestyle{myheadings}
+\ifx\DocInput\undefined \sectionmark{1} \fi
+\@ifundefined{selectfont}{%
+ \let\normal@font=\relax} % old scheme
+ {% new scheme
+ \def\normal@font{\series \mediumseriesdefault
+ \shape \normalshapedefault}}
+\ifx\DocInput\undefined
+\def\@maketitle{%
+ \newpage \thispagestyle{empty} \null
+ \begin{center}
+ {\LARGE \@title \par} \vskip 1.5em
+ {\large \lineskip .5em
+ \begin{tabular}[t]{c} \@author \end{tabular} \par}
+ \vskip 1em {\large \@date}
+ \end{center}
+ \par \vskip 1.5em
+ \topofcontents \tableofcontents \par \botofcontents \newpage }
+\fi
+\ifx\DocInput\undefined
+\def\maketitle{%
+ \par \begingroup
+ \pagenumbering{roman} \setcounter{page}{0}
+ \def\thefootnote{\fnsymbol{footnote}}
+ \def\@makefnmark{\hbox to \z@ {$^{\@thefnmark}$\hss}}
+ \if@twocolumn \twocolumn[\@maketitle]
+ \else \newpage \global\@topnum\z@ \@maketitle \fi
+ \@thanks
+ \endgroup
+ \setcounter{footnote}{0} \pagenumbering{arabic}
+ \let\maketitle\relax \let\@maketitle\relax
+ \gdef\@thanks{}\let\thanks\relax}
+\fi
+\let\@title=\empty \let\@author=\empty
+\def\tableofcontents{%
+ \noindent Section \hfill Page \par \@starttoc{toc}}
+\def\topofcontents{} \def\botofcontents{}
+\let\ttitlefont=\tt \let\titlefont=\rm
+\newcommand{\id}[1]{\mbox{\idfont #1\/\kern.05em}}
+\newcommand{\ida}[1]{\mbox{$ #1 $}}
+\newcommand{\idfont}{\normal@font \it}
+\newcommand{\reservedfont}{\normal@font \bf}
+\newcommand{\res}[1]{\mbox{\reservedfont#1\/}}
+\def\str#1{%
+ \ifmmode \gdef\@tempa{\null$\null}\else \gdef\@tempa{}\fi
+ \@tempa {%
+ \let\\=\BS \let\'=\RQ \let\`=\LQ \let\{=\LB \let\}=\RB
+ \let\~=\TL \let\ =\SP \let\&=\AM \def\^{{\tt \char`\^}}%
+ \leavevmode \normal@font\tt #1}\@tempa}
+\chardef\AM=`\& % ampersand
+\chardef\BS=`\\ % backslash
+\chardef\LB=`\{ % left brace
+\def\LQ{{\tt\char'22}} % left quote
+\chardef\RB=`\} % right brace
+\def\RQ{{\tt\char'23}} % right quote
+\def\UL{{\tt\char`\_}} % underline character in a string
+\def\TL{{\tt\char`\~}} % tilde
+\newcommand{\SP}{\char`\ \discretionary{\hbox{\char`\\}}{}{}}
+\newcommand{\vstr}[1]{\kern 2pt \fbox{\str{#1}}\kern 2pt}
+\setlength{\fboxsep}{2pt}
+\def\const#1{{%
+ \def\?{\kern.2em}%
+ \def\${\ell}% long
+ \def\_{\RealConstFormat{\aftergroup}}% power of ten
+ \def\~{\hbox{\rm \char'23\kern-.2em \it \aftergroup\?\aftergroup}}% octal
+ \def\^{\hbox{\rm "\tt \aftergroup}}% hex
+ #1}} % (\def{\const})
+\newcommand{\RealConstFormat}{\cdot 10^}
+\newcount\ind
+\newbox\bak \setbox\bak=\hbox to \m@ne em{}
+\newbox\bakk \setbox\bakk=\hbox to -2em{}
+\def\0{%
+ \ifmmode
+ \ifinner$\par\hangindent\ind em\noindent\kern\ind em\ignorespaces$\fi
+ \else
+ \par\hangindent\ind em\noindent \kern\ind em\ignorespaces
+ \fi}
+\newcommand{\1}{\global\advance\ind by 1 \hangindent\ind em}
+\newcommand{\2}{\global\advance\ind by \m@ne }
+\newcommand{\3}[1]{\hfil \penalty#10 \hfilneg}
+\newcommand{\4}{\copy\bak}
+\newcommand{\5}{\hfil \penalty \m@ne \hfilneg \kern 2.5em \copy\bakk
+ \ignorespaces}
+\def\6{\ifmmode \else \par
+ \hangindent\ind em\startline \ignorespaces \fi}
+\def\startline{\noindent \count255=\ind \advance\count255 by -2
+ \hskip\count255 em}
+\newcommand{\7}{\Y\6}
+\newcommand{\8}{\unskip}
+\newcommand{\J}{\str{@\&}}
+\def\C#1{\ifmmode\gdef\XX{\null$\null}\else\gdef\XX{}\fi
+ \XX \hfil \penalty \m@ne\hfilneg\quad % original spider
+ $\commentbegin\,$\endcodehook{#1}\startcodehook$\,
+ \commentend$\XX}
+\def\onmaybe{\let\ifon=\maybe} \let\maybe=\iftrue \newif\ifon
+\outer\def\M#1.{%
+ \MN#1.\ifon\vfil\penalty-100\vfilneg
+ \vskip12ptminus3pt \startsection \ignorespaces}
+\def\startsection{\Q \noindent {\let\*=\lapstar \bf \modstar.\quad }}
+\newcommand{\lapstar}{\rlap{*}}
+\outer\def\N#1.#2.{%
+ \MN#1.\headcheck#2\headcheck
+ \typeout{*\modno} % progress report
+ \addcontentsline{toc}{\headcheck@type}
+ {\hbox to 2em{\modno\hfill} \quad \theopen \relax \themodtitle}
+ \markboth{% running headline
+ {\protect\small \qquad\uppercase{\ignorespaces\themodtitle}}
+ \hfill {\protect\small \@title}\qquad{\rm \old@S \modno}}
+ {\rm \old@S \modno\qquad {\protect\small \@title}\hfill
+ {\protect\small \uppercase{\ignorespaces\themodtitle\qquad}}}
+ \ifon\startsection {\bf \ignorespaces \themodtitle.\quad }\ignorespaces}
+
+\def\MN#1.{%
+ \par {\xdef\modstar{#1}\let\*=\empty\xdef\modno{#1}}%
+ \ifx\modno\modstar \onmaybe \else \ontrue \fi
+ \sectionmark{\modno}
+ \let\@tempa\protect
+ \def\protect{\noexpand\protect\noexpand}%
+ \def\@currentlabel{#1}%
+ \let\protect\@tempa} % def\MN
+\def\note#1#2.{\Y \noindent {\hangindent 2em \footnotesize
+ \baselineskip 10pt#1 #2.\par}}
+\newcommand{\A}{\note{See also}}
+\def\l@part{\addpenalty{\@secpenalty}
+ \addvspace{3pt plus 1pt} % space above part line
+ \@dottedtocline{0}{\z@ }{4em}}
+\def\l@norm{\addpenalty{\@secpenalty}
+ \@dottedtocline{0}{\z@ }{4em}}
+\def\l@num{\@dottedtocline{0}{0em}{4em}}
+\newif\ifcancel \cancelfalse
+\def\ifnextchar#1#2#3{%
+ \let\@tempe=#1\def\@tempa{#2}\def\@tempb{#3}\@ifnch}
+\def\@ifnch{%
+ \ifx \@tempc \@tempe\let\@tempd\@tempa
+ \else \let\@tempd\@tempb
+ \fi
+ \@tempd}
+\def\makethechar#1{\let\@tempc=#1}
+\def\headcheck#1#2\headcheck{%
+ \makethechar{#1}%
+ \def\theskipper{\vfil\penalty-100 % skip before new module
+ \vfilneg\vskip12ptminus3pt}%
+ \def\theopen{}% opening skip in toc entry
+ \def\thetocskip{}% vertical skip before toc entry
+ \def\themodtitle{{#2}}%
+ \def\headcheck@type{num}%
+ \ifnextchar={%
+ \def\theskipper{\newpage} \canceltrue
+ \def\headcheck@type{part} \def\theopen{\bf}%
+ \def\thetocskip{\vskip 3pt plus 1in \penalty-100
+ \vskip \z@ plus -1in}%
+ }{\ifnextchar1{%
+ \cancelfalse \def\theskipper{\newpage}%
+ \def\theopen{\hskip2em}%
+ }{\ifnextchar2{%
+ \cancelfalse \def\theopen{\hskip2em}%
+ }{\ifnextchar3{%
+ \cancelfalse \def\theskipper{\newpage}%
+ \def\theopen{\hskip4em}%
+ }{\ifnextchar4{%
+ \cancelfalse \def\theopen{\hskip4em}%
+ }{% else
+ \ifcancel\else \def\theskipper{\newpage}\fi
+ \cancelfalse \def\headcheck@type{norm}%
+ \def\themodtitle{#1{#2}}%
+ }}}}}%
+ \theskipper }
+\newcommand{\code}{%
+ \rightskip=\z@ plus 100pt minus 10pt
+ \sfcode`;=3000 \pretolerance \@M
+ \hyphenpenalty 9999 \exhyphenpenalty \@M
+ \global\ind=2 \1 \startline
+ \startcodehook} % \def\code
+\let\old@=\@ \let\old@S=\S \let\old@percent=\%
+\let\old@hash=\#
+\chardef\code@=`\@
+\def\tt@percent{\hbox{\tt\char`\%}} \def\tt@hash{\hbox{\tt\char`\#}}
+\def\startcodehook{\let\@=\code@ \let\S=\equiv \let\%=\tt@percent
+ \let\#=\tt@hash \def\^{\hbox{\tt\char`\^}}}
+\def\endcodehook{\let\@=\old@ \let\S=\old@S \let\%=\old@percent
+ \let\#=\old@hash \def\^##1{{\accent94 ##1}}}
+\def\Q{\rightskip=\z@ \sfcode`;=1500 \pretolerance 200
+ \endcodehook}
+\def\DC{\endcodehook \egroup}
+\def\CD{\relax
+ \ifmmode \hbox\fi \bgroup \startcodehook}
+\newcommand{\U}{\note{This code is used in}}
+\def\X#1:#2\X{%
+ \ifmmode \gdef\XX{\null$\null}\else \gdef\XX{}\fi
+ \XX$\langle\,$#2{\footnotesize \kern.5em #1}$\,\rangle$\XX }
+\def\XF#1:#2\XF{%
+ \ifmmode \gdef\XX{\null$\null}\else \gdef\XX{}\fi
+ \XX {\tt (#2{\footnotesize \kern.5em #1})}\XX}
+\newcommand{\Y}{\par\yskip}
+\let\yskip=\smallskip
+\newcommand{\D}{\defin{define}} % macro definition
+\newcommand{\F}{\defin{format}} % format definition
+\newcommand{\defin}[1]{\global\advance\ind by 2 \1\res{#1 }}
+\newcommand{\DO}{\hbox{\sl\char'044}} % slant dollar sign (used by awkweb)
+\let\G=\ge % greater than or equal sign
+\let\I=\ne % unequal sign
+\let\K=\gets % left arrow
+\let\L=\le % less than or equal sign
+\let\R=\lnot % logical not
+\let\TI=\sim % tilde
+\let\V=\lor % logical or
+\let\W=\land % logical and
+\def\vert{|} \let\amp=\& \let\PP=\P \let\*=*
+\def\AT!{@}
+\def\ch{\note{The following sections were changed by the change file:}
+ \let\*=\relax}
+\def\inx{%
+ \typeout{Index:}
+ \begin{multicols}{2}
+ \parskip \z@ plus .5pt
+ \parfillskip \z@ plus .6\hsize % try to avoid almost empty lines
+ \outer\def\:##1, {\par\hangindent2em\noindent##1:\kern1em} % index entry
+ \rm \tolerance \@M \let\*=\lapstar
+ \hyphenpenalty \@M \parindent=\z@ }
+\def\fin{%
+ \end{multicols} \newpage
+ \parfillskip \z@ plus 1fil
+ \markboth{{\protect\small NAMES OF THE SECTIONS}\hfill
+ {\protect\small\@title}}
+ {{\protect\small\@title}\hfill
+ {\protect\small NAMES OF THE SECTIONS\quad}}
+ \typeout{Section names:}
+ \def\note##1##2.{\quad{\footnotesize##1 ##2.}}
+ \def\U{\note{Used in}}%
+ \def\:{\par\hangindent 2em}\let\*=*}
+\newcommand{\con}{\end{document}}
+\input{multicol.sty}
+\input{\webmacs}
+\let\webmacs=\empty
+
+%% \endinput
diff --git a/web/latexspider/web.tex b/web/latexspider/web.tex
new file mode 100644
index 0000000000..0154639cf1
--- /dev/null
+++ b/web/latexspider/web.tex
@@ -0,0 +1,13 @@
+\def\webmacs{null}
+\documentstyle[a4,%
+%times,%
+makeidx,%
+newdoc,web]{article}
+\EnableCrossrefs
+\CodelineIndex
+\begin{document}
+\DocInput{web.doc}
+\PrintIndex
+\end{document}
+
+
diff --git a/web/latexspider/webmakefile b/web/latexspider/webmakefile
new file mode 100644
index 0000000000..42070774db
--- /dev/null
+++ b/web/latexspider/webmakefile
@@ -0,0 +1,172 @@
+# Copyright 1989 by Norman Ramsey, Odyssey Research Associates
+# To be used for research purposes only
+# For more information, see file COPYRIGHT in the parent directory
+# Modified by Dave Love, Daresbury Lab (d.love@daresbury.ac.uk) for local
+# setup and to incorporate change files, particularly for LaTeX mods.
+# To make LaTeX versions of weave, set WEAVECHANGEFILE=$(MASTER)/weave.ltx
+# and include -DLaTeX in CFLAGS. To get a version of spider.awk usable for
+# LaTeX or plain, define SPIDERCHANGEFILE=$(MASTER)/spider.ltx and define
+# LaTeX=1 so that spider.awk generates LaTeX-compatible webs. I'm sure all
+# this could be tidied up.
+
+#HOME=/home/users0/fx# # Make no longer inherits environment vars
+# (it does inherit env vars on my system!)
+THETANGLE=tangle
+THEWEAVE=weave
+SPIDER=any.spider
+WEAVECHANGEFILE=
+TANGLECHANGEFILE=
+SPIDERCHANGEFILE=
+
+#
+DVI=dvi
+CFLAGS=-DDEBUG -DSTAT
+
+# CPUTYPE is a grim hack that attempts to solve the problem of multiple
+# cpus sharing a file system. In my environment I have to have different
+# copies of object and executable for vax, sun3, next, iris, and other
+# cpu types. If you will be using Spidery WEB in a homogenous processor
+# environment, you can just set CPUTYPE to a constant, or eliminate it
+# entirely.
+#
+# In my environment, the 'cputype' program returns a string that
+# describes the current processor. That means that the easiest thing
+# for you to do is to define a 'cputype' program that does something
+# sensible. A shell script that says 'echo "vax"' is fine.
+
+#CPUTYPE=`cputype`
+CPUTYPE=`arch`
+
+# Change the following three directories to match your installation
+#
+# the odd placement of # is to prevent any trailing spaces from slipping in
+
+WEBROOT=$(HOME)/ltxspiderweb# # root of the WEB source distribution
+DEST=$(HOME)/bin# # place where the executables go
+MACROS=$(HOME)/tex/inputs# # place where the macros go
+
+MASTER=$(WEBROOT)/master# # master source directory
+OBDIR=$(MASTER)/$(CPUTYPE)# # common object files
+
+TANGLESRC=tangle
+CTANGLE=ceetangle -I$(MASTER)
+CWEAVE=ceeweave -I$(MASTER)
+AWKTANGLE=awktangle -I$(MASTER)
+COMMONOBJS=$(OBDIR)/common.o $(OBDIR)/pathopen.o
+COMMONC=$(MASTER)/common.c $(MASTER)/pathopen.c
+COMMONSRC=$(COMMONC) $(MASTER)/spider.awk
+
+
+
+# Our purpose is to make tangle and weave
+
+web: tangle weave
+
+tangle: $(COMMONOBJS) $(TANGLESRC).o
+ cc $(CFLAGS) -o $(DEST)/$(THETANGLE) $(COMMONOBJS) $(TANGLESRC).o
+
+weave: $(COMMONOBJS) weave.o
+ cc $(CFLAGS) -o $(DEST)/$(THEWEAVE) $(COMMONOBJS) weave.o
+
+
+source: $(TANGLESRC).c $(COMMONSRC) # make tangle.c and common src, then clean
+ if [ -f WebMakefile ]; then exit 1; fi # don't clean the master!
+ if [ -f spiderman.tex ]; then exit 1; fi # don't clean the manual
+ -rm -f tangle.web weave.* common.* # remove links that may be obsolete
+ -rm -f *.unsorted *.list grammar.web outtoks.web scraps.web
+ -rm -f cycle.test spider.slog
+ -rm -f *.o *.tex *.toc *.dvi *.log *.makelog *~ *.wlog *.printlog
+
+# Here is how we make the common stuff
+
+$(MASTER)/common.c: $(MASTER)/common.web $(MASTER)/common.ch
+ $(CTANGLE) $(MASTER)/common $(MASTER)/common
+
+$(OBDIR)/common.o: $(MASTER)/common.c
+ cc $(CFLAGS) -c $(MASTER)/common.c
+ mv common.o $(OBDIR)
+
+
+$(MASTER)/pathopen.c: $(MASTER)/pathopen.web $(MASTER)/pathopen.ch
+ $(CTANGLE) $(MASTER)/pathopen $(MASTER)/pathopen
+ mv pathopen.h $(MASTER)
+
+$(OBDIR)/pathopen.o: $(MASTER)/pathopen.c
+ cc $(CFLAGS) -c $(MASTER)/pathopen.c
+ mv pathopen.o $(OBDIR)
+
+
+## Now we make the tangle and weave source locally
+
+$(TANGLESRC).c: $(MASTER)/$(TANGLESRC).web $(MASTER)/common.h grammar.web \
+ $(TANGLECHANGEFILE)
+ -/bin/rm -f $(TANGLESRC).web
+ ln $(MASTER)/$(TANGLESRC).web $(TANGLESRC).web
+# chmod -w $(TANGLESRC).web
+ $(CTANGLE) $(TANGLESRC) $(TANGLECHANGEFILE)
+
+weave.c: $(MASTER)/weave.web $(MASTER)/common.h grammar.web $(WEAVECHANGEFILE)
+ -/bin/rm -f weave.web
+ ln $(MASTER)/weave.web weave.web
+# chmod -w weave.web
+ $(CTANGLE) weave $(WEAVECHANGEFILE)
+
+## Here's where we run SPIDER to create the source
+
+grammar.web: $(MASTER)/cycle.awk $(MASTER)/spider.awk $(SPIDER)
+ echo "date" `date` | cat - $(SPIDER) | awk -f $(MASTER)/spider.awk \
+ LaTeX=$(LaTeX) -
+ cat $(MASTER)/transcheck.list trans_keys.unsorted | awk -f \
+ $(MASTER)/transcheck.awk
+ awk -f $(MASTER)/cycle.awk < cycle.test
+ sort *.unsorted | awk -f $(MASTER)/nodups.awk
+ mv *web.tex $(MACROS)
+
+## We might have to make spider first.
+
+$(MASTER)/spider.awk: $(MASTER)/spider.web $(SPIDERCHANGEFILE)
+ $(AWKTANGLE) $(MASTER)/spider $(SPIDERCHANGEFILE)
+ mv cycle.awk nodups.awk transcheck.awk $(MASTER)
+ rm junk.list
+
+# $(MASTER)/cycle.awk: $(MASTER)/cycle.web # making spider also makes cycle
+# $(AWKTANGLE) $(MASTER)/cycle
+
+# Weaving:
+
+weave.tex: $(MASTER)/weave.web grammar.web $(WEAVECHANGEFILE)
+ ceeweave -I$(MASTER) $(MASTER)/weave.web $(WEAVECHANGEFILE)
+ mv $(MASTER)/weave.tex .
+
+tangle.tex: $(MASTER)/tangle.web $(TANGLECHANGEFILE)
+ ceeweave -I$(MASTER) $(MASTER)/tangle.web $(TANGLECHANGEFILE)
+ mv $(MASTER)/tangle.tex .
+
+spider.tex: $(MASTER)/spider.web $(SPIDERCHANGEFILE)
+ awkweave -I$(MASTER) $(MASTER)/spider.web $(SPIDERCHANGEFILE)
+ mv $(MASTER)/spider.tex .
+
+# This cleanup applies to every language
+
+clean:
+ if [ -f WebMakefile ]; then exit 1; fi # don't clean the master!
+ if [ -f spiderman.tex ]; then exit 1; fi # don't clean the manual
+ -rm -f tangle.web weave.web common.* # remove links that may be obsolete
+ -rm -f *.unsorted *.list grammar.web outtoks.web scraps.web
+ -rm -f cycle.test spider.slog
+# vital bootstrap files are kept as SAVE..., hence only remove .c files whose
+# names start with lower case
+ -rm -f [a-z]*.c *.o *.tex *.toc *.dvi *.log *.makelog *~ *.wlog *.printlog
+
+
+
+# booting the new distribution
+boot:
+ cd ../master; rm -f *.o; for i in $(COMMONC); do \
+ cc $(CFLAGS) -c $$i; \
+ mv *.o $(OBDIR) ; \
+ done; cd ../c
+ cc $(CFLAGS) -c $(TANGLESRC).c; \
+ cc $(CFLAGS) -o $(DEST)/$(THETANGLE) $(COMMONOBJS) $(TANGLESRC).o
+
+